latest
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"model": "anthropic/claude-3.7-sonnet",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "# Context\r\n\r\n- ESP-32, Platform.io, C17\r\n- avoidance of std\r\n- industrial application, using Modbus-485\r\n\r\n## Instructions\r\n\r\n- Generate documentation for a given class, its types, enumerations, in a new Markdown file located at `./docs/modbus/<filename>.md`.\r\n- The documentation is intended for an Astro static site generator.\r\n- Include frontmatter in the Markdown file with `title`, `description`, and `keywords` fields.\r\n- You will be provided with the content of the component's header file (e.g., `src/modbus/<file-name>.h`).\r\n- Ensure the generated Markdown adheres to standard linting rules.\r\n- The generated Markdown document must follow the specific layout provided below.\r\n- The component's C++ source file will contain an example of how it is constructed and mounted; use this as a basis for the \"Example\" section in the documentation.\r\n- Do not comment or add thoughts, just output plain Markdown\r\n\r\n## Layout\r\n\r\nThe Markdown document must adhere to the following structure:\r\n\r\n----------------------------\r\n\r\n## COMPONENT NAME\r\n\r\n**Path**: `relative/path/to/component-name.cpp` (as a Markdown link)\r\n\r\n**Revision History**: Add a file revision entry in the header to track modifications. For the initial documentation, use \"Initial documentation\". Skip this if a revision history already exists !\r\n\r\nA detailed description of the component\r\n\r\n## REQUIREMENTS\r\n\r\nDetail the hardware pins and software dependencies required by the component.\r\n\r\n## PROVIDES\r\n\r\n- a list of all types, enumerations and classes\r\n\r\n## FEATURES\r\n\r\nList the key features and functionalities of the component.\r\n\r\n## DEPENDENCIES\r\n\r\n- Provide a list of dependencies as Markdown formatted links.\r\n- Include a minimal Mermaid diagram illustrating the dependencies. The diagram node names should not contain braces or brackets.\r\n\r\n## BEHAVIOUR\r\n\r\n- Include a minimal Mermaid diagram illustrating the component's behaviour or state machine. The diagram node names should not contain braces or brackets.\r\n\r\n\r\n## TODOS\r\n\r\n### PERFORMANCE\r\n\r\nOutline any performance considerations or areas for future optimization.\r\n\r\n### SECURITY\r\n\r\nDescribe potential security vulnerabilities or hardening measures.\r\n\r\n### COMPLIANCE\r\n\r\nNote any compliance standards or requirements relevant to the component.\r\n\r\n### RECOMMENDATIONS\r\n\r\nProvide any recommendations for using or extending the component.\r\n"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": ""
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"path": "src/xtypes.h",
|
||||
"content": "#ifndef TYPES_H\n#define TYPES_H\n\n#include <stdint.h>\n\ntypedef const char cchar;\ntypedef unsigned char uchar;\n\ntypedef unsigned long millis_t;\ntypedef unsigned short ushort;\ntypedef unsigned long ulong;\ntypedef long int lint;\ntypedef long long int llint;\n\n\n#endif"
|
||||
}
|
||||
],
|
||||
"tools": []
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
Copyright (c) <year> <owner> All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,83 +0,0 @@
|
||||
POLYMECH LICENSE AGREEMENT
|
||||
|
||||
Version 1.0, 23 October 2025
|
||||
|
||||
Copyright (c) 2025 POLYMECH
|
||||
|
||||
Section I: PREAMBLE
|
||||
|
||||
|
||||
This License governs the use of the model (and its derivatives) and is informed by the model card associated with the model.
|
||||
|
||||
NOW THEREFORE, You and POLYMECH agree as follows:
|
||||
|
||||
1. Definitions
|
||||
"License" means the terms and conditions for use, reproduction, and Distribution as defined in this document.
|
||||
"Data" means a collection of information and/or content extracted from the dataset used with the Model, including to train, pretrain, or otherwise evaluate the Model. The Data is not licensed under this License.
|
||||
"Model" means any accompanying machine-learning based assemblies (including checkpoints), consisting of learnt weights, parameters (including optimizer states), corresponding to the model architecture as embodied in the Complementary Material, that have been trained or tuned, in whole or in part on the Data, using the Complementary Material.
|
||||
"Derivatives of the Model" means all modifications to the Model, works based on the Model, or any other model which is created or initialized by transfer of patterns of the weights, parameters, activations or output of the Model, to the other model, in order to cause the other model to perform similarly to the Model, including - but not limited to - distillation methods entailing the use of intermediate data representations or methods based on the generation of synthetic data by the Model for training the other model.
|
||||
"Complementary Material" means the accompanying source code and scripts used to define, run, load, benchmark or evaluate the Model, and used to prepare data for training or evaluation, if any. This includes any accompanying documentation, tutorials, examples, etc, if any.
|
||||
"Distribution" means any transmission, reproduction, publication or other sharing of the Model or Derivatives of the Model to a third party, including providing the Model as a hosted service made available by electronic or other remote means - e.g. API-based or web access.
|
||||
"POLYMECH" (or "we") means Beijing POLYMECH Artificial Intelligence Fundamental Technology Research Co., Ltd., Hangzhou POLYMECH Artificial Intelligence Fundamental Technology Research Co., Ltd. and/or any of their affiliates.
|
||||
"You" (or "Your") means an individual or Legal Entity exercising permissions granted by this License and/or making use of the Model for whichever purpose and in any field of use, including usage of the Model in an end-use application - e.g. chatbot, translator, etc.
|
||||
"Third Parties" means individuals or legal entities that are not under common control with POLYMECH or You.
|
||||
|
||||
Section II: INTELLECTUAL PROPERTY RIGHTS
|
||||
|
||||
Both copyright and patent grants apply to the Model, Derivatives of the Model and Complementary Material. The Model and Derivatives of the Model are subject to additional terms as described in Section III.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, POLYMECH hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare, publicly display, publicly perform, sublicense, and distribute the Complementary Material, the Model, and Derivatives of the Model.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License and where and as applicable, POLYMECH hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this paragraph) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Model and the Complementary Material, where such license applies only to those patent claims licensable by POLYMECH that are necessarily infringed by its contribution(s). If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Model and/or Complementary Material constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for the Model and/or works shall terminate as of the date such litigation is asserted or filed.
|
||||
|
||||
|
||||
Section III: CONDITIONS OF USAGE, DISTRIBUTION AND REDISTRIBUTION
|
||||
|
||||
4. Distribution and Redistribution. You may host for Third Party remote access purposes (e.g. software-as-a-service), reproduce and distribute copies of the Model or Derivatives of the Model thereof in any medium, with or without modifications, provided that You meet the following conditions:
|
||||
a. Use-based restrictions as referenced in paragraph 5 MUST be included as an enforceable provision by You in any type of legal agreement (e.g. a license) governing the use and/or distribution of the Model or Derivatives of the Model, and You shall give notice to subsequent users You Distribute to, that the Model or Derivatives of the Model are subject to paragraph 5. This provision does not apply to the use of Complementary Material.
|
||||
b. You must give any Third Party recipients of the Model or Derivatives of the Model a copy of this License;
|
||||
c. You must cause any modified files to carry prominent notices stating that You changed the files;
|
||||
d. You must retain all copyright, patent, t1rademark, and attribution notices excluding those notices that do not pertain to any part of the Model, Derivatives of the Model.
|
||||
e. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions - respecting paragraph 4.a. – for use, reproduction, or Distribution of Your modifications, or for any such Derivatives of the Model as a whole, provided Your use, reproduction, and Distribution of the Model otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Use-based restrictions. The restrictions set forth in Attachment A are considered Use-based restrictions. Therefore You cannot use the Model and the Derivatives of the Model for the specified restricted uses. You may use the Model subject to this License, including only for lawful purposes and in accordance with the License. Use may include creating any content with, finetuning, updating, running, training, evaluating and/or reparametrizing the Model. You shall require all of Your users who use the Model or a Derivative of the Model to comply with the terms of this paragraph (paragraph 5).
|
||||
|
||||
6. The Output You Generate. Except as set forth herein, POLYMECH claims no rights in the Output You generate using the Model. You are accountable for the Output you generate and its subsequent uses. No use of the output can contravene any provision as stated in the License.
|
||||
|
||||
Section IV: OTHER PROVISIONS
|
||||
|
||||
7. Updates and Runtime Restrictions. To the maximum extent permitted by law, POLYMECH reserves the right to restrict (remotely or otherwise) usage of the Model in violation of this License.
|
||||
|
||||
8. Trademarks and related. Nothing in this License permits You to make use of POLYMECH’ trademarks, trade names, logos or to otherwise suggest endorsement or misrepresent the relationship between the parties; and any rights not expressly granted herein are reserved by POLYMECH.
|
||||
|
||||
9. Personal information, IP rights and related. This Model may contain personal information and works with IP rights. You commit to complying with applicable laws and regulations in the handling of personal information and the use of such works. Please note that POLYMECH's license granted to you to use the Model does not imply that you have obtained a legitimate basis for processing the related information or works. As an independent personal information processor and IP rights user, you need to ensure full compliance with relevant legal and regulatory requirements when handling personal information and works with IP rights that may be contained in the Model, and are willing to assume solely any risks and consequences that may arise from that.
|
||||
|
||||
10. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, POLYMECH provides the Model and the Complementary Material on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Model, Derivatives of the Model, and the Complementary Material and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
11. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall POLYMECH be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Model and the Complementary Material (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if POLYMECH has been advised of the possibility of such damages.
|
||||
|
||||
12. Accepting Warranty or Additional Liability. While redistributing the Model, Derivatives of the Model and the Complementary Material thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of POLYMECH, and only if You agree to indemnify, defend, and hold POLYMECH harmless for any liability incurred by, or claims asserted against, POLYMECH by reason of your accepting any such warranty or additional liability.
|
||||
|
||||
13. If any provision of this License is held to be invalid, illegal or unenforceable, the remaining provisions shall be unaffected thereby and remain valid as if such provision had not been set forth herein.
|
||||
|
||||
14. Governing Law and Jurisdiction. This agreement will be governed and construed under PRC laws without regard to choice of law principles, and the UN Convention on Contracts for the International Sale of Goods does not apply to this agreement. The courts located in the domicile of Hangzhou POLYMECH Artificial Intelligence Fundamental Technology Research Co., Ltd. shall have exclusive jurisdiction of any dispute arising out of this agreement.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Attachment A
|
||||
|
||||
Use Restrictions
|
||||
|
||||
You agree not to use the Model or Derivatives of the Model:
|
||||
|
||||
- In any way that violates any applicable national or international law or regulation or infringes upon the lawful rights and interests of any third party;
|
||||
- For military use in any way;
|
||||
- For the purpose of exploiting, harming or attempting to exploit or harm minors in any way;
|
||||
- To generate or disseminate verifiably false information and/or content with the purpose of harming others;
|
||||
- To generate or disseminate inappropriate content subject to applicable regulatory requirements;
|
||||
- To generate or disseminate personal identifiable information without due authorization or for unreasonable use;
|
||||
- To defame, disparage or otherwise harass others;
|
||||
- For fully automated decision making that adversely impacts an individual’s legal rights or otherwise creates or modifies a binding, enforceable obligation;
|
||||
- For any use intended to or which has the effect of discriminating against or harming individuals or groups based on online or offline social behavior or known or predicted personal or personality characteristics;
|
||||
- To exploit any of the vulnerabilities of a specific group of persons based on their age, social, physical or mental characteristics, in order to materially distort the behavior of a person pertaining to that group in a manner that causes or is likely to cause that person or another person physical or psychological harm;
|
||||
- For any use intended to or which has the effect of discriminating against individuals or groups based on legally protected characteristics or categories.
|
||||
@@ -1,6 +1,4 @@
|
||||
# PolyMech Firmware Library
|
||||
|
||||
## License
|
||||
|
||||
We have added supplementary usage terms (see [./LICENSE-MODEL.txt](./LICENSE-MODEL.txt)) that explicitly prohibit employing this work to harm others. In particular, the terms forbid its use for brainwashing, profit-driven indoctrination, any kind of exploitation such as the “Precious Plastic” scam that targets young people (see [https://forum.osr-plastic.org/t/preciousplastic-review/11066](https://forum.osr-plastic.org/t/preciousplastic-review/11066)).
|
||||
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
---
|
||||
title: 3-Position Analog Switch Component
|
||||
description: Documentation for the Pos3Analog component that provides a 3-position switch interface with local and remote control modes
|
||||
keywords: [Pos3Analog, 3-position switch, modbus, esp32, analog input]
|
||||
---
|
||||
|
||||
## Pos3Analog
|
||||
|
||||
**Path**: [src/Pos3Analog.h](../../src/Pos3Analog.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Pos3Analog component provides functionality for a 3-position analog switch interface, supporting both local (hardware) and remote (Modbus) control. It reads the state of a physical switch through analog inputs and exposes the switch state via Modbus. The component can be configured to operate in local mode (reading physical inputs) or remote mode (controlled via Modbus).
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- **Hardware**:
|
||||
- Two analog input pins (upPin and downPin)
|
||||
- ESP-32 microcontroller
|
||||
|
||||
- **Software**:
|
||||
- Platform.io build environment
|
||||
- C++17 compatible compiler
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Reads a 3-position switch (UP, MIDDLE, DOWN) using two analog inputs
|
||||
- Supports two control modes: LOCAL (hardware) and REMOTE (Modbus)
|
||||
- Provides Modbus register interface for reading the current position
|
||||
- Allows remote control of the switch position
|
||||
- Configurable Modbus address for integration with industrial systems
|
||||
- Debounced analog input reading with configurable interval
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - For logging functionality
|
||||
- [Component](../../src/Component.h) - Base component class
|
||||
- [xmath](../../src/xmath.h) - For range checking and math utilities
|
||||
- [ModbusTCP](../../src/modbus/ModbusTCP.h) - For Modbus communication
|
||||
- [config.h](../../src/config.h) - For configuration constants
|
||||
- [config-modbus.h](../../src/config-modbus.h) - For Modbus-specific configurations
|
||||
- [enums.h](../../src/enums.h) - For enumerations used by the component
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Pos3Analog --> Component
|
||||
Pos3Analog --> xmath
|
||||
Pos3Analog --> ModbusTCP
|
||||
Pos3Analog --> ArduinoLog
|
||||
Component --> ArduinoLog
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup
|
||||
Setup --> Idle
|
||||
Idle --> ReadLocal: If ControlMode==LOCAL
|
||||
Idle --> ReadRemote: If ControlMode==REMOTE
|
||||
ReadLocal --> UpdateState: If position changed
|
||||
ReadRemote --> UpdateState: If position changed
|
||||
UpdateState --> NotifyChange
|
||||
NotifyChange --> Idle
|
||||
Idle --> ProcessModbus: ModbusRequest
|
||||
ProcessModbus --> ChangeMode: Write to Mode Register
|
||||
ProcessModbus --> ChangeRemoteValue: Write to RemoteValue Register
|
||||
ProcessModbus --> ReturnCurrentValue: Read from Value Register
|
||||
ChangeMode --> Idle
|
||||
ChangeRemoteValue --> UpdateState: If Remote Mode & value changed
|
||||
ReturnCurrentValue --> Idle
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing hysteresis for analog readings to prevent flickering between states
|
||||
- Optimize the loop interval for different application scenarios to balance responsiveness and CPU usage
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add bounds checking on Modbus register access to prevent potential overflows
|
||||
- Consider adding a validation mechanism for state changes to prevent rapid oscillations
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with industrial Modbus protocol standards for wider compatibility
|
||||
- Document conformance to RS-485 electrical standards if used in that context
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use pull-up/pull-down resistors on the analog input pins for more reliable readings
|
||||
- Configure appropriate thresholds in config.h for the specific analog sensors being used
|
||||
- Implement error handling for the case of both UP and DOWN inputs being active
|
||||
- Consider adding a debounce mechanism for the switch position to prevent oscillation
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example demonstrates how to initialize and add a Pos3Analog component to your application:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_POS3_ANALOG_0_UP
|
||||
pos3Analog_0 = new Pos3Analog(
|
||||
this, // owner
|
||||
PIN_POS3_ANALOG_0_UP, // upPin
|
||||
PIN_POS3_ANALOG_0_DOWN,// downPin
|
||||
ID_POS3_ANALOG_0, // id
|
||||
POS3_ANALOG_0_MB_ADDR // modbusAddress
|
||||
);
|
||||
if (pos3Analog_0)
|
||||
{
|
||||
components.push_back(pos3Analog_0);
|
||||
Log.infoln(F("Pos3Analog_0 initialized. UpPin:%d, DownPin:%d, ID:%d, MB:%d"),
|
||||
PIN_POS3_ANALOG_0_UP, PIN_POS3_ANALOG_0_DOWN,
|
||||
ID_POS3_ANALOG_0, POS3_ANALOG_0_MB_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("Pos3Analog_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,116 +0,0 @@
|
||||
---
|
||||
title: "Analog Level Switch Component Documentation"
|
||||
description: "Documentation for the AnalogLevelSwitch component, which reads analog inputs as multi-position switches"
|
||||
keywords: "ESP-32, analog, level switch, multi-position switch, modbus, Arduino, embedded"
|
||||
---
|
||||
|
||||
## Analog Level Switch
|
||||
|
||||
**Path**: [`src/AnalogLevelSwitch.cpp`](../src/AnalogLevelSwitch.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Analog Level Switch component reads an analog input pin and interprets the voltage as a discrete position or "slot". This is useful for interfacing with multi-position switches, potentiometers, or resistor networks connected to an analog input. The component provides smooth reading with configurable debouncing, hysteresis, and auto-calibration for reliable slot detection.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- An analog input pin connected to a voltage divider circuit
|
||||
- Appropriate resistor selection for desired voltage levels (detailed guidance provided in header file)
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Converts analog readings into discrete position slots
|
||||
- Configurable number of positions/slots (up to 32 by default)
|
||||
- Adjustable ADC value offset and step size per slot
|
||||
- Smoothing with moving average or exponential moving average
|
||||
- Configurable debouncing and hysteresis to prevent position flickering
|
||||
- Modbus integration with registers for current level and raw values
|
||||
- Individual slot state monitoring as Modbus coils
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - For logging capabilities
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [ModbusTCP](../src/modbus/ModbusTCP.h) - For Modbus communication
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
AnalogLevelSwitch --> Component
|
||||
AnalogLevelSwitch --> ModbusTCP
|
||||
AnalogLevelSwitch --> ArduinoLog
|
||||
Component --> App
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The AnalogLevelSwitch reads the analog input at regular intervals, applies smoothing, debouncing, and then maps the analog value to a discrete slot.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize
|
||||
Initialize --> ReadAnalog
|
||||
ReadAnalog --> SmoothValues
|
||||
SmoothValues --> DetermineSlot
|
||||
DetermineSlot --> Debounce
|
||||
Debounce --> StateChanged: n confirmations
|
||||
Debounce --> ReadAnalog: not confirmed
|
||||
StateChanged --> NotifyChange
|
||||
NotifyChange --> ReadAnalog
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Review smoothing algorithm choice based on application requirements (MA vs EMA)
|
||||
- Consider using hardware filtering for high-noise environments
|
||||
- Optimize ADC reading intervals based on use case
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Validate Modbus access controls to prevent unauthorized writes
|
||||
- Consider adding range validation for configuration parameters
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure ADC readings are within the ESP-32's input voltage specifications
|
||||
- Review compliance with relevant industrial standards if used in regulated environments
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- For optimal performance, use 1% or better tolerance resistors in voltage divider
|
||||
- Keep equivalent resistance of voltage divider relatively low (1k-100k range) to ensure ADC accuracy
|
||||
- Be mindful of resistor tolerance and ADC non-linearity when designing circuits
|
||||
- Use the resistor calculation guidance in the header file to design appropriate circuits
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_ANALOG_LEVEL_SWITCH
|
||||
analogLevelSwitch = new AnalogLevelSwitch(
|
||||
this, // owner
|
||||
PIN_ANALOG_LEVEL_SWITCH, // analogPin
|
||||
ALS_NUMBER_OF_LEVELS, // numLevels
|
||||
ALS_LEVEL_STEP, // levelStep
|
||||
ALS_ADC_VALUE_OFFSET, // adcValueOffset
|
||||
ID_ANALOG_LEVEL_SWITCH, // id
|
||||
ALS_MODBUS_ADDR // modbusAddress
|
||||
);
|
||||
|
||||
if (analogLevelSwitch)
|
||||
{
|
||||
components.push_back(analogLevelSwitch);
|
||||
Log.infoln(F("AnalogLevelSwitch initialized. Pin:%d, Levels:%d, Step:%d, Offset:%d, ID:%d, MB:%d"),
|
||||
PIN_ANALOG_LEVEL_SWITCH, ALS_NUMBER_OF_LEVELS, ALS_LEVEL_STEP,
|
||||
ALS_ADC_VALUE_OFFSET, ID_ANALOG_LEVEL_SWITCH, ALS_MODBUS_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("AnalogLevelSwitch initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
The component is specifically designed for multi-position switches using voltage dividers. The header file includes detailed information on the resistor selection process for creating a voltage divider setup that can reliably detect different switch positions.
|
||||
@@ -1,128 +0,0 @@
|
||||
---
|
||||
title: "Modbus485 Component"
|
||||
description: "A full-featured Modbus RTU master client implementation for ESP-32 devices, adding extensive error handling and logging."
|
||||
keywords: ["Modbus", "RS485", "ESP32", "industrial", "communication", "RTU"]
|
||||
---
|
||||
|
||||
## Modbus485
|
||||
|
||||
**Path**: [`src/modbus485.h`](../src/modbus485.h)
|
||||
|
||||
**Revision History**:
|
||||
- Initial documentation
|
||||
|
||||
A robust Modbus RTU communication component supporting RS-485 electrical interface for ESP-32 devices. This implementation features comprehensive error handling, logging, and state management, making it suitable for industrial applications requiring reliable communication.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Hardware:
|
||||
- RS-485 transceiver (e.g., MAX485)
|
||||
- UART TX pin
|
||||
- UART RX pin
|
||||
- DE/RE pin for direction control
|
||||
- Software:
|
||||
- HardwareSerial
|
||||
- ArduinoLog or similar for logging
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Full Modbus RTU master client implementation
|
||||
- Configurable baud rate, parity, and stop bits
|
||||
- Support for multiple read and write function codes
|
||||
- Automatic transaction ID management
|
||||
- Comprehensive error handling and reporting
|
||||
- Response timeout management
|
||||
- Debug logging
|
||||
- Modbus frame validation (CRC16)
|
||||
- State machine design for reliable operation
|
||||
- Supports single and block operations for coils, discrete inputs, holding registers and input registers
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log)
|
||||
- [Component](../src/component.h)
|
||||
- [EventManager](../src/event_manager.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Modbus485 --> Component
|
||||
Modbus485 --> EventManager
|
||||
Modbus485 --> ArduinoLog
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> IDLE
|
||||
|
||||
IDLE --> WAITING_TO_SEND: request initiated
|
||||
WAITING_TO_SEND --> SENDING: line ready
|
||||
SENDING --> WAITING_FOR_RESPONSE: frame sent
|
||||
WAITING_FOR_RESPONSE --> PROCESSING_RESPONSE: response received
|
||||
WAITING_FOR_RESPONSE --> TIMEOUT_ERROR: timeout
|
||||
|
||||
PROCESSING_RESPONSE --> IDLE: success
|
||||
PROCESSING_RESPONSE --> ERROR: validation failed
|
||||
|
||||
TIMEOUT_ERROR --> IDLE: reset
|
||||
ERROR --> IDLE: reset
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing a response parser to handle partial responses
|
||||
- Add transaction queuing to handle multiple concurrent requests
|
||||
- Optimize memory usage for constrained devices
|
||||
- Add retry mechanism for failed requests
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement message authentication for critical operations
|
||||
- Consider encryption for sensitive data transmission
|
||||
- Add access control mechanisms for write operations
|
||||
- Implement session timeouts for maintaining connection state
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure full compliance with Modbus RTU specification
|
||||
- Validate against Modbus conformance test suite
|
||||
- Document compatibility with specific Modbus devices
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use proper shielded cables for RS-485 communication
|
||||
- Implement proper termination resistors on the RS-485 bus
|
||||
- Consider using optically isolated RS-485 transceivers in noisy environments
|
||||
- Monitor response times and adjust timeouts accordingly
|
||||
- Implement application-level heartbeats for critical connections
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_RS485_DE
|
||||
modbus485 = new Modbus485(
|
||||
this, // owner
|
||||
PIN_RS485_TX, // TX pin
|
||||
PIN_RS485_RX, // RX pin
|
||||
PIN_RS485_DE, // DE/RE pin
|
||||
RS485_BAUDRATE, // baud rate
|
||||
RS485_CONFIG // UART configuration
|
||||
);
|
||||
|
||||
if (modbus485) {
|
||||
components.push_back(modbus485);
|
||||
Log.infoln(F("Modbus485 initialized. TX:%d, RX:%d, DE:%d, Baud:%d"),
|
||||
PIN_RS485_TX, PIN_RS485_RX, PIN_RS485_DE, RS485_BAUDRATE);
|
||||
} else {
|
||||
Log.errorln(F("Modbus485 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [Modbus Protocol Specification](https://modbus.org/specs.php)
|
||||
- [Modbus RTU Tutorial](https://www.simplymodbus.ca/FAQ.htm)
|
||||
@@ -1,120 +0,0 @@
|
||||
---
|
||||
title: "ModbusRTU"
|
||||
description: "ESP-32 industrial Modbus-485 implementation for bidirectional communication"
|
||||
keywords: ["modbus", "rtu", "485", "esp32", "industrial", "communication", "protocol"]
|
||||
---
|
||||
|
||||
## ModbusRTU
|
||||
|
||||
**Path**: [`src/modbusRTU.h`](../../src/modbusRTU.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
ModbusRTU is a comprehensive implementation of the Modbus RTU protocol over RS-485 for ESP32 devices. It provides a robust, industrial-grade solution for bidirectional communication between master and slave devices, supporting both master functionality for querying other devices and slave functionality for responding to external queries.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- **Hardware**:
|
||||
- RS-485 transceiver (e.g., MAX485)
|
||||
- RX pin (configured in `pins_arduino.h`)
|
||||
- TX pin (configured in `pins_arduino.h`)
|
||||
- DE/RE pin for RS-485 direction control
|
||||
|
||||
- **Software**:
|
||||
- Platform.io with ESP32 support
|
||||
- C17 compiler support
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Supports both Modbus master and slave functionalities
|
||||
- Implements standard Modbus function codes (3, 4, 6, 16)
|
||||
- Automatic CRC calculation and validation
|
||||
- Configurable timeouts and retry mechanisms
|
||||
- Interrupt-driven communication with hardware buffer
|
||||
- Thread-safe operation
|
||||
- Extensible register mapping system
|
||||
- Support for various data types (uint16_t, float, etc.)
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`ArduinoLog`](https://github.com/thijse/Arduino-Log)
|
||||
- [`component.h`](../../src/component.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ModbusRTU --> Component
|
||||
ModbusRTU --> ArduinoLog
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Idle
|
||||
Idle --> Transmitting: Send Request/Response
|
||||
Transmitting --> Waiting: Master Mode
|
||||
Transmitting --> Idle: Slave Mode
|
||||
Waiting --> Processing: Receive Response
|
||||
Waiting --> Timeout: No Response
|
||||
Processing --> Idle: Success/Error
|
||||
Timeout --> Retry: Retries Left
|
||||
Timeout --> Idle: Max Retries
|
||||
Retry --> Transmitting
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing a more efficient buffer management system to reduce memory usage
|
||||
- Optimize CRC calculation for speed using lookup tables
|
||||
- Evaluate interrupt priorities to ensure timely processing of incoming data
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement message authentication to prevent unauthorized commands
|
||||
- Add support for encrypted Modbus communication where security is critical
|
||||
- Consider implementing access control lists for sensitive register operations
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Complete full compliance with Modbus RTU specification
|
||||
- Add support for additional function codes as needed for specific applications
|
||||
- Ensure timing requirements meet the Modbus specification under all operating conditions
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use shielded twisted pair cables for RS-485 communication to maximize reliability
|
||||
- Implement proper line termination (120Ω) at both ends of the RS-485 bus
|
||||
- Consider using galvanic isolation for the RS-485 transceiver in noisy environments
|
||||
- Regularly test communication with various slave devices to ensure compatibility
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example shows how to initialize and mount the ModbusRTU component in master mode:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_RS485_DE
|
||||
modbus = new ModbusRTU(
|
||||
this, // owner
|
||||
SERIAL_RS485, // serial port (defined in pins_arduino.h)
|
||||
PIN_RS485_DE, // direction control pin
|
||||
MODBUS_BAUD_RATE, // baud rate (typically 9600, 19200, or 115200)
|
||||
SERIAL_8N1, // data format (8 bits, no parity, 1 stop bit)
|
||||
1 // device ID for slave mode
|
||||
);
|
||||
|
||||
if (modbus)
|
||||
{
|
||||
components.push_back(modbus);
|
||||
Log.infoln(F("ModbusRTU initialized. DE/RE Pin: %d, Baud: %d, ID: %d"),
|
||||
PIN_RS485_DE, MODBUS_BAUD_RATE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("ModbusRTU initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,118 +0,0 @@
|
||||
---
|
||||
title: "Joystick 4-Position Component"
|
||||
description: "Documentation for the Joystick component, a 4-position joystick controller with local and remote operation modes."
|
||||
keywords: "joystick, ESP32, modbus, component, controller, input device"
|
||||
---
|
||||
|
||||
## Joystick
|
||||
|
||||
**Path**: [`src/components/Joystick.cpp`](../../src/components/Joystick.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Joystick component provides an interface for a 4-position joystick (up, down, left, right) with support for both local physical operation and remote control via Modbus. It features position debouncing for reliable readings, position state tracking, and seamless switching between local and remote operation modes.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Four GPIO pins for joystick inputs (up, down, left, right)
|
||||
- Pull-up resistors (internal or external) for each input
|
||||
- Modbus support for remote operation
|
||||
|
||||
## FEATURES
|
||||
|
||||
- 5 distinct positions: UP, DOWN, LEFT, RIGHT, and CENTER
|
||||
- Configurable debouncing for reliable position readings
|
||||
- Position state tracking with timing information
|
||||
- Switchable operation modes:
|
||||
- LOCAL: reads physical joystick position
|
||||
- REMOTE: accepts position commands via Modbus
|
||||
- Complete Modbus integration
|
||||
- Position holding time tracking
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log)
|
||||
- [ModbusTCP](../../src/modbus/ModbusTCP.h)
|
||||
- [Component](../../src/Component.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Joystick --> Component
|
||||
Joystick --> ModbusTCP
|
||||
Joystick --> ArduinoLog
|
||||
Component --> ArduinoLog
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup
|
||||
Setup --> LocalMode
|
||||
Setup --> RemoteMode
|
||||
|
||||
LocalMode --> ReadPosition
|
||||
LocalMode --> RemoteMode: setMode(REMOTE)
|
||||
|
||||
ReadPosition --> Debouncing: useDebouncing true
|
||||
ReadPosition --> UpdatePosition: useDebouncing false
|
||||
|
||||
Debouncing --> UpdatePosition: confirmCount >= threshold
|
||||
UpdatePosition --> NotifyChange: position changed
|
||||
|
||||
RemoteMode --> LocalMode: setMode(LOCAL)
|
||||
RemoteMode --> OverridePosition: setOverridePosition()
|
||||
OverridePosition --> NotifyChange
|
||||
|
||||
NotifyChange --> LocalMode
|
||||
NotifyChange --> RemoteMode
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider optimizing the debouncing algorithm for specific application needs
|
||||
- Evaluate if READ_INTERVAL_MS (25ms) can be adjusted based on application requirements
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement input validation for Modbus commands
|
||||
- Consider adding authentication for remote mode switching
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with relevant industrial control standards
|
||||
- Review electrical safety requirements for the connected joystick hardware
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use hardware debouncing circuits when possible to reduce CPU load
|
||||
- Implement additional position combinations if needed (e.g., diagonal positions)
|
||||
- Consider adding filter capacitors on input pins for noisy environments
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_JOYSTICK_UP
|
||||
joystick = new Joystick(
|
||||
this, // owner
|
||||
PIN_JOYSTICK_UP, // pinUp
|
||||
PIN_JOYSTICK_DOWN, // pinDown
|
||||
PIN_JOYSTICK_LEFT, // pinLeft
|
||||
PIN_JOYSTICK_RIGHT, // pinRight
|
||||
JOYSTICK_MB_ADDR // modbusAddress
|
||||
);
|
||||
if (joystick) {
|
||||
components.push_back(joystick);
|
||||
Log.infoln(F("Joystick initialized. Pins - Up:%d Down:%d Left:%d Right:%d, MB:%d"),
|
||||
PIN_JOYSTICK_UP, PIN_JOYSTICK_DOWN,
|
||||
PIN_JOYSTICK_LEFT, PIN_JOYSTICK_RIGHT,
|
||||
JOYSTICK_MB_ADDR);
|
||||
} else {
|
||||
Log.errorln(F("Joystick initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,122 +0,0 @@
|
||||
---
|
||||
title: "LED Feedback Component Documentation"
|
||||
description: "Documentation for the LED Feedback component providing visual status indicators using addressable LED strips"
|
||||
keywords: "LED Feedback, NeoPixel, WS2812B, SK6812, ESP32, visual indicator"
|
||||
---
|
||||
|
||||
## LED Feedback
|
||||
|
||||
**Path**: [`src/LEDFeedback.cpp`](../src/LEDFeedback.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The LED Feedback component provides visual status indication through addressable LED strips (NeoPixel compatible). It offers multiple display modes including fading effects, level indicators, and tri-color blinking patterns that can be controlled via Modbus.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Digital output pin connected to WS2812B/SK6812 compatible LED strip
|
||||
- 5V power supply for the LED strip (separate from microcontroller logic)
|
||||
- Modbus TCP connection for remote control
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Multiple display modes:
|
||||
- OFF: All LEDs turned off
|
||||
- FADE_R_B: Smooth color transition between red and blue
|
||||
- RANGE: Level indicator (0-100%) using lit LEDs
|
||||
- TRI_COLOR_BLINK: Three-section traffic light style blinking (red, yellow, green)
|
||||
- Modbus control interface for mode selection and parameters
|
||||
- Adjustable update rate for animations
|
||||
- Configurable pixel count to support different strip lengths
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Adafruit_NeoPixel](https://github.com/adafruit/Adafruit_NeoPixel) - Library for controlling addressable LED strips
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - Logging functionality
|
||||
- [ModbusTCP](../src/modbus/ModbusTCP.h) - For Modbus communication
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
LEDFeedback --> Component
|
||||
LEDFeedback --> Adafruit_NeoPixel
|
||||
LEDFeedback --> ModbusTCP
|
||||
LEDFeedback --> ArduinoLog
|
||||
LEDFeedback --> Bridge
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> OFF
|
||||
OFF --> FADE_R_B: Modbus write mode=1
|
||||
OFF --> RANGE: Modbus write mode=2
|
||||
OFF --> TRI_COLOR_BLINK: Modbus write mode=3
|
||||
|
||||
FADE_R_B --> OFF: Modbus write mode=0
|
||||
FADE_R_B --> RANGE: Modbus write mode=2
|
||||
FADE_R_B --> TRI_COLOR_BLINK: Modbus write mode=3
|
||||
|
||||
RANGE --> OFF: Modbus write mode=0
|
||||
RANGE --> FADE_R_B: Modbus write mode=1
|
||||
RANGE --> TRI_COLOR_BLINK: Modbus write mode=3
|
||||
RANGE: Update level via Modbus
|
||||
|
||||
TRI_COLOR_BLINK --> OFF: Modbus write mode=0
|
||||
TRI_COLOR_BLINK --> FADE_R_B: Modbus write mode=1
|
||||
TRI_COLOR_BLINK --> RANGE: Modbus write mode=2
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider power consumption optimization for battery-powered applications
|
||||
- Investigate using DMA-based LED control to reduce CPU usage
|
||||
- Add brightness control via Modbus to manage power usage
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Validate Modbus values more strictly to prevent unexpected behavior
|
||||
- Consider adding access control for mode changes
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Verify EMC compliance when LEDs change rapidly (potential for EMI)
|
||||
- Ensure ADA compliance for visual indicators in public/commercial settings
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use adequate power supply for LED strips (60mA per pixel at full brightness)
|
||||
- Consider adding a level-shifting circuit when connecting 3.3V microcontrollers to 5V LED strips
|
||||
- Add physical protection for LEDs in industrial environments
|
||||
- Implement custom modes for specific application requirements
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example shows how to initialize and mount an LED Feedback component in an application:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_LED_FEEDBACK_0
|
||||
ledFeedback_0 = new LEDFeedback(
|
||||
this, // owner
|
||||
PIN_LED_FEEDBACK_0, // pin
|
||||
LED_PIXEL_COUNT_0, // pixelCount
|
||||
ID_LED_FEEDBACK_0, // id
|
||||
LED_FEEDBACK_0_MB_ADDR // modbusAddress
|
||||
);
|
||||
if (ledFeedback_0)
|
||||
{
|
||||
components.push_back(ledFeedback_0);
|
||||
Log.infoln(F("LEDFeedback_0 initialized. Pin:%d, Count:%d, ID:%d, MB:%d"),
|
||||
PIN_LED_FEEDBACK_0, LED_PIXEL_COUNT_0,
|
||||
ID_LED_FEEDBACK_0, LED_FEEDBACK_0_MB_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("LEDFeedback_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,123 +0,0 @@
|
||||
---
|
||||
title: "Modbus Logic Engine"
|
||||
description: "A scriptable rule engine for industrial ESP-32 applications using Modbus"
|
||||
keywords: ["ESP-32", "Modbus", "Logic Engine", "Rule Engine", "Automation"]
|
||||
---
|
||||
|
||||
## Modbus Logic Engine
|
||||
|
||||
**Path**: [`src/ModbusLogicEngine.cpp`](../src/ModbusLogicEngine.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Modbus Logic Engine is a programmable rule engine that allows defining conditional logic rules through Modbus registers. It evaluates conditions on register values and executes actions when conditions are met, providing automation capabilities without requiring firmware modifications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP-32 microcontroller
|
||||
- Platform.io development environment
|
||||
- Modbus TCP/RTU implementation
|
||||
- Feature flag `ENABLE_MB_SCRIPT` must be defined in configuration
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Rules-based automation through Modbus registers
|
||||
- Configurable conditions with multiple comparison operators
|
||||
- Multiple action types including:
|
||||
- Writing to Modbus registers
|
||||
- Setting coils
|
||||
- Calling component methods
|
||||
- Debug flags for troubleshooting
|
||||
- Rule status monitoring and counters
|
||||
- Configurable evaluation interval
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component.h](../src/Component.h) - Base component class
|
||||
- [ArduinoLog.h](../lib/ArduinoLog/ArduinoLog.h) - Logging functionality
|
||||
- [ModbusTypes.h](../src/modbus/ModbusTypes.h) - Modbus type definitions
|
||||
- [PHApp.h](../src/PHApp.h) - Application context
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ModbusLogicEngine --> Component
|
||||
ModbusLogicEngine --> ModbusTypes
|
||||
ModbusLogicEngine --> PHApp
|
||||
ModbusLogicEngine --> ArduinoLog
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The Modbus Logic Engine continuously evaluates rules at a configurable interval, checking conditions against Modbus register values and executing actions when conditions are met.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialization
|
||||
Initialization --> Idle
|
||||
Idle --> EvaluateRules: Interval elapsed
|
||||
EvaluateRules --> CheckCondition
|
||||
CheckCondition --> PerformAction: Condition met
|
||||
CheckCondition --> Idle: Condition not met
|
||||
PerformAction --> Idle
|
||||
EvaluateRules --> Idle: All rules processed
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider adding a priority system for rules that need faster evaluation
|
||||
- Optimize condition evaluation by caching register values when multiple rules reference the same address
|
||||
- Implement batch processing for rules that write to sequential registers
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Consider adding authentication for modifying rule configurations
|
||||
- Implement range checking for target addresses to prevent unauthorized access
|
||||
- Add validation for rule parameters to prevent malformed rules
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure rule execution timing meets industrial control requirements
|
||||
- Document rule format for compliance with automation standards
|
||||
- Implement logging capabilities for audit trails in regulated environments
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use separate register blocks for different rule sets to improve organization
|
||||
- Implement a backup/restore mechanism for rule configurations
|
||||
- Consider a graphical rule editor for easier configuration
|
||||
- Add rule dependencies to allow chaining of rules
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
The Modbus Logic Engine is typically constructed early in the application startup:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_MB_SCRIPT
|
||||
modbusLogicEngine = new ModbusLogicEngine(
|
||||
this // Owner (PHApp instance)
|
||||
);
|
||||
if (modbusLogicEngine) {
|
||||
components.push_back(modbusLogicEngine);
|
||||
Log.infoln(F("ModbusLogicEngine initialized."));
|
||||
|
||||
// Register component methods that can be called from rules
|
||||
modbusLogicEngine->registerMethod(
|
||||
COMPONENT_ID_LED, // Component ID
|
||||
1, // Method ID
|
||||
[this](short arg1, short arg2) -> short {
|
||||
// Example method implementation
|
||||
if (ledComponent) {
|
||||
return ledComponent->setPattern(arg1);
|
||||
}
|
||||
return E_COMPONENT_ERROR;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
Log.errorln(F("ModbusLogicEngine initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,137 +0,0 @@
|
||||
---
|
||||
title: "OmronE5 - Temperature Controller Component"
|
||||
description: "Interface for Omron E5 series temperature controllers via Modbus RTU"
|
||||
keywords: "omron, e5, temperature controller, modbus, rs485, industrial automation"
|
||||
---
|
||||
|
||||
## OmronE5
|
||||
|
||||
**Path**: [`./src/components/OmronE5.cpp`](./src/components/OmronE5.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The OmronE5 component provides an interface to Omron E5 series temperature controllers via Modbus-RTU over RS485. It enables temperature monitoring, setpoint control, and advanced heat rate analytics for industrial control applications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Hardware:
|
||||
- RS485 transceiver module connected to ESP32
|
||||
- Properly configured Omron E5 controller with Modbus RTU capabilities
|
||||
- Software:
|
||||
- `ENABLE_RS485` must be defined in the configuration
|
||||
- Optional `ENABLE_TRUTH_COLLECTOR` for advanced statistical analysis
|
||||
- Optional `ENABLE_COOLING` for cooling mode support
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Read Process Value (PV) and Setpoint (SP) from the controller
|
||||
- Control the temperature setpoint
|
||||
- Monitor controller running/heating/cooling status
|
||||
- Start and stop the temperature controller
|
||||
- Advanced statistics (with TRUTH_COLLECTOR enabled):
|
||||
- Track mean error between PV and SP
|
||||
- Calculate heat rate (oscillations per minute)
|
||||
- Monitor power consumption (Wh)
|
||||
- Calculate PV/SP response lag
|
||||
- Track longest heating duration in time windows
|
||||
- Estimate energy costs
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - Logging functionality
|
||||
- [Component](./src/Component.h) - Base component system
|
||||
- [ModbusRTU](./src/modbus/ModbusRTU.h) - Modbus RTU communication
|
||||
- [ModbusTypes](./src/modbus/ModbusTypes.h) - Modbus data types
|
||||
- [OmronE5Types](./src/components/OmronE5Types.h) - Omron E5 specific constants
|
||||
- [xstatistics](./src/xstatistics.h) - Statistical calculations (when TRUTH_COLLECTOR enabled)
|
||||
- [ValueWrapper](./src/ValueWrapper.h) - Value change tracking
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
OmronE5 --> RTU_Base
|
||||
RTU_Base --> Component
|
||||
OmronE5 --> OmronE5Types
|
||||
OmronE5 --> ModbusTypes
|
||||
OmronE5 --> ValueWrapper
|
||||
OmronE5 --> xstatistics
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The component operates through read/write operations to specific Modbus registers on the Omron controller, with additional statistical analysis when enabled.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup
|
||||
Setup --> Running
|
||||
Running --> Reading: Every _readInterval ms
|
||||
Reading --> ProcessData: onRegisterUpdate
|
||||
ProcessData --> UpdateStats: When TRUTH_COLLECTOR enabled
|
||||
ProcessData --> CheckHeatUpState
|
||||
UpdateStats --> Running
|
||||
CheckHeatUpState --> Running
|
||||
Running --> HandleCommands: When command received
|
||||
HandleCommands --> SetSP
|
||||
HandleCommands --> RunStop
|
||||
HandleCommands --> Info
|
||||
HandleCommands --> ResetStats: When TRUTH_COLLECTOR enabled
|
||||
SetSP --> Running
|
||||
RunStop --> Running
|
||||
Info --> Running
|
||||
ResetStats --> Running
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider optimizing the read interval based on controller activity
|
||||
- Reduce read frequency during stable operations to minimize bus traffic
|
||||
- Group register reads where possible to minimize transaction overhead
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add range validation for all incoming Modbus values
|
||||
- Implement authentication for control operations if needed in sensitive installations
|
||||
- Consider adding checksums for critical value modifications
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure component behavior complies with relevant industrial control standards
|
||||
- Verify compatibility with different firmware versions of Omron E5 controllers
|
||||
- Document any deviations from standard Modbus implementations
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Configure the Omron E5 controller with compatible Modbus RTU settings (baud rate, parity)
|
||||
- Set appropriate register access permissions on the controller
|
||||
- Use the TRUTH_COLLECTOR feature for diagnostics and optimization
|
||||
- When using cooling functionality, ensure the controller is properly configured for heat/cool control
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
The following example demonstrates how to initialize an OmronE5 component within a parent component:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_RS485
|
||||
// Create Omron E5 device with slave ID 1
|
||||
OmronE5* temperatureController = new OmronE5(
|
||||
this, // owner component
|
||||
1, // Modbus slave ID
|
||||
300 // read interval in ms
|
||||
);
|
||||
|
||||
if (temperatureController)
|
||||
{
|
||||
components.push_back(temperatureController);
|
||||
Log.infoln(F("OmronE5 temperature controller initialized. SlaveID:%d, ReadInterval:%d"),
|
||||
1, 300);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("OmronE5 temperature controller initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,105 +0,0 @@
|
||||
---
|
||||
title: Omron E5 Thermometer Types and Registers
|
||||
description: Documentation for the Omron E5 thermometer protocol implementation, including status codes, register addresses, and command definitions
|
||||
keywords: Omron, E5, Modbus, thermal controller, industrial, ESP32, PlatformIO
|
||||
---
|
||||
|
||||
## Omron E5 Types
|
||||
|
||||
**Path**: [`src/omron_e5_types.h`](../../src/omron_e5_types.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
This component provides type definitions, register maps, and command codes for interfacing with Omron E5 series thermal controllers via Modbus protocol. It defines all necessary constants, status bit positions, and register addresses to read sensor data and control the Omron E5 device.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Requires an RS-485 hardware interface (for Modbus RTU communication)
|
||||
- Properly connected Omron E5 series temperature controller
|
||||
- Compatible Modbus implementation in the codebase
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Complete register map for Omron E5 series controllers
|
||||
- Status bit position definitions for both status words
|
||||
- Predefined commands for device control operations
|
||||
- Error code definitions for diagnostics
|
||||
- Useful macros for bit manipulation and command creation
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Modbus implementation](../../src/modbus.h)
|
||||
- [Logger](../../src/logger.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
OmronE5 --> Modbus
|
||||
OmronE5 --> Logger
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The component provides definitions that enable the main application to interact with Omron E5 temperature controllers.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
Application->>OmronE5: Request status/temperature
|
||||
OmronE5->>Modbus: Format Modbus request
|
||||
Modbus->>E5Device: Send command via RS-485
|
||||
E5Device->>Modbus: Send response
|
||||
Modbus->>OmronE5: Process response
|
||||
OmronE5->>Application: Return decoded data
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider adding caching mechanisms for frequently accessed values
|
||||
- Implement batch read operations to reduce communication overhead
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add input validation for all commands sent to the device
|
||||
- Implement error recovery mechanisms
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with industrial automation standards
|
||||
- Verify register map against latest Omron E5 documentation
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Create higher-level functions that abstract common operations (e.g., reading temperature, setting limits)
|
||||
- Add temperature unit conversion utilities
|
||||
- Consider implementing automatic reconnection on communication failures
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
#ifdef HAS_OMRON_E5
|
||||
omronE5Controller = new OmronE5Controller(
|
||||
this, // owner
|
||||
&rs485, // modbus interface
|
||||
OMRON_E5_DEVICE_ID, // modbus device id
|
||||
OMRON_E5_MB_ADDR // modbus address
|
||||
);
|
||||
|
||||
if (omronE5Controller) {
|
||||
components.push_back(omronE5Controller);
|
||||
Log.infoln(F("OmronE5Controller initialized. Device ID: %d, MB Address: %d"),
|
||||
OMRON_E5_DEVICE_ID, OMRON_E5_MB_ADDR);
|
||||
|
||||
// Configure initial settings
|
||||
omronE5Controller->setTargetTemperature(DEFAULT_TARGET_TEMP);
|
||||
omronE5Controller->setAlarmLimits(MIN_TEMP_ALARM, MAX_TEMP_ALARM);
|
||||
omronE5Controller->startOperation();
|
||||
} else {
|
||||
Log.errorln(F("OmronE5Controller initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
The Omron E5 implementation is based on the Omron E5 Communications Manual (h175_e5_c_communications_manual_en.pdf). The component provides extensive definitions for all status bits, alarm types, and register addresses as defined in the manual sections 3-24, 3-25, and 5-1 through 5-2.
|
||||
@@ -1,123 +0,0 @@
|
||||
---
|
||||
title: "OMRONE5_EX Component Documentation"
|
||||
description: "Documentation for the OMRONE5_EX component used for communication with Omron E5 temperature controllers"
|
||||
keywords: "OMRONE5_EX, Omron, E5, temperature controller, Modbus, RTU, industrial control"
|
||||
---
|
||||
|
||||
## OMRONE5_EX
|
||||
|
||||
**Path**: [`src/omrone5_ex.h`](../../src/omrone5_ex.h)
|
||||
|
||||
**Revision History**:
|
||||
- Initial documentation
|
||||
|
||||
OMRONE5_EX is a component that provides a comprehensive interface for communication with Omron E5 series temperature controllers via Modbus RTU protocol. It includes an extensive mapping of the E5 controller's Modbus register addresses for temperature monitoring, control settings, alarm management, and device configuration.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP-32 with RS-485 interface for Modbus RTU communication
|
||||
- Omron E5 series temperature controller
|
||||
- RS-485 wiring between ESP-32 and the controller
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Complete mapping of Omron E5 temperature controller Modbus registers
|
||||
- Support for PV (Process Value) temperature monitoring
|
||||
- Access to controller status and settings
|
||||
- Management of control parameters (PID settings, set points)
|
||||
- Alarm configuration and monitoring
|
||||
- Support for various temperature input types and scaling
|
||||
- Communication and display settings control
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ModbusClient](../../src/modbus_client.h)
|
||||
- [Logger](../../src/logger.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
OMRONE5_EX --> ModbusClient
|
||||
OMRONE5_EX --> Logger
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The component primarily serves as a register map for Modbus communication with Omron E5 controllers:
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize
|
||||
Initialize --> Ready
|
||||
Ready --> ReadRegisters: Read temperature
|
||||
Ready --> WriteRegisters: Change settings
|
||||
ReadRegisters --> Ready: Return data
|
||||
WriteRegisters --> Ready: Settings updated
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing register caching to reduce communication overhead
|
||||
- Optimize reading of frequently used registers with multi-register read operations
|
||||
- Implement error recovery mechanisms for communication failures
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add validation of values before writing to controller registers
|
||||
- Implement authentication for critical setting changes
|
||||
- Consider encryption for sensitive parameter transmission
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with industrial control standards (IEC 61131)
|
||||
- Validate operation against Omron E5 series specifications
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Create specialized methods for common operations (e.g., reading temperature, changing set points)
|
||||
- Implement a health monitoring system to detect controller disconnections
|
||||
- Add automatic reconnection capabilities after communication failures
|
||||
- Document temperature scaling factors for different sensor types
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
// Create an instance of the OMRONE5_EX component with Modbus connection
|
||||
#ifdef USE_OMRON_E5_CONTROLLER
|
||||
omronE5Controller = new OMRONE5_EX(
|
||||
this, // owner
|
||||
&modbusClient, // modbus client
|
||||
OMRON_E5_UNIT_ID, // Modbus unit ID for the controller
|
||||
OMRON_E5_UPDATE_RATE // Update rate in milliseconds
|
||||
);
|
||||
|
||||
if (omronE5Controller) {
|
||||
components.push_back(omronE5Controller);
|
||||
Log.infoln(F("OMRONE5_EX initialized. Unit ID: %d, Update rate: %d ms"),
|
||||
OMRON_E5_UNIT_ID, OMRON_E5_UPDATE_RATE);
|
||||
|
||||
// Configure controller with initial settings
|
||||
omronE5Controller->writeRegister(
|
||||
static_cast<uint16_t>(ModbusAddresses::OR_E5_SWR_SET_POINT),
|
||||
initialSetPoint
|
||||
);
|
||||
} else {
|
||||
Log.errorln(F("OMRONE5_EX initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
The OMRONE5_EX component provides an extensive Modbus address map for the Omron E5 series temperature controllers, including addresses for:
|
||||
- Temperature monitoring (PV)
|
||||
- Controller status
|
||||
- Set points and control parameters
|
||||
- PID tuning parameters
|
||||
- Alarm configuration
|
||||
- Input and output settings
|
||||
- Display configuration
|
||||
- Communication parameters
|
||||
|
||||
For detailed information on each register's purpose and valid values, refer to the Omron E5 Series User Manual.
|
||||
@@ -1,147 +0,0 @@
|
||||
---
|
||||
title: "POT - Analog Potentiometer Reader Component"
|
||||
description: "ESP32 analog potentiometer reader with digital filtering capabilities and Modbus integration"
|
||||
keywords: ["ESP32", "potentiometer", "analog", "filtering", "modbus", "industrial control", "embedded systems"]
|
||||
---
|
||||
|
||||
## POT - Analog Potentiometer Reader
|
||||
|
||||
**Path**: [`src/pot.h`](../../../src/pot.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A lightweight, efficient analog potentiometer reader component with multiple filtering options and Modbus integration. It features three damping algorithms (none, moving average, and EMA), deadband processing to suppress noise, and support for both local and remote control modes.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- **Hardware**:
|
||||
- Analog input pin for potentiometer connection
|
||||
- Optional RC low-pass filter hardware for additional noise reduction
|
||||
- **Software**:
|
||||
- Arduino framework
|
||||
- ArduinoLog library
|
||||
- Modbus support (ModbusTCP)
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Three damping algorithms:
|
||||
- No damping (raw readings)
|
||||
- Moving Average (box-car) filtering with configurable window size
|
||||
- Exponential Moving Average (EMA) with configurable alpha
|
||||
- Dead-band filtering to suppress small value changes
|
||||
- Configurable scaling from raw ADC values (0-1023) to application range (0-100 by default)
|
||||
- Modbus TCP integration with support for:
|
||||
- Reading current potentiometer value
|
||||
- Switching between local and remote control modes
|
||||
- Setting remote value for when in remote control mode
|
||||
- No dynamic memory allocation, designed for resource-constrained microcontrollers
|
||||
- Avoids floating-point operations for optimal performance
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](../../../src/Component.h)
|
||||
- [App](../../../src/App.h)
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log)
|
||||
- [Modbus](../../../src/modbus/Modbus.h)
|
||||
- [ModbusTCP](../../../src/modbus/ModbusTCP.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
POT --> Component
|
||||
POT --> App
|
||||
POT --> ArduinoLog
|
||||
POT --> Modbus
|
||||
POT --> ModbusTCP
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup: Initialization
|
||||
Setup --> Local: Default Mode
|
||||
Setup --> Remote: Via Modbus
|
||||
|
||||
state Local {
|
||||
[*] --> ReadAnalogValue
|
||||
ReadAnalogValue --> ApplyFilter
|
||||
ApplyFilter --> ApplyDeadband
|
||||
ApplyDeadband --> NotifyIfChanged
|
||||
}
|
||||
|
||||
state Remote {
|
||||
[*] --> ReadModbusValue
|
||||
ReadModbusValue --> NotifyIfChanged
|
||||
}
|
||||
|
||||
Local --> Remote: Mode Change via Modbus
|
||||
Remote --> Local: Mode Change via Modbus
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider adaptive filtering based on rate of change for better response characteristics
|
||||
- Explore efficient normalization techniques to handle different ADC resolutions (10-bit vs 12-bit)
|
||||
- Implement more sophisticated filtering algorithms if needed for high-noise environments
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add bounds checking for remote control values to prevent overflow/underflow conditions
|
||||
- Implement authentication for remote control mode changes in security-sensitive applications
|
||||
- Consider adding fail-safe behavior for loss of Modbus communication
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Verify compliance with IEC 61131-3 for industrial control systems
|
||||
- Ensure Modbus implementation follows Modbus specification guidelines
|
||||
- Document EMC considerations for analog input circuits
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use a hardware RC low-pass filter as suggested in the component comments for noisy environments
|
||||
- Select appropriate damping algorithm based on application needs:
|
||||
- NONE: Fast response but noisy
|
||||
- MOVING_AVERAGE: Good balance of smoothing and responsiveness
|
||||
- EMA: Smooth response with less memory requirements
|
||||
- Adjust deadband (POT_DEADBAND) based on the stability requirements of the application
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example demonstrates how to initialize a POT component with moving average filtering:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_POT_SPEED
|
||||
potSpeed = new POT(
|
||||
this, // owner
|
||||
PIN_POT_SPEED, // pin
|
||||
ID_POT_SPEED, // id
|
||||
POT_SPEED_MB_ADDR, // modbusAddress
|
||||
POTDampingAlgorithm::DAMPING_MOVING_AVERAGE // filtering algorithm
|
||||
);
|
||||
|
||||
if (potSpeed)
|
||||
{
|
||||
components.push_back(potSpeed);
|
||||
Log.infoln(F("POT Speed initialized. Pin:%d, ID:%d, MB:%d"),
|
||||
PIN_POT_SPEED, ID_POT_SPEED, POT_SPEED_MB_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("POT Speed initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
The component implements several filtering techniques for noise reduction:
|
||||
|
||||
- **Moving Average**: Implemented as an incremental ring buffer with O(1) complexity
|
||||
- **Exponential Moving Average (EMA)**: Uses a 1-pole IIR filter with the formula: `y[n] = y[n-1] + (x[n] - y[n-1]) / 2^k`
|
||||
|
||||
The hardware recommendations include an RC low-pass filter with the potentiometer itself serving as the resistor, and suggested capacitor values based on desired cutoff frequencies:
|
||||
- For faster response (~30 Hz): Use 1 μF
|
||||
- For moderate filtering (~10 Hz): Use 2.2 μF or 3.3 μF
|
||||
- For more smoothing (~5 Hz): Use 4.7 μF or 6.8 μF
|
||||
@@ -1,206 +0,0 @@
|
||||
---
|
||||
title: "Plunger Component Documentation"
|
||||
description: "Documentation for the Plunger component in an ESP-32 industrial device with Modbus-485 capability"
|
||||
keywords: ["ESP-32", "Plunger", "VFD", "Modbus", "industrial", "PlatformIO"]
|
||||
---
|
||||
|
||||
# Plunger
|
||||
|
||||
**Path**: [`src/Plunger.cpp`](../src/Plunger.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Plunger component controls a motor-driven plunger mechanism through a Variable Frequency Drive (VFD). It manages various states including homing, plunging, filling operations, and post-flow sequences while allowing both manual and automatic operation modes.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Hardware
|
||||
- VFD-controlled motor connected to plunger mechanism
|
||||
- Joystick peripheral for manual control
|
||||
- Modbus-485 communication interface
|
||||
|
||||
### Configuration
|
||||
- Multiple configurable speed settings
|
||||
- Operation timing parameters
|
||||
- Auto mode hold durations
|
||||
|
||||
## Features
|
||||
|
||||
- Multiple operation modes:
|
||||
- Manual control via joystick
|
||||
- Auto mode via joystick hold
|
||||
- Replay of recorded plunge sequences
|
||||
- Filling sequence with configurable parameters
|
||||
- Post-flow sequence for pressure maintenance
|
||||
- State machine design with comprehensive state transitions
|
||||
- Jam detection and recovery
|
||||
- Modbus control interface
|
||||
- Configurable timings and speeds
|
||||
- Recording and replaying of plunge operations
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Arduino Framework](https://www.arduino.cc/)
|
||||
- [VFD Component](../src/VFD.cpp)
|
||||
- [Joystick Component](../src/Joystick.cpp)
|
||||
- [Ticker Library](https://github.com/esp8266/Arduino/tree/master/libraries/Ticker)
|
||||
- [ModbusTCP](../src/ModbusTCP.cpp)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Plunger --> VFD
|
||||
Plunger --> Joystick
|
||||
Plunger --> Ticker
|
||||
Plunger --> ModbusTCP
|
||||
Plunger --> Arduino
|
||||
```
|
||||
|
||||
## Behavior
|
||||
|
||||
The Plunger component operates as a state machine with the following states:
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> IDLE
|
||||
|
||||
IDLE --> HOMING_MANUAL: Joystick UP
|
||||
IDLE --> PLUNGING_MANUAL: Joystick DOWN
|
||||
IDLE --> FILLING: Joystick LEFT + HOLD
|
||||
IDLE --> RECORD: Joystick RIGHT + HOLD
|
||||
IDLE --> REPLAY: Joystick RIGHT + BRIEF
|
||||
|
||||
HOMING_MANUAL --> HOMING_AUTO: HOLD > autoModeHoldDuration
|
||||
HOMING_MANUAL --> STOPPING: Joystick release
|
||||
|
||||
PLUNGING_MANUAL --> PLUNGING_AUTO: HOLD > autoModeHoldDuration
|
||||
PLUNGING_MANUAL --> STOPPING: Joystick release
|
||||
|
||||
HOMING_AUTO --> STOPPING: Joystick non-center after release
|
||||
PLUNGING_AUTO --> STOPPING: Joystick non-center after release
|
||||
|
||||
RECORD --> IDLE: Joystick non-RIGHT
|
||||
|
||||
REPLAY --> STOPPING: Joystick non-CENTER
|
||||
REPLAY --> POST_FLOW: Plunge completed, post-flow enabled
|
||||
REPLAY --> IDLE: Plunge completed, post-flow disabled
|
||||
|
||||
FILLING --> STOPPING: Joystick non-CENTER after release
|
||||
|
||||
JAMMED --> RESETTING_JAM
|
||||
RESETTING_JAM --> HOMING_MANUAL: Joystick UP
|
||||
RESETTING_JAM --> IDLE: Joystick non-UP/non-CENTER
|
||||
|
||||
POST_FLOW --> STOPPING: Joystick non-CENTER after release
|
||||
POST_FLOW --> IDLE: Post-flow completed
|
||||
|
||||
STOPPING --> IDLE
|
||||
|
||||
state FILLING {
|
||||
[*] --> PLUNGING
|
||||
PLUNGING --> PLUNGED: Plunge completed
|
||||
PLUNGED --> HOMING: Plunged wait timeout
|
||||
HOMING --> HOMED: Home completed
|
||||
HOMED --> [*]: Homed wait timeout
|
||||
}
|
||||
|
||||
state POST_FLOW {
|
||||
[*] --> POST_FLOW_STOPPING
|
||||
POST_FLOW_STOPPING --> POST_FLOW_STARTING: Stopping wait timeout
|
||||
POST_FLOW_STARTING --> POST_FLOW_COMPLETE: Duration timeout
|
||||
POST_FLOW_COMPLETE --> [*]: Complete wait timeout
|
||||
}
|
||||
|
||||
note right of IDLE: Default state waiting for input
|
||||
note right of JAMMED: Detected overcurrent condition
|
||||
note right of STOPPING: Transitional state to IDLE
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider optimizing timer usage to reduce RAM footprint
|
||||
- Evaluate performance impact of multiple state transitions during operation
|
||||
- Implement configurable acceleration/deceleration profiles for smoother operation
|
||||
- Assess VFD command frequency to prevent communication bottlenecks
|
||||
|
||||
### Security
|
||||
|
||||
- Implement validation of Modbus command sources
|
||||
- Add access control to prevent unauthorized command execution
|
||||
- Consider adding confirmation requirements for critical operations
|
||||
- Log and alert on suspicious command patterns
|
||||
|
||||
### Compliance
|
||||
|
||||
- Ensure compliance with relevant machine safety standards
|
||||
- Consider implementing additional safety interlocks
|
||||
- Document safety requirements and certifications
|
||||
- Follow applicable electrical code requirements for industrial equipment
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Monitor VFD current to detect potential mechanical issues before jam events
|
||||
- Implement a maintenance log for plunger operations
|
||||
- Consider adding physical position sensing for more precise control
|
||||
- Develop UX guidelines for joystick operation to minimize user error
|
||||
- Create a calibration routine for optimal performance with different materials
|
||||
|
||||
## Example
|
||||
|
||||
The following example shows how to initialize and mount a Plunger component:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_PLUNGER_1_ENABLE
|
||||
vfd_1 = new VFD(
|
||||
this, // owner
|
||||
PIN_PLUNGER_1_ENABLE, // enablePin
|
||||
PIN_PLUNGER_1_FORWARD, // forwardPin
|
||||
PIN_PLUNGER_1_COM, // communicationPin
|
||||
PIN_PLUNGER_1_ALARM, // alarmPin
|
||||
PLUNGER_1_ID_VFD // id
|
||||
);
|
||||
|
||||
joystick_1 = new Joystick(
|
||||
this, // owner
|
||||
PIN_PLUNGER_1_JOYSTICK_X, // pinX
|
||||
PIN_PLUNGER_1_JOYSTICK_Y, // pinY
|
||||
PLUNGER_1_ID_JOYSTICK // id
|
||||
);
|
||||
|
||||
if (vfd_1 && joystick_1)
|
||||
{
|
||||
plunger_1 = new Plunger(
|
||||
this, // owner
|
||||
vfd_1, // vfd
|
||||
joystick_1, // joystick
|
||||
PLUNGER_1_ID // id
|
||||
);
|
||||
|
||||
// Configure plunger settings
|
||||
plunger_1->settings.speedRampHz = PLUNGER_1_SPEED_RAMP_HZ;
|
||||
plunger_1->settings.speedSlowHz = PLUNGER_1_SPEED_SLOW_HZ;
|
||||
plunger_1->settings.speedMaxHz = PLUNGER_1_SPEED_MAX_HZ;
|
||||
plunger_1->settings.autoModeHoldDurationMs = PLUNGER_1_AUTO_MODE_HOLD_DURATION_MS;
|
||||
plunger_1->settings.defaultMaxOperationDurationMs = PLUNGER_1_MAX_OPERATION_DURATION_MS;
|
||||
plunger_1->settings.enablePostFlow = PLUNGER_1_ENABLE_POST_FLOW;
|
||||
|
||||
// Add to components list
|
||||
if (plunger_1) {
|
||||
components.push_back(vfd_1);
|
||||
components.push_back(joystick_1);
|
||||
components.push_back(plunger_1);
|
||||
|
||||
Log.infoln(F("Plunger_1 initialized with VFD and Joystick"));
|
||||
}
|
||||
else {
|
||||
Log.errorln(F("Plunger_1 initialization failed."));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log.errorln(F("VFD_1 or Joystick_1 initialization failed, cannot create Plunger_1."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,133 +0,0 @@
|
||||
---
|
||||
title: "Plunger Settings Component"
|
||||
description: "Configuration management for plunger mechanism parameters with persistence capabilities"
|
||||
keywords: ["plunger", "settings", "configuration", "ESP32", "json", "persistence"]
|
||||
---
|
||||
|
||||
## PlungerSettings
|
||||
|
||||
**Path**: [src/PlungerSettings.h](../src/PlungerSettings.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
PlungerSettings is a configuration management component for plunger mechanisms. It provides a structured way to define, store, and retrieve operational parameters for plunger controls, including speeds, timeouts, current thresholds, and behavioral settings. The component supports JSON serialization for persistent storage in the filesystem.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- LittleFS filesystem support for persistent storage
|
||||
- JSON processing capabilities (via ArduinoJson)
|
||||
- Logging functionality (ArduinoLog)
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Comprehensive parameter set for plunger operation control
|
||||
- Default values based on predefined constants
|
||||
- JSON serialization and deserialization
|
||||
- Persistent storage in LittleFS
|
||||
- Type-safe parameter parsing with error handling
|
||||
- Detailed diagnostic logging
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Arduino.h](https://github.com/espressif/arduino-esp32)
|
||||
- [ArduinoJson](https://arduinojson.org/)
|
||||
- [LittleFS](https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html)
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log)
|
||||
- [Plunger.h](../src/Plunger.h) (for default constants)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
PlungerSettings --> Arduino
|
||||
PlungerSettings --> ArduinoJson
|
||||
PlungerSettings --> LittleFS
|
||||
PlungerSettings --> ArduinoLog
|
||||
PlungerSettings --> Plunger
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Constructor] --> B{Default Values}
|
||||
B -->|From Constants| C[Initialize Settings]
|
||||
B -->|From Parameters| D[Initialize Settings]
|
||||
|
||||
E[Load Settings] --> F{File Exists?}
|
||||
F -->|Yes| G[Parse JSON]
|
||||
F -->|No| H[Keep Default Values]
|
||||
G --> I{Parse Success?}
|
||||
I -->|Yes| J[Update Settings]
|
||||
I -->|No| K[Keep Default Values]
|
||||
|
||||
L[Save Settings] --> M[Serialize to JSON]
|
||||
M --> N[Write to File]
|
||||
|
||||
O[fromJson] --> P[Parse Each Setting]
|
||||
P --> Q[Type Validation]
|
||||
Q -->|Valid| R[Update Setting]
|
||||
Q -->|Invalid| S[Keep Default Value]
|
||||
|
||||
T[print] --> U[Log All Settings]
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider using a static JsonDocument with predefined capacity to avoid dynamic memory allocation
|
||||
- Implement selective parameter updates to minimize file writes
|
||||
- Add validation ranges for settings to prevent extreme values that might cause hardware issues
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Consider adding checksums or signatures to detect tampering with settings files
|
||||
- Implement access control mechanisms for settings modification
|
||||
- Sanitize inputs from external sources before applying to settings
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure parameter ranges comply with hardware specifications
|
||||
- Add parameter validation to prevent unsafe mechanical operations
|
||||
- Document any safety-critical parameters and their implications
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Create a web-based configuration interface for easy parameter adjustment
|
||||
- Implement settings profiles for different operational scenarios
|
||||
- Add ability to backup/restore settings to/from external storage
|
||||
- Consider implementing periodic settings validation to detect drift or corruption
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
The PlungerSettings component can be used as follows:
|
||||
|
||||
```cpp
|
||||
// Create settings object with default values
|
||||
PlungerSettings settings;
|
||||
|
||||
// Load saved settings from filesystem
|
||||
if (settings.load()) {
|
||||
Log.infoln("Loaded plunger settings from filesystem");
|
||||
} else {
|
||||
Log.warningln("Using default plunger settings");
|
||||
|
||||
// Save current defaults to create the settings file
|
||||
settings.save();
|
||||
}
|
||||
|
||||
// Access settings
|
||||
uint16_t speed = settings.speedMediumHz;
|
||||
|
||||
// Update a setting
|
||||
settings.currentJamThresholdMa = 1200;
|
||||
|
||||
// Save updated settings
|
||||
settings.save();
|
||||
|
||||
// Debug output all settings
|
||||
settings.print();
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
Documentation for the PlungerSettings class including JSON serialization and deserialization methods, persistent storage capabilities, and configuration parameters for plunger operation control.
|
||||
@@ -1,122 +0,0 @@
|
||||
---
|
||||
title: "RS485 Component - Modbus RTU Interface"
|
||||
description: "RS485 component provides a Modbus RTU interface for industrial applications"
|
||||
keywords: ["ESP32", "RS485", "Modbus", "RTU", "industrial", "interface", "communication"]
|
||||
---
|
||||
|
||||
## RS485
|
||||
|
||||
**Path**: [src/RS485.cpp](src/RS485.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The RS485 component provides a Modbus RTU interface for industrial communications. It acts as a gateway between Modbus TCP and Modbus RTU, managing serial communications with connected hardware devices and exposing them to the higher-level systems.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Hardware:
|
||||
- RS485 transceiver (typically connected to a UART port)
|
||||
- GPIO pin for DE/RE (Data Enable/Receive Enable) control
|
||||
- UART pins (RXD1_PIN, TXD1_PIN)
|
||||
- Software:
|
||||
- ModbusClientRTU library
|
||||
- ModbusRTU implementation
|
||||
- Configuration in config-modbus.h
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Manages communication with multiple Modbus RTU slave devices
|
||||
- Bridges between Modbus TCP and Modbus RTU protocols
|
||||
- Monitors and reports register changes from devices
|
||||
- Provides error handling and reporting
|
||||
- Supports device discovery and monitoring
|
||||
- Dynamic registration of device capabilities with TCP server
|
||||
- Periodic polling of RTU devices
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](src/Component.h) - Base component system
|
||||
- [ModbusRTU](src/modbus/ModbusRTU.h) - Modbus RTU implementation
|
||||
- [ModbusTypes](src/modbus/ModbusTypes.h) - Common Modbus data types
|
||||
- [RTUutils](src/RTUutils.h) - Utilities for RTU communication
|
||||
- [RS485Devices](src/RS485Devices.h) - Device registration
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
RS485 --> Component
|
||||
RS485 --> ModbusRTU
|
||||
RS485 --> ModbusTypes
|
||||
RS485 --> RTUutils
|
||||
RS485 --> RS485Devices
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize
|
||||
Initialize --> Running: Setup successful
|
||||
Initialize --> Error: Setup failed
|
||||
|
||||
Running --> ProcessLoop: RS485_LOOP_INTERVAL_MS
|
||||
ProcessLoop --> HandleRegisterChange: On device register change
|
||||
ProcessLoop --> HandleDeviceStatus: Device status updated
|
||||
ProcessLoop --> Running: Return to main loop
|
||||
|
||||
HandleRegisterChange --> ForwardToTCP: Notify TCP interface
|
||||
HandleRegisterChange --> Running
|
||||
|
||||
Error --> [*]
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider optimizing polling frequency based on device importance or activity
|
||||
- Implement batched read operations for devices with consecutive register addresses
|
||||
- Add performance metrics tracking for RS485 bus utilization and response times
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement validation of received data to prevent buffer overflows
|
||||
- Add authentication mechanisms for critical device communications
|
||||
- Consider encryption for sensitive data transmission
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure full compliance with Modbus RTU specification
|
||||
- Consider implementing Modbus exceptions handling according to standard
|
||||
- Document protocol compatibility with various industrial equipment standards
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Create a configuration tool to easily manage device mappings
|
||||
- Implement automatic baudrate detection for connected devices
|
||||
- Add diagnostic features for bus monitoring and troubleshooting
|
||||
- Consider implementing a fallback mechanism for unreliable connections
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example shows how to initialize and mount the RS485 component in a main application:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_RS485
|
||||
rs485 = new RS485(this); // 'this' is the owner component
|
||||
if (rs485) {
|
||||
components.push_back(rs485);
|
||||
Log.infoln(F("RS485 component initialized."));
|
||||
|
||||
// Register RS485 as ModbusTCP data provider, if TCP is available
|
||||
#ifdef ENABLE_MODBUS_TCP
|
||||
if (modbusTCP) {
|
||||
rs485->mb_tcp_register(modbusTCP);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
Log.errorln(F("RS485 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,109 +0,0 @@
|
||||
---
|
||||
title: "Relay Component Documentation"
|
||||
description: "Documentation for the Relay component which provides control of digital relays with Modbus integration"
|
||||
keywords: [relay, modbus, component, switch, control, esp32]
|
||||
---
|
||||
|
||||
## Relay
|
||||
|
||||
**Path**: [`src/Relay.h`](../../src/Relay.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Relay component provides a simple interface for controlling digital relay outputs with Modbus integration. It enables turning physical relays on and off both programmatically and via Modbus commands, making it suitable for industrial control applications with remote management capabilities.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- A digital output pin for controlling the relay
|
||||
- ESP-32 microcontroller
|
||||
- Modbus-485 infrastructure for remote control
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Control of digital relay outputs (ON/OFF)
|
||||
- Modbus integration for remote control
|
||||
- State persistence and notification
|
||||
- Digital output pin management
|
||||
- Clean API for both direct and Modbus control
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`Component`](../../src/Component.h) - Base class for all system components
|
||||
- [`ArduinoLog`](https://github.com/thijse/Arduino-Log) - Logging utility
|
||||
- [`App`](../../src/App.h) - Application framework
|
||||
- [`enums.h`](../../src/enums.h) - System-wide enumeration definitions
|
||||
- [`config.h`](../../src/config.h) - System configuration
|
||||
- [`Modbus`](../../src/modbus/Modbus.h) - Modbus protocol implementation
|
||||
- [`ModbusTCP`](../../src/modbus/ModbusTCP.h) - Modbus TCP implementation
|
||||
- [`config-modbus.h`](../../src/config-modbus.h) - Modbus configuration
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Relay --> Component
|
||||
Relay --> ArduinoLog
|
||||
Relay --> App
|
||||
Relay --> enums
|
||||
Relay --> config
|
||||
Relay --> Modbus
|
||||
Relay --> ModbusTCP
|
||||
Relay --> configmodbus[config-modbus.h]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The Relay component maintains a simple state machine transitioning between ON and OFF states, controllable both via direct commands and Modbus.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
OFF --> ON: setValue(true) / Modbus Write(1)
|
||||
ON --> OFF: setValue(false) / Modbus Write(0)
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing batch operations for applications requiring multiple relay controls
|
||||
- Evaluate if digital write operations should be debounced or rate-limited in high-frequency scenarios
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add optional authorization for relay state changes
|
||||
- Implement validation logic for Modbus commands based on system state or conditions
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure relay state changes are properly logged for audit in systems requiring operation traceability
|
||||
- Consider adding timing constraints for safety-critical applications
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- For critical applications, implement a watchdog mechanism to set relays to a safe state if communication is lost
|
||||
- When controlling high-power relays, consider implementing safety checks before switching states
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example shows how to instantiate and register a Relay component within the main application:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_RELAY_0
|
||||
relay_0 = new Relay(
|
||||
this, // owner
|
||||
PIN_RELAY_0, // pin
|
||||
ID_RELAY_0, // id
|
||||
RELAY_0_MB_ADDR // modbusAddress
|
||||
);
|
||||
if (relay_0)
|
||||
{
|
||||
components.push_back(relay_0);
|
||||
Log.infoln(F("Relay_0 initialized. Pin:%d, ID:%d, MB:%d"),
|
||||
PIN_RELAY_0, ID_RELAY_0, RELAY_0_MB_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("Relay_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,152 +0,0 @@
|
||||
---
|
||||
title: "REST Server Component Documentation"
|
||||
description: "Documentation for the RESTServer component which provides HTTP and WebSocket APIs for Modbus communication"
|
||||
keywords: ["REST", "API", "WebSocket", "Modbus", "ESP32"]
|
||||
---
|
||||
|
||||
## REST Server
|
||||
|
||||
**Path**: [`src/components/RestServer.cpp`](../src/components/RestServer.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The RESTServer component provides a RESTful API and WebSocket interface for interacting with the Modbus system, allowing remote monitoring and control of registers and coils. It serves static files from the filesystem and implements a comprehensive API for system monitoring and Modbus operations.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- WiFi or Ethernet connectivity
|
||||
- ESP32 with sufficient memory for web server operation
|
||||
- LittleFS filesystem for serving static files (optional, enabled via `ENABLE_LITTLEFS`)
|
||||
- WebSocket support (optional, enabled via `ENABLE_WEBSOCKET`)
|
||||
|
||||
## FEATURES
|
||||
|
||||
- RESTful API for Modbus operations (read/write registers and coils)
|
||||
- WebSocket interface for real-time updates and commands
|
||||
- Serves static files from the filesystem (HTML, CSS, JS)
|
||||
- System information and status endpoint
|
||||
- Log level control
|
||||
- RTU operation queue monitoring
|
||||
- CORS support for cross-origin requests
|
||||
- Pagination support for large datasets
|
||||
- JSON-based communication format
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) - Asynchronous web server library
|
||||
- [AsyncJson](https://github.com/me-no-dev/ESPAsyncWebServer) - JSON support for the async web server
|
||||
- [ArduinoJson](https://arduinojson.org/) - JSON parsing and serialization
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - Logging utility
|
||||
- [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) - Asynchronous TCP library
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [Bridge](../src/Bridge.h) - System bridge
|
||||
- [ModbusTCP](../src/modbus/ModbusTCP.h) - Modbus TCP implementation
|
||||
- [LittleFS](https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html) - Filesystem for static files
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
RESTServer --> ESPAsyncWebServer
|
||||
RESTServer --> AsyncJson
|
||||
RESTServer --> ArduinoJson
|
||||
RESTServer --> ArduinoLog
|
||||
RESTServer --> AsyncTCP
|
||||
RESTServer --> Component
|
||||
RESTServer --> Bridge
|
||||
RESTServer --> ModbusTCP
|
||||
RESTServer --> LittleFS[LittleFS "optional"]
|
||||
RESTServer --> WebSocket[AsyncWebSocket "optional"]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The RESTServer handles API requests and WebSocket communications for interfacing with the Modbus system.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize
|
||||
Initialize --> SetupRoutes
|
||||
SetupRoutes --> Ready
|
||||
|
||||
Ready --> HandleHTTPRequest: HTTP Request
|
||||
HandleHTTPRequest --> ServeStaticFile: File Request
|
||||
HandleHTTPRequest --> ProcessAPICall: API Request
|
||||
HandleHTTPRequest --> Ready
|
||||
|
||||
Ready --> HandleWebSocket: WebSocket Event
|
||||
HandleWebSocket --> ProcessCommand: Message Received
|
||||
HandleWebSocket --> NotifyClient: Client Connected
|
||||
HandleWebSocket --> CleanupClient: Client Disconnected
|
||||
HandleWebSocket --> Ready
|
||||
|
||||
Ready --> BroadcastUpdate: Modbus Data Changed
|
||||
BroadcastUpdate --> Ready
|
||||
|
||||
ProcessAPICall --> ReadModbusData: GET Request
|
||||
ProcessAPICall --> WriteModbusData: POST Request
|
||||
|
||||
ProcessCommand --> ReadModbusData: Read Command
|
||||
ProcessCommand --> WriteModbusData: Write Command
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing message compression for WebSocket communications to reduce bandwidth usage
|
||||
- Optimize JSON serialization for large datasets to reduce memory usage
|
||||
- Implement caching mechanisms for frequently accessed static files
|
||||
- Add pagination for all resource-intensive endpoints to prevent memory issues
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement authentication for API endpoints and WebSocket connections
|
||||
- Add rate limiting to prevent abuse
|
||||
- Consider using HTTPS for encrypted communications
|
||||
- Validate all input parameters more strictly
|
||||
- Implement token-based authentication for long-lived WebSocket connections
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with REST API best practices
|
||||
- Implement proper error handling and status codes according to HTTP standards
|
||||
- Ensure WebSocket implementation complies with RFC 6455
|
||||
- Consider implementing OpenAPI/Swagger documentation for API endpoints
|
||||
- Add proper CORS configuration for security
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Keep WebSocket messages below the maximum size limit (currently 12KB)
|
||||
- Use pagination for large datasets to avoid memory issues
|
||||
- Monitor memory usage during operation, especially with large JSON responses
|
||||
- Consider implementing a websocket message queue for high-traffic systems
|
||||
- Add graceful disconnection handling for WebSocket clients
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This is how you would initialize and mount a RESTServer component:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_WIFI
|
||||
// Create REST server component
|
||||
restServer = new RESTServer(
|
||||
WiFi.localIP(), // Local IP address from WiFi
|
||||
80, // HTTP port
|
||||
&modbusTCP, // Modbus TCP manager
|
||||
this // Owner component (Bridge)
|
||||
);
|
||||
|
||||
if (restServer) {
|
||||
components.push_back(restServer);
|
||||
Log.infoln(F("REST Server initialized on port 80"));
|
||||
} else {
|
||||
Log.errorln(F("REST Server initialization failed"));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [ESPAsyncWebServer Documentation](https://github.com/me-no-dev/ESPAsyncWebServer)
|
||||
- [RFC 6455 - The WebSocket Protocol](https://tools.ietf.org/html/rfc6455)
|
||||
- [RESTful API Design Guide](https://restfulapi.net/)
|
||||
- [ArduinoJson Documentation](https://arduinojson.org/v6/doc/)
|
||||
@@ -1,126 +0,0 @@
|
||||
```markdown
|
||||
---
|
||||
title: "SAKO VFD Component Documentation"
|
||||
description: "Documentation for the SAKO Variable Frequency Drive (VFD) control component for ESP32"
|
||||
keywords: ["VFD", "SAKO", "Modbus", "RS485", "motor control", "ESP32"]
|
||||
---
|
||||
|
||||
## SAKO VFD
|
||||
|
||||
**Path**: [`src/SAKO_VFD.cpp`](../src/SAKO_VFD.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
SAKO_VFD is a component for controlling SAKO Variable Frequency Drives via Modbus RTU over RS485. It provides comprehensive monitoring and control capabilities for industrial applications, allowing for frequency setting, direction control, status monitoring, and fault handling.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP32 with RS485 interface capability
|
||||
- SAKO VFD connected via RS485
|
||||
- Modbus RTU communication enabled on the VFD
|
||||
- Proper connection to GND, A+, B- lines of RS485 bus
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Real-time monitoring of VFD parameters (frequency, current, power, torque)
|
||||
- Control of VFD operation (start, stop, reverse, frequency setting)
|
||||
- Fault detection and reset capability
|
||||
- Support for retract sequences
|
||||
- Statistical tracking of operational parameters
|
||||
- TCP Modbus mapping for remote monitoring and control
|
||||
- Configurable read intervals for performance optimization
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component.h](../src/Component.h)
|
||||
- [ModbusRTU.h](../src/modbus/ModbusRTU.h)
|
||||
- [ModbusTypes.h](../src/modbus/ModbusTypes.h)
|
||||
- [xstatistics.h](../src/xstatistics.h)
|
||||
- [Logger.h](../src/Logger.h)
|
||||
- [Bridge.h](../src/Bridge.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
SAKO_VFD --> RTU_Base
|
||||
RTU_Base --> Component
|
||||
SAKO_VFD --> ModbusRTU
|
||||
SAKO_VFD --> ModbusTypes
|
||||
SAKO_VFD --> xstatistics
|
||||
SAKO_VFD --> Enums
|
||||
SAKO_VFD --> Config
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> STOPPED
|
||||
STOPPED --> ACCELERATING: run/reverse
|
||||
STOPPED --> ERROR: fault
|
||||
ACCELERATING --> RUNNING: reached setpoint
|
||||
ACCELERATING --> DECELERATING: new lower setpoint
|
||||
ACCELERATING --> ERROR: fault
|
||||
RUNNING --> DECELERATING: stop/new lower setpoint
|
||||
RUNNING --> ERROR: fault
|
||||
DECELERATING --> STOPPED: reached zero
|
||||
DECELERATING --> ACCELERATING: new higher setpoint
|
||||
DECELERATING --> ERROR: fault
|
||||
ERROR --> STOPPED: resetFault
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider adding a caching mechanism for registers that don't change frequently
|
||||
- Optimize read block configuration for specific SAKO VFD models
|
||||
- Implement batch writes for sending multiple parameters in a single transaction
|
||||
- Add power consumption tracking and optimization features
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add validation for frequency and command values before sending to VFD
|
||||
- Implement password protection for critical parameter changes
|
||||
- Add communication failure recovery mechanisms
|
||||
- Consider adding CRC validation for received data
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure proper handling of motor parameters according to manufacturer specifications
|
||||
- Implement safety shutdown procedures for emergency situations
|
||||
- Add support for compliance with IEC 61800 standards for variable speed drives
|
||||
- Consider implementing EN/IEC 60204-1 safety requirements
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Configure proper acceleration/deceleration times to prevent mechanical stress
|
||||
- Use motor auto-tuning functionality before production use
|
||||
- Implement proper fault handling and logging for diagnostic purposes
|
||||
- Consider adding thermal protection monitoring
|
||||
- Implement proper error handling and reporting for network communication failures
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_SAKO_VFD
|
||||
sakoVFD = new SAKO_VFD(
|
||||
MB_SAKO_VFD_SLAVE_ID, // Modbus slave ID
|
||||
SAKO_VFD_DEFAULT_READ_INTERVAL // Read interval in milliseconds
|
||||
);
|
||||
if (sakoVFD) {
|
||||
if (sakoVFD->setup() == E_OK) {
|
||||
components.push_back(sakoVFD);
|
||||
Log.infoln(F("SAKO VFD initialized. SlaveID: %d, Interval: %d ms"),
|
||||
MB_SAKO_VFD_SLAVE_ID, SAKO_VFD_DEFAULT_READ_INTERVAL);
|
||||
} else {
|
||||
Log.errorln(F("SAKO VFD setup failed."));
|
||||
delete sakoVFD;
|
||||
sakoVFD = nullptr;
|
||||
}
|
||||
} else {
|
||||
Log.errorln(F("SAKO VFD initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,104 +0,0 @@
|
||||
---
|
||||
title: "Sako Modbus Register Enums"
|
||||
description: "Comprehensive documentation for the Sako drive Modbus register enumeration mappings"
|
||||
keywords: ["Sako", "VFD", "Modbus", "registers", "ESP32", "industrial-automation"]
|
||||
---
|
||||
|
||||
## Sako Modbus Register Enums
|
||||
|
||||
**Path**: [`./src/devices/sako/sako_modbus_registers.h`](./src/devices/sako/sako_modbus_registers.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
This component defines enumeration values for Sako VFD drive parameters accessible via Modbus. It provides a comprehensive mapping of control and configuration registers for Sako frequency inverters with descriptive comments on parameter functions and values.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Modbus RTU communication capability
|
||||
- RS485 interface connected to Sako VFD
|
||||
- Properly configured Modbus client implementation
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Complete parameter mapping for Sako VFD registers
|
||||
- Human-readable enumeration names that describe register purposes
|
||||
- Detailed comments for parameter options and value ranges
|
||||
- Hexadecimal address values with logical grouping by parameter sections
|
||||
- Support for all major drive control and configuration functions
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Modbus client implementation](./src/protocols/modbus/modbus_client.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Application --> SakoModbusRegisters
|
||||
SakoModbusRegisters --> ModbusClient
|
||||
ModbusClient --> RS485Hardware
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The component provides enumeration constants that map to specific Modbus registers in the Sako VFD. It doesn't implement any behavior itself but provides the addressing information needed for the application to communicate with the device.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
Application->>ModbusClient: Use Register Address from E_SAKO_PARAM
|
||||
ModbusClient->>SakoVFD: Send Modbus Request
|
||||
SakoVFD->>ModbusClient: Send Register Data
|
||||
ModbusClient->>Application: Return Result
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider organizing registers into separate enum classes for different parameter groups
|
||||
- Evaluate if a more structured approach like a map or class with methods would improve usability
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add validation ranges for each parameter to prevent sending invalid values
|
||||
- Consider adding read/write permissions to prevent accidental modification of critical parameters
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Verify all register addresses and descriptions against the latest Sako VFD documentation
|
||||
- Ensure compatibility with different Sako VFD series and firmware versions
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use constants from this enumeration rather than hardcoded values in application code
|
||||
- When sending values to the VFD, always check the allowed range from the parameter description
|
||||
- Consider implementing a higher-level interface that uses these enum values but provides type safety and validation
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
// Example of using the Sako register enums with a Modbus client
|
||||
ModbusClient* modbusClient = new ModbusClient(
|
||||
&Serial2,
|
||||
PIN_RS485_DE_RE,
|
||||
MODBUS_BAUD_RATE
|
||||
);
|
||||
|
||||
// Read motor control mode
|
||||
uint16_t controlMode;
|
||||
if (modbusClient->readHoldingRegister(
|
||||
SAKO_MODBUS_ADDRESS,
|
||||
static_cast<uint16_t>(E_SAKO_PARAM::E_SAKO_PARAM_P00_01_MOTOR_CONTROL_MODE),
|
||||
controlMode
|
||||
)) {
|
||||
Serial.printf("Motor control mode: %d\n", controlMode);
|
||||
}
|
||||
|
||||
// Set motor frequency to 50Hz (value needs to be scaled according to parameter specification)
|
||||
uint16_t frequencyValue = 5000; // 50.00Hz, assuming two decimal places
|
||||
modbusClient->writeHoldingRegister(
|
||||
SAKO_MODBUS_ADDRESS,
|
||||
static_cast<uint16_t>(E_SAKO_PARAM::E_SAKO_PARAM_P00_08_PRESET_FREQUENCY),
|
||||
frequencyValue
|
||||
);
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,117 +0,0 @@
|
||||
---
|
||||
title: "SAKO VFD Control Library"
|
||||
description: "Documentation for SAKO VFD (Variable Frequency Drive) interface component"
|
||||
keywords: [SAKO, VFD, Variable Frequency Drive, Modbus, ESP32, Industrial Control]
|
||||
---
|
||||
|
||||
## SAKO VFD Control Library
|
||||
|
||||
**Path**: [`src/SAKO.h`](../src/SAKO.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A library for interfacing with SAKO Variable Frequency Drives (VFDs) via Modbus communication. This component provides standardized access to SAKO VFD registers, enabling monitoring and control of motors in industrial applications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- RS-485 communication interface (hardware or software)
|
||||
- Modbus RTU protocol support
|
||||
- SAKO VFD with Modbus communication capability
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Comprehensive enumeration of SAKO VFD registers
|
||||
- Support for monitoring parameters (frequency, voltage, current, etc.)
|
||||
- Direction control (forward, reverse, jogging, etc.)
|
||||
- Error code definitions and handling
|
||||
- Parameter group communication access
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Modbus RTU Library](../src/modbusRTU.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
App --> SAKO
|
||||
SAKO --> ModbusRTU
|
||||
ModbusRTU --> UART
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize
|
||||
Initialize --> Idle
|
||||
Idle --> ReadStatus: Poll Status
|
||||
Idle --> Control: Set Direction
|
||||
Idle --> ReadRegisters: Request Data
|
||||
ReadStatus --> Idle: Process Status
|
||||
Control --> Idle: Command Sent
|
||||
ReadRegisters --> Idle: Process Data
|
||||
ReadStatus --> ErrorHandling: Error Detected
|
||||
ErrorHandling --> Idle: Reset Error
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Optimize polling frequency based on application requirements
|
||||
- Consider implementing caching mechanism for frequently accessed registers
|
||||
- Add prioritization for critical status parameters
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement validation for register values before writing
|
||||
- Add support for communication timeouts
|
||||
- Consider checksum validation for critical commands
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Verify compatibility with all SAKO VFD models
|
||||
- Ensure compliance with industrial communication standards
|
||||
- Document parameter ranges according to SAKO specifications
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Maintain a minimum poll interval of 50ms to avoid bus contention
|
||||
- Use parameter group access addresses as specified in the SAKO manual
|
||||
- Implement error handling and retry logic for communication failures
|
||||
- Consider using separate tasks for status monitoring and control operations
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_SAKO_VFD
|
||||
sakoVFD = new SAKOVFD(
|
||||
this, // owner
|
||||
&modbus, // modbus interface
|
||||
SAKO_VFD_SLAVE_ADDR, // modbus slave address
|
||||
SAKO_VFD_ID // component ID
|
||||
);
|
||||
|
||||
if (sakoVFD) {
|
||||
components.push_back(sakoVFD);
|
||||
Log.infoln(F("SAKO VFD initialized. Slave Address: %d, ID: %d"),
|
||||
SAKO_VFD_SLAVE_ADDR, SAKO_VFD_ID);
|
||||
|
||||
// Configure monitoring parameters
|
||||
sakoVFD->enableMonitoring(E_SAKO_MON::E_SAKO_MON_RUNNING_FREQUENCY_HZ, true);
|
||||
sakoVFD->enableMonitoring(E_SAKO_MON::E_SAKO_MON_OUTPUT_CURRENT_A, true);
|
||||
sakoVFD->enableMonitoring(E_SAKO_MON::E_SAKO_MON_OUTPUT_VOLTAGE_V, true);
|
||||
}
|
||||
else {
|
||||
Log.errorln(F("SAKO VFD initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
The SAKO VFD component uses parameter group communication access addresses as defined in the SAKO VFD manual:
|
||||
- P0 ~ PE Group: 0xF000 - 0xFEFF
|
||||
- A0 ~ AC Group: 0xA000 - 0xACFF
|
||||
- U0 Group (Monitoring): 0x7000 - 0x70FF
|
||||
|
||||
For detailed information about specific registers and their meanings, refer to the SAKO VFD Operation Manual.
|
||||
@@ -1,125 +0,0 @@
|
||||
---
|
||||
title: "StatusLight - LED Status Indicator Component"
|
||||
description: "A component for controlling a status LED with simple on/off and blinking capabilities"
|
||||
keywords: ["ESP32", "status LED", "indicator", "modbus", "feedback"]
|
||||
---
|
||||
|
||||
## StatusLight
|
||||
|
||||
**Path**: [`src/StatusLight.h`](../../src/StatusLight.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
StatusLight is a component for controlling a status LED, providing simple on/off and blinking capabilities. It supports Modbus integration for remote monitoring and control of the status indicator.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- **Hardware**:
|
||||
- Digital GPIO pin for controlling an LED
|
||||
- **Software**:
|
||||
- Configuration for pin assignment in `config.h`
|
||||
- Modbus address configuration in `config-modbus.h`
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Steady on/off LED control
|
||||
- Blinking functionality with configurable interval
|
||||
- Modbus integration for remote monitoring and control
|
||||
- Support for multiple instances with different Modbus addresses
|
||||
- Component state tracking
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Arduino.h](https://github.com/espressif/arduino-esp32)
|
||||
- [ArduinoLog.h](https://github.com/thijse/Arduino-Log)
|
||||
- [Component.h](../../src/Component.h)
|
||||
- [macros.h](../../src/macros.h)
|
||||
- [xmath.h](../../src/xmath.h)
|
||||
- [Bridge.h](../../src/Bridge.h)
|
||||
- [enums.h](../../src/enums.h)
|
||||
- [config.h](../../src/config.h)
|
||||
- [config-modbus.h](../../src/config-modbus.h)
|
||||
- [modbus/ModbusTCP.h](../../src/modbus/ModbusTCP.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
StatusLight --> Component
|
||||
StatusLight --> Bridge
|
||||
StatusLight --> Arduino
|
||||
StatusLight --> ArduinoLog
|
||||
StatusLight --> macros
|
||||
StatusLight --> xmath
|
||||
StatusLight --> enums
|
||||
StatusLight --> config
|
||||
StatusLight --> configmodbus
|
||||
StatusLight --> ModbusTCP
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> OFF
|
||||
OFF --> ON: set(1)
|
||||
ON --> OFF: set(0)
|
||||
OFF --> BLINK: set(0,1)
|
||||
ON --> BLINK: set(1,1)
|
||||
BLINK --> OFF: set(0,0)
|
||||
BLINK --> ON: set(1,0)
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider using hardware PWM for smoother blinking effects
|
||||
- Review blinking implementation for efficiency (currently using polling in loop)
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add validation for input parameters in set() method
|
||||
- Consider authentication for Modbus write operations
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure blinking rates are appropriate for industrial environments
|
||||
- Comply with industrial standards for visual indicators
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use hardware with appropriate LED drivers for high-brightness applications
|
||||
- Consider adding additional blink patterns for varied status indications
|
||||
- Add support for RGB LEDs for multi-state visualization
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
Below is an example of how to initialize and use the StatusLight component:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_STATUS_LIGHT
|
||||
statusLight = new StatusLight(
|
||||
this, // owner
|
||||
PIN_STATUS_LIGHT, // pin
|
||||
COMPONENT_KEY_FEEDBACK_0, // id
|
||||
MB_MONITORING_STATUS_FEEDBACK_0 // modbusAddress
|
||||
);
|
||||
if (statusLight)
|
||||
{
|
||||
components.push_back(statusLight);
|
||||
Log.infoln(F("StatusLight initialized. Pin:%d, ID:%d, MB:%d"),
|
||||
PIN_STATUS_LIGHT, COMPONENT_KEY_FEEDBACK_0,
|
||||
MB_MONITORING_STATUS_FEEDBACK_0);
|
||||
|
||||
// Example usage
|
||||
statusLight->on(); // Turn the LED on
|
||||
// statusLight->off(); // Turn the LED off
|
||||
// statusLight->setBlink(true); // Make the LED blink
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("StatusLight initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,136 +0,0 @@
|
||||
---
|
||||
title: "Stepper Controller"
|
||||
description: "A component for controlling stepper motors with Modbus integration, direction control, and overload protection."
|
||||
keywords: ["ESP-32", "stepper motor", "Modbus", "motor control", "industrial automation"]
|
||||
---
|
||||
|
||||
## StepperController
|
||||
|
||||
**Path**: [`src/StepperController.h`](../src/StepperController.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
StepperController is a component designed for precise control of stepper motors in industrial applications. It provides Modbus integration through ModbusValue, allowing remote control of motor speed and direction while monitoring status and overload conditions.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Hardware:
|
||||
- Direction pin (GPIO)
|
||||
- Pulse pin (GPIO)
|
||||
- Feedback pin (GPIO) for monitoring motor status
|
||||
- Overload pin (analog input) for detecting motor overload
|
||||
- Compatible stepper motor driver
|
||||
- Software:
|
||||
- AccelStepper library
|
||||
- Modbus capabilities for remote control
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Control stepper motor speed and direction via Modbus
|
||||
- Pulse width configuration for different stepper driver requirements
|
||||
- Overload detection for motor protection
|
||||
- Status monitoring (running, idle, error states)
|
||||
- Speed clamping for safety
|
||||
- Bidirectional control
|
||||
- Configurable motor parameters
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Arduino.h](https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/Arduino.h)
|
||||
- [ArduinoLog.h](https://github.com/thijse/Arduino-Log)
|
||||
- [osr-base.h](../src/osr-base.h)
|
||||
- [App.h](../src/App.h)
|
||||
- [Addon.h](../src/Addon.h)
|
||||
- [Component.h](../src/Component.h)
|
||||
- [ModbusValue.h](../src/ModbusValue.h)
|
||||
- [types.h](../src/types.h)
|
||||
- [AccelStepper.h](https://www.airspayce.com/mikem/arduino/AccelStepper/)
|
||||
- [xmath.h](../src/xmath.h)
|
||||
- [features.h](../src/features.h)
|
||||
- [enums.h](../src/enums.h)
|
||||
- [config.h](../src/config.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
StepperController --> Component
|
||||
StepperController --> ModbusValue
|
||||
StepperController --> AccelStepper
|
||||
Component --> osrBase
|
||||
ModbusValue --> types
|
||||
StepperController --> xmath
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> MOTOR_IDLE
|
||||
MOTOR_IDLE --> MOTOR_RUNNING: speed > 0
|
||||
MOTOR_RUNNING --> MOTOR_IDLE: speed = 0
|
||||
MOTOR_RUNNING --> MOTOR_OVERLOAD: isOverloaded() == true
|
||||
MOTOR_OVERLOAD --> MOTOR_RUNNING: isOverloaded() == false
|
||||
MOTOR_RUNNING --> MOTOR_ERROR: hardware failure
|
||||
MOTOR_ERROR --> MOTOR_IDLE: reset
|
||||
MOTOR_UNKNOWN --> [*]
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Add acceleration profiles for smoother movement
|
||||
- Implement microstepping control for higher precision
|
||||
- Optimize interrupt handling for more precise timing
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add parameter validation before applying motor settings
|
||||
- Implement authentication for Modbus control commands
|
||||
- Add motor limits based on system conditions
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with motor manufacturer specifications
|
||||
- Verify compatibility with industrial Modbus implementations
|
||||
- Review power management for energy efficiency standards
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use shielded cables for motor connections to reduce EMI
|
||||
- Configure appropriate current limits on the stepper driver
|
||||
- Implement a soft start mechanism for heavy loads
|
||||
- Add emergency stop functionality for safety-critical applications
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_STEPPER_0
|
||||
stepperController_0 = new StepperController(
|
||||
this, // owner
|
||||
PIN_STEPPER_0_DIR, // dirPin
|
||||
PIN_STEPPER_0_PULSE, // pulsePin
|
||||
PIN_STEPPER_0_FEEDBACK, // feedbackPin
|
||||
PIN_STEPPER_0_OVERLOAD, // overloadPin
|
||||
STEPPER_0_ENABLED, // enabled
|
||||
STEPPER_0_SPEED, // speed
|
||||
STEPPER_0_PULSE_WIDTH, // pulseWidth
|
||||
STEPPER_0_DIR, // dir
|
||||
ID_STEPPER_0, // id
|
||||
STEPPER_0_MB_ADDR // addressStart
|
||||
);
|
||||
|
||||
if (stepperController_0)
|
||||
{
|
||||
components.push_back(stepperController_0);
|
||||
Log.infoln(F("StepperController_0 initialized. Dir:%d, Pulse:%d, Speed:%d, ID:%d, MB:%d"),
|
||||
PIN_STEPPER_0_DIR, PIN_STEPPER_0_PULSE, STEPPER_0_SPEED,
|
||||
ID_STEPPER_0, STEPPER_0_MB_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("StepperController_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
@@ -1,82 +0,0 @@
|
||||
# Addon
|
||||
|
||||
**Path**: [`src/modbus/Addon.h`](../src/modbus/Addon.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
Addon is a base class that extends the Component class, providing a foundation for creating modular extensions within the modbus system. It serves as a backward compatibility layer while ensuring consistent behavior across different types of add-ons.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP-32 microcontroller
|
||||
- Platform.io development environment
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `Addon` class: Base class for creating modular components
|
||||
- `Addons` type: A Vector container for storing Addon pointers
|
||||
- `AddonFnPtr` type: Function pointer type for addon methods
|
||||
- `byId()` utility function: Find an addon by its ID in a collection
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Inheritance from Component class for consistent behavior
|
||||
- Default run flags for standard execution modes
|
||||
- Support for identifying addons through unique IDs
|
||||
- Vector-based storage and retrieval of addons
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component.h](../src/modbus/Component.h)
|
||||
- [enums.h](../src/modbus/enums.h)
|
||||
- [error_codes.h](../src/modbus/error_codes.h)
|
||||
- [macros.h](../src/modbus/macros.h)
|
||||
- [WString.h](https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/WString.h)
|
||||
- [Vector.h](https://github.com/janelia-arduino/Vector)
|
||||
- [Arduino.h](https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/Arduino.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Addon --> Component
|
||||
Addon --> enums
|
||||
Addon --> error_codes
|
||||
Addon --> macros
|
||||
Addon --> WString
|
||||
Addon --> Vector
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The Addon class extends Component, inheriting its lifecycle methods and adding specific functionality for modular components.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start[Initialize Addon] --> Construct[Constructor sets name, id, flags]
|
||||
Construct --> Setup[Setup phase]
|
||||
Setup --> Loop[Loop function execution]
|
||||
Loop --> Info[Info reporting]
|
||||
Info --> Loop
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider optimizing the `byId()` function for large collections using more efficient data structures or search algorithms
|
||||
- Evaluate memory usage when multiple addons are instantiated
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add validation for addon IDs to prevent duplication
|
||||
- Consider implementing access control mechanisms for sensitive addons
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compatibility with industrial Modbus-485 specifications
|
||||
- Maintain backward compatibility with existing addon implementations
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use meaningful, unique IDs for each addon to simplify management
|
||||
- Consider implementing a registration system to avoid manual management of addon collections
|
||||
- Document specific addon implementations with clear usage examples
|
||||
@@ -1,95 +0,0 @@
|
||||
---
|
||||
title: "App - Application Component"
|
||||
description: "The App class is the main application component that manages the lifecycle and interactions of all components in the system."
|
||||
keywords: ["ESP32", "App", "Component", "PlatformIO", "ModbusRTU", "embedded system"]
|
||||
---
|
||||
|
||||
## App
|
||||
|
||||
**Path**: [`src/App.cpp`](src/App.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The App class serves as the main application component responsible for managing the lifecycle and execution of all components in the system. It is derived from the Component base class and provides functionality for setting up, running the main loop, debugging, and retrieving information about the application and its components. The App acts as a container and orchestrator for all child components.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP32 microcontroller
|
||||
- PlatformIO build environment
|
||||
- C++17 support
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `App` class that manages the application lifecycle
|
||||
- Component management functionality
|
||||
- Component registration with Bridge for communication
|
||||
- Debugging infrastructure
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Component management (adding, retrieving, and querying components)
|
||||
- Application lifecycle management (setup, loop)
|
||||
- Component setup and execution orchestration
|
||||
- Debug facilities with configurable intervals
|
||||
- Component registration with Bridge for communication
|
||||
- Component filtering by flags
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](./Component.md)
|
||||
- [Bridge](./Bridge.md)
|
||||
- [Vector](./Vector.md)
|
||||
- [xtypes](./xtypes.md)
|
||||
- [xtimer](./xtimer.md)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
App --> Component
|
||||
App --> Bridge
|
||||
App --> Vector
|
||||
App --> xtypes
|
||||
App --> xtimer
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The App class follows a standard application lifecycle pattern:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start[Start] --> Constructor[Constructor]
|
||||
Constructor --> Setup[Setup]
|
||||
Setup --> RegisterComponents[Register Components]
|
||||
RegisterComponents --> OnRun[onRun]
|
||||
OnRun --> Loop[Loop]
|
||||
Loop --> Debug[Debug if interval passed]
|
||||
Debug --> Loop
|
||||
Loop --> End[End]
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing component prioritization for the main loop
|
||||
- Optimize component lookup by ID using a hashmap instead of linear search
|
||||
- Implement a more efficient mechanism for component flag filtering
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement component access control or validation mechanisms
|
||||
- Add proper error handling for component operations
|
||||
- Consider adding checks for component validity before operations
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure memory management follows best practices for embedded systems
|
||||
- Validate that the application meets real-time requirements for industrial settings
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use the `byId` method to retrieve components when you know their IDs
|
||||
- Configure appropriate debug intervals based on the application's performance requirements
|
||||
- Group related components with similar flags for easier management
|
||||
- Implement a more structured approach for component initialization and dependency management
|
||||
- Consider implementing a component health monitoring system
|
||||
@@ -1,99 +0,0 @@
|
||||
# Bridge
|
||||
|
||||
**Path**: [src/modbus/Bridge.h](../../../src/modbus/Bridge.h)
|
||||
|
||||
**Revision History**:
|
||||
- Initial documentation
|
||||
|
||||
A Bridge component that enables inter-component messaging and remote method invocation in an ESP32-based system. It allows components to register member functions that can be called via a message passing mechanism, typically triggered by Modbus commands.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- No specific hardware pins required
|
||||
- Software dependencies for messaging and component management
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `SComponentInfo`: A structure that stores information about registered component methods
|
||||
- Stores component key, instance pointer, method name, and function pointer
|
||||
- `Bridge`: Main class that manages component method registration and message handling
|
||||
- Inherits from `Component` base class
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Register component member functions for remote invocation
|
||||
- Message routing between components
|
||||
- Method lookup by component ID and method name
|
||||
- Debug support for listing registered methods
|
||||
- Support for component discovery for Modbus management
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](./Component.md): Base class for all components
|
||||
- [WString](https://github.com/espressif/arduino-esp32): String manipulation
|
||||
- [xtypes](./xtypes.md): Type definitions
|
||||
- [enums](./enums.md): Enumeration definitions
|
||||
- [macros](./macros.md): Macro definitions
|
||||
- [Vector](./Vector.md): Container for storing component information
|
||||
- [Streaming](./Streaming.md): Stream output utilities
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Bridge --> Component
|
||||
Bridge --> WString
|
||||
Bridge --> xtypes
|
||||
Bridge --> enums
|
||||
Bridge --> macros
|
||||
Bridge --> Vector
|
||||
Bridge --> Streaming
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The Bridge acts as a message router between components. It maintains a registry of component methods and handles method invocation based on message parameters.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Caller
|
||||
participant Bridge
|
||||
participant Component
|
||||
|
||||
Caller->>Bridge: onMessage(id, verb, flags, user, src)
|
||||
alt EC_METHOD verb
|
||||
Bridge->>Bridge: Parse method parameters
|
||||
Bridge->>Bridge: hasMethod(id, methodName)
|
||||
alt Method found
|
||||
Bridge->>Component: Invoke method
|
||||
Component-->>Bridge: Return result
|
||||
Bridge-->>Caller: Return result
|
||||
else Method not found
|
||||
Bridge-->>Caller: Return E_NOT_FOUND
|
||||
end
|
||||
else Other verbs
|
||||
Bridge-->>Caller: Return E_OK
|
||||
end
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- The current implementation uses dynamic memory allocation for component registration which could lead to heap fragmentation. Consider using a fixed-size pool for `SComponentInfo` objects.
|
||||
- Message parsing could be optimized for cases with large numbers of registered components.
|
||||
|
||||
### SECURITY
|
||||
|
||||
- There is no authentication mechanism for method invocation. Consider adding a permission system.
|
||||
- Method invocation through Modbus should be validated to prevent buffer overflows and other security issues.
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure proper memory management to comply with embedded system best practices.
|
||||
- Test for compliance with industrial communication standards when used with Modbus.
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use descriptive method names and consistent component IDs to make debugging easier.
|
||||
- Keep registered method count below the `MAX_COMPONENTS` limit (defined in configuration).
|
||||
- When adding new components, always register their methods during initialization.
|
||||
- Consider implementing an unregister mechanism for dynamically loaded/unloaded components.
|
||||
@@ -1,93 +0,0 @@
|
||||
---
|
||||
title: "CommandMessage Class - Message Parsing System"
|
||||
description: "Documentation for the CommandMessage class used to parse and structure messages in a Modbus system"
|
||||
keywords: ["ESP-32", "Modbus", "communication", "command parsing", "messaging"]
|
||||
---
|
||||
|
||||
## CommandMessage
|
||||
|
||||
**Path**: [src/modbus/command_message.h](../src/modbus/command_message.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The CommandMessage class provides a structured approach to parse, validate, and manage command messages within the system. It supports message serialization and deserialization with defined start/end markers and delimiters. This class is designed for efficient messaging in industrial Modbus-485 communications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- No specific hardware pins required
|
||||
- Requires StringUtils and enums support
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- **CommandMessage**: The main class for message handling
|
||||
- **DEBUG_MESSAGES_PARSE**: Conditional compilation flag for verbose message parsing output
|
||||
- **DEBUG_MESSAGES_PARSER**: Macro for debug logging of message parsing operations
|
||||
- **MESSAGE_TOKENS**: Constant defining the expected number of tokens in a valid message
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Structured message storage with ID, verb, flags, and payload
|
||||
- Timestamp tracking for message receipt
|
||||
- Validation of message format with start/end markers
|
||||
- Parsing of delimited message content
|
||||
- Clear method for resetting message state
|
||||
- Match checking for message format validation
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Vector](../src/Vector.h)
|
||||
- [ArduinoLog](../src/ArduinoLog.h)
|
||||
- [StringUtils](../src/StringUtils.h)
|
||||
- [Enums](../src/modbus/enums.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
CommandMessage --> StringUtils
|
||||
CommandMessage --> ArduinoLog
|
||||
CommandMessage --> Vector
|
||||
CommandMessage --> Enums
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant CommandMessage
|
||||
|
||||
Client->>CommandMessage: Create message with id, verb, flags
|
||||
Client->>CommandMessage: parse(message)
|
||||
CommandMessage->>CommandMessage: clear()
|
||||
CommandMessage->>CommandMessage: Extract content between markers
|
||||
CommandMessage->>CommandMessage: Split by delimiters
|
||||
CommandMessage->>CommandMessage: Validate token count
|
||||
CommandMessage->>CommandMessage: Assign id, verb, flags, payload
|
||||
CommandMessage->>CommandMessage: Set timestamp
|
||||
CommandMessage-->>Client: Return success/failure
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider pre-allocating memory for the message parsing to avoid heap fragmentation
|
||||
- Evaluate the use of String vs. char arrays for payload handling in memory-constrained environments
|
||||
- Potential for optimizing token parsing with a more efficient approach than strtok
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Consider implementing message integrity checking (checksums or CRC)
|
||||
- Add length validation to prevent buffer overflows
|
||||
- Implement validation of message payload content based on expected verb/command
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure all message processing complies with Modbus protocol standards where applicable
|
||||
- Consider adding support for standard industrial message formats
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Add support for binary payloads for more efficient communication
|
||||
- Consider implementing a message queue system to handle multiple messages
|
||||
- Add methods to serialize a CommandMessage back to a string for bidirectional communication
|
||||
- Consider adding timeout functionality for message handling
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
title: "Component Class"
|
||||
description: "A generic component class for embedded systems"
|
||||
keywords: ["component", "ESP-32", "modbus", "industrial application"]
|
||||
---
|
||||
|
||||
## Component
|
||||
|
||||
**Path**: [`src/modbus/Component.h`](../src/modbus/Component.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Component class represents a generic component for industrial applications. It provides a foundation for creating various types of components with consistent behavior and interface. These components can be integrated into a modbus-based industrial control system.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP-32 platform
|
||||
- No specific hardware pins required as this is a base class
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `Component` class - A base class for creating components in an industrial application
|
||||
- Constants:
|
||||
- `COMPONENT_DEFAULT` - Default run flags for a component
|
||||
- `COMPONENT_NO_ID` - Default ID for a component
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Name-based component identification
|
||||
- ID-based component identification
|
||||
- Configurable run flags
|
||||
- Support for owner-child relationship between components
|
||||
- Type identification through enumeration
|
||||
- Integration with Modbus communication
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`WString.h`](../src/WString.h) - String handling
|
||||
- [`ArduinoLog.h`](../src/ArduinoLog.h) - Logging functionality
|
||||
- [`Vector.h`](../src/Vector.h) - Dynamic array implementation
|
||||
- [`enums.h`](../src/modbus/enums.h) - Enumeration definitions
|
||||
- [`constants.h`](../src/modbus/constants.h) - Constant definitions
|
||||
- [`error_codes.h`](../src/modbus/error_codes.h) - Error code definitions
|
||||
- [`macros.h`](../src/modbus/macros.h) - Macro definitions
|
||||
- [`xtypes.h`](../src/modbus/xtypes.h) - Extended type definitions
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Component --> WString
|
||||
Component --> ArduinoLog
|
||||
Component --> Vector
|
||||
Component --> enums
|
||||
Component --> constants
|
||||
Component --> error_codes
|
||||
Component --> macros
|
||||
Component --> xtypes
|
||||
ModbusBlock[ModbusBlockView] --> Component
|
||||
ModbusTCP --> Component
|
||||
RS485 --> Component
|
||||
Bridge --> Component
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The Component class operates as a base class that defines common behavior for various industrial components.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Init[Initialize Component] --> Setup[Setup Component]
|
||||
Setup --> Loop[Run Loop]
|
||||
Loop --> |Run Flags| Loop
|
||||
Loop --> |End of loop| Cleanup[Cleanup]
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing lazy initialization for components with high initialization costs
|
||||
- Evaluate the memory footprint of components in resource-constrained environments
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement access control mechanisms for sensitive components
|
||||
- Ensure proper validation of component IDs and types to prevent misuse
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Review compliance with industrial standards for component interfaces
|
||||
- Ensure compatibility with Modbus protocol specifications
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Extend this base class for specific component types rather than modifying the base class
|
||||
- Use meaningful names and IDs for components to improve system maintainability
|
||||
- Set appropriate run flags based on the component's intended behavior
|
||||
- Organize components in a logical hierarchy using the owner-child relationship
|
||||
@@ -1,108 +0,0 @@
|
||||
---
|
||||
title: "CircularLogPrinter - In-Memory Logging with Optional Output"
|
||||
description: "A circular buffer for storing log messages with ESP-IDF integration"
|
||||
keywords: ["ESP32", "logging", "circular buffer", "ESP-IDF", "modbus"]
|
||||
---
|
||||
|
||||
## CircularLogPrinter
|
||||
|
||||
**Path**: [`src/modbus/circular_log_printer.h`](../../src/modbus/circular_log_printer.h)
|
||||
|
||||
**Revision History**:
|
||||
- 2023-11-15: Initial documentation
|
||||
|
||||
CircularLogPrinter is an Arduino-compatible Print implementation that stores the last N log lines in a circular buffer. It can optionally mirror all output to another stream (like Serial). The component is designed to be 100% reinterpret-cast-free for MISRA/CPPCHECK compliance, making it suitable for industrial applications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- FreeRTOS (for optional thread safety)
|
||||
- ESP32 IDF framework
|
||||
- Global Serial object (when using default constructor)
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `using LogRingBuffer = char[LOG_BUFFER_LINES][LOG_BUFFER_LINE_LENGTH]`
|
||||
- `class CircularLogPrinter`: A Print implementation storing log lines in a circular buffer
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Configurable circular buffer size via macros
|
||||
- Thread-safe operation (optional)
|
||||
- Ability to attach to ESP-IDF's logging system
|
||||
- No pointer type casting (MISRA compliant)
|
||||
- Retrieves log history by line number
|
||||
- Optional mirroring to any Print-compatible output
|
||||
- Efficient multi-byte writes
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Arduino.h](https://github.com/espressif/arduino-esp32)
|
||||
- [Print.h](https://github.com/espressif/arduino-esp32)
|
||||
- [esp_log.h](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/log.html)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
CircularLogPrinter --> Arduino
|
||||
CircularLogPrinter --> Print
|
||||
CircularLogPrinter --> ESP_Log
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Ready
|
||||
Ready --> Accumulating: write(byte)
|
||||
Accumulating --> Accumulating: write non-newline
|
||||
Accumulating --> CommittingLine: write newline
|
||||
CommittingLine --> Ready: Store line & update indices
|
||||
Ready --> Cleared: clear()
|
||||
Cleared --> Ready: write(byte)
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider using a more efficient buffer strategy for high-volume logging
|
||||
- Potential optimization by pre-allocating buffer space when attaching to ESP-IDF log
|
||||
|
||||
### SECURITY
|
||||
|
||||
- No direct security concerns as this is an output-only component
|
||||
- Consider adding sanitization for control characters that could affect terminal displays
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Already designed for MISRA/CPPCHECK compliance with no reinterpret casts
|
||||
- Consider adding formal verification of buffer access bounds
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Adjust `LOG_BUFFER_LINES` and `LOG_BUFFER_LINE_LENGTH` based on available memory and application needs
|
||||
- For performance-critical applications, consider disabling thread safety with `LOG_BUFFER_THREAD_SAFE=0`
|
||||
- When using with Modbus, attach to ESP-IDF logging to capture all system messages including Modbus communication logs
|
||||
|
||||
## Example
|
||||
|
||||
```cpp
|
||||
#include "circular_log_printer.h"
|
||||
|
||||
// Create logger with default output (Serial)
|
||||
CircularLogPrinter logger;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Attach to ESP-IDF logging system
|
||||
logger.attachToEspLog();
|
||||
|
||||
// Log some messages
|
||||
logger.println("System initializing...");
|
||||
|
||||
// Later, retrieve historical logs
|
||||
for (size_t i = 0; i < logger.lines(); i++) {
|
||||
Serial.println(logger.getLine(i));
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
title: "SerialMessage - Serial Communication Component"
|
||||
description: "A component that handles serial communication over a stream, providing methods for reading and parsing command messages."
|
||||
keywords: "SerialMessage, serial communication, command parsing, ESP32, modbus"
|
||||
---
|
||||
|
||||
## SerialMessage
|
||||
|
||||
**Path**: [`src/modbus/SerialMessage.h`](../src/modbus/SerialMessage.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
SerialMessage is a component that handles serial communication over a provided Stream. It is responsible for reading incoming data from the serial port, parsing it into structured command messages, and forwarding these messages to its owner component. The class periodically checks for new messages on the configured serial interface.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- A valid Stream object (like Serial, Serial1, etc.) for communication
|
||||
- Sufficient memory for the receive buffer (SERIAL_RX_BUFFER_SIZE, defaults to 256 bytes)
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- **SerialMessage class**: Main component for handling serial communication
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Periodic checking for new serial commands (configurable interval)
|
||||
- Parsing of raw serial data into structured CommandMessage objects
|
||||
- Event-based message handling through owner component notification
|
||||
- Configurable message delimiter (default: newline)
|
||||
- Debug capabilities for troubleshooting communication issues
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Vector](../src/Vector.h)
|
||||
- [ArduinoLog](../src/ArduinoLog.h)
|
||||
- [Arduino.h](https://www.arduino.cc/reference/en/)
|
||||
- [xtypes.h](../src/xtypes.h)
|
||||
- [Component.h](../src/Component.h)
|
||||
- [CommandMessage.h](../src/CommandMessage.h)
|
||||
- [config.h](../src/config.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
SerialMessage --> Component
|
||||
SerialMessage --> CommandMessage
|
||||
SerialMessage --> Vector
|
||||
SerialMessage --> ArduinoLog
|
||||
SerialMessage --> xtypes
|
||||
SerialMessage --> config
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The SerialMessage component operates on a time-based polling mechanism:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start([Start]) --> Setup[Setup SerialMessage]
|
||||
Setup --> Loop[Loop]
|
||||
Loop --> CheckInterval{Time to check?}
|
||||
CheckInterval -->|No| Loop
|
||||
CheckInterval -->|Yes| ReadSerial[Read from serial]
|
||||
ReadSerial --> DataAvailable{Data available?}
|
||||
DataAvailable -->|No| UpdateTime[Update lastRead time]
|
||||
DataAvailable -->|Yes| ParseMessage[Parse to CommandMessage]
|
||||
ParseMessage --> ValidMessage{Valid message?}
|
||||
ValidMessage -->|No| UpdateTime
|
||||
ValidMessage -->|Yes| NotifyOwner[Notify owner component]
|
||||
NotifyOwner --> UpdateTime
|
||||
UpdateTime --> Loop
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing interrupt-driven serial reading rather than polling for high-throughput applications
|
||||
- Optimize buffer handling for memory-constrained environments
|
||||
- Evaluate the impact of the polling interval on application responsiveness
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add input validation to prevent buffer overflow attacks
|
||||
- Consider implementing message authentication for secure applications
|
||||
- Evaluate the need for encryption for sensitive data transmission
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with relevant industrial communication standards when used in Modbus-485 applications
|
||||
- Verify error handling mechanisms meet application reliability requirements
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Set an appropriate SERIAL_COMMAND_PARSE_INTERVAL based on your application's requirements
|
||||
- For debugging communication issues, enable DEBUG_SERIAL_MESSAGES in your build configuration
|
||||
- When extending this component, consider implementing additional message validation logic
|
||||
- For applications with multiple serial interfaces, create separate SerialMessage instances for each interface
|
||||
@@ -1,89 +0,0 @@
|
||||
---
|
||||
title: "StringUtils - String Manipulation Utilities"
|
||||
description: "A utility class for string manipulation and type conversion for ESP-32 applications"
|
||||
keywords: "ESP-32, C++17, string utilities, type conversion, industrial application, Modbus"
|
||||
---
|
||||
|
||||
## StringUtils
|
||||
|
||||
**Path**: [`src/modbus/StringUtils.h`](../src/modbus/StringUtils.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
StringUtils provides a set of utility functions for string manipulation and type conversion in an industrial ESP-32 application. It enables parsing and converting string values to native C types, which is particularly useful for configuration and communication scenarios in Modbus applications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
No specific hardware pins are required as this is a software utility helper.
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `E_VALUE_TYPE` enumeration for representing different value types
|
||||
- Template function `convertTo<T>` for converting strings to various native types
|
||||
- Type detection functions (`isInteger`, `isFloat`, `detectType`)
|
||||
- Hex data printing utility
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Specialized template implementations for converting strings to:
|
||||
- Integer types (`int`, `short`, `long int`)
|
||||
- Floating-point (`float`)
|
||||
- Boolean values (`bool`)
|
||||
- Type detection to determine if a string represents a valid integer or floating-point value
|
||||
- Platform-specific adaptations for string tokenization across different compilers
|
||||
- Hex data visualization for debugging
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`./xtypes.h`](../src/modbus/xtypes.h)
|
||||
- Standard C libraries: `<stdio.h>`, `<string.h>`, `<ctype.h>`, `<stdlib.h>`
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
StringUtils --> xtypes
|
||||
StringUtils --> "Standard C Libraries"
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The StringUtils component follows a simple conversion and detection workflow:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Input[Input String] --> Detect[Detect Type]
|
||||
Detect --> |Integer| ConvertInt[Convert to Integer]
|
||||
Detect --> |Float| ConvertFloat[Convert to Float]
|
||||
Detect --> |Boolean| ConvertBool[Convert to Boolean]
|
||||
Detect --> |Text| HandleText[Handle as String]
|
||||
ConvertInt --> Result[Native Type Result]
|
||||
ConvertFloat --> Result
|
||||
ConvertBool --> Result
|
||||
HandleText --> Result
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider using `strtol`, `strtof`, etc. for all conversions to provide better error handling
|
||||
- Optimize the string scanning operations for large strings
|
||||
- Add string length validation to avoid buffer overruns
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add input validation to prevent exploitation through malformed strings
|
||||
- Consider adding bounds checking for numeric conversions
|
||||
- Implement sanitization for strings that will be used in sensitive contexts
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compatibility with C17 standard
|
||||
- Verify that all functions work correctly in the target ESP-32 environment
|
||||
- Audit for potential compliance issues with industrial standards
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Extend type support to include additional numeric types as needed
|
||||
- Add more robust error handling for conversion failures
|
||||
- Consider adding string formatting utilities for consistent output generation
|
||||
- For improved performance, use static or cached conversions for frequently used values
|
||||
@@ -1,96 +0,0 @@
|
||||
---
|
||||
title: "ValueWrapper Template Class"
|
||||
description: "A templated class for managing values with threshold-based notifications through Modbus"
|
||||
keywords: "ValueWrapper, Modbus, threshold, notification, embedded systems, ESP32"
|
||||
---
|
||||
|
||||
## ValueWrapper
|
||||
|
||||
**Path**: [`src/modbus/ValueWrapper.h`](../src/modbus/ValueWrapper.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A template class that wraps values of any type with threshold-based update notifications through Modbus. This class monitors changes in a value and sends notifications to the owner component when changes exceed specified thresholds, using different comparison modes. It helps reduce network traffic by only sending updates when significant changes occur.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- An owning Component instance that receives notifications
|
||||
- A Modbus address space for notifications
|
||||
- Function code configuration for the Modbus messages
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `ValueWrapper<T>` - Template class for wrapping values of any type
|
||||
- `ThresholdMode` enumeration:
|
||||
- `DIFFERENCE` - Triggers when absolute difference between old and new values exceeds threshold
|
||||
- `INTERVAL_STEP` - Triggers when values cross step boundaries defined by the threshold
|
||||
|
||||
- Macros:
|
||||
- `DEFAULT_VW_POST_NOTIFY_LAMBDA` - Helper for creating standard post-notification logging lambdas
|
||||
- `INIT_COMPONENT_VALUE_WRAPPER` - Simplifies ValueWrapper initialization
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Wraps any data type, including enums, with transparent type conversion
|
||||
- Provides automatic threshold-based notifications through Modbus
|
||||
- Supports different threshold modes for different types of data
|
||||
- Handles both arithmetic types and enumerations correctly
|
||||
- Provides callbacks when notifications are sent
|
||||
- Automatic typecasting for Modbus message values
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`Component.h`](../src/Component.md)
|
||||
- [`modbus/ModbusTypes.h`](../src/modbus/ModbusTypes.md)
|
||||
- [`enums.h`](../src/enums.md)
|
||||
- [`Logger.h`](../src/Logger.md)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ValueWrapper --> Component
|
||||
ValueWrapper --> ModbusTypes
|
||||
ValueWrapper --> enums
|
||||
ValueWrapper --> Logger
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The ValueWrapper monitors changes to a value and sends notifications when thresholds are exceeded.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialized: Constructor
|
||||
Initialized --> Comparing: update(newValue)
|
||||
Comparing --> ThresholdNotMet: Below threshold
|
||||
Comparing --> ThresholdExceeded: Above threshold
|
||||
ThresholdNotMet --> ValueUpdated: Update value without notification
|
||||
ThresholdExceeded --> NotifyOwner: Send Modbus update
|
||||
NotifyOwner --> CallbackExecution: Execute post-notification callback
|
||||
CallbackExecution --> ValueUpdated: Value updated
|
||||
ValueUpdated --> Initialized: Ready for next update
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider providing specialized implementations for common types to avoid template instantiation overhead
|
||||
- Investigate using std::variant for better type safety and potentially reduced memory footprint
|
||||
- Add an optional hysteresis parameter to prevent rapid oscillations around threshold values
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add bounds checking for Modbus addresses to prevent accidental overwrites
|
||||
- Consider adding validation callbacks to ensure values remain within acceptable ranges
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure all Modbus messages conform to the Modbus specification requirements
|
||||
- Consider adding support for additional Modbus function codes as needed
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use the `INIT_COMPONENT_VALUE_WRAPPER` macro to simplify instance creation
|
||||
- Choose appropriate threshold values to balance responsiveness and network traffic
|
||||
- For enum types, use threshold value of 1 to notify on any state change
|
||||
- For float values, consider the INTERVAL_STEP mode to create logical boundaries for notifications
|
||||
@@ -1,58 +0,0 @@
|
||||
# Constants
|
||||
|
||||
**Path**: [`src/modbus/constants.h`](../src/modbus/constants.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
This file defines global constants used throughout the application, particularly for component management and debug settings.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
No specific hardware requirements. This is a header-only file that provides constant values.
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- Global constant definitions:
|
||||
- `MAX_COMPONENTS`: Maximum number of components in the system
|
||||
- `DEFAULT_DEBUG_INTERVAL`: Default interval for debug operations in milliseconds
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Defines system-wide constants for configuration
|
||||
- Sets limits for component management
|
||||
- Establishes default timing values
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
None. This is a standalone header file.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Constants["Constants"]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
This component doesn't have behavior as it only provides constant definitions.
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider evaluating if `MAX_COMPONENTS` is appropriately sized for the application's needs
|
||||
- Review if any constants should be configurable at compile time based on target hardware
|
||||
|
||||
### SECURITY
|
||||
|
||||
- No direct security concerns as these are compile-time constants
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure constant values comply with any relevant industrial standards or specifications
|
||||
- Consider documenting the reasoning behind specific values for future reference
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use these constants throughout the application rather than hard-coding values
|
||||
- Consider moving to a more structured configuration system if the number of constants grows substantially
|
||||
- Document the impact of changing these values on system behavior and resource usage
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
title: "Modbus Enums and Constants"
|
||||
description: "Documentation for the Modbus enumerations and constants used in the industrial control application"
|
||||
keywords: "Modbus, ESP32, Industrial Control, Enumerations, Constants, Error Codes"
|
||||
---
|
||||
|
||||
## Modbus Enumerations and Constants
|
||||
|
||||
**Path**: [/src/modbus/enums.h](../../../src/modbus/enums.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
This file defines the core enumerations and constants used throughout the industrial control application, particularly for Modbus communications, component management, and error handling.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- No direct hardware requirements
|
||||
- Consistent implementation across the codebase
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `COMPONENT_KEY_BASE` - Base key identifiers for system components
|
||||
- `COMPONENT_TYPE` - Component type classification
|
||||
- Error Code Constants - System-wide error definitions
|
||||
- `OBJECT_RUN_FLAGS` - Runtime behavior flags for components
|
||||
- `OBJECT_NET_CAPS` - Network capability flags
|
||||
- `MB_REGISTER_MODE` - Modbus register access modes
|
||||
- `E_CALLS` - Call type definitions
|
||||
- `E_MessageFlags` - Message processing flags
|
||||
- `MB_FC` - Modbus function codes
|
||||
- `MODBUS_ERRORS` - Standard Modbus error codes
|
||||
- `E_ModbusType` - Modbus data type definitions
|
||||
- `E_ModbusAccess` - Modbus access permissions
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Comprehensive error code system with reserved ranges for subsystems
|
||||
- Modbus protocol constants aligned with industry standards
|
||||
- Component type classification for system organization
|
||||
- Runtime behavior flags for component lifecycle management
|
||||
- Message handling flags for inter-component communication
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- No direct dependencies on other components
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Enums[Modbus Enumerations and Constants]
|
||||
OtherComponents[Other System Components]
|
||||
OtherComponents --> Enums
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The enumerations and constants in this file define the protocol and behavior parameters used by other components in the system.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Constants[Constants Definition] --> Usage[Used by Components]
|
||||
Usage --> ComponentInteraction[Component Interaction]
|
||||
Usage --> ErrorHandling[Error Handling]
|
||||
Usage --> ModbusProtocol[Modbus Protocol Execution]
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider using more compact types for memory-constrained applications
|
||||
- Evaluate if any enumerations could be consolidated to reduce memory usage
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Ensure error codes don't leak sensitive information in production environments
|
||||
- Consider adding authentication/authorization related constants for secure Modbus implementations
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Maintain alignment with Modbus specification for all Modbus-related constants
|
||||
- Consider adding comments with references to specific sections of the Modbus specification
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- When extending error codes, maintain the hierarchical structure
|
||||
- When adding new component types, ensure they follow the established naming convention
|
||||
- Consider adding range validation macros alongside the constants
|
||||
@@ -1,75 +0,0 @@
|
||||
# Error Codes
|
||||
|
||||
**Path**: [`src/modbus/error_codes.h`](../../src/modbus/error_codes.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A comprehensive collection of error codes used throughout the Modbus implementation. This header defines specific error code enumerations for different types of errors that can occur during Modbus operations.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
No specific hardware pins required. This is a pure software component providing error code definitions.
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `ModbusErrorCode` - Enumeration for general Modbus error codes
|
||||
- `ModbusDeviceErrorCode` - Enumeration for device-specific Modbus error codes
|
||||
- `ModbusExceptionCode` - Enumeration for standard Modbus exception codes
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Standardized error code definitions for Modbus protocol implementation
|
||||
- Clear separation between different categories of errors
|
||||
- Compliance with standard Modbus exception codes
|
||||
- Error codes to handle both protocol-level and device-specific errors
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
None. This is a standalone header file defining error code enumerations.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ErrorCodes[Error Codes]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The error codes are used to report and handle various error conditions throughout the Modbus implementation.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start[Operation Start] --> Operation[Modbus Operation]
|
||||
Operation --> CheckError{Error?}
|
||||
CheckError -->|No| Success[Operation Successful]
|
||||
CheckError -->|Yes| Identify[Identify Error Type]
|
||||
Identify -->|Protocol Error| ProtocolError[ModbusErrorCode]
|
||||
Identify -->|Device Error| DeviceError[ModbusDeviceErrorCode]
|
||||
Identify -->|Exception| Exception[ModbusExceptionCode]
|
||||
ProtocolError --> Handle[Handle Error]
|
||||
DeviceError --> Handle
|
||||
Exception --> Handle
|
||||
Handle --> End[End Operation]
|
||||
Success --> End
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider optimizing error handling mechanisms for minimal runtime overhead
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Review error codes to ensure they don't expose sensitive system information
|
||||
- Consider adding error codes for security-related issues (authentication failures, access violations)
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Verify that all Modbus exception codes match the latest Modbus specification
|
||||
- Consider adding compliance with IEC 61131-3 error handling recommendations
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use appropriate error codes consistently across the codebase
|
||||
- Consider extending error codes with additional information for debugging purposes
|
||||
- Implement comprehensive error logging using these error codes
|
||||
@@ -1,81 +0,0 @@
|
||||
---
|
||||
title: "JSON Utilities"
|
||||
description: "Utility functions for parsing JSON data in embedded applications"
|
||||
keywords: ["JSON", "ArduinoJson", "parsing", "ESP32", "embedded"]
|
||||
---
|
||||
|
||||
## JSON Utilities
|
||||
|
||||
**Path**: [`src/utils/json_utils.h`](../../src/utils/json_utils.h)
|
||||
|
||||
**Revision History**:
|
||||
- Initial documentation
|
||||
|
||||
A collection of inline utility functions for parsing JSON data in embedded applications. These functions provide a consistent way to extract values from JSON objects, with built-in type validation and error reporting.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ArduinoJson library
|
||||
- ArduinoLog library
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `JsonUtils` namespace containing utility functions:
|
||||
- `parseJsonFieldUint32`: Parses a 32-bit unsigned integer from JSON
|
||||
- `parseJsonFieldUint8`: Parses an 8-bit unsigned integer from JSON
|
||||
- `parseJsonFieldBool`: Parses a boolean value from JSON
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Type validation for JSON field parsing
|
||||
- Maintains default values when fields are missing or of incorrect type
|
||||
- Debug logging for parsing errors
|
||||
- Consistent parsing interface across different data types
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ArduinoJson](https://arduinojson.org/)
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
JsonUtils --> ArduinoJson
|
||||
JsonUtils --> ArduinoLog
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start([Parse JSON Field]) --> CheckField{Field exists?}
|
||||
CheckField -- Yes --> CheckType{Correct type?}
|
||||
CheckField -- No --> UseDefault[Use default value]
|
||||
CheckType -- Yes --> AssignValue[Assign parsed value]
|
||||
CheckType -- No --> LogWarning[Log warning] --> UseDefault
|
||||
AssignValue --> End([End])
|
||||
UseDefault --> End
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider providing batch parsing functions to reduce parsing overhead for multiple fields
|
||||
- Evaluate memory usage when parsing large JSON objects
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Currently no validation for value ranges; consider adding range validation options
|
||||
- Implement protection against malformed JSON that could lead to buffer overflows
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure all error messages follow consistent formatting standards
|
||||
- Consider adding more documentation for compliance with project coding standards
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Add support for additional data types (e.g., float, string)
|
||||
- Consider a more structured approach to error handling (e.g., error codes or exceptions)
|
||||
- Add functions for array parsing and nested object traversal
|
||||
- Provide examples of common JSON parsing scenarios
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
title: "Macros Utility Header"
|
||||
description: "Documentation for the macros utility header which provides various helper macros for ESP32 C17 development"
|
||||
keywords: "ESP32, C17, macros, utilities, embedded, industrial"
|
||||
---
|
||||
|
||||
# Macros Utility
|
||||
|
||||
**Path**: [`src/modbus/macros.h`](../src/modbus/macros.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A comprehensive collection of utility macros for ESP-32 development. This header provides macro definitions for commonly used operations in embedded systems programming, avoiding the use of the standard library. It includes macros for type manipulation, bit operations, mathematical functions, array handling, compile-time optimizations, and more.
|
||||
|
||||
## Requirements
|
||||
|
||||
- ESP-32 platform
|
||||
- C17 compliant compiler
|
||||
- No standard library dependencies
|
||||
|
||||
## Provides
|
||||
|
||||
- **Incrementation/Decrementation**: `INC_X`, `DEC_X`, `INCREMENT`, `DECREMENT`
|
||||
- **Compiler Optimizations**: `FORCE_INLINE`, `_UNUSED`, `NOOP`
|
||||
- **Argument Counting/Testing**: `NUM_ARGS`, `TWO_ARGS`
|
||||
- **String Helpers**: `CAT`, `_CAT`
|
||||
- **Conditional Compilation**: `ENABLED`, `DISABLED`, `ANY`, `ALL`, `NONE`
|
||||
- **Bit Manipulation**: `__BV`, `TEST`, `SBI`, `CBI`, `SET_BIT_TO`
|
||||
- **Math Operations**: `WITHIN`, `RADIANS`, `DEGREES`, `NEAR_ZERO`
|
||||
- **Time Helpers**: `PENDING`, `ELAPSED`, `HOUR_MS`, `MIN_MS`
|
||||
- **Array Initialization**: `ARRAY_N`, `ARRAY_1` through `ARRAY_6`
|
||||
- **C++11 Template Utilities**: Min/Max templates, SFINAE helpers
|
||||
|
||||
## Features
|
||||
|
||||
- Preprocessor macros for common calculations and operations
|
||||
- Bit manipulation utilities
|
||||
- Compile-time optimizations
|
||||
- Safe type conversion helpers
|
||||
- Template-based compile-time checks
|
||||
- Time management utilities
|
||||
- Array initialization helpers
|
||||
- Conditional execution based on feature flags
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [`./xtypes.h`](../src/modbus/xtypes.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Macros --> XTypes
|
||||
```
|
||||
|
||||
## Behavior
|
||||
|
||||
The macros in this header provide utility functions that are used throughout the codebase. They do not have state or flow by themselves but enable cleaner, more efficient code.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Application[Application Code] -->|Uses macros| Macros
|
||||
Macros -->|Expand at compile time| Optimized[Optimized Binary]
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider separating into multiple headers for faster compilation
|
||||
- Add pre-processor optimization for frequently used macro combinations
|
||||
|
||||
### Security
|
||||
|
||||
- No direct security concerns as these are compile-time macros
|
||||
- Ensure macros don't introduce unintended behaviors when used with user input
|
||||
|
||||
### Compliance
|
||||
|
||||
- Compatible with C17 standard
|
||||
- Designed for ESP-32 and industrial Modbus applications
|
||||
- No use of standard library functions
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Group related macros when using in implementation files
|
||||
- Use the ENABLED/DISABLED macros for feature toggling
|
||||
- Prefer the template-based MIN/MAX over macro versions when in C++ code
|
||||
- Consider the resource constraints of ESP-32 when using complex macro expansions
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
title: "Cassandra 650 Test Data Constants"
|
||||
description: "Reference constants and verified test data for the Cassandra 650 hot-plate system"
|
||||
keywords: ["modbus", "cassandra", "hotplate", "test data", "constants"]
|
||||
---
|
||||
|
||||
## Cassandra 650 Test Data
|
||||
|
||||
**Path**: [`src/modbus/cassandra650_testdata.h`](../../../src/modbus/cassandra650_testdata.h)
|
||||
|
||||
**Revision History**:
|
||||
- 2025-05-01: Initial verified version with full equation markup.
|
||||
|
||||
This header file provides verified test data constants for the Cassandra 650 hot-plate system, serving as a reference for simulation, testing, and validation of the hot-plate control system.
|
||||
|
||||
The constants follow specific notation:
|
||||
- Values ending in `_X100` are stored multiplied by 100 (e.g., 1.25 becomes 125)
|
||||
- Dimensions are in millimeters unless otherwise noted
|
||||
- Time units: s = seconds, min = minutes
|
||||
- Frequency: mHz = milli-hertz (10⁻³ Hz)
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- No specific hardware pins required as this is a constants-only header
|
||||
- Compatible with C17 standard
|
||||
- ESP-32 platform as target
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- **Heat-plate geometry constants**: Dimensions of the heat plate
|
||||
- **Heater configuration constants**: Specifications for the heating elements
|
||||
- **Cooling performance constants**: Natural cooling rates
|
||||
- **Temperature-loop precision constants**: Control precision specifications
|
||||
- **Oscillation constants**: Timing parameters for temperature holding
|
||||
- **Heating performance constants**: Rate of temperature increase under different conditions
|
||||
- **Derived thermodynamic properties**: Calculated constants based on measured data
|
||||
- **Sequential heating constants**: Parameters for multi-partition heating systems
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Comprehensive set of validated constants for the Cassandra 650 hot-plate system
|
||||
- Clear organization of constants by functional category
|
||||
- Documented equations showing relationships between constants
|
||||
- Scaled values (×100) to maintain precision with integer constants
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
None - this is a self-contained constants header
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
cassandra650_testdata[cassandra650_testdata.h]
|
||||
|
||||
style cassandra650_testdata fill:#f9f,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
As a constants header file, this component doesn't have behavior or state transitions.
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider adding temperature gradient constants across the plate surface
|
||||
- Add thermal profile constants for different materials/loads
|
||||
|
||||
### SECURITY
|
||||
|
||||
- No security concerns for constant definitions
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Constants should be verified periodically against actual measurements to ensure continued accuracy
|
||||
- Consider adding IEC or other industrial standards references for measurement methodologies
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- When updating constant values, maintain the equation references to document the relationships
|
||||
- Consider adding a table or graph representation of heating/cooling curves in documentation
|
||||
- To extend this module, consider adding constants for:
|
||||
- Different material loads (e.g., glass, metal, ceramic)
|
||||
- Energy consumption metrics
|
||||
- Wear and aging factors
|
||||
@@ -1,83 +0,0 @@
|
||||
---
|
||||
title: "XMath - Utility Functions for Mathematical Operations"
|
||||
description: "Lightweight mathematical functions including template-based clamping and range checking"
|
||||
keywords: ["ESP-32", "math", "clamp", "range", "normalize"]
|
||||
---
|
||||
|
||||
## XMath
|
||||
|
||||
**Path**: [`src/modbus/xmath.h`](../src/modbus/xmath.h)
|
||||
|
||||
**Revision History**:
|
||||
- Initial documentation
|
||||
|
||||
A lightweight utility header that provides essential mathematical operations for embedded systems. It includes a template-based clamp function and macros for range checking and normalized clamping.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- C++17 compiler support
|
||||
- No hardware-specific requirements
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `clamp<T>()` - Template function for clamping values within specified bounds
|
||||
- `RANGE()` - Macro for checking if a value is within a specified range
|
||||
- `NCLAMP()` - Macro for normalizing a value within a range to [0.0, 1.0]
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Type-generic clamping through template implementation
|
||||
- Range checking for value validation
|
||||
- Value normalization to a [0.0, 1.0] range
|
||||
- Conditional compilation for C++ environments
|
||||
- No standard library dependencies
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- None
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Application --> XMath
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The XMath utilities provide deterministic mathematical operations:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Input Value] --> B{clamp}
|
||||
B --> |value < low| C[Return low]
|
||||
B --> |value > high| D[Return high]
|
||||
B --> |low ≤ value ≤ high| E[Return value]
|
||||
|
||||
F[Input Value] --> G{RANGE}
|
||||
G --> |min < value < max| H[Return true]
|
||||
G --> |else| I[Return false]
|
||||
|
||||
J[Input Value] --> K{NCLAMP}
|
||||
K --> L[Normalize to 0.0-1.0 range]
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider specialized implementations for common numeric types to avoid template instantiation overhead
|
||||
- Evaluate potential for SIMD optimizations on compatible platforms
|
||||
|
||||
### SECURITY
|
||||
|
||||
- No known security concerns as the utilities perform pure mathematical operations without side effects
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure all mathematical operations maintain expected precision for safety-critical applications
|
||||
- Verify behavior with edge cases (e.g., handling of NaN, Inf values)
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use `clamp<T>()` when working with specific types to leverage compile-time type checking
|
||||
- Prefer the NCLAMP macro when normalizing sensor readings or other input values to a standardized range
|
||||
- Consider adding additional mathematical utilities as needed for specific application domains
|
||||
@@ -1,90 +0,0 @@
|
||||
---
|
||||
title: "XStatistics Class - Statistical Analysis Toolkit"
|
||||
description: "A lightweight C++ class for statistical analysis, providing functionality for calculating mean, min/max, variance, and standard deviation of numerical datasets"
|
||||
keywords: ["ESP32", "statistics", "C++", "industrial", "standard deviation", "variance", "average"]
|
||||
---
|
||||
|
||||
## XStatistics
|
||||
|
||||
**Path**: [`src/modbus/xstatistics.h`](../src/modbus/xstatistics.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The XStatistics module provides a lightweight statistical analysis toolkit for numerical datasets. It is designed for use in industrial applications on ESP32 platforms where standard C++ libraries might not be available. The Statistic class enables efficient calculation of basic statistical measures like average, minimum, maximum, variance, and standard deviations without requiring dynamic memory allocation.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- No specific hardware requirements
|
||||
- C++ compiler supporting C++11 features
|
||||
- Arduino core for ESP32
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `Statistic` class for collecting and analyzing numerical datasets
|
||||
- Template functions for basic operations (`MIN`, `MAX`, `ABS`)
|
||||
- Conditional compilation for standard deviation functionality using the `STAT_USE_STDEV` flag
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Calculation of basic statistical measures (count, sum, min, max, average)
|
||||
- Optional calculation of variance and standard deviation
|
||||
- Memory-efficient implementation suitable for embedded systems
|
||||
- No dynamic memory allocation required
|
||||
- Incremental calculation methods that avoid storing the entire dataset
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Arduino.h](https://www.arduino.cc/reference/en/)
|
||||
- [math.h](https://en.cppreference.com/w/cpp/header/cmath)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
XStatistics --> Arduino
|
||||
XStatistics --> Math
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The Statistic class collects numerical data points one at a time and maintains running calculations of statistical measures.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start[Create Statistic object] --> Clear[Initialize counters]
|
||||
Clear --> Add[Add data point]
|
||||
Add --> Calculate[Calculate statistics]
|
||||
Add --> |More data points| Add
|
||||
Calculate --> |mean/average| Mean
|
||||
Calculate --> |min/max| MinMax
|
||||
Calculate --> |count| Count
|
||||
Calculate --> |sum| Sum
|
||||
|
||||
subgraph "Optional functionality"
|
||||
Calculate --> |STAT_USE_STDEV| Variance
|
||||
Variance --> PopStdev[Population standard deviation]
|
||||
Variance --> UnbiasedStdev[Unbiased standard deviation]
|
||||
end
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- The code includes an optimization comment indicating a 10% faster calculation method for standard deviation, but it limits samples to 65K due to potential overflow. Consider implementing a version that handles larger datasets.
|
||||
- For larger datasets, consider adding functionality to discard outliers or implement online algorithms that require less memory.
|
||||
|
||||
### SECURITY
|
||||
|
||||
- No significant security concerns as this is a mathematical utility class without I/O operations.
|
||||
- Consider adding bounds checking to prevent potential numerical overflows in extreme use cases.
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- The implementation follows standard computational formulas for statistical measures.
|
||||
- The class might need additional methods like confidence intervals or hypothesis testing for compliance with specific industrial data analysis standards.
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use this class when you need to monitor trends and statistics for sensor data or control variables.
|
||||
- When using on systems with limited floating-point performance, consider monitoring the computational overhead.
|
||||
- The optional standard deviation features can be disabled by removing the `STAT_USE_STDEV` definition to reduce code size and execution time.
|
||||
- Consider extending the class with additional statistical functions like median, mode, or quartile calculations for more comprehensive analysis.
|
||||
@@ -1,93 +0,0 @@
|
||||
---
|
||||
title: "XTimer - A Lightweight Timer Implementation"
|
||||
description: "A template-based timer utility for scheduling tasks at specific intervals or times"
|
||||
keywords: ["timer", "ESP-32", "embedded", "C++", "scheduling", "task management"]
|
||||
---
|
||||
|
||||
## XTimer
|
||||
|
||||
**Path**: [`src/modbus/xtimer.h`](../src/modbus/xtimer.h)
|
||||
|
||||
**Revision History**:
|
||||
- Initial documentation
|
||||
|
||||
A lightweight, template-based timer implementation designed for embedded systems, specifically targeting ESP-32. The timer provides functionality for scheduling tasks to run after a delay, at a specific time, or at regular intervals. It avoids using the standard library, making it suitable for resource-constrained environments.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- No specific hardware pins required
|
||||
- C++17 support
|
||||
- Arduino framework or equivalent (`millis()` function)
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `Timer<size_t max_tasks, unsigned long (*time_func)()>` - Main timer class template
|
||||
- `handler_t` - Function pointer type for task callbacks
|
||||
- `timer_create_default()` - Utility function to create a timer with default settings
|
||||
- `task` struct - Internal structure to represent scheduled tasks
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Schedule tasks to run after a specified delay
|
||||
- Schedule tasks to run at specific time points
|
||||
- Schedule recurring tasks at regular intervals
|
||||
- Configurable number of maximum concurrent tasks
|
||||
- Customizable time function (defaults to `millis()`)
|
||||
- Small memory footprint with fixed-size task array
|
||||
- No dynamic memory allocation
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`src/modbus/macros.h`](../src/modbus/macros.h)
|
||||
- Arduino core (`Arduino.h` or `WProgram.h` for older versions)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
XTimer --> Macros
|
||||
XTimer --> Arduino["Arduino Core"]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The timer operates by tracking tasks and their scheduled execution times:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start[Initialize Timer] --> AddTask[Add Task to Queue]
|
||||
AddTask --> Tick[Timer Tick]
|
||||
Tick --> CheckTasks[Check Task Expiry]
|
||||
CheckTasks --> TaskExpired{Task Expired?}
|
||||
TaskExpired -- Yes --> Execute[Execute Task Handler]
|
||||
TaskExpired -- No --> Tick
|
||||
Execute --> IsRepeat{Is Recurring?}
|
||||
IsRepeat -- Yes --> ResetTask[Reset Timer for Next Run]
|
||||
ResetTask --> Tick
|
||||
IsRepeat -- No --> RemoveTask[Remove Task from Queue]
|
||||
RemoveTask --> Tick
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider a more efficient data structure than a simple array for tasks, especially for systems with many scheduled tasks
|
||||
- Implement a priority queue to optimize the `tick()` function when handling many tasks
|
||||
- Provide options to reduce memory usage for systems with very limited RAM
|
||||
|
||||
### SECURITY
|
||||
|
||||
- No major security concerns as this is a local timer implementation
|
||||
- Ensure task handlers do not introduce timing vulnerabilities in security-critical applications
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Review for MISRA C++ compliance if used in safety-critical applications
|
||||
- Ensure thread safety if used in multi-threaded environments
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Keep task handlers lightweight to avoid blocking the main loop
|
||||
- Avoid using too many concurrent tasks as it may impact performance
|
||||
- For time-critical operations, consider using hardware timers instead
|
||||
- When using the `every()` function for periodic tasks, be aware of potential timing drift over long periods
|
||||
- Consider implementing a task ID return value to allow for cancellation of scheduled tasks
|
||||
@@ -1,64 +0,0 @@
|
||||
# Types
|
||||
|
||||
**Path**: [`src/modbus/types.h`](../src/modbus/types.h)
|
||||
|
||||
**Revision History**:
|
||||
- Initial documentation
|
||||
|
||||
A core utility header that defines fundamental type aliases used throughout the codebase. This file provides standardized type definitions to ensure consistent data type usage across the application.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
No specific hardware requirements. This is a pure software utility.
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- `cchar`: A type alias for constant character data
|
||||
- `uchar`: A type alias for unsigned character data
|
||||
- `millis_t`: A type alias for millisecond time representations
|
||||
- `ushort`: A type alias for unsigned short integers
|
||||
- `ulong`: A type alias for unsigned long integers
|
||||
- `lint`: A type alias for long integers
|
||||
- `llint`: A type alias for long long integers
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Simple, standardized type definitions
|
||||
- Cross-platform compatibility
|
||||
- Consistent naming convention for derived types
|
||||
- Avoids usage of standard library types
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`<stdint.h>`](https://en.cppreference.com/w/c/types/integer) - Standard C library for integer types
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Types --> stdint
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
This component is a passive header-only utility that doesn't have runtime behavior.
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- No specific performance considerations as these are basic type aliases
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Consider defining overflow-safe numeric types for sensitive operations
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Verify that these type definitions are consistent with the target hardware architecture
|
||||
- Ensure compliance with C17 standard
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use these type aliases consistently throughout the codebase
|
||||
- Consider adding more explicit sizing (e.g., `uint32_t`) for architecture-dependent types where exact bit sizes are critical
|
||||
- When adding new types, maintain the established naming convention
|
||||
- Document the expected size (in bits) for each type to avoid platform-specific issues
|
||||
@@ -1,71 +0,0 @@
|
||||
# Modbus
|
||||
|
||||
**Path**: [src/modbus/Modbus.h](src/modbus/Modbus.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A header file providing standardized macros for initializing Modbus communication blocks in ESP-32 industrial applications.
|
||||
|
||||
## Requirements
|
||||
|
||||
- ESP-32 microcontroller
|
||||
- PlatformIO development environment
|
||||
- C++17 support
|
||||
|
||||
## Provides
|
||||
|
||||
- **INIT_MODBUS_BLOCK_TCP**: Macro for initializing Modbus blocks with TCP base address
|
||||
- **INIT_MODBUS_BLOCK**: Macro for initializing standard Modbus blocks
|
||||
- **LOW_WORD / HIGH_WORD**: Macros for handling 32-bit word operations
|
||||
|
||||
## Features
|
||||
|
||||
- Standardized initialization of Modbus communication blocks
|
||||
- Automated address calculations based on specified offsets
|
||||
- Consistent parameter setting for both TCP and standard interfaces
|
||||
- Streamlined documentation and organization through group identifiers
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [ModbusTypes.h](src/modbus/ModbusTypes.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Modbus[Modbus.h] --> ModbusTypes[ModbusTypes.h]
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The Modbus header provides initialization macros that ensure consistent formatting and values when setting up Modbus blocks. These macros handle address calculations, function codes, and access permissions.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start[Application code] --> UsesMacros[Uses INIT_MODBUS_BLOCK macros]
|
||||
UsesMacros --> TCP{Is TCP?}
|
||||
TCP -->|Yes| TCPMACRO[INIT_MODBUS_BLOCK_TCP]
|
||||
TCP -->|No| STDMACRO[INIT_MODBUS_BLOCK]
|
||||
TCPMACRO --> ModbusBlock[Initialized Modbus Block]
|
||||
STDMACRO --> ModbusBlock
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider pre-computing constant addresses at compile time where possible to reduce runtime calculations
|
||||
|
||||
### Security
|
||||
|
||||
- Add validation macros to ensure proper function code and access flag combinations
|
||||
- Implement range checking for addresses to prevent potential buffer overflows
|
||||
|
||||
### Compliance
|
||||
|
||||
- Validate against Modbus specifications for both RTU and TCP implementations
|
||||
- Ensure error handling complies with industrial standards
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Use these macros consistently across the codebase to maintain uniformity
|
||||
- Document the address range and offset enumerations carefully to avoid address conflicts
|
||||
- Consider adding specific macros for different function types (read vs. write operations)
|
||||
@@ -1,126 +0,0 @@
|
||||
---
|
||||
title: "ModbusRTU - Industrial Modbus-485 RTU Interface"
|
||||
description: "A robust Modbus RTU interface for ESP32 industrial applications"
|
||||
keywords: ["modbus", "modbus-rtu", "rs485", "industrial", "esp32", "communication"]
|
||||
---
|
||||
|
||||
## ModbusRTU
|
||||
|
||||
**Path**: [`src/modbus/ModbusRTU.h`](../../src/modbus/ModbusRTU.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
ModbusRTU is a comprehensive class that provides a robust interface for Modbus RTU communication over RS-485. It is designed for industrial applications on ESP32, offering efficient queue management, adaptive timeouts, and extensive error handling capabilities.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Hardware:
|
||||
- ESP32 microcontroller
|
||||
- RS-485 transceiver (with DE/RE pin for direction control)
|
||||
- Serial interface for communication
|
||||
|
||||
- Software:
|
||||
- Arduino framework
|
||||
- ModbusClientRTU library
|
||||
- HardwareSerial for serial communication
|
||||
- ArduinoLog for logging
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- **Enumerations**:
|
||||
- `E_InitState`: Tracks initialization states (`INIT_NOT_STARTED`, `INIT_SERIAL_STARTED`, `INIT_CLIENT_STARTED`, `INIT_READY`, `INIT_FAILED`)
|
||||
|
||||
- **Classes**:
|
||||
- `ModbusRTU`: Main class for Modbus RTU communication
|
||||
- `Manager`: Device management class for handling multiple Modbus slave devices
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Non-blocking initialization and operation
|
||||
- Flexible queue management with priority levels
|
||||
- Read/write operations for coils and registers (single and multiple)
|
||||
- Automatic value caching with synchronization status tracking
|
||||
- Comprehensive error handling and retry mechanisms
|
||||
- Adaptive minimum operation interval to adjust for network conditions
|
||||
- Filter chain for operation validation and duplicate prevention
|
||||
- Callback system for register changes, write completions, and error handling
|
||||
- Status reporting and debugging utilities
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Arduino.h](https://www.arduino.cc/reference/en/)
|
||||
- [ModbusClientRTU.h](https://github.com/eModbus/eModbus)
|
||||
- [HardwareSerial.h](https://www.arduino.cc/reference/en/language/functions/communication/serial/)
|
||||
- [ArduinoLog.h](https://github.com/thijse/Arduino-Log)
|
||||
- [ModbusTypes.h](../../src/modbus/ModbusTypes.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ModbusRTU --> Arduino
|
||||
ModbusRTU --> ModbusClientRTU
|
||||
ModbusRTU --> HardwareSerial
|
||||
ModbusRTU --> ArduinoLog
|
||||
ModbusRTU --> ModbusTypes
|
||||
Manager --> ArduinoLog
|
||||
Manager --> ModbusTypes
|
||||
Manager --> ModbusRTU
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> INIT_NOT_STARTED
|
||||
INIT_NOT_STARTED --> INIT_SERIAL_STARTED: begin()
|
||||
INIT_SERIAL_STARTED --> INIT_CLIENT_STARTED: Serial init delay elapsed
|
||||
INIT_CLIENT_STARTED --> INIT_READY: Client init delay elapsed
|
||||
INIT_READY --> [*]: end()
|
||||
|
||||
INIT_NOT_STARTED --> INIT_FAILED: Error
|
||||
INIT_SERIAL_STARTED --> INIT_FAILED: Error
|
||||
INIT_CLIENT_STARTED --> INIT_FAILED: Error
|
||||
|
||||
state Operations {
|
||||
[*] --> Idle
|
||||
Idle --> QueueOperation: Read/Write request
|
||||
QueueOperation --> FilterOperation: Apply filters
|
||||
FilterOperation --> ExecuteOperation: If passed filters
|
||||
FilterOperation --> Idle: If rejected
|
||||
ExecuteOperation --> WaitForResponse: Operation sent
|
||||
WaitForResponse --> ProcessResponse: Response received
|
||||
WaitForResponse --> HandleError: Timeout/Error
|
||||
ProcessResponse --> Idle: Update cache
|
||||
HandleError --> Retry: If retries < max
|
||||
HandleError --> Idle: If max retries exceeded
|
||||
Retry --> ExecuteOperation: After backoff
|
||||
}
|
||||
|
||||
INIT_READY --> Operations: Ready for operations
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider buffer pooling for multiple register operations to reduce memory fragmentation
|
||||
- Implement batch processing for adjacent registers to reduce number of transactions
|
||||
- Explore more granular timeouts for different device types or operation types
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement authentication mechanisms for secure Modbus communication
|
||||
- Add validation for incoming data values to prevent exploitation
|
||||
- Consider adding packet encryption for sensitive industrial applications
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure full compliance with Modbus RTU protocol specification
|
||||
- Add support for additional function codes to cover all Modbus operations
|
||||
- Implement proper exception code handling according to the standard
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Monitor operation success rates and adjust retry limits based on network reliability
|
||||
- Configure adaptive timeouts based on device response characteristics
|
||||
- Implement device-specific wrappers for common industrial equipment
|
||||
- Use high priority flag for critical operations (safety or timing-sensitive commands)
|
||||
@@ -1,134 +0,0 @@
|
||||
---
|
||||
title: "ModbusTCP Class Documentation"
|
||||
description: "Documentation for the ModbusTCP class that manages Modbus TCP communication in an industrial environment"
|
||||
keywords: ["ESP32", "ModbusTCP", "Modbus Server", "Industrial", "Communication"]
|
||||
---
|
||||
|
||||
## ModbusTCP
|
||||
|
||||
**Path**: [`src/modbus/ModbusTCP.h`](../src/modbus/ModbusTCP.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The ModbusTCP class manages Modbus TCP communication, acting as a Server/Slave. It listens for Modbus TCP requests, finds the target component, and uses the Component's network interface (read/mb_tcp_write) to process the request.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP32 with TCP/IP connectivity
|
||||
- ModbusServerTCPasync instance (from eModbus library)
|
||||
- Component hierarchy with a parent owner component (typically PHApp)
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- **ModbusTCP Class**: Main class for managing Modbus TCP server functionality
|
||||
- **Address Mapping Functionality**: Maps Modbus addresses to component functions
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Handles Modbus TCP slave/server functionality
|
||||
- Supports standard Modbus function codes:
|
||||
- Read Coils (01)
|
||||
- Read Holding Registers (03)
|
||||
- Write Single Coil (05)
|
||||
- Write Single Register (06)
|
||||
- Write Multiple Coils (15)
|
||||
- Write Multiple Registers (16)
|
||||
- Manages address mapping between Modbus addresses and components
|
||||
- Routes Modbus requests to appropriate component handlers
|
||||
- Provides component registration system for Modbus address ranges
|
||||
- Maps internal errors to Modbus exception codes
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component.h](../src/core/Component.h)
|
||||
- [enums.h](../src/util/enums.h)
|
||||
- [config-modbus.h](../src/config/config-modbus.h)
|
||||
- [ArduinoLog.h](../lib/ArduinoLog/ArduinoLog.h)
|
||||
- [Vector.h](../lib/Vector/Vector.h)
|
||||
- [ModbusServerTCPasync.h](../lib/eModbus/ModbusServerTCPasync.h)
|
||||
- [ModbusTypes.h](../src/modbus/ModbusTypes.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ModbusTCP --> Component
|
||||
ModbusTCP --> enums
|
||||
ModbusTCP --> ModbusTypes
|
||||
ModbusTCP --> ModbusServerTCPasync
|
||||
ModbusTCP --> Vector
|
||||
ModbusTCP --> ArduinoLog
|
||||
ModbusTCP --> configmodbus[config-modbus.h]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as Modbus TCP Client
|
||||
participant Server as ModbusTCP Server
|
||||
participant Component as Component
|
||||
|
||||
Client->>Server: TCP Connection
|
||||
Client->>Server: Modbus Request (Function Code + Address)
|
||||
Server->>Server: Find component for address
|
||||
alt Component found
|
||||
Server->>Component: mb_tcp_read() or mb_tcp_write()
|
||||
Component->>Server: Return data/status
|
||||
Server->>Client: Modbus Response with data
|
||||
else No component or mapping found
|
||||
Server->>Client: Exception Response
|
||||
end
|
||||
```
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
#include "ModbusTCP.h"
|
||||
|
||||
// Create ModbusServerTCPasync instance
|
||||
ModbusServerTCPasync mbTCPServer;
|
||||
|
||||
// Create and initialize ModbusTCP
|
||||
ModbusTCP modbusTCP(appComponent, &mbTCPServer);
|
||||
|
||||
// Register component with Modbus address block
|
||||
MB_Registers tempSensorRegisters = {
|
||||
.startAddress = 1000,
|
||||
.count = 10,
|
||||
.type = FN_READ_HOLD_REGISTER,
|
||||
.access = MB_ACCESS_READ_WRITE,
|
||||
.componentId = 0 // Will be filled by ModbusTCP
|
||||
};
|
||||
modbusTCP.registerModbus(temperatureComponent, tempSensorRegisters);
|
||||
|
||||
// Setup and start the Modbus TCP manager
|
||||
modbusTCP.setup();
|
||||
|
||||
// Call this regularly in the main loop
|
||||
modbusTCP.loop();
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing a more efficient lookup method for address mappings (e.g., hash map) for projects with many components
|
||||
- Add optional caching for frequently read values to reduce component calls
|
||||
- Optimize byte packing/unpacking for multi-coil operations
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add IP filtering capability to restrict access to authorized clients
|
||||
- Implement authentication mechanism for Modbus TCP connections
|
||||
- Consider adding encrypted Modbus TCP support for sensitive applications
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure full compliance with Modbus Application Protocol Specification V1.1b3
|
||||
- Add support for other function codes (Read Input Registers, Read Discrete Inputs) if needed
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Create unit tests to validate mapping and routing functionality
|
||||
- Maintain detailed logs of Modbus communications for debugging
|
||||
- Implement a strict mode that returns exceptions for unmapped addresses (currently configurable)
|
||||
- Consider adding diagnostic counters for monitoring communication quality
|
||||
@@ -1,131 +0,0 @@
|
||||
---
|
||||
title: "ModbusTypes Reference"
|
||||
description: "Comprehensive reference for the ModbusTypes component used in Modbus RS-485 industrial applications"
|
||||
keywords: ["modbus", "industrial", "esp32", "rs485", "communication"]
|
||||
---
|
||||
|
||||
# ModbusTypes
|
||||
|
||||
**Path**: [`src/modbus/ModbusTypes.h`](../../../src/modbus/ModbusTypes.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A collection of enumerations, structures, and classes that define the foundational types used by the Modbus implementation. This component provides the core data types and interfaces for working with Modbus communication in industrial applications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP32 microcontroller
|
||||
- Platform.io development environment
|
||||
- C++17 compatible compiler
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- **Enumerations**:
|
||||
- `E_FN_CODE`: Modbus function codes
|
||||
- `E_MB_OpType`: Modbus operation types
|
||||
- `E_MB_OpStatus`: Operation status
|
||||
- `MB_Error`: Error codes
|
||||
- `E_FilterType`: Filter types for operation filtering
|
||||
- `E_ModbusAccess`: Access types (from config-modbus.h)
|
||||
|
||||
- **Structures**:
|
||||
- `MB_Registers`: Register definition structure
|
||||
- `ModbusBlockView`: Non-owning view of register blocks
|
||||
- `MB_UpdateData`: RTU update data
|
||||
- `ModbusOperation`: Modbus operation structure
|
||||
- `ModbusValueEntry`: Register or coil value entry
|
||||
- `SlaveData`: Modbus slave data
|
||||
- `ModbusReadBlock`: Mandatory read block definition
|
||||
|
||||
- **Classes**:
|
||||
- `ModbusOperationFilter`: Base class for operation filters
|
||||
- `DuplicateOperationFilter`: Filter to remove duplicate operations
|
||||
- `RateLimitFilter`: Filter to limit operation rates
|
||||
- `PriorityFilter`: Filter for prioritizing operations
|
||||
- `OperationLifecycleFilter`: Filter for managing operation lifecycle
|
||||
- `RegisterState`: Class for register state management
|
||||
- `RTU_Base`: Base class for RTU devices
|
||||
|
||||
- **Callback Types**:
|
||||
- `ResponseCallback`: Callback for slave responses
|
||||
- `OnRegisterChangeCallback`: Callback for register changes
|
||||
- `OnWriteCallback`: Callback for write operations
|
||||
- `OnErrorCallback`: Callback for error handling
|
||||
- `OperationExistsCallback`: Callback for checking if operation exists
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Comprehensive Modbus function code support
|
||||
- Error handling with detailed error codes
|
||||
- Operation filtering system for queue management
|
||||
- Register state management
|
||||
- Device state management through RTU_Base
|
||||
- Support for mandatory read blocks
|
||||
- Priority-based operation scheduling
|
||||
- Callback systems for events
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Arduino.h](https://www.arduino.cc/reference/en/)
|
||||
- [ArduinoLog.h](https://github.com/thijse/Arduino-Log)
|
||||
- [Component.h](../../../src/Component.h)
|
||||
- [Vector.h](../../../src/Vector.h)
|
||||
- [enums.h](../../../src/enums.h)
|
||||
- [macros.h](../../../src/macros.h)
|
||||
- [constants.h](../../../src/constants.h)
|
||||
- [config-modbus.h](../../../src/config-modbus.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ModbusTypes --> ArduinoLog
|
||||
ModbusTypes --> Component
|
||||
ModbusTypes --> Vector
|
||||
ModbusTypes --> macros
|
||||
ModbusTypes --> constants
|
||||
ModbusTypes --> config-modbus
|
||||
ModbusTypes --> enums
|
||||
ModbusRTU --> ModbusTypes
|
||||
RTUDevices --> ModbusTypes
|
||||
RS485 --> ModbusTypes
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> UNINITIALIZED
|
||||
UNINITIALIZED --> INITIALIZING: initialize()
|
||||
INITIALIZING --> IDLE: initialization complete
|
||||
IDLE --> RUNNING: operations pending
|
||||
RUNNING --> IDLE: operations complete
|
||||
IDLE --> ERROR: timeout
|
||||
RUNNING --> ERROR: timeout
|
||||
ERROR --> IDLE: response received
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider more efficient data structures for queuing operations
|
||||
- Optimize memory usage in filter chain implementations
|
||||
- Implement operation batching for improved throughput
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add validation for input parameters to prevent buffer overflows
|
||||
- Consider implementing authentication mechanisms for Modbus TCP
|
||||
- Add checks for unauthorized register access
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure full compliance with Modbus specification
|
||||
- Review handling of exceptional responses
|
||||
- Validate operation against industrial standards
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Implement appropriate error handling strategies
|
||||
- Set appropriate timeouts based on network characteristics
|
||||
- Use the filter chain to customize operation processing
|
||||
- Leverage the callback system for event-based programming
|
||||
@@ -1,132 +0,0 @@
|
||||
---
|
||||
title: 3-Position Analog Switch
|
||||
description: A component for handling 3-position analog switches with UP/MIDDLE/DOWN positions
|
||||
keywords: [analog, switch, 3-position, input, modbus, ESP32]
|
||||
---
|
||||
|
||||
# 3-Position Analog Switch
|
||||
|
||||
**Path**: [src/components/3PosAnalog.h](../src/components/3PosAnalog.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The 3-Position Analog Switch (`Pos3Analog`) component provides an interface to hardware switches with three positions (UP, MIDDLE, DOWN). It reads from two analog input pins and determines the current position. The component supports both local (physical) and remote (Modbus) control modes, making it suitable for industrial automation applications that require flexible control mechanisms.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Hardware
|
||||
- ESP32 microcontroller
|
||||
- Two analog input pins for position detection (upPin and downPin)
|
||||
|
||||
### Software
|
||||
- Arduino framework
|
||||
- ArduinoLog library
|
||||
- Modbus TCP support
|
||||
|
||||
## Features
|
||||
|
||||
- Three-position state detection (UP, MIDDLE, DOWN)
|
||||
- Dual control modes:
|
||||
- LOCAL: Position determined by physical input readings
|
||||
- REMOTE: Position controlled via Modbus
|
||||
- Modbus integration with read/write capabilities
|
||||
- Configurable sampling interval
|
||||
- State change notifications
|
||||
- Comprehensive error handling and validation
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Component](../src/Component.h): Base component class providing core functionality
|
||||
- [ModbusTCP](../src/modbus/ModbusTCP.h): Modbus TCP protocol implementation
|
||||
- [Bridge](../src/Bridge.h): Serial command bridge for component communication
|
||||
- [App](../src/App.h): Application framework integration
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Pos3Analog --> Component
|
||||
Pos3Analog --> ModbusTCP
|
||||
Pos3Analog --> Bridge
|
||||
Component --> App
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The component operates in one of two modes (LOCAL or REMOTE) and has three possible positions (UP, MIDDLE, DOWN).
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> LOCAL
|
||||
LOCAL --> REMOTE: Modbus Write
|
||||
REMOTE --> LOCAL: Modbus Write
|
||||
|
||||
state LOCAL {
|
||||
[*] --> MIDDLE
|
||||
MIDDLE --> UP: upPin Active
|
||||
MIDDLE --> DOWN: downPin Active
|
||||
UP --> MIDDLE: No pins Active
|
||||
DOWN --> MIDDLE: No pins Active
|
||||
}
|
||||
|
||||
state REMOTE {
|
||||
[*] --> REMOTE_MIDDLE
|
||||
REMOTE_MIDDLE --> REMOTE_UP: Modbus Write
|
||||
REMOTE_MIDDLE --> REMOTE_DOWN: Modbus Write
|
||||
REMOTE_UP --> REMOTE_MIDDLE: Modbus Write
|
||||
REMOTE_DOWN --> REMOTE_MIDDLE: Modbus Write
|
||||
}
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider implementing debounce functionality for more stable readings
|
||||
- Optimize analog reading frequency based on application requirements
|
||||
|
||||
### Security
|
||||
|
||||
- Implement authentication for remote control mode changes
|
||||
- Add permission levels for Modbus write operations
|
||||
|
||||
### Compliance
|
||||
|
||||
- Ensure compliance with industrial control systems standards
|
||||
- Verify compatibility with Modbus specification
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Use pull-up or pull-down resistors on the analog inputs for more reliable readings
|
||||
- Implement filtering for noisy environments
|
||||
- Consider adding hysteresis to prevent rapid state changes near thresholds
|
||||
|
||||
## Example
|
||||
|
||||
Below is an example of how to initialize and use the 3-Position Analog Switch component:
|
||||
|
||||
```cpp
|
||||
#ifdef AUX_ANALOG_3POS_SWITCH_0
|
||||
analog3PosSwitch_0 = new Pos3Analog(
|
||||
this, // owner
|
||||
AUX_ANALOG_3POS_SWITCH_0, // upPin
|
||||
AUX_ANALOG_3POS_SWITCH_0 + 1, // downPin (assuming sequential pins)
|
||||
COMPONENT_KEY_ANALOG_3POS_SWITCH_0, // id
|
||||
MB_ANALOG_3POS_SWITCH_0_ADDR // modbusAddress
|
||||
);
|
||||
if (analog3PosSwitch_0)
|
||||
{
|
||||
components.push_back(analog3PosSwitch_0);
|
||||
Log.infoln(F("3-Position Analog Switch 0 initialized. UpPin:%d, DownPin:%d, ID:%d, MB:%d"),
|
||||
AUX_ANALOG_3POS_SWITCH_0, AUX_ANALOG_3POS_SWITCH_0 + 1,
|
||||
COMPONENT_KEY_ANALOG_3POS_SWITCH_0, MB_ANALOG_3POS_SWITCH_0_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("3-Position Analog Switch 0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [Arduino Analog Input Documentation](https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/)
|
||||
- [Modbus Protocol Specification](https://modbus.org/specs.php)
|
||||
@@ -1,126 +0,0 @@
|
||||
---
|
||||
title: "AnalogLevelSwitch Component"
|
||||
description: "Analog Level Switch Component for multi-position switch detection via analog input"
|
||||
keywords: ["analog", "level", "switch", "ESP32", "voltage divider", "multi-position"]
|
||||
---
|
||||
|
||||
# AnalogLevelSwitch
|
||||
|
||||
**Path**: [`src/components/AnalogLevelSwitch.h`](../src/components/AnalogLevelSwitch.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The AnalogLevelSwitch component interprets an analog voltage as a discrete position or slot. It enables reading an analog input as a multi-position switch by mapping voltage levels to specific slots or positions, with built-in smoothing and debouncing functionality.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- An analog input pin on the ESP32
|
||||
- A voltage divider circuit with different resistor values for each switch position
|
||||
- Pull-down resistor (typically 10kΩ) connected to the analog pin
|
||||
|
||||
### Software
|
||||
- Arduino framework
|
||||
- ArduinoLog library
|
||||
- ModbusTCP support
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Maps analog voltage readings to discrete positions (slots)
|
||||
- Configurable number of positions/slots (up to 32 positions)
|
||||
- Adjustable ADC step size per slot
|
||||
- Configurable ADC value offset for the first slot
|
||||
- Built-in signal smoothing using moving average or EMA
|
||||
- Debouncing algorithm to prevent spurious readings
|
||||
- Hysteresis to prevent jitter between adjacent positions
|
||||
- Modbus integration for industrial control systems
|
||||
- Customizable reading interval
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [ModbusTCP](../src/modbus/ModbusTCP.h) - Modbus TCP communication
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - Logging functionality
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
AnalogLevelSwitch --> Component
|
||||
AnalogLevelSwitch --> ModbusTCP
|
||||
AnalogLevelSwitch --> ArduinoLog
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialization
|
||||
Initialization --> ReadAnalogValue
|
||||
ReadAnalogValue --> SmoothValue
|
||||
SmoothValue --> DetermineSlot
|
||||
DetermineSlot --> CheckIfChanged
|
||||
CheckIfChanged --> ConfirmChange: Slot different
|
||||
CheckIfChanged --> ReadAnalogValue: Slot same
|
||||
ConfirmChange --> UpdateSlot: Confirmed
|
||||
ConfirmChange --> ReadAnalogValue: Not confirmed
|
||||
UpdateSlot --> NotifyStateChange
|
||||
NotifyStateChange --> ReadAnalogValue
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider optimizing the moving average calculation for better performance
|
||||
- Evaluate if the current reading interval is optimal for the application
|
||||
- Investigate using hardware filtering in addition to software smoothing
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement range checking for analog readings to prevent unexpected behavior
|
||||
- Add validation for Modbus register access
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compatibility with industrial standards for analog input processing
|
||||
- Verify noise immunity meets requirements for industrial environments
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use 1% tolerance resistors in the voltage divider circuit for better accuracy
|
||||
- Ensure the voltage divider resistance values create sufficient separation between positions
|
||||
- Keep the overall equivalent resistance of the voltage divider in the 1kΩ to 100kΩ range
|
||||
- Add appropriate ESD protection for the analog input pin in industrial environments
|
||||
- When using mechanical switches, consider adding hardware debouncing in addition to software debouncing
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
Here's an example of how to initialize and use the AnalogLevelSwitch component:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_ANALOG_LEVEL_SWITCH_0
|
||||
analogLevelSwitch_0 = new AnalogLevelSwitch(
|
||||
this, // owner
|
||||
PIN_ANALOG_LEVEL_SWITCH_0, // analogPin
|
||||
ALS_0_NUM_LEVELS, // numLevels
|
||||
ALS_0_ADC_STEP, // levelStep
|
||||
ALS_0_ADC_OFFSET, // adcValueOffset
|
||||
ID_ANALOG_LEVEL_SWITCH_0, // id
|
||||
ALS_0_MB_ADDR // modbusAddress
|
||||
);
|
||||
if (analogLevelSwitch_0) {
|
||||
components.push_back(analogLevelSwitch_0);
|
||||
Log.infoln(F("AnalogLevelSwitch_0 initialized. Pin:%d, Levels:%d, Step:%d, Offset:%d, ID:%d, MB:%d"),
|
||||
PIN_ANALOG_LEVEL_SWITCH_0, ALS_0_NUM_LEVELS,
|
||||
ALS_0_ADC_STEP, ALS_0_ADC_OFFSET,
|
||||
ID_ANALOG_LEVEL_SWITCH_0, ALS_0_MB_ADDR);
|
||||
} else {
|
||||
Log.errorln(F("AnalogLevelSwitch_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
-121
@@ -1,121 +0,0 @@
|
||||
---
|
||||
title: "Bridge Component"
|
||||
description: "A communication bridge component for handling inter-component messaging and registering method calls"
|
||||
keywords: ["bridge", "communication", "messaging", "inter-component", "method registry", "ESP-32", "industrial"]
|
||||
---
|
||||
|
||||
# BRIDGE
|
||||
|
||||
**Path**: [src/Bridge.cpp](../../src/Bridge.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A communication bridge component that facilitates inter-component messaging and method registration. The Bridge acts as a central hub for communication between different system components and provides services for Modbus management.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- No specific hardware pins required
|
||||
- Component base class
|
||||
- String manipulation capabilities
|
||||
- Vector container support
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Component method registration and management
|
||||
- Inter-component message handling
|
||||
- Component instance tracking and retrieval
|
||||
- Debugging and listing capabilities
|
||||
- Method delimiter-based parsing
|
||||
- Integration with Modbus Manager
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](./Component.md)
|
||||
- WString
|
||||
- Vector
|
||||
- Streaming
|
||||
- xtypes
|
||||
- enums
|
||||
- macros
|
||||
|
||||
```mermaid
|
||||
graph TD;
|
||||
Bridge["Bridge"] -->|extends| Component["Component"];
|
||||
Bridge -->|uses| WString["WString"];
|
||||
Bridge -->|uses| Vector["Vector"];
|
||||
Bridge -->|uses| Streaming["Streaming"];
|
||||
Bridge -->|uses| xtypes["xtypes"];
|
||||
Bridge -->|uses| enums["enums"];
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> INITIALIZATION
|
||||
INITIALIZATION --> REGISTRATION : setup()
|
||||
REGISTRATION --> READY : register components
|
||||
READY --> MESSAGE_HANDLING : onMessage()
|
||||
MESSAGE_HANDLING --> DEBUGGING : debug()
|
||||
MESSAGE_HANDLING --> READY : return status
|
||||
DEBUGGING --> READY
|
||||
READY --> LISTING : getComponentList()
|
||||
LISTING --> READY
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Implement component method caching for faster lookups
|
||||
- Optimize memory usage by pre-allocating component storage
|
||||
- Add method call frequency monitoring
|
||||
- Consider asynchronous message processing
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement access control for component method registration
|
||||
- Implement message authentication and encryption
|
||||
- Add signed message data integrity checks
|
||||
- Enable inter-component communication logging
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure error handling complies with industrial standards
|
||||
- Implement message logging for audit requirements
|
||||
- Validate time-critical communication performance
|
||||
- Consider system failover and redundancy in communication
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use structured error codes for consistent message handling
|
||||
- Maintain component hierarchies to maintain clear dependencies
|
||||
- Implement event driven architecture for inter-component synchronization
|
||||
- Add component lifecycle tracking
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
Based on the available header file:
|
||||
|
||||
```cpp
|
||||
#defdef ENABLE_BRIDGE_COMMUNICATION
|
||||
bridge = new Bridge(
|
||||
this // owner
|
||||
);
|
||||
if (bridge)
|
||||
{
|
||||
components.push_back(bridge);
|
||||
Log.infoln(F("Bridge initialized."));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("Bridge initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
@@ -1,121 +0,0 @@
|
||||
---
|
||||
title: CircularLogPrinter
|
||||
description: A thread-safe circular buffer logger for ESP32 applications
|
||||
keywords: [logger, esp32, circular buffer, thread-safe, logging]
|
||||
---
|
||||
|
||||
# CircularLogPrinter
|
||||
|
||||
**Path**: [`src/Logger.h`](../src/Logger.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
CircularLogPrinter is a high-performance, thread-safe logging utility designed for ESP32 applications. It maintains a configurable circular buffer of log messages in memory while optionally mirroring output to a Serial or other Print-compatible stream. The implementation is compliant with MISRA/CPPCHECK standards, avoiding reinterpret casts for improved safety.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Hardware
|
||||
- No specific hardware pins required
|
||||
- Compatible with ESP32 platforms
|
||||
|
||||
### Software
|
||||
- Arduino framework
|
||||
- FreeRTOS (for thread-safety features)
|
||||
- ESP-IDF (for ESP log integration)
|
||||
|
||||
## Features
|
||||
|
||||
- Configurable circular buffer for storing the last N log lines
|
||||
- Thread-safe operation (optional via configuration)
|
||||
- Ability to redirect ESP-IDF logging macros (ESP_LOGx) into this printer
|
||||
- MISRA/CPPCHECK compliant implementation with no pointer type casting
|
||||
- Memory-efficient design with fixed buffer sizes
|
||||
- Optional output mirroring to any Arduino Print-compatible stream
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Arduino.h](https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/Arduino.h)
|
||||
- [Print.h](https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/Print.h)
|
||||
- [esp_log.h](https://github.com/espressif/esp-idf/blob/master/components/log/include/esp_log.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
CircularLogPrinter --> Print
|
||||
CircularLogPrinter --> Arduino
|
||||
CircularLogPrinter --> esp_log
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The CircularLogPrinter maintains a circular buffer of log lines. When the buffer is full, new log entries overwrite the oldest entries. Log entries are committed when a newline character is encountered or when the maximum line length is reached.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize: Constructor
|
||||
Initialize --> Ready
|
||||
Ready --> AppendChar: write(byte)
|
||||
Ready --> AppendMultipleChars: write(buffer, size)
|
||||
AppendChar --> CommitLine: If newline
|
||||
AppendChar --> AppendChar: If not newline
|
||||
AppendMultipleChars --> CommitLine: If newline encountered
|
||||
AppendMultipleChars --> Ready: After processing
|
||||
CommitLine --> Ready
|
||||
Ready --> Clear: clear() called
|
||||
Clear --> Ready
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider using a more efficient memory layout for the circular buffer
|
||||
- Evaluate the impact of thread-safety mechanisms on performance in high-frequency logging scenarios
|
||||
- Add compile-time options to disable features not needed for specific applications
|
||||
|
||||
### Security
|
||||
|
||||
- Add configurable log level filtering to prevent sensitive information leakage
|
||||
- Consider adding encryption options for logs containing sensitive information
|
||||
- Implement log rotation to persistent storage for critical deployments
|
||||
|
||||
### Compliance
|
||||
|
||||
- The implementation is already MISRA/CPPCHECK compliant by avoiding pointer type casting
|
||||
- Consider adding support for standardized log formats like RFC5424
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Use reasonable buffer sizes to avoid excessive memory usage
|
||||
- Consider the performance impact of thread-safety in high-frequency logging scenarios
|
||||
- When using with ESP-IDF logging, ensure consistent configuration across components
|
||||
- For production environments, implement a strategy for persistent log storage
|
||||
|
||||
## Example
|
||||
|
||||
This example shows how to initialize and use the CircularLogPrinter:
|
||||
|
||||
```cpp
|
||||
// Create a CircularLogPrinter that mirrors to Serial
|
||||
CircularLogPrinter logger(&Serial);
|
||||
|
||||
// Clear the buffer
|
||||
logger.clear();
|
||||
|
||||
// Write some logs
|
||||
logger.println("Starting application...");
|
||||
logger.printf("System initialized with version: %s", VERSION);
|
||||
|
||||
// Attach to ESP-IDF logging
|
||||
logger.attachToEspLog();
|
||||
|
||||
// Now ESP_LOGx macros will also be captured
|
||||
ESP_LOGI("TAG", "This will be captured by the CircularLogPrinter");
|
||||
|
||||
// Retrieve a specific line from history (0 is most recent)
|
||||
const char* lastLine = logger.getLine(0);
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [ESP-IDF Logging Library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/log.html)
|
||||
- [Arduino Print Class](https://www.arduino.cc/reference/en/language/functions/communication/serial/print/)
|
||||
@@ -1,139 +0,0 @@
|
||||
---
|
||||
title: Component Class
|
||||
description: Base class for all hardware and software components in the system
|
||||
keywords: [component, base class, modular architecture, ESP32]
|
||||
---
|
||||
|
||||
## Component
|
||||
|
||||
**Path**: [src/Component.h](../src/Component.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Component class serves as the foundational base class for all hardware and software components in the system. It provides a standardized interface for component initialization, runtime behavior, and communication with other system components. The class implements a modular architecture that allows components to be easily added, removed, or modified without affecting the rest of the system.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- Arduino framework
|
||||
- ESP32 platform
|
||||
- WString.h for string handling
|
||||
- ArduinoLog.h for logging functionality
|
||||
- Vector.h for dynamic arrays
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Component identification with unique IDs and names
|
||||
- Standardized initialization and setup processes
|
||||
- Runtime flags for controlling component behavior
|
||||
- Owner-child component relationship hierarchy
|
||||
- Integration with Modbus communication
|
||||
- Network capability flags
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [WString.h](https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/)
|
||||
- [ArduinoLog.h](https://github.com/thijse/Arduino-Log)
|
||||
- [Vector.h](https://github.com/janelia-arduino/Vector)
|
||||
- [enums.h](../src/enums.h)
|
||||
- [constants.h](../src/constants.h)
|
||||
- [error_codes.h](../src/error_codes.h)
|
||||
- [macros.h](../src/macros.h)
|
||||
- [xtypes.h](../src/xtypes.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Component --> WString
|
||||
Component --> ArduinoLog
|
||||
Component --> Vector
|
||||
Component --> enums
|
||||
Component --> constants
|
||||
Component --> error_codes
|
||||
Component --> macros
|
||||
Component --> xtypes
|
||||
Component --> Bridge[Bridge class]
|
||||
Component --> ModbusTCP[ModbusTCP class]
|
||||
Component --> ModbusBlockView[ModbusBlockView class]
|
||||
Component --> MB_Registers[MB_Registers class]
|
||||
Component --> RS485[RS485 class]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The Component class follows a lifecycle pattern that includes initialization, setup, and runtime phases. Components can be dynamically enabled or disabled through runtime flags.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Constructed
|
||||
Constructed --> Setup: setup()
|
||||
Setup --> Running: flags & E_OF_SETUP
|
||||
Running --> LoopExecution: flags & D_OF_LOOP
|
||||
LoopExecution --> Running
|
||||
Running --> Disabled: disable()
|
||||
Disabled --> Running: enable()
|
||||
Running --> [*]: destroy()
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Optimize component instantiation for memory-constrained environments
|
||||
- Consider implementing lazy initialization for components with heavy setup requirements
|
||||
- Review the component hierarchy for potential performance bottlenecks in deeply nested structures
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement access control mechanisms for components with critical functionality
|
||||
- Add validation for component parameters passed through Modbus or other interfaces
|
||||
- Consider encryption for sensitive component data communication
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure component implementation adheres to industrial communication standards
|
||||
- Verify compatibility with Modbus protocol specifications
|
||||
- Document compliance with relevant industrial control system standards
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use meaningful component names and IDs to facilitate debugging and maintenance
|
||||
- Consider implementing a component registry for easier system-wide management
|
||||
- Implement proper error handling in component constructors and methods
|
||||
- Use the owner-child relationship to implement clean component lifecycle management
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This section illustrates how to create and configure a Component instance. Since the complete implementation in Component.cpp is not accessible, this example provides a general pattern for component creation based on the header file.
|
||||
|
||||
```cpp
|
||||
// Create a basic component with default settings
|
||||
Component* basicComponent = new Component("BasicComponent", 100, Component::COMPONENT_DEFAULT);
|
||||
|
||||
// Add the component to the components vector
|
||||
if (basicComponent) {
|
||||
components.push_back(basicComponent);
|
||||
Log.infoln(F("Basic component initialized. ID:%d"), 100);
|
||||
} else {
|
||||
Log.errorln(F("Basic component initialization failed."));
|
||||
}
|
||||
|
||||
// Example with an owner component
|
||||
Component* parentComponent = new Component("ParentComponent", 200, Component::COMPONENT_DEFAULT);
|
||||
Component* childComponent = new Component(
|
||||
"ChildComponent", // name
|
||||
201, // id
|
||||
Component::COMPONENT_DEFAULT, // flags
|
||||
parentComponent // owner
|
||||
);
|
||||
|
||||
if (childComponent) {
|
||||
components.push_back(childComponent);
|
||||
Log.infoln(F("Child component initialized. Name:%s, ID:%d"),
|
||||
"ChildComponent", 201);
|
||||
} else {
|
||||
Log.errorln(F("Child component initialization failed."));
|
||||
}
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- None available
|
||||
@@ -1,129 +0,0 @@
|
||||
---
|
||||
title: Extruder Component
|
||||
description: Documentation for the Extruder component which manages VFD-controlled extrusion with joystick and potentiometer control
|
||||
keywords: extruder, VFD, joystick, potentiometer, torque monitoring, jam detection
|
||||
---
|
||||
|
||||
# Extruder
|
||||
|
||||
**Path**: [`src/components/Extruder.h`](../src/components/Extruder.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Extruder component provides control over a SAKO VFD-driven extruder motor. It supports both manual and automatic extrusion modes, with configurable speed and overload protection via potentiometers. The component integrates with a joystick for manual control and features jam detection based on motor torque feedback.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Hardware
|
||||
- SAKO VFD (Variable Frequency Drive) for motor control
|
||||
- Joystick for manual control (optional)
|
||||
- Potentiometer for speed control (optional)
|
||||
- Potentiometer for overload threshold control (optional)
|
||||
|
||||
### Pins
|
||||
- No direct pin requirements (manages components that have their own pin requirements)
|
||||
|
||||
## Features
|
||||
|
||||
- Dual operating modes: manual (joystick-controlled) and auto (timed operation)
|
||||
- Configurable extrusion speed via potentiometer
|
||||
- Adjustable overload/jam detection threshold
|
||||
- Automatic jam detection based on motor torque feedback
|
||||
- Modbus TCP interface for remote control and monitoring
|
||||
- Safety features including maximum runtime limits
|
||||
- Auto-mode activation via joystick hold
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [SAKO_VFD](../src/components/SAKO_VFD.h) - VFD motor controller
|
||||
- [Pos3Analog](../src/components/3PosAnalog.h) - 3-position analog input (joystick)
|
||||
- [POT](../src/components/POT.h) - Potentiometer interface
|
||||
- [ModbusTCP](../src/modbus/ModbusTCP.h) - Modbus interface
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Extruder --> Component
|
||||
Extruder --> SAKO_VFD
|
||||
Extruder --> Pos3Analog
|
||||
Extruder --> POT
|
||||
Extruder --> ModbusTCP
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The Extruder component implements a state machine with the following states:
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> IDLE
|
||||
IDLE --> EXTRUDING_MANUAL: Joystick UP
|
||||
EXTRUDING_MANUAL --> EXTRUDING_AUTO: Hold joystick UP for set duration
|
||||
EXTRUDING_MANUAL --> IDLE: Release joystick
|
||||
EXTRUDING_AUTO --> STOPPING: Auto time complete or manual stop
|
||||
EXTRUDING_MANUAL --> JAMMED: Torque exceeds threshold
|
||||
EXTRUDING_AUTO --> JAMMED: Torque exceeds threshold
|
||||
STOPPING --> IDLE: VFD stopped
|
||||
JAMMED --> RESETTING_JAM: Reset command
|
||||
RESETTING_JAM --> IDLE: Reset complete
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider implementing acceleration/deceleration ramps for smoother operation
|
||||
- Optimize VFD polling frequency based on system requirements
|
||||
- Evaluate the potential for predictive jam detection using torque trend analysis
|
||||
|
||||
### Security
|
||||
|
||||
- Implement authentication for Modbus commands that control the extruder
|
||||
- Consider adding physical emergency stop integration
|
||||
- Validate input values from potentiometers to prevent unexpected behavior
|
||||
|
||||
### Compliance
|
||||
|
||||
- Ensure conformance with industrial safety standards for automated machinery
|
||||
- Implement proper error handling and logging for diagnostic purposes
|
||||
- Consider adding UL/CE compliance features if required for deployment environment
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Add temperature monitoring to prevent motor overheating
|
||||
- Consider implementing a material feed sensor to detect material availability
|
||||
- Implement a maintenance tracking system based on operation hours
|
||||
- Add visual feedback (e.g., LED indicators) for different states, especially jammed condition
|
||||
|
||||
## Example
|
||||
|
||||
The following example shows how to create and configure an Extruder component:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_EXTRUDER
|
||||
// First ensure required components exist
|
||||
if (sakoVFD && joystick && speedPot && overloadPot) {
|
||||
extruder = new Extruder(
|
||||
this, // owner
|
||||
sakoVFD, // VFD controller
|
||||
joystick, // joystick for manual control
|
||||
speedPot, // potentiometer for speed control
|
||||
overloadPot // potentiometer for overload threshold
|
||||
);
|
||||
|
||||
if (extruder) {
|
||||
components.push_back(extruder);
|
||||
Log.infoln(F("Extruder initialized"));
|
||||
} else {
|
||||
Log.errorln(F("Extruder initialization failed"));
|
||||
}
|
||||
} else {
|
||||
Log.warningln(F("Extruder not initialized - missing dependencies"));
|
||||
}
|
||||
#endif
|
||||
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
---
|
||||
title: Joystick Component
|
||||
description: Documentation for the Joystick input component for ESP32 platform
|
||||
keywords: [joystick, input device, ESP32, modbus, industrial]
|
||||
---
|
||||
|
||||
## Joystick
|
||||
|
||||
**Path**: [`./src/components/Joystick.cpp`](../src/components/Joystick.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Joystick component provides an interface for a 4-position digital joystick (Up, Down, Left, Right) with a center position. It supports both local physical input and remote control via Modbus, allowing for integration into industrial control systems.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- 4 digital input pins connected to joystick switches
|
||||
- ESP32 microcontroller
|
||||
|
||||
### Software
|
||||
- Arduino framework
|
||||
- ArduinoLog library
|
||||
- Platform.io environment
|
||||
|
||||
## FEATURES
|
||||
|
||||
- 5-position detection (UP, DOWN, LEFT, RIGHT, CENTER)
|
||||
- Local and remote operation modes
|
||||
- Position override capability via Modbus
|
||||
- Input debouncing for reliable operation
|
||||
- Position hold time tracking
|
||||
- State change notification system
|
||||
- Modbus integration for industrial control systems
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](./Component.md) - Base component class
|
||||
- [ModbusTCP](./ModbusTCP.md) - Modbus TCP protocol implementation
|
||||
- [Bridge](./Bridge.md) - Serial communication bridge
|
||||
- [config.h](./config.md) - System configuration
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Joystick --> Component
|
||||
Joystick --> ModbusTCP
|
||||
Joystick --> Bridge
|
||||
Joystick --> Config
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The Joystick operates in two modes: LOCAL and REMOTE. In LOCAL mode, it reads physical inputs from pins. In REMOTE mode, it uses an override position set via Modbus.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup
|
||||
Setup --> Idle
|
||||
Idle --> ReadPosition: If LOCAL mode
|
||||
ReadPosition --> Debounce: Read inputs
|
||||
Debounce --> UpdatePosition: Confirmed
|
||||
Debounce --> Idle: Not confirmed
|
||||
UpdatePosition --> Notify: Position changed
|
||||
Notify --> Idle
|
||||
Idle --> CheckRemote: If REMOTE mode
|
||||
CheckRemote --> UpdatePosition: Override changed
|
||||
CheckRemote --> Idle: No change
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider optimizing the debouncing algorithm for faster response in time-critical applications
|
||||
- Evaluate interrupt-based approach instead of polling for reduced CPU overhead
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add input validation for Modbus commands to prevent unexpected behavior
|
||||
- Consider adding authentication for remote control mode switching
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with industrial standards for joystick controls
|
||||
- Consider implementing emergency stop functionality
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use pull-up or pull-down resistors with the input pins to ensure stable readings
|
||||
- When using in industrial environments, consider adding hardware debouncing
|
||||
- Implement application-level validation for critical operations controlled by the joystick
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example shows how to initialize and mount a Joystick component:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_JOYSTICK_UP
|
||||
joystick = new Joystick(
|
||||
this, // owner
|
||||
PIN_JOYSTICK_UP, // UP pin
|
||||
PIN_JOYSTICK_DOWN, // DOWN pin
|
||||
PIN_JOYSTICK_LEFT, // LEFT pin
|
||||
PIN_JOYSTICK_RIGHT, // RIGHT pin
|
||||
COMPONENT_KEY_JOYSTICK_0 // modbus address
|
||||
);
|
||||
if (joystick)
|
||||
{
|
||||
components.push_back(joystick);
|
||||
Log.infoln(F("Joystick initialized. Pins: UP=%d, DOWN=%d, LEFT=%d, RIGHT=%d, ID=%d"),
|
||||
PIN_JOYSTICK_UP, PIN_JOYSTICK_DOWN,
|
||||
PIN_JOYSTICK_LEFT, PIN_JOYSTICK_RIGHT,
|
||||
COMPONENT_KEY_JOYSTICK_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("Joystick initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
---
|
||||
title: LEDFeedback Component
|
||||
description: LED-based visual feedback system for indicating device status
|
||||
keywords: LED, visual feedback, NeoPixel, status indicator, ESP32
|
||||
---
|
||||
|
||||
## LEDFeedback
|
||||
|
||||
**Path**: [src/LEDFeedback.cpp](../src/LEDFeedback.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The LEDFeedback component provides visual status indication through addressable LEDs (NeoPixels). It allows for controlling color, intensity, and pattern of LEDs to convey system status or feedback to users.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- Addressable LED strip/array (NeoPixels)
|
||||
- Data pin connected to ESP32 GPIO
|
||||
- Appropriate power supply for LEDs
|
||||
|
||||
### Software
|
||||
- Adafruit_NeoPixel library
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Control of individual addressable LEDs
|
||||
- Multiple color patterns for status indication
|
||||
- Modbus integration for remote control
|
||||
- Configurable update interval
|
||||
- Support for various LED counts
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [Adafruit_NeoPixel](https://github.com/adafruit/Adafruit_NeoPixel) - Library for controlling NeoPixels
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
LEDFeedback --> Component
|
||||
LEDFeedback --> Adafruit_NeoPixel
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize
|
||||
Initialize --> Idle
|
||||
Idle --> UpdateLEDs: Update interval reached
|
||||
UpdateLEDs --> Idle
|
||||
Idle --> ChangePattern: Modbus command received
|
||||
ChangePattern --> Idle
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Optimize LED update frequency to minimize CPU usage
|
||||
- Consider implementing brightness scaling based on system load
|
||||
|
||||
### SECURITY
|
||||
|
||||
- None identified - LED feedback is output-only
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure power consumption stays within device specifications
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Consider adding support for more complex animation patterns
|
||||
- Add power-saving modes that reduce brightness during idle periods
|
||||
- Implement error indication patterns for system diagnostics
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
The LEDFeedback component is constructed and mounted as follows:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_LED_FEEDBACK_0
|
||||
ledFeedback_0 = new LEDFeedback(
|
||||
this, // owner
|
||||
PIN_LED_FEEDBACK_0, // pin
|
||||
LED_PIXEL_COUNT_0, // pixelCount
|
||||
ID_LED_FEEDBACK_0, // id
|
||||
LED_FEEDBACK_0_MB_ADDR // modbusAddress
|
||||
);
|
||||
if (ledFeedback_0)
|
||||
{
|
||||
components.push_back(ledFeedback_0);
|
||||
Log.infoln(F("LEDFeedback_0 initialized. Pin:%d, Count:%d, ID:%d, MB:%d"),
|
||||
PIN_LED_FEEDBACK_0, LED_PIXEL_COUNT_0,
|
||||
ID_LED_FEEDBACK_0, LED_FEEDBACK_0_MB_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("LEDFeedback_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [NeoPixel Documentation](https://learn.adafruit.com/adafruit-neopixel-uberguide)
|
||||
@@ -1,148 +0,0 @@
|
||||
---
|
||||
title: ModbusLogicEngine Component
|
||||
description: A programmable logic rule engine that operates on Modbus registers to execute conditional commands
|
||||
keywords: modbus, automation, rules engine, logic, conditional execution, industrial automation
|
||||
---
|
||||
|
||||
# ModbusLogicEngine
|
||||
|
||||
**Path**: [`src/components/ModbusLogicEngine.h`](../src/components/ModbusLogicEngine.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The ModbusLogicEngine component provides a programmable logic rule engine that executes conditional actions based on Modbus register values. It functions similar to a basic PLC (Programmable Logic Controller), allowing the system to be configured with a set of if-then rules via Modbus registers without requiring firmware modifications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- No specific hardware pins required
|
||||
- Operates entirely on Modbus data
|
||||
|
||||
### Software
|
||||
- Requires `ENABLE_MB_SCRIPT` to be defined in the configuration
|
||||
- Access to Modbus register data (holding registers, coils, etc.)
|
||||
- PHApp instance to interact with other components
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Supports up to 8 configurable logic rules (adjustable via `MAX_LOGIC_RULES`)
|
||||
- Each rule includes:
|
||||
- A condition based on Modbus register or coil values
|
||||
- An action to execute when the condition is met
|
||||
- Status tracking (trigger count, last execution time, etc.)
|
||||
- Condition types: equal, not equal, less than, less or equal, greater than, greater or equal
|
||||
- Action types:
|
||||
- Write to a Modbus holding register
|
||||
- Write to a Modbus coil
|
||||
- Call a registered component method
|
||||
- Rule debugging capabilities via flags
|
||||
- Rules are fully configurable via Modbus registers
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](../src/Component.h)
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log)
|
||||
- [config.h](../src/config.h)
|
||||
- [ModbusTypes.h](../src/modbus/ModbusTypes.h)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ModbusLogicEngine --> Component
|
||||
ModbusLogicEngine --> PHApp
|
||||
ModbusLogicEngine --> ArduinoLog
|
||||
ModbusLogicEngine --> ModbusTypes
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The ModbusLogicEngine evaluates rules at regular intervals (default 100ms). For each enabled rule:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Check if rule enabled] -->|Yes| B[Read condition source value]
|
||||
B --> C[Evaluate condition]
|
||||
C -->|Condition true| D[Execute action]
|
||||
D --> E[Update status registers]
|
||||
C -->|Condition false| E
|
||||
A -->|No| F[Skip rule]
|
||||
F --> E
|
||||
```
|
||||
|
||||
Each rule occupies a block of 13 consecutive Modbus registers with the following structure:
|
||||
|
||||
1. Enabled (0/1)
|
||||
2. Condition Source Type (register type)
|
||||
3. Condition Source Address (Modbus address)
|
||||
4. Condition Operator (0=Equal, 1=Not Equal, 2=Less Than, etc.)
|
||||
5. Condition Value (to compare against)
|
||||
6. Command Type (2=Write Coil, 3=Write Register, 100=Call Method)
|
||||
7. Command Target (address or component ID)
|
||||
8. Command Parameter 1 (value or method ID)
|
||||
9. Command Parameter 2 (additional argument)
|
||||
10. Flags (debug settings)
|
||||
11. Last Status (execution result code)
|
||||
12. Last Trigger Timestamp
|
||||
13. Trigger Count
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider optimizing the rule evaluation frequency based on application needs
|
||||
- Implement priority levels for rules to ensure critical rules execute first
|
||||
- Add rate limiting options for high-frequency triggers
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement range checking on Modbus addresses to prevent unauthorized memory access
|
||||
- Add authorization mechanism for registering and modifying component methods
|
||||
- Consider adding CRC or checksum validation for rule configurations
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Document compatibility with IEC 61131-3 (PLC programming standard) concepts
|
||||
- Add options for meeting real-time response requirements for industrial control systems
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use debug flags during initial rule setup and disable for production
|
||||
- Organize rule addresses logically to group related functionality
|
||||
- Implement a backup/restore mechanism for rule configurations
|
||||
- Consider adding a web interface for easier rule configuration
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This section would typically show how the component is constructed and mounted, but the CPP file couldn't be located. However, based on the header file, a typical initialization would look like:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_MB_SCRIPT
|
||||
// Create the ModbusLogicEngine component
|
||||
modbusLogicEngine = new ModbusLogicEngine(this); // 'this' is PHApp instance
|
||||
|
||||
if (modbusLogicEngine)
|
||||
{
|
||||
components.push_back(modbusLogicEngine);
|
||||
|
||||
// Register methods that can be called by logic rules
|
||||
modbusLogicEngine->registerMethod(
|
||||
COMPONENT_KEY_RELAY_0, // component ID
|
||||
1, // method ID for toggle
|
||||
[this](short arg1, short arg2) -> short {
|
||||
// Method implementation
|
||||
return 0; // Success
|
||||
}
|
||||
);
|
||||
|
||||
Log.infoln(F("ModbusLogicEngine initialized"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("ModbusLogicEngine initialization failed"));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [Modbus Specification](https://modbus.org/specs.php)
|
||||
- [PLC Programming Concepts](https://en.wikipedia.org/wiki/Programmable_logic_controller)
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
---
|
||||
title: OmronE5 Component
|
||||
description: Modbus RTU interface for Omron E5 temperature controllers
|
||||
keywords: omron, e5, temperature, controller, modbus, rtu, rs485
|
||||
---
|
||||
|
||||
# OmronE5
|
||||
|
||||
**Path**: [`src/components/OmronE5.h`](../src/components/OmronE5.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The OmronE5 component provides a Modbus RTU interface for Omron E5 series temperature controllers. It enables reading current temperature values (PV), setting target temperatures (SP), and controlling the device operation through an RS485 interface.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Hardware
|
||||
- RS485 interface connected to ESP32
|
||||
- Omron E5 series temperature controller(s) with Modbus RTU capability
|
||||
|
||||
### Software
|
||||
- RS485 and Modbus RTU communication enabled in configuration
|
||||
- Modbus slave ID configuration for each Omron device
|
||||
|
||||
## Features
|
||||
|
||||
- Temperature monitoring (PV - Process Value)
|
||||
- Temperature control (SP - Setpoint)
|
||||
- Device status monitoring (running, heating, cooling, auto-tuning)
|
||||
- Run/stop control
|
||||
- Optional statistics collection (error rates, heating patterns, energy consumption)
|
||||
- Optional cooling support
|
||||
- Modbus TCP to RTU mapping for remote access
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [ModbusRTU](../src/modbus/ModbusRTU.h) - Modbus RTU communication
|
||||
- [ModbusTypes](../src/modbus/ModbusTypes.h) - Modbus data types
|
||||
- [OmronE5Types](../src/components/OmronE5Types.h) - Omron E5 specific types
|
||||
- [ValueWrapper](../src/ValueWrapper.h) - Value state management
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
OmronE5 --> Component
|
||||
OmronE5 --> ModbusRTU
|
||||
OmronE5 --> ValueWrapper
|
||||
OmronE5 --> OmronE5Types
|
||||
Component --> Arduino
|
||||
ModbusRTU --> RS485
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The OmronE5 component operates by regularly polling connected Omron E5 controllers via Modbus RTU, storing current values and status information, and providing both read and write functionality to control the temperature regulation process.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize
|
||||
Initialize --> ReadValues: setup() complete
|
||||
ReadValues --> UpdateState: Data received
|
||||
UpdateState --> ReadValues: After interval
|
||||
ReadValues --> HandleCommand: Command received
|
||||
HandleCommand --> UpdateState
|
||||
UpdateState --> CalculateStatistics: If ENABLE_TRUTH_COLLECTOR
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider optimizing polling frequency based on controller response time
|
||||
- Implement batch reading of multiple controllers when multiple devices are present
|
||||
- Evaluate caching strategies for frequently accessed values
|
||||
|
||||
### Security
|
||||
|
||||
- Implement validation for setpoint ranges to prevent unsafe temperature settings
|
||||
- Consider adding authentication for critical temperature control operations
|
||||
- Add CRC validation for Modbus communications to ensure data integrity
|
||||
|
||||
### Compliance
|
||||
|
||||
- Ensure temperature control limits comply with relevant safety standards
|
||||
- Document energy consumption monitoring for regulatory reporting
|
||||
- Validate operations against Omron E5 series specifications
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Configure appropriate read intervals based on the temperature control requirements
|
||||
- Implement error handling for communication failures
|
||||
- Use the statistics collection feature for process optimization and energy monitoring
|
||||
- When controlling multiple devices, consider staggering polling to prevent bus congestion
|
||||
|
||||
## Example
|
||||
|
||||
Below is an example of how to create and initialize an OmronE5 component:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_RS485_DEVICES
|
||||
#ifdef ENABLE_OMRON_E5
|
||||
// Initialize Omron E5 temperature controllers
|
||||
for (uint8_t i = 0; i < NUM_OMRON_DEVICES; i++)
|
||||
{
|
||||
uint8_t slaveId = OMRON_E5_SLAVE_ID_BASE + i;
|
||||
omronE5Devices[i] = new OmronE5(this, slaveId);
|
||||
|
||||
if (omronE5Devices[i])
|
||||
{
|
||||
components.push_back(omronE5Devices[i]);
|
||||
Log.infoln(F("OmronE5 initialized. SlaveID:%d"), slaveId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("OmronE5 initialization failed for SlaveID:%d"), slaveId);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [Omron E5 Series Datasheet](https://www.ia.omron.com/products/family/1363/)
|
||||
- [Modbus RTU Specification](https://modbus.org/specs.php)
|
||||
@@ -1,129 +0,0 @@
|
||||
---
|
||||
title: Omron E5 Temperature Controller Device
|
||||
description: Documentation for the Omron E5 temperature controller device component
|
||||
keywords: [omron, e5, temperature, controller, modbus, rs485]
|
||||
---
|
||||
|
||||
## OmronE5Device
|
||||
|
||||
**Path**: [src/components/OmronE5Device.cpp](../src/components/OmronE5Device.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The OmronE5Device component provides an interface for controlling and monitoring Omron E5 temperature controllers via Modbus RTU over RS485. It allows reading current temperature values, setting target temperatures, and managing controller status and parameters.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- RS485 communication interface
|
||||
- Omron E5 temperature controller with Modbus RTU support
|
||||
|
||||
### Software
|
||||
- RS485 driver component
|
||||
- Modbus RTU implementation
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Reading current temperature (Process Value - PV)
|
||||
- Setting target temperature (Set Point - SP)
|
||||
- Reading controller status
|
||||
- Setting controller parameters (PID values, alarm thresholds, etc.)
|
||||
- Auto-tuning control
|
||||
- Run/Stop control
|
||||
- Error handling and status reporting
|
||||
- Support for multiple temperature controllers on the same RS485 bus
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [RS485](../src/components/RS485.h) - RS485 communication interface
|
||||
- [OmronE5Types](../src/components/OmronE5Types.h) - Omron E5 register definitions and constants
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
OmronE5Device --> Component
|
||||
OmronE5Device --> RS485
|
||||
OmronE5Device --> OmronE5Types
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The OmronE5Device component manages communication with an Omron E5 temperature controller through a state machine pattern:
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialize
|
||||
Initialize --> Ready: Device configured
|
||||
Ready --> Reading: Read request
|
||||
Ready --> Writing: Write request
|
||||
Reading --> Processing: Data received
|
||||
Writing --> Processing: Command sent
|
||||
Processing --> Ready: Complete
|
||||
Processing --> Error: Timeout/Error
|
||||
Error --> Ready: Reset
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Implement batched read/write operations to improve communication efficiency
|
||||
- Optimize polling frequency based on application requirements
|
||||
- Consider implementing caching of infrequently changing parameters
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement validation for all input parameters before sending to the device
|
||||
- Consider adding authentication for critical operations (if supported by the device)
|
||||
- Add bounds checking for all register values
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with Modbus RTU protocol specifications
|
||||
- Validate implementation against Omron E5 communications manual
|
||||
- Consider implementing safety measures for temperature-critical applications
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use appropriate timeout settings based on the network configuration
|
||||
- Implement error recovery mechanisms for communication failures
|
||||
- Consider implementing a monitoring system for device health
|
||||
- Use appropriate error checking and retries for industrial environments
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```cpp
|
||||
// Example from OmronE5Manager.cpp
|
||||
#ifdef ENABLE_OMRON_E5
|
||||
// Create 8 Omron E5 devices
|
||||
for (uint8_t i = 0; i < NUM_OMRON_DEVICES; i++)
|
||||
{
|
||||
omronDevices[i] = new OmronE5Device(
|
||||
this, // owner
|
||||
rs485, // RS485 interface
|
||||
OMRON_E5_SLAVE_ID_BASE + i, // Modbus slave ID
|
||||
COMPONENT_KEY::COMPONENT_KEY_RELAY_0 + i // Component ID
|
||||
);
|
||||
|
||||
if (omronDevices[i])
|
||||
{
|
||||
components.push_back(omronDevices[i]);
|
||||
Log.infoln(F("Omron E5 device %d initialized. SlaveID: %d"),
|
||||
i, OMRON_E5_SLAVE_ID_BASE + i);
|
||||
|
||||
// Set default parameters
|
||||
omronDevices[i]->setTargetTemperature(25.0);
|
||||
omronDevices[i]->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("Omron E5 device %d initialization failed."), i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- Omron E5_C Communications Manual (H175)
|
||||
- Modbus RTU Protocol Specification
|
||||
-140
@@ -1,140 +0,0 @@
|
||||
---
|
||||
title: "POT Component"
|
||||
description: "Analog potentiometer reader with lightweight digital filtering for ESP32 and other microcontrollers"
|
||||
keywords: ["potentiometer", "analog", "filter", "ESP32", "Modbus", "component"]
|
||||
---
|
||||
|
||||
# POT
|
||||
|
||||
**Path**: [src/components/POT.h](../src/components/POT.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The POT component provides an analog potentiometer reader with lightweight digital filtering. It's designed for small AVR/ESP32 class MCUs with no dynamic memory allocation and no floating-point operations. The component supports local and remote control modes, making it ideal for industrial applications with Modbus integration.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- Analog input pin connected to a potentiometer wiper
|
||||
- Recommended: RC low-pass filter (using the potentiometer as R and adding a capacitor)
|
||||
|
||||
### Software
|
||||
- Arduino framework
|
||||
- ArduinoLog library
|
||||
- Modbus TCP implementation
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Three damping modes:
|
||||
- NONE (raw readings)
|
||||
- MOVING-AVERAGE (box-car filter with O(1) implementation)
|
||||
- EMA (Exponential Moving Average with 1-pole IIR filter)
|
||||
- Dead-band implementation to suppress ±1-LSB chatter after scaling
|
||||
- Scaling from raw ADC values (0-4095 for ESP32) to application values (0-100 by default)
|
||||
- Local/Remote control modes via Modbus
|
||||
- Efficient implementation with no dynamic memory allocation
|
||||
- Configurable sampling interval and filter parameters
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [Arduino](https://www.arduino.cc/reference/en/) - Core Arduino framework
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - Logging functionality
|
||||
- [ModbusTCP](../src/modbus/ModbusTCP.h) - Modbus TCP implementation
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
POT --> Component
|
||||
POT --> ArduinoLog
|
||||
POT --> ModbusTCP
|
||||
Component --> ArduinoLog
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The POT component reads analog values at a configurable interval, applies filtering based on the selected algorithm, and exposes the value through Modbus registers. It supports two control modes: Local (reading from the physical potentiometer) and Remote (accepting values through Modbus).
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup
|
||||
Setup --> Idle
|
||||
Idle --> ReadAnalog: Sample Interval Elapsed
|
||||
ReadAnalog --> ApplyFilter
|
||||
ApplyFilter --> CheckMode
|
||||
|
||||
CheckMode --> LocalMode: Mode == Local
|
||||
CheckMode --> RemoteMode: Mode == Remote
|
||||
|
||||
LocalMode --> ApplyDeadband
|
||||
RemoteMode --> UpdateFromModbus
|
||||
|
||||
ApplyDeadband --> ValueChanged
|
||||
UpdateFromModbus --> ValueChanged
|
||||
|
||||
ValueChanged --> NotifyStateChange: Value Changed
|
||||
ValueChanged --> Idle: No Change
|
||||
NotifyStateChange --> Idle
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing interrupt-based sampling for more precise timing
|
||||
- Evaluate filter performance with high-frequency noise
|
||||
- Profile performance impact of different filter algorithms on various platforms
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add range validation for Modbus-supplied remote values
|
||||
- Consider authentication for mode switching between local and remote control
|
||||
- Implement rate limiting for remote value changes
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Verify ADC reading methods across different platforms for consistent behavior
|
||||
- Ensure proper error handling for edge cases (e.g., disconnected potentiometer)
|
||||
- Document requirements for electrical compliance (input voltage ranges, etc.)
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use the hardware RC filter recommendation provided in the component header:
|
||||
- For 5kΩ potentiometer: Add 1-3.3µF capacitor between wiper and ground
|
||||
- Adjust capacitor value based on desired cutoff frequency and noise conditions
|
||||
- Start with the EMA filter for most applications as it provides good smoothing with minimal resources
|
||||
- For applications requiring precise readings, increase the sampling rate and adjust the filtering parameters
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example shows how to initialize and use a POT component with an ESP32:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_ANALOG_0
|
||||
pot_0 = new POT(
|
||||
this, // owner
|
||||
PIN_ANALOG_0, // pin
|
||||
COMPONENT_KEY_ANALOG_0, // id
|
||||
MB_ANALOG_0, // modbusAddress
|
||||
POTDampingAlgorithm::DAMPING_EMA // filtering algorithm
|
||||
);
|
||||
|
||||
if (pot_0)
|
||||
{
|
||||
components.push_back(pot_0);
|
||||
Log.infoln(F("POT_0 initialized. Pin:%d, ID:%d, MB:%d"),
|
||||
PIN_ANALOG_0, COMPONENT_KEY_ANALOG_0, MB_ANALOG_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("POT_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
For more information on analog filtering techniques and implementation details, refer to the following resources:
|
||||
|
||||
- [ESP32 ADC Documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html)
|
||||
- [Digital Filtering Basics](https://www.analog.com/media/en/technical-documentation/dsp-book/dsp_book_Ch8.pdf)
|
||||
- [Exponential Moving Average (EMA) Overview](https://www.investopedia.com/terms/e/ema.asp)
|
||||
-165
@@ -1,165 +0,0 @@
|
||||
---
|
||||
title: "Plunger Component"
|
||||
description: "Documentation for the Plunger component that controls plunging operations with a SAKO VFD"
|
||||
keywords: ["plunger", "VFD", "SAKO", "filling", "industrial", "component", "ESP32"]
|
||||
---
|
||||
|
||||
# Plunger
|
||||
|
||||
**Path**: [src/components/Plunger.cpp](../src/components/Plunger.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Plunger component provides control for a plunger mechanism driven by a SAKO Variable Frequency Drive (VFD). It manages plunging, homing, filling operations, and detects jams through current monitoring. The component supports both manual joystick control and automated operational modes.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Hardware
|
||||
- SAKO Variable Frequency Drive (VFD)
|
||||
- Joystick for manual control
|
||||
- Two potentiometers (POTs):
|
||||
- Speed POT for controlling plunging speed
|
||||
- Torque POT for controlling jam sensitivity
|
||||
- ESP32 with appropriate GPIO pins for interfaces
|
||||
|
||||
### Configuration
|
||||
- Plunger component uses the component ID 760 (`PLUNGER_COMPONENT_ID`)
|
||||
- Modbus base address is configured using `COMPONENT_KEY_PLUNGER` (670)
|
||||
- VFD must be properly configured to report current values
|
||||
|
||||
## Features
|
||||
|
||||
- **Manual Control**: Direct joystick-based plunger movement control
|
||||
- **Automatic Operations**: Timed automatic plunging and homing
|
||||
- **Record and Replay**: Ability to record plunging operations and replay them (up to 20 seconds)
|
||||
- **Filling Cycle**: Automated fill procedure with configurable parameters
|
||||
- **Post-Flow Control**: Additional material flow control after main operations
|
||||
- **Jam Detection**: Current-based jam detection with automatic recovery
|
||||
- **Modbus Interface**: Remote control and monitoring via Modbus TCP
|
||||
- **Configurable Settings**: Adjustable speed, current thresholds, and timing parameters
|
||||
- **Persistence**: Settings can be saved to and loaded from JSON files
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [SAKO_VFD](./SAKO_VFD.md) - Controls the Variable Frequency Drive
|
||||
- [Joystick](./Joystick.md) - Provides manual control input
|
||||
- [POT](./POT.md) - Analog inputs for speed and torque control
|
||||
- [Component](./Component.md) - Base component class
|
||||
- [ModbusTCP](./ModbusTCP.md) - For Modbus communication
|
||||
- [ArduinoJson](https://arduinojson.org/) - For settings management
|
||||
- [PlungerSettings](./PlungerSettings.md) - Configuration parameters
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Plunger --> SAKO_VFD
|
||||
Plunger --> Joystick
|
||||
Plunger --> POT
|
||||
Plunger --> Component
|
||||
Plunger --> ModbusTCP
|
||||
Plunger --> PlungerSettings
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The Plunger component implements a state machine that manages different operational states:
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
IDLE --> HOMING_MANUAL: Joystick DOWN
|
||||
IDLE --> PLUNGING_MANUAL: Joystick UP
|
||||
IDLE --> RECORD: Hold Joystick RIGHT
|
||||
IDLE --> FILLING: Hold Joystick LEFT
|
||||
IDLE --> REPLAY: Command
|
||||
|
||||
HOMING_MANUAL --> HOMING_AUTO: Hold time reached
|
||||
HOMING_MANUAL --> IDLE: Joystick released
|
||||
HOMING_AUTO --> IDLE: Complete/Stop
|
||||
|
||||
PLUNGING_MANUAL --> PLUNGING_AUTO: Hold time reached
|
||||
PLUNGING_MANUAL --> IDLE: Joystick released
|
||||
PLUNGING_AUTO --> IDLE: Complete/Stop
|
||||
|
||||
PLUNGING_AUTO --> POST_FLOW: Enable post-flow
|
||||
POST_FLOW --> IDLE: Complete
|
||||
|
||||
PLUNGING_AUTO --> JAMMED: High current
|
||||
HOMING_AUTO --> JAMMED: High current
|
||||
JAMMED --> RESETTING_JAM: Auto-recovery
|
||||
RESETTING_JAM --> IDLE: Reset complete
|
||||
|
||||
RECORD --> IDLE: Complete/Stop
|
||||
REPLAY --> IDLE: Complete/Stop
|
||||
|
||||
FILLING --> IDLE: Complete/Stop
|
||||
|
||||
STOPPING --> IDLE: VFD stopped
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider optimizing the current monitoring frequency to reduce CPU load
|
||||
- Evaluate the need for additional filtering of current readings to avoid false jam detections
|
||||
- Profile the performance impact of JSON operations for settings management
|
||||
- Optimize state transition logic to reduce processing overhead
|
||||
|
||||
### Security
|
||||
|
||||
- Implement validation of Modbus command values to prevent unexpected operations
|
||||
- Consider adding authentication for settings modification via REST API
|
||||
- Ensure proper bounds checking for all user-configurable parameters
|
||||
- Add protection against invalid state transitions triggered by external commands
|
||||
|
||||
### Compliance
|
||||
|
||||
- Verify compliance with relevant industrial safety standards for automated machinery
|
||||
- Ensure emergency stop functionality meets IEC 60204-1 requirements
|
||||
- Consider implementing logging for operational data to support audit requirements
|
||||
- Add failure mode analysis and redundant safety mechanisms
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Implement a calibration procedure for current thresholds based on actual plunger load
|
||||
- Consider adding temperature monitoring to detect VFD overheating
|
||||
- Add additional sensor inputs (e.g., limit switches) for improved position feedback
|
||||
- Implement more sophisticated jam detection based on current trend analysis rather than fixed thresholds
|
||||
- Consider expanding the configuration options to support different materials and plunger sizes
|
||||
- Add persistent logging of jam events to identify patterns
|
||||
|
||||
## Example
|
||||
|
||||
This example shows how to initialize the Plunger component in a system:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_PLUNGER
|
||||
// Check if required components are available
|
||||
if (sakoVfd && joystick && speedPot && torquePot) {
|
||||
plunger = new Plunger(
|
||||
this, // owner
|
||||
sakoVfd, // VFD controller
|
||||
joystick, // joystick for manual control
|
||||
speedPot, // POT for speed control
|
||||
torquePot // POT for torque/jam sensitivity
|
||||
);
|
||||
|
||||
if (plunger) {
|
||||
components.push_back(plunger);
|
||||
Log.infoln(F("Plunger initialized with VFD, Joystick, and POTs"));
|
||||
|
||||
// Load stored settings or use defaults
|
||||
plunger->loadDefaultSettings();
|
||||
} else {
|
||||
Log.errorln(F("Plunger initialization failed."));
|
||||
}
|
||||
} else {
|
||||
Log.warningln(F("Plunger not initialized - missing required components."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
---
|
||||
title: RS485 Component
|
||||
description: Documentation for the RS485 component that provides Modbus RTU communication over RS-485 serial protocol
|
||||
keywords: [RS485, Modbus, RTU, serial, industrial communication, ESP32]
|
||||
---
|
||||
|
||||
# RS485
|
||||
|
||||
**Path**: [`src/RS485.cpp`](../src/RS485.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The RS485 component provides Modbus RTU master functionality for industrial communications over the RS-485 serial protocol. It enables communication with various industrial devices that support the Modbus RTU protocol and acts as an interface between these devices and the internal system components.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- RS-485 transceiver (typically integrated on ESP32 industrial boards)
|
||||
- Properly wired RS-485 network (A/B/GND connections)
|
||||
|
||||
### Software
|
||||
- ModbusClientRTU library for Modbus RTU communication
|
||||
- ModbusRTU and ModbusTypes dependencies
|
||||
- Configuration settings in config-modbus.h
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Modbus RTU master implementation
|
||||
- Integration with Modbus TCP for remote access to RTU devices
|
||||
- Device management for multiple slave devices
|
||||
- Register read/write operations
|
||||
- Register change notifications
|
||||
- Periodic device polling
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](./Component.md) - Base class for all components
|
||||
- [ModbusTCP](./ModbusTCP.md) - For Modbus TCP to RTU bridging
|
||||
- [ModbusBlockView](./ModbusBlockView.md) - For register organization and access
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - For logging capabilities
|
||||
- [ModbusClientRTU](https://github.com/eModbus/eModbus) - For Modbus RTU communication
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
RS485 --> Component
|
||||
RS485 --> ModbusRTU
|
||||
RS485 --> ModbusTCP
|
||||
RS485 --> ModbusBlockView
|
||||
RS485 --> Manager
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The RS485 component initializes during setup and then periodically polls connected devices in its loop function. It also handles Modbus TCP requests by translating them to RTU operations and manages the communication with the RTU slave devices.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialization
|
||||
Initialization --> Ready
|
||||
Ready --> ProcessingTcpRequests: TCP Request Received
|
||||
Ready --> PollingDevices: Timer Triggered
|
||||
ProcessingTcpRequests --> Ready: Response Sent
|
||||
PollingDevices --> Ready: Polling Complete
|
||||
Ready --> HandleRegisterChange: Register Changed
|
||||
HandleRegisterChange --> Ready
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Optimize polling frequency based on device response times
|
||||
- Implement more efficient register caching to reduce network traffic
|
||||
- Consider batch operations for multiple registers to improve throughput
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement proper error handling for malformed Modbus packets
|
||||
- Consider adding CRC validation for extra reliability
|
||||
- Implement timeout handling for unresponsive devices
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with Modbus RTU specification
|
||||
- Validate against industrial standards for RS-485 communication
|
||||
- Test with different vendor implementations for compatibility
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use proper RS-485 termination resistors on the physical network
|
||||
- Configure appropriate timeouts based on network complexity and device count
|
||||
- Implement error recovery mechanisms for robust operation
|
||||
- Use shielded twisted pair cables for RS-485 connections in noisy environments
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
Below is an example of how the RS485 component might be constructed and mounted in an application:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_RS485
|
||||
rs485 = new RS485(
|
||||
this // owner
|
||||
);
|
||||
if (rs485)
|
||||
{
|
||||
components.push_back(rs485);
|
||||
Log.infoln(F("RS485 initialized."));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("RS485 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [Modbus RTU Specification](https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf)
|
||||
- [ESP32 Serial Interface Documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/uart.html)
|
||||
-111
@@ -1,111 +0,0 @@
|
||||
---
|
||||
title: Relay Component
|
||||
description: A digital output component for controlling relays via GPIO pins with Modbus integration
|
||||
keywords: relay, GPIO, digital output, modbus, coil
|
||||
---
|
||||
|
||||
# Relay
|
||||
|
||||
**Path**: [`src/components/Relay.h`](../src/components/Relay.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The Relay component provides a simple interface for controlling digital outputs typically connected to relays. It supports toggling the state of a GPIO pin between HIGH and LOW and exposes this functionality through both a programmatic API and Modbus integration.
|
||||
|
||||
## Requirements
|
||||
|
||||
- A GPIO pin capable of digital output
|
||||
- Properly configured hardware relay circuitry
|
||||
- Modbus TCP server (if using Modbus control)
|
||||
|
||||
## Features
|
||||
|
||||
- Simple ON/OFF control of a digital output pin
|
||||
- State change notifications
|
||||
- Full Modbus integration via coil operations
|
||||
- Serial bridge command interface
|
||||
- Thread-safe operation
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Component](./Component.md) - Base class for all components
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - Logging facility
|
||||
- [Modbus](./Modbus.md) - Modbus protocol support
|
||||
- [ModbusTCP](./ModbusTCP.md) - Modbus TCP implementation
|
||||
- [Bridge](./Bridge.md) - Serial command interface
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Relay --> Component
|
||||
Relay --> ArduinoLog
|
||||
Relay --> Modbus
|
||||
Relay --> ModbusTCP
|
||||
Relay --> Bridge
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The Relay component maintains a simple state machine that toggles between ON and OFF states. State changes can be triggered by direct method calls, Modbus commands, or serial bridge commands.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> OFF: Initialize
|
||||
OFF --> ON: setValue(true) / Modbus Write Coil(1)
|
||||
ON --> OFF: setValue(false) / Modbus Write Coil(0)
|
||||
ON --> ON: setValue(true) / No Change
|
||||
OFF --> OFF: setValue(false) / No Change
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider adding pulse mode functionality for timed relay activation
|
||||
- Implement debounce or rate limiting for rapidly changing states
|
||||
|
||||
### Security
|
||||
|
||||
- Add authentication for critical relay operations
|
||||
- Implement secure state persistence across power cycles
|
||||
|
||||
### Compliance
|
||||
|
||||
- Ensure proper handling of inductive loads to prevent electrical hazards
|
||||
- Add electrical certification compliance documentation if used in industrial applications
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Use external protection circuitry for high-current or inductive loads
|
||||
- Implement a heartbeat mechanism to ensure relay states are as expected
|
||||
- Consider adding fault detection for relay feedback
|
||||
|
||||
## Example
|
||||
|
||||
Below is an example of how to initialize and use a Relay component:
|
||||
|
||||
```cpp
|
||||
#ifdef GPIO_PIN_CH1
|
||||
relay_0 = new Relay(
|
||||
this, // owner
|
||||
GPIO_PIN_CH1, // pin
|
||||
COMPONENT_KEY_RELAY_0, // id
|
||||
MB_RELAY_0_ADDR // modbusAddress
|
||||
);
|
||||
if (relay_0)
|
||||
{
|
||||
components.push_back(relay_0);
|
||||
Log.infoln(F("Relay_0 initialized. Pin:%d, ID:%d, MB:%d"),
|
||||
GPIO_PIN_CH1, COMPONENT_KEY_RELAY_0, MB_RELAY_0_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("Relay_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
@@ -1,133 +0,0 @@
|
||||
---
|
||||
title: RestServer Component
|
||||
description: RESTful API server implementation for ESP32 with WebSocket support
|
||||
keywords: [REST API, WebSocket, ESP32, Modbus, AsyncWebServer]
|
||||
---
|
||||
|
||||
## RestServer
|
||||
|
||||
**Path**: [`src/components/RestServer.h`](../src/components/RestServer.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The RestServer component implements a RESTful API server that interfaces with the Modbus system. It provides HTTP endpoints for accessing and manipulating Modbus registers and coils, as well as WebSocket functionality for real-time communication with clients.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- ESP32 microcontroller
|
||||
- WiFi connectivity
|
||||
|
||||
### Software
|
||||
- Arduino core for ESP32
|
||||
- AsyncWebServer library
|
||||
- AsyncJSON library
|
||||
- ArduinoJSON library
|
||||
- AsyncTCP library
|
||||
- LittleFS for serving static files
|
||||
|
||||
## FEATURES
|
||||
|
||||
- RESTful API endpoints for Modbus system interaction
|
||||
- WebSocket support for real-time data updates
|
||||
- System information retrieval
|
||||
- Modbus coil and register access and manipulation
|
||||
- Log level configuration
|
||||
- File system browsing capabilities
|
||||
- Static file serving from LittleFS
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](../src/Component.h) - Base class for component functionality
|
||||
- [Bridge](../src/Bridge.h) - Communication interface
|
||||
- [ModbusTCP](../src/ModbusTCP.h) - Modbus TCP implementation
|
||||
- [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) - Asynchronous web server library
|
||||
- [ArduinoJSON](https://arduinojson.org/) - JSON parsing and creation library
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
RestServer --> Component
|
||||
RestServer --> Bridge
|
||||
RestServer --> ModbusTCP
|
||||
RestServer --> AsyncWebServer
|
||||
RestServer --> ArduinoJSON
|
||||
RestServer --> AsyncTCP
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The RestServer component initializes an AsyncWebServer and sets up various RESTful API endpoints. When WebSocket support is enabled, it also initializes an AsyncWebSocket server for real-time communication.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup
|
||||
Setup --> Running: setup()
|
||||
Running --> ProcessRequests: loop()
|
||||
ProcessRequests --> Running
|
||||
Running --> BroadcastUpdates: WebSocket event
|
||||
BroadcastUpdates --> Running
|
||||
Running --> HandleMessage: onMessage()
|
||||
HandleMessage --> Running
|
||||
```
|
||||
|
||||
The component responds to HTTP requests for system information, Modbus coil/register access, and file system operations. When WebSocket is enabled, it broadcasts updates to connected clients in real-time.
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing caching mechanisms for frequently accessed data
|
||||
- Optimize JSON document size based on actual needs
|
||||
- Investigate memory usage during peak concurrent connections
|
||||
- Consider implementing pagination for large data sets
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement authentication for API access
|
||||
- Consider HTTPS support for secure communication
|
||||
- Add rate limiting to prevent abuse
|
||||
- Implement input validation for all API endpoints
|
||||
- Consider implementing CORS protection
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure GDPR compliance for any data collected
|
||||
- Follow RESTful API best practices
|
||||
- Document API endpoints using OpenAPI/Swagger specification
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use environment variables or configuration files for server settings
|
||||
- Implement proper error handling and logging
|
||||
- Consider implementing API versioning
|
||||
- Separate API logic from server implementation for better maintainability
|
||||
- Provide client-side libraries or SDK for easier integration
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
The following example shows how to initialize and mount the RestServer component:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_REST_SERVER
|
||||
IPAddress localIP = WiFi.localIP();
|
||||
restServer = new RESTServer(
|
||||
localIP, // IP address
|
||||
80, // Port
|
||||
modbusTCPServer, // ModbusTCP manager
|
||||
this // Owner component
|
||||
);
|
||||
if (restServer) {
|
||||
components.push_back(restServer);
|
||||
Log.infoln(F("RESTServer initialized. IP:%s, Port:%d"),
|
||||
localIP.toString().c_str(), 80);
|
||||
} else {
|
||||
Log.errorln(F("RESTServer initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
@@ -1,134 +0,0 @@
|
||||
---
|
||||
title: SAKO VFD Component
|
||||
description: Documentation for the SAKO Variable Frequency Drive component interface
|
||||
keywords: [VFD, SAKO, RS485, Modbus, frequency, motor control]
|
||||
---
|
||||
|
||||
# SAKO VFD
|
||||
|
||||
**Path**: [`src/components/SAKO_VFD.cpp`](../src/components/SAKO_VFD.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The SAKO_VFD component provides an interface for controlling and monitoring SAKO Variable Frequency Drives over RS485 using Modbus RTU protocol. It enables setting frequency, controlling motor direction, reading operational status, and retrieving fault information.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- ESP32 or compatible microcontroller
|
||||
- RS485 transceiver hardware
|
||||
- SAKO VFD connected to RS485 bus
|
||||
|
||||
### Software
|
||||
- ENABLE_RS485 flag must be defined in config.h
|
||||
- ModbusRTU library for communication
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Control motor speed by setting frequency in 0.01 Hz units
|
||||
- Start and stop motor operation
|
||||
- Change motor direction (forward/reverse)
|
||||
- Monitor operational parameters:
|
||||
- Current frequency
|
||||
- Set frequency
|
||||
- Output current
|
||||
- Output power (kW)
|
||||
- Output torque percentage
|
||||
- Read VFD status and fault codes
|
||||
- Automatic retract operation with state machine
|
||||
- Integration with Modbus TCP for remote control
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](../src/Component.h) - Base component functionality
|
||||
- [ModbusRTU](../src/modbus/ModbusRTU.h) - RS485 Modbus communication
|
||||
- [ModbusTypes](../src/modbus/ModbusTypes.h) - Modbus data type definitions
|
||||
- [xstatistics](../src/xstatistics.h) - Statistics collection for VFD parameters
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
SAKOVFD[SAKO_VFD] --> RTUBase[RTU_Base]
|
||||
RTUBase --> Component[Component]
|
||||
SAKOVFD --> ModbusRTU[ModbusRTU]
|
||||
SAKOVFD --> Statistics[xstatistics]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Stopped
|
||||
Stopped --> Accelerating: run()
|
||||
Accelerating --> Running
|
||||
Running --> Decelerating: stop()
|
||||
Decelerating --> Stopped
|
||||
Running --> Reversing: reverse()
|
||||
Reversing --> Running
|
||||
Error --> Stopped: resetFault()
|
||||
Stopped --> Retract: retract()
|
||||
Retract --> Braking
|
||||
Braking --> ReverseStopped
|
||||
ReverseStopped --> Reversing
|
||||
Reversing --> BrakeReversing
|
||||
BrakeReversing --> Retracted
|
||||
Retracted --> [*]
|
||||
|
||||
state Error {
|
||||
[*] --> FaultCode
|
||||
}
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing a more efficient polling mechanism for less critical parameters
|
||||
- Add caching of VFD parameters with configurable refresh rates
|
||||
- Implement rate limiting for write operations to prevent overloading the RS485 bus
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Add validation for input values before sending to the VFD
|
||||
- Implement error handling for unexpected responses from the VFD
|
||||
- Consider adding authentication for control operations
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with industrial standards for VFD control
|
||||
- Add proper error handling and recovery mechanisms
|
||||
- Implement data logging for compliance with maintenance requirements
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Set appropriate read intervals based on system requirements
|
||||
- Implement proper error handling for Modbus communication failures
|
||||
- Consider adding more advanced control features like PID control for motor speed
|
||||
- Use statistics tracking to monitor performance and detect potential issues
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example shows how to initialize and mount a SAKO_VFD component in a system:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_SAKO_VFD
|
||||
sakoVFD = new SAKO_VFD(
|
||||
MB_SAKO_VFD_SLAVE_ID, // Modbus slave ID of the VFD
|
||||
MB_SAKO_VFD_READ_INTERVAL // Polling interval in milliseconds
|
||||
);
|
||||
if (sakoVFD)
|
||||
{
|
||||
components.push_back(sakoVFD);
|
||||
Log.infoln(F("SAKO VFD initialized. SlaveID:%d, ReadInterval:%d ms"),
|
||||
MB_SAKO_VFD_SLAVE_ID, MB_SAKO_VFD_READ_INTERVAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("SAKO VFD initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- SAKO VFD User Manual (refer to manufacturer documentation)
|
||||
- Modbus RTU specification for register definitions
|
||||
@@ -1,409 +0,0 @@
|
||||
---
|
||||
title: "SerialMessage Component"
|
||||
description: "Serial communication component for handling command message parsing and processing"
|
||||
keywords: ["serial", "communication", "command", "message", "parsing", "ESP32", "Modbus", "industrial"]
|
||||
---
|
||||
|
||||
## SerialMessage
|
||||
|
||||
**Path**: [`src/SerialMessage.cpp`](../src/SerialMessage.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A serial communication component that handles reading, parsing, and processing of command messages from a serial stream. This component provides buffered serial communication with configurable message parsing intervals for industrial applications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- Serial communication interface (UART)
|
||||
- No specific pin requirements (uses provided Stream object)
|
||||
|
||||
### Software Dependencies
|
||||
- ArduinoLog library for logging
|
||||
- Vector library for data structures
|
||||
- Arduino Stream interface
|
||||
- Component base class
|
||||
|
||||
### Configuration
|
||||
- `SERIAL_RX_BUFFER_SIZE`: Receive buffer size (default: 256 bytes)
|
||||
- `SERIAL_COMMAND_PARSE_INTERVAL`: Message parsing interval (default: 50ms)
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Buffered serial message reading
|
||||
- Command message parsing and validation
|
||||
- Configurable message delimiters
|
||||
- Serial connection status tracking
|
||||
- Debug message handling with hex output
|
||||
- Non-blocking message processing
|
||||
- Integration with Component architecture
|
||||
- Owner notification system for parsed messages
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`Component`](./Component.md) - Base component class
|
||||
- [`CommandMessage`](./CommandMessage.md) - Message structure and parsing
|
||||
- **ArduinoLog** - Logging functionality
|
||||
- **Vector** - Data structure library
|
||||
- **Arduino Stream** - Serial communication interface
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
SerialMessage --> Component
|
||||
SerialMessage --> CommandMessage
|
||||
SerialMessage --> ArduinoLog
|
||||
SerialMessage --> Stream
|
||||
Component --> Owner[Owner Component]
|
||||
CommandMessage --> MessageParsing[Message Parsing Logic]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup
|
||||
Setup --> Idle
|
||||
Idle --> CheckInterval: loop()
|
||||
CheckInterval --> ReadMessage: interval elapsed
|
||||
CheckInterval --> Idle: interval not elapsed
|
||||
ReadMessage --> ParseMessage: message available
|
||||
ReadMessage --> Idle: no message
|
||||
ParseMessage --> ValidateMessage: parsing successful
|
||||
ParseMessage --> Idle: parsing failed
|
||||
ValidateMessage --> NotifyOwner: message valid
|
||||
ValidateMessage --> Idle: message invalid
|
||||
NotifyOwner --> Idle: owner notified
|
||||
Idle --> [*]: component destroyed
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing circular buffer for improved memory efficiency
|
||||
- Optimize string operations to reduce memory fragmentation
|
||||
- Implement message queuing for high-frequency communication
|
||||
- Add configurable buffer overflow handling
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement message authentication for command validation
|
||||
- Add input sanitization for malformed messages
|
||||
- Consider implementing rate limiting for message processing
|
||||
- Add checksum validation for message integrity
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with Modbus serial communication standards
|
||||
- Implement proper error handling according to industrial communication protocols
|
||||
- Add support for standard industrial message formats
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use hardware serial interfaces for better reliability
|
||||
- Configure appropriate baud rates for industrial environments
|
||||
- Implement proper error recovery mechanisms
|
||||
- Consider using DMA for high-speed serial communication
|
||||
- Add message statistics and monitoring capabilities
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This section illustrates how the SerialMessage component is constructed and mounted:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_SERIAL_COMMANDS
|
||||
serialMessage = new SerialMessage(
|
||||
Serial, // stream (Hardware Serial)
|
||||
this // owner component
|
||||
);
|
||||
if (serialMessage)
|
||||
{
|
||||
components.push_back(serialMessage);
|
||||
Log.infoln(F("SerialMessage initialized. Stream: Hardware Serial"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("SerialMessage initialization failed."));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Alternative with Serial1 for RS485 communication
|
||||
#ifdef ENABLE_RS485_SERIAL
|
||||
rs485SerialMessage = new SerialMessage(
|
||||
Serial1, // stream (Hardware Serial1)
|
||||
this // owner component
|
||||
);
|
||||
if (rs485SerialMessage)
|
||||
{
|
||||
components.push_back(rs485SerialMessage);
|
||||
Log.infoln(F("RS485 SerialMessage initialized. Stream: Hardware Serial1"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("RS485 SerialMessage initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### Message Handling Example
|
||||
|
||||
```cpp
|
||||
// Owner component implements onMessage to handle parsed commands
|
||||
void MyComponent::onMessage(uint16_t id, uint8_t verb, uint8_t flags,
|
||||
const String& payload, Component* sender)
|
||||
{
|
||||
if (sender == serialMessage)
|
||||
{
|
||||
Log.infoln(F("Received serial command: ID=%d, Verb=%d, Payload=%s"),
|
||||
id, verb, payload.c_str());
|
||||
|
||||
// Process the command based on ID and verb
|
||||
switch (id)
|
||||
{
|
||||
case COMMAND_SET_CONFIG:
|
||||
handleConfigCommand(verb, flags, payload);
|
||||
break;
|
||||
case COMMAND_GET_STATUS:
|
||||
handleStatusRequest(verb, flags, payload);
|
||||
break;
|
||||
default:
|
||||
Log.warningln(F("Unknown command ID: %d"), id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
</parameter>
|
||||
</invoke>
|
||||
|
||||
<invoke name="str_replace_editor">
|
||||
<parameter name="command">str_replace</parameter>
|
||||
<parameter name="path">./docs/SerialMessage.md</parameter>
|
||||
<parameter name="old_str">Now I'll create the documentation file for the SerialMessage component.
|
||||
|
||||
<invoke name="str_replace_editor">
|
||||
<parameter name="command">create</parameter>
|
||||
<parameter name="path">./docs/SerialMessage.md</parameter>
|
||||
<parameter name="file_text">---
|
||||
title: "SerialMessage Component"
|
||||
description: "Serial communication component for handling command message parsing and processing"
|
||||
keywords: ["serial", "communication", "command", "message", "parsing", "ESP32", "Modbus", "industrial"]
|
||||
---
|
||||
|
||||
## SerialMessage
|
||||
|
||||
**Path**: [`src/SerialMessage.cpp`](../src/SerialMessage.cpp)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A serial communication component that handles reading, parsing, and processing of command messages from a serial stream. This component provides buffered serial communication with configurable message parsing intervals for industrial applications.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
### Hardware
|
||||
- Serial communication interface (UART)
|
||||
- No specific pin requirements (uses provided Stream object)
|
||||
|
||||
### Software Dependencies
|
||||
- ArduinoLog library for logging
|
||||
- Vector library for data structures
|
||||
- Arduino Stream interface
|
||||
- Component base class
|
||||
|
||||
### Configuration
|
||||
- `SERIAL_RX_BUFFER_SIZE`: Receive buffer size (default: 256 bytes)
|
||||
- `SERIAL_COMMAND_PARSE_INTERVAL`: Message parsing interval (default: 50ms)
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Buffered serial message reading
|
||||
- Command message parsing and validation
|
||||
- Configurable message delimiters
|
||||
- Serial connection status tracking
|
||||
- Debug message handling with hex output
|
||||
- Non-blocking message processing
|
||||
- Integration with Component architecture
|
||||
- Owner notification system for parsed messages
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [`Component`](./Component.md) - Base component class
|
||||
- [`CommandMessage`](./CommandMessage.md) - Message structure and parsing
|
||||
- **ArduinoLog** - Logging functionality
|
||||
- **Vector** - Data structure library
|
||||
- **Arduino Stream** - Serial communication interface
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
SerialMessage --> Component
|
||||
SerialMessage --> CommandMessage
|
||||
SerialMessage --> ArduinoLog
|
||||
SerialMessage --> Stream
|
||||
Component --> Owner[Owner Component]
|
||||
CommandMessage --> MessageParsing[Message Parsing Logic]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Setup
|
||||
Setup --> Idle
|
||||
Idle --> CheckInterval: loop()
|
||||
CheckInterval --> ReadMessage: interval elapsed
|
||||
CheckInterval --> Idle: interval not elapsed
|
||||
ReadMessage --> ParseMessage: message available
|
||||
ReadMessage --> Idle: no message
|
||||
ParseMessage --> ValidateMessage: parsing successful
|
||||
ParseMessage --> Idle: parsing failed
|
||||
ValidateMessage --> NotifyOwner: message valid
|
||||
ValidateMessage --> Idle: message invalid
|
||||
NotifyOwner --> Idle: owner notified
|
||||
Idle --> [*]: component destroyed
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider implementing circular buffer for improved memory efficiency
|
||||
- Optimize string operations to reduce memory fragmentation
|
||||
- Implement message queuing for high-frequency communication
|
||||
- Add configurable buffer overflow handling
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement message authentication for command validation
|
||||
- Add input sanitization for malformed messages
|
||||
- Consider implementing rate limiting for message processing
|
||||
- Add checksum validation for message integrity
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Ensure compliance with Modbus serial communication standards
|
||||
- Implement proper error handling according to industrial communication protocols
|
||||
- Add support for standard industrial message formats
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use hardware serial interfaces for better reliability
|
||||
- Configure appropriate baud rates for industrial environments
|
||||
- Implement proper error recovery mechanisms
|
||||
- Consider using DMA for high-speed serial communication
|
||||
- Add message statistics and monitoring capabilities
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This section illustrates how the SerialMessage component is constructed and mounted:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_SERIAL_COMMANDS
|
||||
serialMessage = new SerialMessage(
|
||||
Serial, // stream (Hardware Serial)
|
||||
this // owner component
|
||||
);
|
||||
if (serialMessage)
|
||||
{
|
||||
components.push_back(serialMessage);
|
||||
Log.infoln(F("SerialMessage initialized. Stream: Hardware Serial"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("SerialMessage initialization failed."));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Alternative with Serial1 for RS485 communication
|
||||
#ifdef ENABLE_RS485_SERIAL
|
||||
rs485SerialMessage = new SerialMessage(
|
||||
Serial1, // stream (Hardware Serial1)
|
||||
this // owner component
|
||||
);
|
||||
if (rs485SerialMessage)
|
||||
{
|
||||
components.push_back(rs485SerialMessage);
|
||||
Log.infoln(F("RS485 SerialMessage initialized. Stream: Hardware Serial1"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("RS485 SerialMessage initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### Message Handling Example
|
||||
|
||||
```cpp
|
||||
// Owner component implements onMessage to handle parsed commands
|
||||
void MyComponent::onMessage(uint16_t id, uint8_t verb, uint8_t flags,
|
||||
const String& payload, Component* sender)
|
||||
{
|
||||
if (sender == serialMessage)
|
||||
{
|
||||
Log.infoln(F("Received serial command: ID=%d, Verb=%d, Payload=%s"),
|
||||
id, verb, payload.c_str());
|
||||
|
||||
// Process the command based on ID and verb
|
||||
switch (id)
|
||||
{
|
||||
case COMMAND_SET_CONFIG:
|
||||
handleConfigCommand(verb, flags, payload);
|
||||
break;
|
||||
case COMMAND_GET_STATUS:
|
||||
handleStatusRequest(verb, flags, payload);
|
||||
break;
|
||||
default:
|
||||
Log.warningln(F("Unknown command ID: %d"), id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
</parameter>
|
||||
</invoke>
|
||||
|
||||
<invoke name="str_replace_editor">
|
||||
<parameter name="command">str_replace</parameter>
|
||||
<parameter name="path">./docs/SerialMessage.md</parameter>
|
||||
<parameter name="old_str">Now I'll create the documentation file for the SerialMessage component.</parameter>
|
||||
<parameter name="new_str"></parameter>
|
||||
</invoke>
|
||||
|
||||
The documentation has been successfully created! Here's a summary of what was generated:
|
||||
|
||||
## SerialMessage Component Documentation
|
||||
|
||||
The documentation file has been created at `./docs/SerialMessage.md` with the following key sections:
|
||||
|
||||
### Key Features Documented:
|
||||
- **Serial Communication**: Handles reading and parsing of command messages from serial streams
|
||||
- **Buffered Processing**: Uses configurable buffer size and parsing intervals
|
||||
- **Message Validation**: Parses and validates incoming command messages
|
||||
- **Owner Notification**: Integrates with the Component architecture to notify owners of parsed messages
|
||||
|
||||
### Technical Details:
|
||||
- **Requirements**: Hardware serial interface, various software dependencies
|
||||
- **Configuration**: Configurable buffer size (256 bytes default) and parsing interval (50ms default)
|
||||
- **Dependencies**: Component base class, CommandMessage, ArduinoLog, Vector library
|
||||
- **Behavior**: State machine showing message processing flow
|
||||
|
||||
### Documentation Structure:
|
||||
- Standard frontmatter for Astro static site generator
|
||||
- Comprehensive feature list and requirements
|
||||
- Mermaid diagrams for dependencies and behavior
|
||||
- TODO sections covering performance, security, compliance, and recommendations
|
||||
- Practical examples showing component construction and message handling
|
||||
|
||||
The documentation is ready for use in an Astro static site and follows all the specified formatting requirements including proper Markdown linting standards.
|
||||
@@ -1,113 +0,0 @@
|
||||
---
|
||||
title: "StatusLight Component"
|
||||
description: "A component for controlling and monitoring status lights with blinking capability"
|
||||
keywords: ["status", "light", "LED", "feedback", "modbus", "blinking"]
|
||||
---
|
||||
|
||||
# StatusLight
|
||||
|
||||
**Path**: [`src/components/StatusLight.h`](../src/components/StatusLight.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The StatusLight component provides functionality to control and monitor status indicators such as LEDs. It supports three states: OFF, ON, and BLINKING, with configurable blinking intervals. It integrates with the Modbus system for remote monitoring and control.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Digital output pin for connecting the status light/LED
|
||||
- STATUS_BLINK_INTERVAL defined in configuration (default: 800ms)
|
||||
- Optional Modbus address for network control
|
||||
|
||||
## Features
|
||||
|
||||
- Three operation modes: OFF, ON, and BLINKING
|
||||
- Configurable blinking intervals
|
||||
- Modbus integration for remote monitoring and control
|
||||
- Serial bridge interface for local control
|
||||
- Automatic pin state management during state transitions
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Component](../src/Component.h) - Base class for all components
|
||||
- [Bridge](../src/Bridge.h) - For serial command interface
|
||||
- [ModbusTCP](../src/modbus/ModbusTCP.h) - For Modbus network integration
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
StatusLight --> Component
|
||||
StatusLight --> Bridge
|
||||
StatusLight --> ModbusTCP
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The StatusLight component manages a digital output pin with three possible states: OFF, ON, and BLINKING. When in BLINKING state, it toggles the output at the configured interval.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> OFF
|
||||
OFF --> ON: set(1)
|
||||
ON --> OFF: set(0)
|
||||
OFF --> BLINK: status_blink(true)
|
||||
ON --> BLINK: status_blink(true)
|
||||
BLINK --> OFF: status_blink(false) + state==OFF
|
||||
BLINK --> ON: status_blink(false) + state==ON
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider using non-blocking timers for more precise blinking intervals
|
||||
- Evaluate performance impact of continuous polling in the loop method
|
||||
|
||||
### Security
|
||||
|
||||
- Validate input parameters in public methods to prevent unexpected behavior
|
||||
- Consider adding authentication for Modbus write operations
|
||||
|
||||
### Compliance
|
||||
|
||||
- Ensure proper error handling for hardware failures
|
||||
- Add support for different blinking patterns for various status indications
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Use consistent addressing scheme when multiple status lights are used
|
||||
- Consider using PWM for dimming capability in future versions
|
||||
- When using with critical systems, consider adding a watchdog timer
|
||||
|
||||
## Example
|
||||
|
||||
The following example shows how to initialize and use a StatusLight component:
|
||||
|
||||
```cpp
|
||||
#ifdef STATUS_WARNING_PIN
|
||||
StatusLight* warningLight = new StatusLight(
|
||||
this, // owner
|
||||
STATUS_WARNING_PIN, // pin
|
||||
COMPONENT_KEY_FEEDBACK_0, // id
|
||||
MB_MONITORING_STATUS_FEEDBACK_0 // modbusAddress
|
||||
);
|
||||
if (warningLight)
|
||||
{
|
||||
components.push_back(warningLight);
|
||||
Log.infoln(F("Warning Status Light initialized. Pin:%d"), STATUS_WARNING_PIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("Warning Status Light initialization failed."));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Later in the code, control the status light:
|
||||
warningLight->on(); // Turn on the light
|
||||
warningLight->off(); // Turn off the light
|
||||
warningLight->setBlink(true); // Make it blink
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
@@ -1,129 +0,0 @@
|
||||
---
|
||||
title: StepperController Component
|
||||
description: A component for controlling stepper motors with AccelStepper library
|
||||
keywords: [stepper, motor, controller, modbus, hardware]
|
||||
---
|
||||
|
||||
# StepperController
|
||||
|
||||
**Path**: [`src/components/StepperController.h`](../src/components/StepperController.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The StepperController component provides an interface for controlling stepper motors using the AccelStepper library. It supports configuration of motor parameters such as speed, direction, and pulse width, and integrates with the Modbus system for remote control capabilities. The component monitors motor status including overload conditions.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Hardware
|
||||
- Direction pin (GPIO)
|
||||
- Pulse pin (GPIO)
|
||||
- Feedback pin (analog input, optional)
|
||||
- Overload pin (analog input, optional)
|
||||
|
||||
### Software
|
||||
- AccelStepper library
|
||||
- Arduino framework
|
||||
|
||||
## Features
|
||||
|
||||
- Configurable motor direction and rotation speed
|
||||
- Adjustable pulse width for motor stepping
|
||||
- Modbus integration for remote control
|
||||
- Motor status monitoring (running, idle, overload, error)
|
||||
- Overload detection using analog feedback
|
||||
- Speed clamping to prevent damage
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Component](../src/Component.h) - Base component class
|
||||
- [ModbusValue](../src/ModbusValue.h) - Modbus interface
|
||||
- [AccelStepper](https://www.airspayce.com/mikem/arduino/AccelStepper/) - Stepper motor control library
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
StepperController --> Component
|
||||
StepperController --> ModbusValue
|
||||
StepperController --> AccelStepper
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
The StepperController continuously updates the motor based on either local settings or values received via Modbus. It monitors for overload conditions and updates the motor status accordingly.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> IDLE
|
||||
IDLE --> RUNNING: Speed > 0
|
||||
RUNNING --> IDLE: Speed = 0
|
||||
RUNNING --> OVERLOAD: Analog reading > threshold
|
||||
OVERLOAD --> RUNNING: Analog reading < threshold
|
||||
RUNNING --> ERROR: Hardware failure
|
||||
ERROR --> IDLE: Reset
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
### Performance
|
||||
|
||||
- Consider implementing acceleration and deceleration profiles for smoother motor operation
|
||||
- Evaluate interrupt-based stepping for more precise timing
|
||||
- Optimize speed scaling for different motor types
|
||||
|
||||
### Security
|
||||
|
||||
- Implement limits on maximum speed and acceleration to prevent mechanical damage
|
||||
- Add authentication for modbus commands that control the motor
|
||||
- Consider adding emergency stop functionality
|
||||
|
||||
### Compliance
|
||||
|
||||
- Verify compatibility with industrial motor control standards
|
||||
- Ensure proper error handling meets safety requirements
|
||||
- Document power requirements and limitations
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Use external motor drivers with proper current limiting for larger motors
|
||||
- Implement soft limits and homing procedures for positioning applications
|
||||
- Add physical endstops for critical applications
|
||||
- Consider adding encoder feedback for closed-loop operation
|
||||
|
||||
## Example
|
||||
|
||||
Below is an example of how to instantiate and configure a StepperController:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_STEPPER_0
|
||||
// Create stepper controller instance
|
||||
stepperController_0 = new StepperController(
|
||||
this, // owner
|
||||
PIN_STEPPER_0_DIR, // dirPin
|
||||
PIN_STEPPER_0_PULSE, // pulsePin
|
||||
PIN_STEPPER_0_FEEDBACK, // feedbackPin
|
||||
PIN_STEPPER_0_OVERLOAD, // overloadPin
|
||||
STEPPER_0_ENABLED, // enabled
|
||||
STEPPER_0_SPEED, // speed
|
||||
STEPPER_0_PULSE_WIDTH, // pulseWidth
|
||||
STEPPER_0_DIR, // dir
|
||||
COMPONENT_KEY_STEPPER_0, // id
|
||||
MB_RW_STEPPER_0_START // addressStart
|
||||
);
|
||||
|
||||
if (stepperController_0)
|
||||
{
|
||||
components.push_back(stepperController_0);
|
||||
Log.infoln(F("StepperController_0 initialized. Dir:%d, Pulse:%d, Speed:%d"),
|
||||
PIN_STEPPER_0_DIR, PIN_STEPPER_0_PULSE, STEPPER_0_SPEED);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("StepperController_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: "ValueWrapper - Threshold-based Value Change Notification"
|
||||
description: "A template class that wraps values with threshold-based change notification logic, designed for efficient Modbus communication"
|
||||
keywords: ["ESP32", "Modbus", "ValueWrapper", "Threshold", "Notification", "C++", "Template"]
|
||||
---
|
||||
|
||||
## ValueWrapper
|
||||
|
||||
**Path**: [`src/ValueWrapper.h`](../../src/ValueWrapper.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
ValueWrapper is a template class that wraps a value (of any type T) and provides threshold-based change notification. When the value changes beyond a specified threshold, it automatically generates Modbus notification messages, reducing network traffic by only sending significant changes.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- C++17 compiler support
|
||||
- No specific hardware pins required
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Supports any data type, including primitives and enums
|
||||
- Two threshold check modes:
|
||||
- DIFFERENCE: Notifies when absolute difference exceeds threshold
|
||||
- INTERVAL_STEP: Notifies when value crosses interval boundaries
|
||||
- Automatic Modbus message generation when thresholds are crossed
|
||||
- Callback support for additional logic on value changes
|
||||
- Type-safe conversion operations
|
||||
- Specialized handling for different data types (signed, unsigned, enum)
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Component](./Component.md): Base component functionality
|
||||
- [ModbusTypes](./modbus/ModbusTypes.md): Modbus data structures
|
||||
- [enums](./enums.md): System-wide enumeration definitions
|
||||
- [Logger](./Logger.md): Logging facility
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
---
|
||||
title: Configuration System
|
||||
description: Global configuration and constants for firmware
|
||||
keywords: [configuration, pins, platform, ESP32, defines, settings]
|
||||
---
|
||||
|
||||
## Configuration System
|
||||
|
||||
**Path**: [src/config.h](../src/config.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
The configuration system is a centralized header file containing all global settings, pin definitions, platform-specific configurations, and feature flags. It provides a unified interface for configuring hardware dependencies, communication protocols, and enabling/disabling various features of the firmware.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP-32 microcontroller (with support for other platforms like Portenta H7, Controllino Mega)
|
||||
- Platform.io development environment
|
||||
- Configuration is designed to work with Modbus-485 protocol for industrial applications
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Automatic platform detection (ESP32, Portenta H7, Controllino Mega, Arduino Uno)
|
||||
- Component ID enumeration for consistent system-wide component identification
|
||||
- Configurable GPIO pin assignments for various peripherals
|
||||
- Network configuration for WiFi in both station and access point modes
|
||||
- Modbus TCP and RS485 communication settings
|
||||
- Temperature profile and signal plotting configuration
|
||||
- Customizable debugging and logging options
|
||||
- Feature flags for enabling/disabling system components
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [Arduino.h](https://www.arduino.cc/reference/en/) - Core Arduino library
|
||||
- [config_adv.h](../src/config_adv.h) - Advanced configuration settings
|
||||
- [stdint.h](https://en.cppreference.com/w/cpp/header/cstdint) - Standard integer types
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
config[config.h] --> arduino[Arduino.h]
|
||||
config --> configadv[config_adv.h]
|
||||
config --> stdint[stdint.h]
|
||||
config --> platformlibs[Platform-specific Libraries]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
The configuration system is a static definition file that controls the behavior of the firmware at compile time. It doesn't have runtime behavior itself, but dictates which components are initialized and how they operate.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Config[Configuration System] --> PlatformDetection[Platform Detection]
|
||||
Config --> ComponentIDs[Component ID Assignment]
|
||||
Config --> FeatureFlags[Feature Flags]
|
||||
FeatureFlags --> EnabledComponents[Enabled Components]
|
||||
FeatureFlags --> DisabledComponents[Disabled Components]
|
||||
Config --> NetworkSettings[Network Settings]
|
||||
Config --> PinAssignments[Pin Assignments]
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider separating platform-specific configurations into dedicated files
|
||||
- Evaluate the impact of enabled debugging flags on performance
|
||||
- Review pin assignment efficiency for optimal GPIO usage
|
||||
|
||||
### SECURITY
|
||||
|
||||
- WiFi credentials are hardcoded - implement secure storage or configuration mechanism
|
||||
- Consider encryption for sensitive communications
|
||||
- Review and secure default access point settings
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Review for compliance with industrial standards
|
||||
- Consider adding provisions for safety-critical systems where applicable
|
||||
- Document electrical specifications for compliance with relevant regulations
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use preprocessor guards when modifying to ensure backward compatibility
|
||||
- When adding new components, follow the existing ID assignment pattern
|
||||
- Consider implementing a runtime configuration system to complement static definitions
|
||||
- Separate network credentials into a separate secure file
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
The configuration system is used primarily as an include in other components. For example, when initializing an LED Feedback component:
|
||||
|
||||
```cpp
|
||||
#ifdef PIN_LED_FEEDBACK_0
|
||||
ledFeedback_0 = new LEDFeedback(
|
||||
this, // owner
|
||||
PIN_LED_FEEDBACK_0, // pin
|
||||
LED_PIXEL_COUNT_0, // pixelCount
|
||||
ID_LED_FEEDBACK_0, // id
|
||||
LED_FEEDBACK_0_MB_ADDR // modbusAddress
|
||||
);
|
||||
if (ledFeedback_0)
|
||||
{
|
||||
components.push_back(ledFeedback_0);
|
||||
Log.infoln(F("LEDFeedback_0 initialized. Pin:%d, Count:%d, ID:%d, MB:%d"),
|
||||
PIN_LED_FEEDBACK_0, LED_PIXEL_COUNT_0,
|
||||
ID_LED_FEEDBACK_0, LED_FEEDBACK_0_MB_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("LEDFeedback_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- ESP32 GPIO Pin documentation: [ESP32 Technical Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf)
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
---
|
||||
title: "JSON Utilities"
|
||||
description: "JSON parsing utility functions for safe field extraction from ArduinoJSON objects"
|
||||
keywords: ["json", "parsing", "arduino", "utilities", "type safety"]
|
||||
---
|
||||
|
||||
# JSON Utilities
|
||||
|
||||
**Path**: [`src/json.h`](src/json.h)
|
||||
|
||||
**Revision History**: Initial documentation
|
||||
|
||||
A collection of inline utility functions for safe JSON field parsing with ArduinoJSON. These functions provide type checking, default value fallback, and graceful error handling for JSON data extraction.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- No specific hardware pins required
|
||||
- ArduinoJSON library
|
||||
- ArduinoLog library
|
||||
|
||||
## FEATURES
|
||||
|
||||
- Safe type-checked JSON field parsing for uint32_t, uint8_t, and bool data types
|
||||
- Graceful error handling with default value fallback
|
||||
- Comprehensive logging with component and field name information
|
||||
- Inline functions for optimal performance
|
||||
- Robust null value handling
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [ArduinoJSON](https://github.com/bblanchard/ArduinoJSON)
|
||||
- [ArduinoLog](https://github.com/thijse/Arduino-Log)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
json["JSON Utilities"] --> arduinojson[ArduinoJSON]
|
||||
json --> arduinolog[Arduino-Log]
|
||||
```
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
jsonobject["JSON Object"] --> check["Type Check"]
|
||||
check --> valid["Valid"]
|
||||
check --> invalid["Invalid"]
|
||||
valid --> update["Update Target Value"]
|
||||
invalid --> logwarn[Log Warning]
|
||||
update --> complete["Completed"]
|
||||
logwarn --> complete
|
||||
```
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Consider using function templates to reduce code duplication across data types
|
||||
- Add support for floating and string data types
|
||||
- Implement validation range checking for numeric types
|
||||
|
||||
### SECURITY
|
||||
|
||||
- No immediate security risks identified
|
||||
- JSON input injection attacks - explicit field and component names should be validated to prevent log injection
|
||||
- Input sanitization recommended prior to working with JSON data
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- No specific compliance requirements
|
||||
- C++17 minimal security practices
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
- Use with the correct component and field names in logging
|
||||
- Provide reasonable default values for all fields
|
||||
- Validate JSON structure before combining with these utilities
|
||||
- Ensure adequate error handling in upper-layer application code
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This example demonstrates the usage of the JSON extraction utilities:
|
||||
|
||||
```cpp
|
||||
using namespace JsonUtils;
|
||||
|
||||
void parseSettings(const char* jsonStr) {
|
||||
staticJsonDocument<512> doc;
|
||||
DeserializationError error = deserializeJson(doc, jsonStr);
|
||||
|
||||
if (error) {
|
||||
Log.errorln("Failed to parse JSON: %s", error.f_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Default values
|
||||
uint32_t baudRate = 115200;
|
||||
uint8_t retryCount = 3;
|
||||
bool debugEnabled = false;
|
||||
|
||||
// Safe parsing with default fallback
|
||||
parseJsonFieldUint32(doc, "baud_rate", baudRate, "Baud Rate", "Settings");
|
||||
parseJsonFieldUint8(doc, "retry_count", retryCount, "Retry Count", "Settings");
|
||||
parseJsonFieldBool(doc, "debug_enabled", debugEnabled, "Debug Enabled", "Settings");
|
||||
|
||||
// Use the parsed values
|
||||
Log.infoln(F("Settings loaded: Baud=%lu, Retry=%d, Debug=%s"),
|
||||
baudRate, retryCount, debugEnabled ? "YES" : "NO");
|
||||
}
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER_COMMENT}
|
||||
|
||||
${ VENDOR_PLACEHOLDER_COMMENT}
|
||||
@@ -1,122 +0,0 @@
|
||||
---
|
||||
title: "SignalPlot"
|
||||
description: "Discrete signal control component for time-based automation and process control"
|
||||
keywords: ["signal-control", "automation", "discrete-states", "modbus", "time-based", "industrial-control", "plot-profile"]
|
||||
---
|
||||
|
||||
## SignalPlot
|
||||
|
||||
**Path** : [src/profiles/SignalPlot.h](src/profiles/SignalPlot.h)
|
||||
**revision history** - initial documentation
|
||||
|
||||
A component for managing discrete signal state changes over time. Inherits from PlotBase to provide time-based automation capabilities for industrial applications.
|
||||
|
||||
## Requirements
|
||||
|
||||
- *-*Inheritance**: PlotBase (component)
|
||||
- **Memory**: Maximum 20 control points
|
||||
|
||||
## Features
|
||||
|
||||
- Discrete state control with time-based triggering
|
||||
- Multiple signal types (Modbus, GPIO, Method calls)
|
||||
- Modbus TCP integration
|
||||
- JSON configuration loading
|
||||
- State querying and user value retrieval
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [PlotBase](#plotbase) - Base class for plot functionality
|
||||
- [ModbusTCP](#modbus-tcp) - Modbus communication
|
||||
- [ArduinoJson](#arduino-json) - JSON configuration
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
PlotBase --> SignalPlot
|
||||
ModbusTCP --> SignalPlot
|
||||
JSONConfig --> SignalPlot
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Start] --> B[LoadConfig]
|
||||
B --> C[InitControlPoints]
|
||||
C --> D[RunLoop]
|
||||
D --> E[CheckElapsedTime]
|
||||
E --> F{C.time_elapsed?}
|
||||
F --> Yes| GoexeuteAction
|
||||
F --> No | D
|
||||
G --> H[UpdateState]
|
||||
H --> D
|
||||
```
|
||||
|
||||
## Todos
|
||||
|
||||
### Performance
|
||||
|
||||
- Optimize control point lookup algorithm
|
||||
- Implement binary search for larger datasets
|
||||
|
||||
### Security
|
||||
|
||||
- Validate control point parameters
|
||||
- Implement safe gaurds for critical GPIO operations
|
||||
|
||||
### Compliance
|
||||
|
||||
- Verify Modbus compliance
|
||||
- Implement error handling for industrial standards
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Implement remaining signal types (CALL_METHOD, CALL_FUNCTION, CALL_REST, USER_DEFINED)
|
||||
- Add state validation and error handling
|
||||
- Implement advanced GPIO control modes (SERVO, TONE)
|
||||
|
||||
## Example
|
||||
|
||||
Here an example how such component is being constructed and mounted:
|
||||
|
||||
```cpp
|
||||
#define SIGNAL_PLOT_SLOT_0 0
|
||||
#define COMPONENT_KEY_SIGNAL_PLOT_0 920
|
||||
|
||||
signalPlot_0 = new SignalPlot(
|
||||
this, // owner
|
||||
SIGNAL_PLOT_SLOT_0, // slot
|
||||
COMPONENT_KEY_SIGNAL_PLOT_0 // componentId
|
||||
);
|
||||
|
||||
if (signalPlot_0)
|
||||
{
|
||||
components.push_back(signalPlot_0);
|
||||
Log.infoln(F("SignalPlot_0 initialized. Slot:%d, ID:%d"),
|
||||
SIGNAL_PLOT_SLOT_0, COMPONENT_KEY_SIGNAL_PLOT_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("SignalPlot_0 initialization failed."));
|
||||
}
|
||||
```
|
||||
|
||||
Example JSON configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "TISControlPlot",
|
||||
"duration": 300000,
|
||||
"controlPoints": [
|
||||
{ "id": 1, "time": 0, "state": 2, "type": 6, "arg_0": 21, "arg_1": 0, "arg_2": 1 },
|
||||
{ "id": 2, "time": 5000, "state": 3, "type": 2, "arg_0": 100, "arg_1": 500, "arg_2": 0 },
|
||||
{ "id": 3, "time": 10000, "state": 2, "type": 1, "arg_0": 20, "arg_1": 1, "arg_2": 0 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
title: "Temperature Profile Component"
|
||||
description: "Interpolated temperature profile controller for industrial applications with Modbus-485 integration"
|
||||
keywords: ["temperature", "profile", "modbus", "interpolation", "industrial", "pid", "control"]
|
||||
---
|
||||
|
||||
## Temperature Profile
|
||||
|
||||
**Path** : [src/profiles/TemperatureProfile.h](../../src/profiles/TemperatureProfile.h)
|
||||
|
||||
Interpolated temperature profile component for industrial process control with support for both linear and cubic interpolation. Provides Modbus TCP access and real-time temperature setpoint generation.
|
||||
|
||||
## Requirements
|
||||
|
||||
- ESP-32 microcontroller
|
||||
- Modbus TCP connection
|
||||
- Timer capabilities for precise signal generation
|
||||
- "ENABLE_PROFILE_TEMPERATURE" defined
|
||||
|
||||
## Features
|
||||
|
||||
- **Interpolated Profiles**: Linear and cubic BÉlier curve interpolation
|
||||
- **Multi-point Control**: Up to 10 control points per profile
|
||||
- **Modbus Integration**: Full Modbus TCP support for rmote control
|
||||
- **Real-time Monitoring**: Live entemperature and status feedback
|
||||
- **Signal Plot Integration**: Associated plot tracking
|
||||
- **Command Management**: Start/stop/pause/resume control
|
||||
- **Dynamic Setpoint**: Automatic setpoint updates vo target registers
|
||||
- **JSON Configuration**: File-based configuration support
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [PlotBase](./plot-base.md) - Base plot component
|
||||
- [Component](../component.md) - Base component class
|
||||
- [ModbusTCP](../modbus/modbus-tcp.md) - Modbus TCP implementation
|
||||
- [ValueWrapper](../value-wrapper.md) - Threshold-based notifications
|
||||
- [Arduino JSON](https://arduinojson.org/) - JSON configuration
|
||||
|
||||
## Todos
|
||||
|
||||
### Performance
|
||||
|
||||
- Optimize interpolation algorithm for real-time performance
|
||||
- Implement fixed-point arithmetic for cubic interpolation
|
||||
- Minimize memory usage for large control point arrays
|
||||
|
||||
### Security
|
||||
|
||||
- Implement input validation for setpoint ranges
|
||||
- Add authentication for Modbus write operations
|
||||
- Enable logging of all control modifications
|
||||
|
||||
### Compliance
|
||||
|
||||
- IEC 61131 Modbus standard compliance
|
||||
- Safety interlocks for critical temperature limits
|
||||
- DOT-compliant data logging for process traceability
|
||||
|
||||
## Example
|
||||
|
||||
Here an example how such component is being constructed and mounted:
|
||||
|
||||
```cpp
|
||||
#ifdef ENABLE_PROFILE_TEMPERATURE
|
||||
for (int i = 0; i < PROFILE_TEMPERATURE_COUNT; i++)
|
||||
{
|
||||
temperatureProfiles[i] = new TemperatureProfile(
|
||||
this, // owner
|
||||
i, // slot
|
||||
COMPONENT_KEY_PROFILE_START + i // componentId
|
||||
);
|
||||
if (temperatureProfiles[i])
|
||||
{
|
||||
components.push_back(temperatureProfiles[i]);
|
||||
Log.infoln("TemperatureProfile[%d] initialized. ID:%d",
|
||||
i, COMPONENT_KEY_PROFILE_START + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln("TemperatureProfile[%d] initialization failed.", i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
```
|
||||
@@ -1,108 +0,0 @@
|
||||
---
|
||||
title: WiFi Network Settings
|
||||
description: Configurable WiFi network settings for STA and AP modes on ESP-32
|
||||
keywords: [WiFi, network, configuration, ESP-32, STA, access point, AP, modbus, IP]
|
||||
---
|
||||
|
||||
## WIFI NETWORK SETTINGS
|
||||
|
||||
**Path** : [src/profiles/WiFiNetworkSettings.h](src/profiles/WiFiNetworkSettings.h)
|
||||
|
||||
Structure for managing WiFi network configuration for ESP-32 based industrial applications. Supports both STA (station) and AP (Access Point) modes.
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
- ESP-32 platform
|
||||
- WiFi capability
|
||||
- ArduinoJson library
|
||||
- Arduino core libraries
|
||||
- IPAddress class
|
||||
|
||||
## FEATURES
|
||||
|
||||
- STA (WiFi station) configuration management
|
||||
- AP (Access Point) configuration management
|
||||
- Conditional APSTA mode support
|
||||
- JSON serialization/deserialization
|
||||
- IP address, gateway, and DNS configuration
|
||||
- Configuration loading from file/storage
|
||||
- Debugging and logging support
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- [config.h](config.h)
|
||||
- [enums.h](enums.h)
|
||||
- [Logger.h](Logger.h)
|
||||
- [ArduinoJson](https://arduinojson.org/)
|
||||
- [ArduinoLog](https://github.com/thylakoid/213-arduino-logger)
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
- Implement memory efficient JSON handling
|
||||
- Optimize IP address parsing
|
||||
- Add caching mechanism for settings
|
||||
|
||||
### SECURITY
|
||||
|
||||
- Implement password encryption
|
||||
- Add input validation for IP addresses
|
||||
- Implement secure configuration storage
|
||||
- Add configuration bup and restore functionality
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
- Verify WiFiAlliance compliance
|
||||
- Implement industrial WiFi best practices
|
||||
- Add network security protocol support
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
Here an example how such component is being constructed and mounted:
|
||||
|
||||
```cpp
|
||||
// Initialize WiFi settings
|
||||
WiFiNetworkSettings wifiSettings;
|
||||
|
||||
// Load settings from JSON configuration
|
||||
If (LittleFS.exists("/network.json")) {
|
||||
File configFile = LittleFS.open("/network.json", "r");
|
||||
DynamicJsonDocument doc(1024);
|
||||
deserializeJson(doc, configFile);
|
||||
configFile.close();
|
||||
|
||||
wifiSettings.loadSettings(doc.as<JsonObject>());
|
||||
}
|
||||
|
||||
// Configure WiFi based on settings
|
||||
WiFi.config(
|
||||
wifiSettings.sta_local_IP,
|
||||
wifiSettings.sta_gateway,
|
||||
wifiSettings.sta_subnet,
|
||||
wifiSettings.sta_primary_dns,
|
||||
wifiSettings.sta_secondary_dns
|
||||
);
|
||||
|
||||
WiFi.begin(
|
||||
wifiSettings.sta_ssid.c_str(),
|
||||
wifiSettings.sta_password.c_str()
|
||||
);
|
||||
|
||||
// In AP_STA moftAPAPaT mode, also configure AP
|
||||
#ifdef ENABLE_AP_STA
|
||||
WiFi.softAP(
|
||||
wifiSettings.ap_ssid.c_str(),
|
||||
wifiSettings.ap_password.c_str()
|
||||
);
|
||||
|
||||
WiFi.softAPConfig(
|
||||
wifiSettings.ap_config_ip,
|
||||
wifiSettings.ap_config_gateway,
|
||||
wifiSettings.ap_config_subnet
|
||||
);
|
||||
#endif
|
||||
|
||||
// Print current configuration
|
||||
wifiSettings.print();
|
||||
```
|
||||
+2
-2
@@ -2,10 +2,10 @@ name=polymech-base
|
||||
version=1.0.0
|
||||
author=mc007
|
||||
maintainer=mc007
|
||||
sentence=polymech-base Library
|
||||
sentence=polymech-base library
|
||||
paragraph=
|
||||
category=Uncategorized
|
||||
url=https://github/osr_base
|
||||
url=https://git.polymech.info/polymech/firmware-base.git
|
||||
architectures=*
|
||||
includes=PolymechBase.h
|
||||
depends=ArduinoLog,Vector,Streaming
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Context
|
||||
|
||||
- ESP-32, Platform.io, C17
|
||||
|
||||
Create a brief report for potential bugs, leaks or race coditions, in ./docs/issues/profiles/[filename].md
|
||||
|
||||
|
||||
Ignore: enums.h, Components.h, config.h
|
||||
|
||||
Ignore kind of issues : null pointer checks, thread safety, uninitialized pins, and any other overkill checks:)
|
||||
|
||||
Layout / Content :
|
||||
|
||||
|
||||
## File Name
|
||||
|
||||
**Path** : relative path (markdown link)
|
||||
|
||||
### Issues Summary
|
||||
|
||||
Table of issues : severity, function, quick solution
|
||||
|
||||
### Issues
|
||||
|
||||
### Name of the issue
|
||||
|
||||
- location of function code
|
||||
|
||||
the code
|
||||
|
||||
#### Potential solutions
|
||||
|
||||
...code
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
kbot-d --router2=openai --model=anthropic/claude-3.7-sonnet:th \
|
||||
--prompt=./scripts/bugs.md \
|
||||
--each=./src/profiles/*.h \
|
||||
--include=./src/enums.h \
|
||||
--include=../../src/config.h \
|
||||
--include2=./src/NetworkComponent.h \
|
||||
--include2=./src/profiles/PlotBase.h \
|
||||
--wrap=meta \
|
||||
--mode=tools \
|
||||
--preferences=none \
|
||||
--disableTools=read_file,read_files,list_files,file_exists,modify_project_files \
|
||||
--tools="fs" \
|
||||
--filters=code \
|
||||
--globExtension=match-cpp
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
# Context
|
||||
|
||||
- ESP-32, Platform.io, C17
|
||||
- avoidance of std
|
||||
- industrial application, using Modbus-485
|
||||
|
||||
# Instructions
|
||||
|
||||
- Generate documentation for a given component in a new Markdown file located at `./docs/<component-name>.md`.
|
||||
- The documentation is intended for an Astro static site generator.
|
||||
- Include frontmatter in the Markdown file with `title`, `description`, and `keywords` fields.
|
||||
- You will be provided with the content of the component's header file (e.g., `src/<component-name>.h`).
|
||||
- Ensure the generated Markdown adheres to standard linting rules.
|
||||
- The generated Markdown document must follow the specific layout provided below.
|
||||
- The component's C++ source file will contain an example of how it is constructed and mounted; use this as a basis for the "Example" section in the documentation.
|
||||
- Do not comment or add thoughts, just output plain Markdown
|
||||
|
||||
## Layout
|
||||
|
||||
The Markdown document must adhere to the following structure:
|
||||
|
||||
----------------------------
|
||||
|
||||
## COMPONENT NAME
|
||||
|
||||
**Path**: `relative/path/to/component-name.cpp` (as a Markdown link)
|
||||
|
||||
**Revision History**: Add a file revision entry in the header to track modifications. For the initial documentation, use "Initial documentation". Skip this if a revision history already exists !
|
||||
|
||||
A short description of the component, highlight features
|
||||
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
Detail the hardware pins and software dependencies required by the component.
|
||||
|
||||
## FEATURES
|
||||
|
||||
List the key features and functionalities of the component.
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- Provide a list of dependencies as Markdown formatted links.
|
||||
- Include a minimal Mermaid diagram illustrating the dependencies. The diagram node names should not contain braces or brackets.
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
- Include a minimal Mermaid diagram illustrating the component's behaviour or state machine. The diagram node names should not contain braces or brackets.
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
Outline any performance considerations or areas for future optimization.
|
||||
|
||||
### SECURITY
|
||||
|
||||
Describe potential security vulnerabilities or hardening measures.
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
Note any compliance standards or requirements relevant to the component.
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
Provide any recommendations for using or extending the component.
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This section should illustrate how the component is constructed and mounted.
|
||||
Refer to the component's C++ source file for an example.
|
||||
A general example structure is:
|
||||
|
||||
#ifdef PIN_LED_FEEDBACK_0
|
||||
ledFeedback_0 = new LEDFeedback(
|
||||
this, // owner
|
||||
PIN_LED_FEEDBACK_0, // pin
|
||||
LED_PIXEL_COUNT_0, // pixelCount
|
||||
ID_LED_FEEDBACK_0, // id
|
||||
LED_FEEDBACK_0_MB_ADDR // modbusAddress
|
||||
);
|
||||
if (ledFeedback_0)
|
||||
{
|
||||
components.push_back(ledFeedback_0);
|
||||
Log.infoln(F("LEDFeedback_0 initialized. Pin:%d, Count:%d, ID:%d, MB:%d"),
|
||||
PIN_LED_FEEDBACK_0, LED_PIXEL_COUNT_0,
|
||||
ID_LED_FEEDBACK_0, LED_FEEDBACK_0_MB_ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.errorln(F("LEDFeedback_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
@@ -1,10 +0,0 @@
|
||||
kbot-d --model=anthropic/claude-3.7-sonnet \
|
||||
--prompt=./scripts/docs-c.md \
|
||||
--each=./src/*.h \
|
||||
--globExtension=match-cpp \
|
||||
--mode=completion \
|
||||
--filters=markdown \
|
||||
--preferences=none \
|
||||
--exclude='./docs-c/${SRC_NAME}*.md' \
|
||||
--dst='./docs-c/${SRC_NAME}.md'
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
kbot-d --model2=anthropic/claude-3.7-sonnet \
|
||||
--prompt=./scripts/docs.md \
|
||||
--each=./src/Serial*.h \
|
||||
--globExtension=match-cpp \
|
||||
--wrap=meta \
|
||||
--mode=completion \
|
||||
--preferences=none \
|
||||
--filters2=code \
|
||||
--dst='./docs/${SRC_NAME}.md'
|
||||
@@ -1,70 +0,0 @@
|
||||
# Context
|
||||
|
||||
- ESP-32, Platform.io, C17
|
||||
- avoidance of std
|
||||
- industrial application, using Modbus-485
|
||||
|
||||
## Instructions
|
||||
|
||||
- Generate documentation for a given class, its types, enumerations, in a new Markdown file located at `./docs/modbus/<filename>.md`.
|
||||
- The documentation is intended for an Astro static site generator.
|
||||
- Include frontmatter in the Markdown file with `title`, `description`, and `keywords` fields.
|
||||
- You will be provided with the content of the component's header file (e.g., `src/modbus/<file-name>.h`).
|
||||
- Ensure the generated Markdown adheres to standard linting rules.
|
||||
- The generated Markdown document must follow the specific layout provided below.
|
||||
- The component's C++ source file will contain an example of how it is constructed and mounted; use this as a basis for the "Example" section in the documentation.
|
||||
- Do not comment or add thoughts, just output plain Markdown
|
||||
|
||||
## Layout
|
||||
|
||||
The Markdown document must adhere to the following structure:
|
||||
|
||||
----------------------------
|
||||
|
||||
## COMPONENT NAME
|
||||
|
||||
**Path**: `relative/path/to/component-name.cpp` (as a Markdown link)
|
||||
|
||||
**Revision History**: Add a file revision entry in the header to track modifications. For the initial documentation, use "Initial documentation". Skip this if a revision history already exists !
|
||||
|
||||
A detailed description of the component
|
||||
|
||||
## REQUIREMENTS
|
||||
|
||||
Detail the hardware pins and software dependencies required by the component.
|
||||
|
||||
## PROVIDES
|
||||
|
||||
- a list of all types, enumerations and classes
|
||||
|
||||
## FEATURES
|
||||
|
||||
List the key features and functionalities of the component.
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- Provide a list of dependencies as Markdown formatted links.
|
||||
- Include a minimal Mermaid diagram illustrating the dependencies. The diagram node names should not contain braces or brackets.
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
- Include a minimal Mermaid diagram illustrating the component's behaviour or state machine. The diagram node names should not contain braces or brackets.
|
||||
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
Outline any performance considerations or areas for future optimization.
|
||||
|
||||
### SECURITY
|
||||
|
||||
Describe potential security vulnerabilities or hardening measures.
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
Note any compliance standards or requirements relevant to the component.
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
Provide any recommendations for using or extending the component.
|
||||
@@ -1,9 +0,0 @@
|
||||
kbot-d --model=anthropic/claude-3.7-sonnet \
|
||||
--prompt=./scripts/docs-m.md \
|
||||
--each=./src/*.h \
|
||||
--globExtension=match-cpp \
|
||||
--mode=completion \
|
||||
--filters=markdown \
|
||||
--preferences=none \
|
||||
--exclude='./docs-c/core/${SRC_NAME}.md' \
|
||||
--dst='./docs-c/core/${SRC_NAME}.md'
|
||||
+15
-62
@@ -4,74 +4,33 @@
|
||||
- avoidance of std
|
||||
- industrial application, using Modbus-485
|
||||
|
||||
# Instructions
|
||||
Create a brief documentation, in ./docs/component-name.md,
|
||||
|
||||
- Generate documentation for a given component in a new Markdown file located at `./docs/<component-name>.md`.
|
||||
- The documentation is intended for an Astro static site generator.
|
||||
- Include frontmatter in the Markdown file with `title`, `description`, and `keywords` fields.
|
||||
- You will be provided with the content of the component's header file (e.g., `src/<component-name>.h`).
|
||||
- You must also open and refer to the corresponding C++ source file located at `src/<component-name>.cpp`.
|
||||
- Do not open or access any other files, specifically `src/Component.cpp` !!!
|
||||
- Ensure the generated Markdown adheres to standard linting rules.
|
||||
- When using a tool to write the documentation file, ensure the file content is base64 encoded and provide the relative path to the file.
|
||||
- The generated Markdown document must follow the specific layout provided below.
|
||||
- The component's C++ source file will contain an example of how it is constructed and mounted; use this as a basis for the "Example" section in the documentation.
|
||||
- To read files, use the read_file tool, JSON payload : {"path":"relative path"}
|
||||
Layout / Content :
|
||||
|
||||
## Layout
|
||||
## Component Name
|
||||
|
||||
The Markdown document must adhere to the following structure:
|
||||
**Path** : relative path (markdown link)
|
||||
|
||||
----------------------------
|
||||
**revision history** - add file revision in header to track modification, for this task, 'initial documentation' (skip if already done)
|
||||
|
||||
## COMPONENT NAME
|
||||
short description
|
||||
|
||||
**Path**: `relative/path/to/component-name.cpp` (as a Markdown link)
|
||||
## Requirements
|
||||
|
||||
**Revision History**: Add a file revision entry in the header to track modifications. For the initial documentation, use "Initial documentation". Skip this if a revision history already exists !
|
||||
pins, dependencies
|
||||
|
||||
A short description of the component.
|
||||
## Features
|
||||
|
||||
## REQUIREMENTS
|
||||
## Todos
|
||||
|
||||
Detail the hardware pins and software dependencies required by the component.
|
||||
## Example
|
||||
|
||||
## FEATURES
|
||||
------------
|
||||
|
||||
List the key features and functionalities of the component.
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
- Provide a list of dependencies as Markdown formatted links.
|
||||
- Include a minimal Mermaid diagram illustrating the dependencies. The diagram node names should not contain braces or brackets.
|
||||
|
||||
## BEHAVIOUR
|
||||
|
||||
- Include a minimal Mermaid diagram illustrating the component's behaviour or state machine. The diagram node names should not contain braces or brackets.
|
||||
|
||||
## TODOS
|
||||
|
||||
### PERFORMANCE
|
||||
|
||||
Outline any performance considerations or areas for future optimization.
|
||||
|
||||
### SECURITY
|
||||
|
||||
Describe potential security vulnerabilities or hardening measures.
|
||||
|
||||
### COMPLIANCE
|
||||
|
||||
Note any compliance standards or requirements relevant to the component.
|
||||
|
||||
### RECOMMENDATIONS
|
||||
|
||||
Provide any recommendations for using or extending the component.
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
This section should illustrate how the component is constructed and mounted.
|
||||
Refer to the component's C++ source file for an example.
|
||||
A general example structure is:
|
||||
- use standard markdown lint rules
|
||||
- chapters in capital
|
||||
- components are added as follows :
|
||||
|
||||
#ifdef PIN_LED_FEEDBACK_0
|
||||
ledFeedback_0 = new LEDFeedback(
|
||||
@@ -93,9 +52,3 @@ A general example structure is:
|
||||
Log.errorln(F("LEDFeedback_0 initialization failed."));
|
||||
}
|
||||
#endif
|
||||
|
||||
### References
|
||||
|
||||
${DOXYGEN_PLACEHOLDER}
|
||||
|
||||
${VENDOR_PLACEHOLDER}
|
||||
|
||||
+7
-17
@@ -1,20 +1,10 @@
|
||||
kbot-d --router2=openai --model=anthropic/claude-3.7-sonnet:thinking \
|
||||
kbot-d --router2=openai --model=anthropic/claude-3.7-sonnet:th \
|
||||
--prompt=./scripts/docs.md \
|
||||
--each=./src/Serial*.h \
|
||||
--globExtension=match-cpp \
|
||||
--include=../polymech-fw-apps/cassandra-rc2/src/config.h \
|
||||
--include=./src/Component.h \
|
||||
--wrap2=meta \
|
||||
--mode=tools \
|
||||
--preferences=none \
|
||||
--disableTools=read_files,list_files,file_exists,modify_project_files \
|
||||
--each=./src/components/*.h \
|
||||
--include=../../src/config.h \
|
||||
--wrap=meta \
|
||||
--mode=tools --preferences=none \
|
||||
--disableTools=read_file,read_files,list_files,file_exists,modify_project_files \
|
||||
--tools="fs" \
|
||||
--filters=code \
|
||||
--exclude=./src/components/ModbusLogicEngine.h \
|
||||
--exclude=./src/components/Extruder.h \
|
||||
--exclude=./src/components/OmronE5_Ex.h \
|
||||
--exclude=./src/components/PlungerSettings.h \
|
||||
--exclude=./src/components/OmronE5Types.h \
|
||||
--exclude=./src/components/SakoTypes.h
|
||||
|
||||
--filters=code
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Context
|
||||
|
||||
- ESP-32, Platform.io, C17
|
||||
|
||||
- Create a comprehensive documentation for all Modbus related classes, with diagrams (mermaid, no braces in node names), in ./docs/modbus/readme.md
|
||||
- Create a performance analysis, in ./docs/modbus/performance.md
|
||||
- Find bottlenecks and improvements, ./docs/modbus/todos.md
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
kbot-d --router2=openai --model=anthropic/claude-3.7-sonnet:th \
|
||||
--prompt=./scripts/modbus.md \
|
||||
--include=./src/modbus/*.h \
|
||||
--include=./src/Component.h \
|
||||
--include=./src/NetworkComponent.h \
|
||||
--wrap=meta \
|
||||
--mode=tools \
|
||||
--preferences=none \
|
||||
--disableTools=read_file,read_files,list_files,file_exists,modify_project_files \
|
||||
--tools="fs" \
|
||||
--filters=code \
|
||||
--globExtension=match-cpp
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Context
|
||||
|
||||
- ESP-32, Platform.io, C17
|
||||
|
||||
Create a brief memory footprint report, in ./docs/stats/[component-sub-dir]/[component-file-name].md
|
||||
|
||||
Layout / Content :
|
||||
|
||||
## File Name
|
||||
|
||||
**Path** : relative path (markdown link)
|
||||
**Overall Memory Footprint** : totals
|
||||
|
||||
Table of member variables and their memory footprint
|
||||
|
||||
### Recommendations
|
||||
|
||||
Recommendations / optimizations, per variable/member
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
kbot-d --router2=openai --model=anthropic/claude-3.7-sonnet:th \
|
||||
--prompt=./scripts/stats.md \
|
||||
--each=./src/modbus/*.h \
|
||||
--include=../../src/config.h \
|
||||
--include=./src/NetworkComponent.h \
|
||||
--include2=./src/profiles/PlotBase.h \
|
||||
--wrap=meta \
|
||||
--mode=tools \
|
||||
--preferences=none \
|
||||
--disableTools=read_file,read_files,list_files,file_exists,modify_project_files \
|
||||
--tools="fs" \
|
||||
--filters=code \
|
||||
--globExtension=match-cpp
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#include "Addon.h"
|
||||
#include <Streaming.h>
|
||||
#include <Vector.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
Addon *byId(Addons addons, uchar id)
|
||||
{
|
||||
uchar s = addons.size();
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (addon->id == id)
|
||||
{
|
||||
return addon;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
#ifndef ADDON_H
|
||||
#define ADDON_H
|
||||
|
||||
#include <WString.h>
|
||||
#include <Vector.h>
|
||||
|
||||
#include "enums.h"
|
||||
#include "error_codes.h"
|
||||
#include "macros.h"
|
||||
#include "Component.h"
|
||||
|
||||
// back compat
|
||||
class Addon : public Component
|
||||
{
|
||||
|
||||
public:
|
||||
static const int ADDON_FLAGS_DEFAULT = 1 << OBJECT_RUN_FLAGS::E_OF_LOOP | 1 << OBJECT_RUN_FLAGS::E_OF_INFO | 1 << OBJECT_RUN_FLAGS::E_OF_SETUP;
|
||||
|
||||
/*
|
||||
Addon(
|
||||
String _name,
|
||||
short _id) : Component(_name, _id),
|
||||
name(_name),
|
||||
id(_id),
|
||||
now(0),
|
||||
flags(COMPONENT_DEFAULT)
|
||||
{
|
||||
}
|
||||
|
||||
Addon(
|
||||
String _name,
|
||||
short _id,
|
||||
short _flags) : Component(_name, _id, _flags),
|
||||
name(_name),
|
||||
id(_id),
|
||||
flags(_flags)
|
||||
{
|
||||
}
|
||||
|
||||
Addon(
|
||||
String _name,
|
||||
short _id,
|
||||
short _flags,
|
||||
Addon *_owner) : Component(_name, _id, _flags, _owner),
|
||||
name(_name),
|
||||
id(_id),
|
||||
flags(_flags),
|
||||
owner(_owner)
|
||||
{
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
typedef Vector<Addon *> Addons;
|
||||
Addon *byId(Addons addons, uchar id);
|
||||
typedef short (Addon::*AddonFnPtr)(short);
|
||||
|
||||
#endif
|
||||
+31
-7
@@ -6,16 +6,27 @@
|
||||
#include "error_codes.h"
|
||||
#include "enums.h"
|
||||
#include "constants.h"
|
||||
#include "config.h"
|
||||
|
||||
static Component *componentsArray[MAX_COMPONENTS];
|
||||
#include <esp_heap_caps.h>
|
||||
|
||||
App::App() : Component("APP", COMPONENT_KEY_APP, Component::COMPONENT_DEFAULT)
|
||||
#define ENABLE_COMPONENT_STATS
|
||||
|
||||
|
||||
App::App() : Component("APP", COMPONENT_KEY_APP, Component::COMPONENT_DEFAULT),
|
||||
debugTS(0),
|
||||
loopTS(0),
|
||||
_lastHeapCheck(0),
|
||||
_heapFragmentationPercent(0.0f)
|
||||
{
|
||||
DEBUG_INTERVAL = DEFAULT_DEBUG_INTERVAL;
|
||||
components.setStorage(componentsArray);
|
||||
debugTS = 0;
|
||||
components.reserve(MAX_COMPONENTS);
|
||||
}
|
||||
|
||||
float App::getHeapFragmentation() const
|
||||
{
|
||||
return _heapFragmentationPercent;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
//
|
||||
// Component related functions
|
||||
@@ -69,6 +80,7 @@ short App::setup()
|
||||
|
||||
short App::registerComponents(Bridge *bridge)
|
||||
{
|
||||
#ifdef ENABLE_SERIAL_BRIDGE
|
||||
short s = components.size();
|
||||
for (short i = 0; i < s; i++)
|
||||
{
|
||||
@@ -79,6 +91,7 @@ short App::registerComponents(Bridge *bridge)
|
||||
}
|
||||
component->serial_register(bridge);
|
||||
}
|
||||
#endif
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
@@ -90,12 +103,23 @@ short App::loop()
|
||||
for (short i = 0; i < s; i++)
|
||||
{
|
||||
Component *component = components[i];
|
||||
if (component->hasFlag(OBJECT_RUN_FLAGS::E_OF_LOOP))
|
||||
if (component->hasFlag(OBJECT_RUN_FLAGS::E_OF_LOOP) &&
|
||||
component->enabled())
|
||||
{
|
||||
component->now = now;
|
||||
|
||||
component->_loop_start_time_us = micros();
|
||||
component->now = millis();
|
||||
component->loop();
|
||||
component->_loop_duration_us = micros() - component->_loop_start_time_us;
|
||||
}
|
||||
}
|
||||
|
||||
if (now - _lastHeapCheck > 150)
|
||||
{
|
||||
_heapFragmentationPercent = (1.0 - (float)heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT) / ESP.getFreeHeap()) * 100.0;
|
||||
_lastHeapCheck = now;
|
||||
}
|
||||
|
||||
debug();
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef APP_H
|
||||
#define APP_H
|
||||
|
||||
#include <Vector.h>
|
||||
#include <vector>
|
||||
#include <xtypes.h>
|
||||
#include <Component.h>
|
||||
#include <Bridge.h>
|
||||
@@ -18,6 +18,9 @@ class Bridge;
|
||||
*/
|
||||
class App : public Component
|
||||
{
|
||||
private:
|
||||
float _heapFragmentationPercent = 0.0;
|
||||
millis_t _lastHeapCheck = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -68,6 +71,7 @@ public:
|
||||
* @return A status code indicating the result of the info operation.
|
||||
*/
|
||||
virtual short info();
|
||||
float getHeapFragmentation() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the number of components with a specific flag.
|
||||
@@ -80,7 +84,7 @@ public:
|
||||
/**
|
||||
* @brief The list of components in the application.
|
||||
*/
|
||||
Vector<Component *> components;
|
||||
std::vector<Component *> components;
|
||||
|
||||
/**
|
||||
* @brief The timestamp for the last debug operation.
|
||||
|
||||
+11
-10
@@ -1,24 +1,25 @@
|
||||
#include "macros.h"
|
||||
#include <ArduinoLog.h>
|
||||
#include "Bridge.h"
|
||||
#include <Vector.h>
|
||||
|
||||
#include <Streaming.h>
|
||||
#include "constants.h"
|
||||
#include <StringUtils.h>
|
||||
#include "./enums.h"
|
||||
#include <enums.h>
|
||||
#include "constants.h"
|
||||
|
||||
#include "Bridge.h"
|
||||
#include "config.h"
|
||||
|
||||
#define BRIDGE_DEBUG_REGISTER
|
||||
#define BRIDGE_DEBUG_CALL_METHOD
|
||||
//#define BRIDGE_DEBUG_REGISTER
|
||||
//#define BRIDGE_DEBUG_CALL_METHOD
|
||||
#define DISABLE_BRIDGE
|
||||
#define NB_PAYLOAD_ELEMENTS 3
|
||||
|
||||
class SComponentInfo;
|
||||
SComponentInfo *componentsArray[MAX_COMPONENTS];
|
||||
Vector<SComponentInfo *> componentList;
|
||||
std::vector<SComponentInfo *> componentList;
|
||||
|
||||
Bridge::Bridge(Component *_owner) : Component("Bridge", COMPONENT_KEY_MB_BRIDGE, Component::COMPONENT_DEFAULT, _owner)
|
||||
{
|
||||
componentList.setStorage(componentsArray);
|
||||
componentList.reserve(MAX_COMPONENTS);
|
||||
}
|
||||
short Bridge::setup()
|
||||
{
|
||||
@@ -83,7 +84,7 @@ SComponentInfo *Bridge::registerMemberFunction(ushort id, Component *clazz, char
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Vector<SComponentInfo *> &Bridge::getComponentList() const
|
||||
const std::vector<SComponentInfo *> &Bridge::getComponentList() const
|
||||
{
|
||||
return componentList;
|
||||
}
|
||||
|
||||
+8
-5
@@ -1,14 +1,17 @@
|
||||
#ifndef BRIDGE_H
|
||||
#define BRIDGE_H
|
||||
|
||||
#include "Component.h"
|
||||
#include <vector>
|
||||
|
||||
#include <Component.h>
|
||||
#include <WString.h>
|
||||
#include <xtypes.h>
|
||||
#include <enums.h>
|
||||
#include <macros.h>
|
||||
#include <Vector.h>
|
||||
|
||||
#include <enums.h>
|
||||
|
||||
#include <Streaming.h>
|
||||
#include "./enums.h"
|
||||
|
||||
class SComponentInfo;
|
||||
|
||||
@@ -38,7 +41,7 @@ public:
|
||||
ComponentFnPtr ptr);
|
||||
|
||||
short onMessage(int id, E_CALLS verb, E_MessageFlags flags, String user, Component *src);
|
||||
const Vector<SComponentInfo *> &getComponentList() const;
|
||||
const std::vector<SComponentInfo *> &getComponentList() const;
|
||||
|
||||
// Component implementation
|
||||
short debug();
|
||||
@@ -52,7 +55,7 @@ public:
|
||||
* This current implementation returns pointers stored in the internal vector.
|
||||
* @return A vector of Component pointers.
|
||||
*/
|
||||
Vector<Component*> getAllComponents();
|
||||
std::vector<Component*> getAllComponents();
|
||||
|
||||
static constexpr char *METHOD_DELIMITER = C_STR(":");
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "Component.h"
|
||||
|
||||
const int Component::COMPONENT_DEFAULT;
|
||||
|
||||
+670
-515
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -12,11 +12,11 @@
|
||||
// • LOG_BUFFER_THREAD_SAFE – 1 = wrap writes in a FreeRTOS critical section
|
||||
// -----------------------------------------------------------------------------
|
||||
#ifndef LOG_BUFFER_LINES
|
||||
#define LOG_BUFFER_LINES 100
|
||||
#define LOG_BUFFER_LINES 10
|
||||
#endif
|
||||
|
||||
#ifndef LOG_BUFFER_LINE_LENGTH
|
||||
#define LOG_BUFFER_LINE_LENGTH 120
|
||||
#define LOG_BUFFER_LINE_LENGTH 50
|
||||
#endif
|
||||
|
||||
#ifndef LOG_BUFFER_THREAD_SAFE
|
||||
@@ -28,7 +28,7 @@ using LogRingBuffer = char[LOG_BUFFER_LINES][LOG_BUFFER_LINE_LENGTH];
|
||||
// -----------------------------------------------------------------------------
|
||||
// CircularLogPrinter -----------------------------------------------------------
|
||||
// Stores the last N lines in a ring buffer and optionally mirrors everything to
|
||||
// an arbitrary Print stream. 100 % reinterpret‑cast‑free for MISRA/CPPCHECK
|
||||
// an arbitrary Print stream. 100 % reinterpret‑cast‑free for MISRA/CPPCHECK
|
||||
// compliance: the code never converts between pointer types, only between
|
||||
// scalar values.
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -151,4 +151,4 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // CIRCULAR_LOG_PRINTER_H
|
||||
#endif // CIRCULAR_LOG_PRINTER_H
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef MESSAGE_QUEUE_H
|
||||
#define MESSAGE_QUEUE_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifndef MESSAGE_QUEUE_CAPACITY
|
||||
#define MESSAGE_QUEUE_CAPACITY 5
|
||||
#endif
|
||||
|
||||
#ifndef MESSAGE_MAX_LENGTH
|
||||
#define MESSAGE_MAX_LENGTH 128
|
||||
#endif
|
||||
|
||||
#ifndef MESSAGE_QUEUE_THREAD_SAFE
|
||||
#define MESSAGE_QUEUE_THREAD_SAFE 1
|
||||
#endif
|
||||
|
||||
using MessageBuffer = char[MESSAGE_QUEUE_CAPACITY][MESSAGE_MAX_LENGTH];
|
||||
|
||||
class MessageQueue final {
|
||||
public:
|
||||
MessageQueue() { clear(); }
|
||||
|
||||
void clear() {
|
||||
memset(_buf, 0, sizeof(_buf));
|
||||
_head = 0;
|
||||
_filled = 0;
|
||||
}
|
||||
|
||||
void addMessage(const char* message) {
|
||||
#if MESSAGE_QUEUE_THREAD_SAFE
|
||||
portENTER_CRITICAL(&_mux);
|
||||
#endif
|
||||
strncpy(_buf[_head], message, MESSAGE_MAX_LENGTH - 1);
|
||||
_buf[_head][MESSAGE_MAX_LENGTH - 1] = '\0'; // Ensure null termination
|
||||
_head = (_head + 1) % MESSAGE_QUEUE_CAPACITY;
|
||||
if (_filled < MESSAGE_QUEUE_CAPACITY) {
|
||||
_filled++;
|
||||
}
|
||||
#if MESSAGE_QUEUE_THREAD_SAFE
|
||||
portEXIT_CRITICAL(&_mux);
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* getLine(size_t i) const {
|
||||
if (i >= lines()) return nullptr;
|
||||
size_t index = (_head + MESSAGE_QUEUE_CAPACITY - i - 1) % MESSAGE_QUEUE_CAPACITY;
|
||||
return _buf[index];
|
||||
}
|
||||
|
||||
size_t lines() const {
|
||||
return (_filled < MESSAGE_QUEUE_CAPACITY) ? _filled : MESSAGE_QUEUE_CAPACITY;
|
||||
}
|
||||
|
||||
private:
|
||||
MessageBuffer _buf{};
|
||||
size_t _head = 0U;
|
||||
size_t _filled = 0U;
|
||||
#if MESSAGE_QUEUE_THREAD_SAFE
|
||||
portMUX_TYPE _mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // MESSAGE_QUEUE_H
|
||||
@@ -0,0 +1,818 @@
|
||||
#ifndef NETWORK_VALUE_H
|
||||
#define NETWORK_VALUE_H
|
||||
|
||||
#include "Component.h"
|
||||
#include "modbus/ModbusTypes.h"
|
||||
#include <ArduinoLog.h>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <components/commons.h>
|
||||
#include "macros.h"
|
||||
#include "enums.h"
|
||||
#include <net/commons.h>
|
||||
|
||||
#define NETWORKVALUE_PERSISTENCE_ENABLED
|
||||
|
||||
#ifdef NETWORKVALUE_PERSISTENCE_ENABLED
|
||||
#include <ArduinoJson.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* =====================================================================================
|
||||
* FEATURE FLAGS
|
||||
* =====================================================================================
|
||||
* These flags control which features are compiled into the NetworkValue class.
|
||||
* They can be overridden in `platformio.ini` via `build_flags`.
|
||||
* Example: build_flags = -DNETWORKVALUE_ENABLE_LOGGING=0
|
||||
* By default, all features are enabled.
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef NETWORKVALUE_ENABLE_LOGGING
|
||||
#define NETWORKVALUE_ENABLE_LOGGING 0
|
||||
#endif
|
||||
#ifndef NETWORKVALUE_ENABLE_MODBUS
|
||||
#define NETWORKVALUE_ENABLE_MODBUS 1
|
||||
#endif
|
||||
#ifndef NETWORKVALUE_ENABLE_NOTIFY
|
||||
#define NETWORKVALUE_ENABLE_NOTIFY 1
|
||||
#endif
|
||||
#ifndef NETWORKVALUE_ENABLE_PROTOBUF
|
||||
#define NETWORKVALUE_ENABLE_PROTOBUF 0
|
||||
#endif
|
||||
|
||||
#if (NETWORKVALUE_ENABLE_PROTOBUF == 1)
|
||||
#include "NetworkValuePB.h"
|
||||
#define NETWORKVALUE_PROTOBUF_INHERITANCE , public maybe<NETWORKVALUE_ENABLE_PROTOBUF, NV_Protobuf>
|
||||
#else
|
||||
#define NETWORKVALUE_PROTOBUF_INHERITANCE
|
||||
#endif
|
||||
|
||||
enum class NetworkValue_ThresholdMode : uint8_t
|
||||
{
|
||||
DIFFERENCE, // Trigger if abs(newVal - oldVal) >= threshold
|
||||
INTERVAL_STEP // Trigger if floor(newVal / threshold) != floor(oldVal / threshold)
|
||||
};
|
||||
/*
|
||||
* =====================================================================================
|
||||
* FEATURE DEFINITIONS
|
||||
* =====================================================================================
|
||||
* These are modular classes that provide specific functionalities (e.g., logging,
|
||||
* network exposure, value tracking). They are composed by the NetworkValue class.
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class NV_Logging
|
||||
* @brief A feature that adds logging capabilities.
|
||||
*/
|
||||
class NV_Logging
|
||||
{
|
||||
protected:
|
||||
bool m_loggingEnabled = false;
|
||||
|
||||
public:
|
||||
void init_feature(bool enable)
|
||||
{
|
||||
enableLogging(enable);
|
||||
}
|
||||
|
||||
void enableLogging(bool enable)
|
||||
{
|
||||
m_loggingEnabled = enable;
|
||||
}
|
||||
|
||||
void clear_feature()
|
||||
{
|
||||
m_loggingEnabled = false;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void log(int level, const char *componentName, const char *fmt, Args... args) const { }
|
||||
void setup_feature() {}
|
||||
void loop_feature() {}
|
||||
void info_feature() const { }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class NV_Modbus
|
||||
* @brief A feature that makes the value available over Modbus.
|
||||
*/
|
||||
class NV_Modbus
|
||||
{
|
||||
protected:
|
||||
MB_Registers m_regInfo;
|
||||
|
||||
public:
|
||||
void init_feature(ushort startAddress, ushort count, ushort componentId, ushort slaveId, E_FN_CODE type, const char *name, const char *group)
|
||||
{
|
||||
configureModbus(startAddress, count, componentId, slaveId, type, name, group);
|
||||
}
|
||||
|
||||
void configureModbus(ushort startAddress, ushort count, ushort componentId, ushort slaveId, E_FN_CODE type, const char *name, const char *group)
|
||||
{
|
||||
m_regInfo = MB_Registers(startAddress, count, type, MB_ACCESS_READ_WRITE, componentId, slaveId, name, group);
|
||||
}
|
||||
|
||||
void clear_feature()
|
||||
{
|
||||
m_regInfo = {}; // Default constructs the struct
|
||||
}
|
||||
|
||||
MB_Registers getRegisterInfo() const { return m_regInfo; }
|
||||
|
||||
void setup_feature() {}
|
||||
void loop_feature() {}
|
||||
void info_feature() const
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class NV_Notify
|
||||
* @brief A feature that handles wrapping and tracking a value.
|
||||
*/
|
||||
template <typename T>
|
||||
class NV_Notify
|
||||
{
|
||||
private:
|
||||
// Helper for threshold comparison - DIFFERENCE mode, enum types
|
||||
template <typename U = T, typename std::enable_if<std::is_enum<U>::value, int>::type = 0>
|
||||
static bool checkThresholdDifference(U newVal, U oldVal, U threshold)
|
||||
{
|
||||
return newVal != oldVal;
|
||||
}
|
||||
|
||||
// Helper for threshold comparison - DIFFERENCE mode, non-enum, signed types
|
||||
template <typename U = T, typename std::enable_if<!std::is_enum<U>::value && std::is_signed<U>::value, int>::type = 0>
|
||||
static bool checkThresholdDifference(U newVal, U oldVal, U threshold)
|
||||
{
|
||||
return std::abs(newVal - oldVal) >= threshold;
|
||||
}
|
||||
|
||||
// Helper for threshold comparison - DIFFERENCE mode, non-enum, unsigned types
|
||||
template <typename U = T, typename std::enable_if<!std::is_enum<U>::value && std::is_unsigned<U>::value, int>::type = 0>
|
||||
static bool checkThresholdDifference(U newVal, U oldVal, U threshold)
|
||||
{
|
||||
U diff = (newVal > oldVal) ? (newVal - oldVal) : (oldVal - newVal);
|
||||
return diff >= threshold;
|
||||
}
|
||||
|
||||
// Helper for threshold comparison - INTERVAL_STEP mode (for arithmetic types)
|
||||
template <typename U = T, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0>
|
||||
static bool checkThresholdIntervalStep(U newVal, U oldVal, U stepInterval)
|
||||
{
|
||||
if (stepInterval == 0)
|
||||
return false; // Avoid division by zero
|
||||
return (static_cast<long long>(newVal / stepInterval)) != (static_cast<long long>(oldVal / stepInterval));
|
||||
}
|
||||
|
||||
// Fallback for non-arithmetic types with INTERVAL_STEP (should ideally not be chosen or error)
|
||||
template <typename U = T, typename std::enable_if<!std::is_arithmetic<U>::value, int>::type = 0>
|
||||
static bool checkThresholdIntervalStep(U newVal, U oldVal, U stepInterval)
|
||||
{
|
||||
return false; // Or throw, or static_assert(false, ...)
|
||||
}
|
||||
|
||||
protected:
|
||||
T m_value{};
|
||||
T m_lastValueOnUpdate{};
|
||||
T m_threshold{};
|
||||
NetworkValue_ThresholdMode m_thresholdMode = NetworkValue_ThresholdMode::DIFFERENCE;
|
||||
void (*m_onUpdateCallback)(const T &, const T &) = nullptr;
|
||||
|
||||
public:
|
||||
void init_feature(T initial, T threshold, NetworkValue_ThresholdMode mode, void (*cb)(const T &, const T &) = nullptr)
|
||||
{
|
||||
configureValue(initial, threshold, mode, cb);
|
||||
}
|
||||
|
||||
void configureValue(T initial, T threshold, NetworkValue_ThresholdMode mode, void (*cb)(const T &, const T &) = nullptr)
|
||||
{
|
||||
m_value = initial;
|
||||
m_lastValueOnUpdate = initial;
|
||||
m_threshold = threshold;
|
||||
m_thresholdMode = mode;
|
||||
m_onUpdateCallback = cb;
|
||||
}
|
||||
|
||||
void clear_feature()
|
||||
{
|
||||
m_value = T{};
|
||||
m_lastValueOnUpdate = T{};
|
||||
m_threshold = T{};
|
||||
m_onUpdateCallback = nullptr;
|
||||
m_thresholdMode = NetworkValue_ThresholdMode::DIFFERENCE;
|
||||
}
|
||||
|
||||
bool checkChanged(const T &newValue) const
|
||||
{
|
||||
// Compare the new value to the value at the time of the last update.
|
||||
bool changed = false;
|
||||
if (m_thresholdMode == NetworkValue_ThresholdMode::INTERVAL_STEP)
|
||||
{
|
||||
changed = checkThresholdIntervalStep(newValue, m_lastValueOnUpdate, m_threshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
changed = checkThresholdDifference(newValue, m_lastValueOnUpdate, m_threshold);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool applyUpdate(const T &newValue)
|
||||
{
|
||||
if (!checkChanged(newValue)) {
|
||||
return false;
|
||||
}
|
||||
T oldValue = m_lastValueOnUpdate;
|
||||
m_value = newValue;
|
||||
m_lastValueOnUpdate = newValue;
|
||||
if (m_onUpdateCallback)
|
||||
{
|
||||
m_onUpdateCallback(oldValue, m_value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
T getValue() const { return m_value; }
|
||||
T& getValueRef() { return m_value; }
|
||||
|
||||
void setup_feature() {}
|
||||
void loop_feature() {}
|
||||
void info_feature() const {}
|
||||
};
|
||||
|
||||
// Template specialization of NV_Notify for std::array
|
||||
template <typename T, size_t N>
|
||||
class NV_Notify<std::array<T, N>>
|
||||
{
|
||||
protected:
|
||||
std::array<T, N> m_value{};
|
||||
std::array<T, N> m_lastValueOnUpdate{};
|
||||
std::array<T, N> m_threshold{}; // Not used for arrays, but kept for signature compatibility
|
||||
NetworkValue_ThresholdMode m_thresholdMode = NetworkValue_ThresholdMode::DIFFERENCE;
|
||||
void (*m_onUpdateCallback)(const std::array<T, N> &, const std::array<T, N> &) = nullptr;
|
||||
|
||||
public:
|
||||
void init_feature(const std::array<T, N> &initial, const std::array<T, N> &threshold, NetworkValue_ThresholdMode mode, void (*cb)(const std::array<T, N> &, const std::array<T, N> &) = nullptr)
|
||||
{
|
||||
configureValue(initial, threshold, mode, cb);
|
||||
}
|
||||
|
||||
void configureValue(const std::array<T, N> &initial, const std::array<T, N> &threshold, NetworkValue_ThresholdMode mode, void (*cb)(const std::array<T, N> &, const std::array<T, N> &) = nullptr)
|
||||
{
|
||||
m_value = initial;
|
||||
m_lastValueOnUpdate = initial;
|
||||
m_threshold = threshold;
|
||||
m_thresholdMode = mode;
|
||||
m_onUpdateCallback = cb;
|
||||
}
|
||||
|
||||
void clear_feature()
|
||||
{
|
||||
m_value.fill(T{});
|
||||
m_lastValueOnUpdate.fill(T{});
|
||||
m_threshold.fill(T{});
|
||||
m_onUpdateCallback = nullptr;
|
||||
m_thresholdMode = NetworkValue_ThresholdMode::DIFFERENCE;
|
||||
}
|
||||
|
||||
// This specialized version of checkChanged now compares the new value against the last known state.
|
||||
bool checkChanged(const std::array<T, N> &newValue) const
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (newValue[i] != m_lastValueOnUpdate[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool applyUpdate(const std::array<T, N> &newValue)
|
||||
{
|
||||
if (!checkChanged(newValue)) {
|
||||
return false;
|
||||
}
|
||||
std::array<T, N> oldValue = m_lastValueOnUpdate;
|
||||
m_value = newValue;
|
||||
m_lastValueOnUpdate = newValue;
|
||||
if (m_onUpdateCallback)
|
||||
{
|
||||
m_onUpdateCallback(oldValue, m_value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::array<T, N> getValue() const { return m_value; }
|
||||
std::array<T, N>& getValueRef() { return m_value; }
|
||||
|
||||
void setup_feature() {}
|
||||
void loop_feature() {}
|
||||
void info_feature() const {}
|
||||
};
|
||||
|
||||
// Template specialization of NV_Notify for std::array<bool, N>
|
||||
template <size_t N>
|
||||
class NV_Notify<std::array<bool, N>>
|
||||
{
|
||||
protected:
|
||||
std::array<bool, N> m_value{};
|
||||
std::array<bool, N> m_lastValueOnUpdate{};
|
||||
std::array<bool, N> m_threshold{}; // Not used for bool arrays
|
||||
NetworkValue_ThresholdMode m_thresholdMode = NetworkValue_ThresholdMode::DIFFERENCE;
|
||||
void (*m_onUpdateCallback)(const std::array<bool, N> &, const std::array<bool, N> &) = nullptr;
|
||||
|
||||
public:
|
||||
void init_feature(const std::array<bool, N> &initial, const std::array<bool, N> &threshold, NetworkValue_ThresholdMode mode, void (*cb)(const std::array<bool, N> &, const std::array<bool, N> &) = nullptr)
|
||||
{
|
||||
configureValue(initial, threshold, mode, cb);
|
||||
}
|
||||
|
||||
void configureValue(const std::array<bool, N> &initial, const std::array<bool, N> &threshold, NetworkValue_ThresholdMode mode, void (*cb)(const std::array<bool, N> &, const std::array<bool, N> &) = nullptr)
|
||||
{
|
||||
m_value = initial;
|
||||
m_lastValueOnUpdate = initial;
|
||||
m_threshold = threshold; // Not used, but kept for signature compatibility
|
||||
m_thresholdMode = mode;
|
||||
m_onUpdateCallback = cb;
|
||||
}
|
||||
|
||||
void clear_feature()
|
||||
{
|
||||
m_value.fill(false);
|
||||
m_lastValueOnUpdate.fill(false);
|
||||
m_threshold.fill(false);
|
||||
m_onUpdateCallback = nullptr;
|
||||
m_thresholdMode = NetworkValue_ThresholdMode::DIFFERENCE;
|
||||
}
|
||||
|
||||
bool checkChanged(const std::array<bool, N> &newValue) const
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (newValue[i] != m_lastValueOnUpdate[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool applyUpdate(const std::array<bool, N> &newValue)
|
||||
{
|
||||
if (!checkChanged(newValue)) {
|
||||
return false;
|
||||
}
|
||||
std::array<bool, N> oldValue = m_lastValueOnUpdate;
|
||||
m_value = newValue;
|
||||
m_lastValueOnUpdate = newValue;
|
||||
if (m_onUpdateCallback)
|
||||
{
|
||||
m_onUpdateCallback(oldValue, m_value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::array<bool, N> getValue() const { return m_value; }
|
||||
std::array<bool, N>& getValueRef() { return m_value; }
|
||||
|
||||
void setup_feature() {}
|
||||
void loop_feature() {}
|
||||
void info_feature() const {}
|
||||
};
|
||||
|
||||
/*
|
||||
* =====================================================================================
|
||||
* NetworkValue AGGREGATOR
|
||||
* =====================================================================================
|
||||
* This class composes the features into a single Component.
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
class NetworkValueBase : public Component
|
||||
{
|
||||
public:
|
||||
using Component::Component;
|
||||
virtual ~NetworkValueBase() = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class NetworkValue : public NetworkValueBase,
|
||||
public maybe<NETWORKVALUE_ENABLE_LOGGING, NV_Logging>,
|
||||
public maybe<NETWORKVALUE_ENABLE_MODBUS, NV_Modbus>,
|
||||
public maybe<NETWORKVALUE_ENABLE_NOTIFY, NV_Notify<T>>
|
||||
NETWORKVALUE_PROTOBUF_INHERITANCE
|
||||
{
|
||||
private:
|
||||
// --- Tag Dispatching for update() method ---
|
||||
struct regular_type_tag
|
||||
{
|
||||
};
|
||||
struct array_type_tag
|
||||
{
|
||||
};
|
||||
|
||||
template <typename U>
|
||||
struct get_update_tag
|
||||
{
|
||||
using type = regular_type_tag;
|
||||
};
|
||||
template <typename U, size_t M>
|
||||
struct get_update_tag<std::array<U, M>>
|
||||
{
|
||||
using type = array_type_tag;
|
||||
};
|
||||
|
||||
// Implementation for regular types (sends onMessage)
|
||||
void update_impl(const T &newValue, regular_type_tag, E_PRIORITY priority)
|
||||
{
|
||||
// The value has already been applied by update(), so we just send notifications.
|
||||
if (this->owner)
|
||||
{
|
||||
#if (NETWORKVALUE_ENABLE_PROTOBUF == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_PROTOBUF)) {
|
||||
uint8_t buffer[64]; // Static buffer for PB encoding
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
MB_Registers regInfo = this->getRegisterInfo();
|
||||
if (this->encode(&stream, regInfo, newValue)) {
|
||||
PB_UpdateData pb_msg;
|
||||
pb_msg.data = buffer;
|
||||
pb_msg.len = stream.bytes_written;
|
||||
pb_msg.componentId = this->id;
|
||||
this->owner->onMessage(this->id, E_CALLS::EC_PROTOBUF_UPDATE, E_MessageFlags::E_MF_NONE, &pb_msg, this->owner);
|
||||
} else {
|
||||
Log.warningln(F(" [update_impl] Protobuf encoding failed for '%s'"), this->name.c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (NETWORKVALUE_ENABLE_MODBUS && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
{
|
||||
MB_UpdateData update_msg{}; // Zero-initialize
|
||||
MB_Registers regInfo = this->getRegisterInfo();
|
||||
update_msg.address = regInfo.startAddress;
|
||||
// For single values, we point to the stable internal value.
|
||||
update_msg.userData = const_cast<void *>(static_cast<const void *>(&this->m_value));
|
||||
update_msg.count = 1;
|
||||
update_msg.value = getModbusValueHelper(newValue); // Keep for coil compatibility
|
||||
update_msg.slaveId = regInfo.slaveId;
|
||||
update_msg.functionCode = regInfo.type;
|
||||
update_msg.priority = priority;
|
||||
update_msg.componentId = this->id;
|
||||
this->owner->onMessage(this->id, E_CALLS::EC_USER, E_MessageFlags::E_MF_NONE, &update_msg, this->owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for std::array (now sends onMessage)
|
||||
template <typename U, size_t M>
|
||||
void update_impl(const std::array<U, M> &newValue, array_type_tag, E_PRIORITY priority)
|
||||
{
|
||||
// The value has already been applied by update(), so we just send notifications.
|
||||
if (this->owner)
|
||||
{
|
||||
#if (NETWORKVALUE_ENABLE_PROTOBUF == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_PROTOBUF)) {
|
||||
uint8_t buffer[256]; // Larger buffer for arrays
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
MB_Registers regInfo = this->getRegisterInfo();
|
||||
if (this->encode(&stream, regInfo, newValue)) {
|
||||
PB_UpdateData pb_msg;
|
||||
pb_msg.data = buffer;
|
||||
pb_msg.len = stream.bytes_written;
|
||||
pb_msg.componentId = this->id;
|
||||
this->owner->onMessage(this->id, E_CALLS::EC_PROTOBUF_UPDATE, E_MessageFlags::E_MF_NONE, &pb_msg, this->owner);
|
||||
} else {
|
||||
Log.warningln(F(" [update_impl] Protobuf encoding failed for array '%s'"), this->name.c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (NETWORKVALUE_ENABLE_MODBUS && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
{
|
||||
MB_UpdateData update_msg{}; // Zero-initialize
|
||||
MB_Registers regInfo = this->getRegisterInfo();
|
||||
update_msg.address = regInfo.startAddress;
|
||||
update_msg.count = this->m_value.size();
|
||||
update_msg.userData = const_cast<void *>(static_cast<const void *>(this->m_value.data()));
|
||||
update_msg.slaveId = regInfo.slaveId;
|
||||
update_msg.functionCode = regInfo.type;
|
||||
update_msg.priority = priority;
|
||||
update_msg.componentId = this->id;
|
||||
this->owner->onMessage(this->id, E_CALLS::EC_USER, E_MessageFlags::E_MF_NONE, &update_msg, this->owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to get value for Modbus message (short) - enabled for enum types
|
||||
template <typename U = T, typename std::enable_if<std::is_enum<U>::value, int>::type = 0>
|
||||
static short getModbusValueHelper(U val)
|
||||
{
|
||||
return static_cast<short>(static_cast<typename std::underlying_type<U>::type>(val));
|
||||
}
|
||||
|
||||
// Helper to get value for Modbus message (short) - enabled for non-enum types
|
||||
template <typename U = T, typename std::enable_if<!std::is_enum<U>::value, int>::type = 0>
|
||||
static short getModbusValueHelper(U val)
|
||||
{
|
||||
return static_cast<short>(val);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
NetworkValue(Component *owner, ushort id,
|
||||
const char *name,
|
||||
T initial, T threshold, NetworkValue_ThresholdMode mode, void (*cb)(const T &, const T &) = nullptr,
|
||||
uint8_t featureFlags = static_cast<uint8_t>(E_NetworkValueFeatureFlags::E_NVFF_ALL))
|
||||
: NetworkValueBase(name, id, COMPONENT_DEFAULT, owner, featureFlags)
|
||||
{
|
||||
initNotify(initial, threshold, mode, cb);
|
||||
|
||||
#if (NETWORKVALUE_ENABLE_LOGGING == 1)
|
||||
if (owner && owner->hasFlag(OBJECT_RUN_FLAGS::E_OF_DEBUG))
|
||||
{
|
||||
this->setFlag(OBJECT_RUN_FLAGS::E_OF_DEBUG);
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
{
|
||||
this->initLogging(true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NetworkValue(Component *owner, ushort id,
|
||||
const char *name,
|
||||
uint8_t featureFlags = static_cast<uint8_t>(E_NetworkValueFeatureFlags::E_NVFF_ALL))
|
||||
: NetworkValueBase(name, id, COMPONENT_DEFAULT, owner, featureFlags)
|
||||
{
|
||||
#if (NETWORKVALUE_ENABLE_LOGGING == 1)
|
||||
if (owner && owner->hasFlag(OBJECT_RUN_FLAGS::E_OF_DEBUG))
|
||||
{
|
||||
this->setFlag(OBJECT_RUN_FLAGS::E_OF_DEBUG);
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
{
|
||||
this->initLogging(true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
this->flags = 0;
|
||||
this->nFlags = 0;
|
||||
#if (NETWORKVALUE_ENABLE_LOGGING == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
this->NV_Logging::clear_feature();
|
||||
#endif
|
||||
if (NETWORKVALUE_ENABLE_MODBUS && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
this->NV_Modbus::clear_feature();
|
||||
if (NETWORKVALUE_ENABLE_NOTIFY && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_NOTIFY))
|
||||
this->NV_Notify<T>::clear_feature();
|
||||
#if (NETWORKVALUE_ENABLE_PROTOBUF == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_PROTOBUF))
|
||||
this->NV_Protobuf::clear_feature();
|
||||
#endif
|
||||
}
|
||||
|
||||
short setup() override
|
||||
{
|
||||
#if (NETWORKVALUE_ENABLE_LOGGING == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
this->NV_Logging::setup_feature();
|
||||
#endif
|
||||
if (NETWORKVALUE_ENABLE_MODBUS && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
this->NV_Modbus::setup_feature();
|
||||
if (NETWORKVALUE_ENABLE_NOTIFY && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_NOTIFY))
|
||||
this->NV_Notify<T>::setup_feature();
|
||||
#if (NETWORKVALUE_ENABLE_PROTOBUF == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_PROTOBUF))
|
||||
this->NV_Protobuf::setup_feature();
|
||||
#endif
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
short loop() override
|
||||
{
|
||||
Component::loop();
|
||||
#if (NETWORKVALUE_ENABLE_LOGGING == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
this->NV_Logging::loop_feature();
|
||||
#endif
|
||||
if (NETWORKVALUE_ENABLE_MODBUS && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
this->NV_Modbus::loop_feature();
|
||||
if (NETWORKVALUE_ENABLE_NOTIFY && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_NOTIFY))
|
||||
this->NV_Notify<T>::loop_feature();
|
||||
#if (NETWORKVALUE_ENABLE_PROTOBUF == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_PROTOBUF))
|
||||
this->NV_Protobuf::loop_feature();
|
||||
#endif
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
short info() override {
|
||||
Component::info();
|
||||
#if (NETWORKVALUE_ENABLE_LOGGING == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
this->NV_Logging::info_feature();
|
||||
#endif
|
||||
if (NETWORKVALUE_ENABLE_MODBUS && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
this->NV_Modbus::info_feature();
|
||||
if (NETWORKVALUE_ENABLE_NOTIFY && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_NOTIFY))
|
||||
this->NV_Notify<T>::info_feature();
|
||||
#if (NETWORKVALUE_ENABLE_PROTOBUF == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_PROTOBUF))
|
||||
this->NV_Protobuf::info_feature();
|
||||
#endif
|
||||
return E_OK;
|
||||
}
|
||||
template <typename U = T>
|
||||
bool update(const U &newValue, E_PRIORITY priority = E_PRIORITY::E_PRIORITY_LOWEST)
|
||||
{
|
||||
if (!this->applyUpdate(newValue)) {
|
||||
return false; // If no change, do nothing further.
|
||||
}
|
||||
|
||||
#if (NETWORKVALUE_ENABLE_LOGGING == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
{
|
||||
// this->log(LOG_LEVEL_TRACE, this->name.c_str(), "Value is changing.");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Dispatch notifications
|
||||
if (this->owner) {
|
||||
update_impl(newValue, typename get_update_tag<U>::type(), priority);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- Feature-specific API ---
|
||||
|
||||
// Logging API
|
||||
void initLogging(bool enableLogging)
|
||||
{
|
||||
#if (NETWORKVALUE_ENABLE_LOGGING == 1)
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
{
|
||||
NV_Logging::init_feature(enableLogging);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Modbus API
|
||||
void initModbus(ushort startAddress, ushort count, ushort componentId, ushort slaveId, E_FN_CODE type, const char *name, const char *group)
|
||||
{
|
||||
if (NETWORKVALUE_ENABLE_MODBUS && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
{
|
||||
NV_Modbus::init_feature(startAddress, count, componentId, slaveId, type, name, group);
|
||||
}
|
||||
}
|
||||
|
||||
MB_Registers getRegisterInfo() const
|
||||
{
|
||||
if (NETWORKVALUE_ENABLE_MODBUS && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
{
|
||||
return NV_Modbus::getRegisterInfo();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Notify API
|
||||
void initNotify(T initial, T threshold, NetworkValue_ThresholdMode mode, void (*cb)(const T &, const T &) = nullptr)
|
||||
{
|
||||
if (NETWORKVALUE_ENABLE_NOTIFY && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_NOTIFY))
|
||||
{
|
||||
NV_Notify<T>::init_feature(initial, threshold, mode, cb);
|
||||
}
|
||||
}
|
||||
|
||||
bool applyUpdate(const T& newValue) {
|
||||
if (NETWORKVALUE_ENABLE_NOTIFY && hasFeature(E_NetworkValueFeatureFlags::E_NVFF_NOTIFY)) {
|
||||
return NV_Notify<T>::applyUpdate(newValue);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
T getValue() const { return NV_Notify<T>::getValue(); }
|
||||
T& getValueRef() { return NV_Notify<T>::getValueRef(); }
|
||||
|
||||
using NV_Notify<T>::getValue;
|
||||
using NV_Notify<T>::getValueRef;
|
||||
using NV_Modbus::getRegisterInfo;
|
||||
|
||||
template <typename JsonObjT>
|
||||
void toJSON(JsonObjT &obj) const
|
||||
{
|
||||
obj["id"] = this->id;
|
||||
obj["name"] = this->name;
|
||||
obj["flags"] = this->flags;
|
||||
obj["nFlags"] = this->nFlags;
|
||||
obj["fFlags"] = this->fFlags;
|
||||
|
||||
#if NETWORKVALUE_ENABLE_LOGGING
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING))
|
||||
{
|
||||
obj["logging_enabled"] = this->m_loggingEnabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NETWORKVALUE_ENABLE_MODBUS
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS))
|
||||
{
|
||||
auto mod = obj.createNestedObject("modbus");
|
||||
MB_Registers reg = this->getRegisterInfo();
|
||||
mod["startAddress"] = reg.startAddress;
|
||||
mod["count"] = reg.count;
|
||||
mod["slaveId"] = reg.slaveId;
|
||||
mod["type"] = reg.type;
|
||||
mod["name"] = reg.name ? reg.name : "";
|
||||
mod["group"] = reg.group ? reg.group : "";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NETWORKVALUE_ENABLE_PROTOBUF == 1)
|
||||
// Protobuf feature is stateless, nothing to serialize to JSON.
|
||||
#endif
|
||||
|
||||
#if NETWORKVALUE_ENABLE_NOTIFY
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_NOTIFY))
|
||||
{
|
||||
auto notify = obj.createNestedObject("notify");
|
||||
notify["threshold"] = this->m_threshold;
|
||||
notify["mode"] = static_cast<int>(this->m_thresholdMode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename JsonObjT>
|
||||
void fromJSON(const JsonObjT &obj)
|
||||
{
|
||||
#if NETWORKVALUE_ENABLE_LOGGING
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_LOGGING) && obj.containsKey("logging_enabled"))
|
||||
{
|
||||
this->enableLogging(obj["logging_enabled"].template as<bool>());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NETWORKVALUE_ENABLE_MODBUS
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_MODBUS) && obj.containsKey("modbus"))
|
||||
{
|
||||
auto mod = obj["modbus"].template as<ArduinoJson::JsonObjectConst>();
|
||||
ushort startAddress = mod["startAddress"].template as<ushort>();
|
||||
ushort count = mod["count"].template as<ushort>();
|
||||
ushort slaveId = mod["slaveId"].template as<ushort>();
|
||||
E_FN_CODE fn = static_cast<E_FN_CODE>(mod["type"].template as<uint8_t>());
|
||||
const char *mname = mod["name"].template as<const char *>();
|
||||
const char *group = mod["group"].template as<const char *>();
|
||||
this->configureModbus(startAddress, count, this->id, slaveId, fn, mname, group);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NETWORKVALUE_ENABLE_NOTIFY
|
||||
if (hasFeature(E_NetworkValueFeatureFlags::E_NVFF_NOTIFY) && obj.containsKey("notify"))
|
||||
{
|
||||
auto notify = obj["notify"].template as<ArduinoJson::JsonObjectConst>();
|
||||
T threshold = notify["threshold"].template as<T>();
|
||||
NetworkValue_ThresholdMode mode = static_cast<NetworkValue_ThresholdMode>(notify["mode"].template as<uint8_t>());
|
||||
this->configureValue(this->getValue(), threshold, mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* =====================================================================================
|
||||
* EXAMPLE USAGE (POC)
|
||||
* =====================================================================================
|
||||
* To disable a feature at compile-time, add e.g. `-DNETWORKVALUE_ENABLE_LOGGING=0` to build_flags.
|
||||
* To disable a feature at runtime, use the new API.
|
||||
* =====================================================================================
|
||||
* In TemperatureProfile.h:
|
||||
*
|
||||
* #include "NetworkValue.h"
|
||||
*
|
||||
* using StatusValue = NetworkValue<PlotStatus>;
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
* =====================================================================================
|
||||
* In TemperatureProfile.cpp constructor:
|
||||
*
|
||||
* // Instantiate with only Modbus and Notify features enabled at runtime
|
||||
* _statusValue(this, this->id, "TProf Status",
|
||||
* static_cast<uint8_t>(NetworkValueFeatureFlags::MODBUS) |
|
||||
* static_cast<uint8_t>(NetworkValueFeatureFlags::NOTIFY));
|
||||
*
|
||||
* // Configure the enabled features
|
||||
* _statusValue.initNotify(...);
|
||||
* _statusValue.initModbus(...);
|
||||
* _statusValue.initLogging(true);
|
||||
*
|
||||
* // You can also toggle features later
|
||||
* _statusValue.enableFeature(NetworkValueFeatureFlags::LOGGING);
|
||||
*
|
||||
*/
|
||||
|
||||
#endif // NETWORK_VALUE_H
|
||||
@@ -0,0 +1,88 @@
|
||||
#ifndef NETWORK_VALUE_PB_H
|
||||
#define NETWORK_VALUE_PB_H
|
||||
|
||||
#include "pb_encode.h"
|
||||
#include "modbus/ModbusTypes.h"
|
||||
#include <type_traits>
|
||||
#include <Arduino.h> // For millis()
|
||||
|
||||
class NV_Protobuf {
|
||||
protected:
|
||||
// This is a feature class, and its methods will be called from NetworkValue.
|
||||
// It is stateless.
|
||||
|
||||
public:
|
||||
void init_feature() {}
|
||||
void clear_feature() {}
|
||||
void setup_feature() {}
|
||||
void loop_feature() {}
|
||||
|
||||
void debug_pb_feature() const {
|
||||
Serial.println("[NV_Debug] ==> NV_Protobuf::debug_pb_feature() CALLED <==");
|
||||
}
|
||||
|
||||
void info_feature() const {
|
||||
Log.traceln(F(" [Feature: Protobuf] Enabled"));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool encode(pb_ostream_t *stream, const MB_Registers& regInfo, const T& value) const {
|
||||
// Field 1: address (uint32)
|
||||
if (!pb_encode_tag(stream, PB_WT_VARINT, 1)) return false;
|
||||
if (!pb_encode_varint(stream, regInfo.startAddress)) return false;
|
||||
|
||||
// Field 2: timestamp (uint64)
|
||||
if (!pb_encode_tag(stream, PB_WT_VARINT, 2)) return false;
|
||||
if (!pb_encode_varint(stream, millis())) return false;
|
||||
|
||||
// oneof value
|
||||
return encode_value(stream, value);
|
||||
}
|
||||
|
||||
private:
|
||||
// For bool
|
||||
bool encode_value(pb_ostream_t *stream, const bool& value) const {
|
||||
if (!pb_encode_tag(stream, PB_WT_VARINT, 4)) return false; // field 4
|
||||
return pb_encode_varint(stream, value);
|
||||
}
|
||||
|
||||
// For integers (signed and unsigned) and enums
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, bool>::type
|
||||
encode_value(pb_ostream_t *stream, const T& value) const {
|
||||
if (!pb_encode_tag(stream, PB_WT_VARINT, 3)) return false; // field 3
|
||||
return pb_encode_svarint(stream, static_cast<int64_t>(value));
|
||||
}
|
||||
|
||||
// For enums
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_enum<T>::value, bool>::type
|
||||
encode_value(pb_ostream_t *stream, const T& value) const {
|
||||
if (!pb_encode_tag(stream, PB_WT_VARINT, 3)) return false; // field 3, same as integers
|
||||
return pb_encode_svarint(stream, static_cast<int64_t>(value));
|
||||
}
|
||||
|
||||
// For floats/doubles
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_floating_point<T>::value, bool>::type
|
||||
encode_value(pb_ostream_t *stream, const T& value) const {
|
||||
float float_val = static_cast<float>(value);
|
||||
if (!pb_encode_tag(stream, PB_WT_32BIT, 5)) return false; // field 5
|
||||
return pb_encode_fixed32(stream, &float_val);
|
||||
}
|
||||
|
||||
// For std::array
|
||||
template <typename T, size_t N>
|
||||
bool encode_value(pb_ostream_t *stream, const std::array<T, N>& value) const {
|
||||
if (!pb_encode_tag(stream, PB_WT_STRING, 6)) return false; // field 6
|
||||
return pb_encode_string(stream, (pb_byte_t*)value.data(), value.size() * sizeof(T));
|
||||
}
|
||||
|
||||
// For std::string
|
||||
bool encode_value(pb_ostream_t *stream, const std::string& value) const {
|
||||
if (!pb_encode_tag(stream, PB_WT_STRING, 6)) return false; // field 6
|
||||
return pb_encode_string(stream, (const pb_byte_t*)value.c_str(), value.length());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // NETWORK_VALUE_PB_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user