From 60133f5791fd9e0e4092cc5282eb77e41e7c9cea Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Fri, 26 Aug 2022 21:44:17 +0200 Subject: [PATCH 1/8] [P138] Add Power mgt - IP5306 plugin --- platformio_esp32_envs.ini | 1 + platformio_esp82xx_base.ini | 1 + src/Custom-sample.h | 1 + src/_P138_IP5306.ino | 227 +++++++++++++++++++++ src/src/CustomBuild/define_plugin_sets.h | 12 ++ src/src/PluginStructs/P138_data_struct.cpp | 152 ++++++++++++++ src/src/PluginStructs/P138_data_struct.h | 59 ++++++ 7 files changed, 453 insertions(+) create mode 100644 src/_P138_IP5306.ino create mode 100644 src/src/PluginStructs/P138_data_struct.cpp create mode 100644 src/src/PluginStructs/P138_data_struct.h diff --git a/platformio_esp32_envs.ini b/platformio_esp32_envs.ini index 034612c12..1f1b9866b 100644 --- a/platformio_esp32_envs.ini +++ b/platformio_esp32_envs.ini @@ -44,6 +44,7 @@ lib_deps = VL53L0X @ 1.3.0 RAK12019_LTR390_UV_Light Adafruit NeoMatrix + codewitch-honey-crisis/htcw_ip5306@^0.1.0 extra_scripts = post:tools/pio/post_esp32.py ${extra_scripts_default.extra_scripts} build_unflags = -Wall diff --git a/platformio_esp82xx_base.ini b/platformio_esp82xx_base.ini index 368bc2909..2943f8563 100644 --- a/platformio_esp82xx_base.ini +++ b/platformio_esp82xx_base.ini @@ -94,6 +94,7 @@ lib_deps = VL53L0X @ 1.3.0 RAK12019_LTR390_UV_Light Adafruit NeoMatrix + codewitch-honey-crisis/htcw_ip5306@^0.1.0 lib_ignore = ${esp82xx_defaults.lib_ignore} IRremoteESP8266 HeatpumpIR diff --git a/src/Custom-sample.h b/src/Custom-sample.h index 915df5a14..4c31062b7 100644 --- a/src/Custom-sample.h +++ b/src/Custom-sample.h @@ -450,6 +450,7 @@ static const char DATA_ESPEASY_DEFAULT_MIN_CSS[] PROGMEM = { // #define USES_P131 // NeoMatrix // #define USES_P132 // INA3221 // #define USES_P133 // LTR390 UV +// #define USES_P138 // IP5306 // #define USES_P128 // NeoPixelBusFX // #define P128_USES_GRB // Default diff --git a/src/_P138_IP5306.ino b/src/_P138_IP5306.ino new file mode 100644 index 000000000..135686287 --- /dev/null +++ b/src/_P138_IP5306.ino @@ -0,0 +1,227 @@ +#include "_Plugin_Helper.h" +#ifdef USES_P138 + +// ####################################################################################################### +// #################################### Plugin 138: IP5306 Powermanagement ############################### +// ####################################################################################################### + +/** + * Changelog: + * 2022-08-236 tonhuisman: Initial plugin development, using codewitch-honey-crisis/htcw_ip5306 library + **/ + +/** + * Supported commands: (none yet) + **/ +/** + * Get Config options: + * [#batcurrent] : Battery current + * [#chundervolt] : Charge Undervoltage + * [#stopvolt] : Input voltage + * [#inpcurrent] : Input current + * [#pwrsource] : Powersource + * // To re-use these lines: + * [#vbuscurr] : VBus current + * [#inttemp] : Internal temperature + * [#apsvolt] : APS voltage + * [#ldo2volt] : LDO2 voltage + * [#ldo3volt] : LDO3 voltage + * [#gpio0volt] : GPIO0 voltage + **/ + + +# define PLUGIN_138 +# define PLUGIN_ID_138 138 +# define PLUGIN_NAME_138 "Power mgt - IP5306 Power management [TESTING]" + +# include "./src/PluginStructs/P138_data_struct.h" + +boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_138; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_138); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + for (uint8_t i = 0; i < VARS_PER_TASK; ++i) { + if (i < P138_NR_OUTPUT_VALUES) { + safe_strncpy( + ExtraTaskSettings.TaskDeviceValueNames[i], + toString(static_cast(PCONFIG(P138_CONFIG_BASE + i)), false), + sizeof(ExtraTaskSettings.TaskDeviceValueNames[i])); + } else { + ZERO_FILL(ExtraTaskSettings.TaskDeviceValueNames[i]); + } + } + break; + } + + case PLUGIN_GET_DEVICEVALUECOUNT: + { + event->Par1 = P138_NR_OUTPUT_VALUES; + success = true; + break; + } + + case PLUGIN_GET_DEVICEVTYPE: + { + event->sensorType = static_cast(PCONFIG(P138_SENSOR_TYPE_INDEX)); + event->idx = P138_SENSOR_TYPE_INDEX; + success = true; + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + { + success = event->Par1 == 0x75; + break; + } + + case PLUGIN_SET_DEFAULTS: + { + PCONFIG(0) = static_cast(P138_valueOptions_e::StopVoltage); + PCONFIG(1) = static_cast(P138_valueOptions_e::InCurrent); + PCONFIG(2) = static_cast(P138_valueOptions_e::BatteryCurrent); + PCONFIG(3) = static_cast(P138_valueOptions_e::ChargeLevel); + PCONFIG(P138_SENSOR_TYPE_INDEX) = static_cast(Sensor_VType::SENSOR_TYPE_QUAD); + P138_CONFIG_DECIMALS = 2; // 2 decimals for all get config values + bitSet(P138_CONFIG_FLAGS, P138_FLAG_POWERCHANGE); // Enable event + + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + { + const __FlashStringHelper *valOptions[] = { + toString(P138_valueOptions_e::None), + + // toString(P138_valueOptions_e::BatteryVoltage), + toString(P138_valueOptions_e::BatteryCurrent), + toString(P138_valueOptions_e::ChargeUnderVoltage), + toString(P138_valueOptions_e::StopVoltage), + toString(P138_valueOptions_e::InCurrent), + toString(P138_valueOptions_e::ChargeLevel), + toString(P138_valueOptions_e::PowerSource), + }; + const int valValues[] = { + static_cast(P138_valueOptions_e::None), + + // static_cast(P138_valueOptions_e::BatteryVoltage), + static_cast(P138_valueOptions_e::BatteryCurrent), + static_cast(P138_valueOptions_e::ChargeUnderVoltage), + static_cast(P138_valueOptions_e::StopVoltage), + static_cast(P138_valueOptions_e::InCurrent), + static_cast(P138_valueOptions_e::ChargeLevel), + static_cast(P138_valueOptions_e::PowerSource), + }; + + for (uint8_t i = 0; i < P138_NR_OUTPUT_VALUES; i++) { + sensorTypeHelper_loadOutputSelector(event, + P138_CONFIG_BASE + i, + i, + sizeof(valValues) / sizeof(int), + valOptions, + valValues); + } + } + + addFormNumericBox(F("Decimals for config values"), F("decimals"), P138_CONFIG_DECIMALS, 0, 4); + + addFormCheckBox(F("Event on PowerSource change"), F("eventpwrchg"), bitRead(P138_CONFIG_FLAGS, P138_FLAG_POWERCHANGE)); + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + for (uint8_t i = 0; i < P138_NR_OUTPUT_VALUES; i++) { + sensorTypeHelper_saveOutputSelector(event, P138_CONFIG_BASE + i, i, + toString(static_cast(PCONFIG(P138_CONFIG_BASE + i)), false)); + } + + P138_CONFIG_DECIMALS = getFormItemInt(F("decimals")); + bitWrite(P138_CONFIG_FLAGS, P138_FLAG_POWERCHANGE, isFormItemChecked(F("eventpwrchg"))); + + success = true; + break; + } + + case PLUGIN_INIT: + { + initPluginTaskData(event->TaskIndex, new (std::nothrow) P138_data_struct(event)); + P138_data_struct *P138_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P138_data) { + success = true; + } + + break; + } + + case PLUGIN_READ: + { + P138_data_struct *P138_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P138_data) { + success = P138_data->plugin_read(event); + } + break; + } + + case PLUGIN_FIFTY_PER_SECOND: + { + P138_data_struct *P138_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P138_data) { + success = P138_data->plugin_fifty_per_second(event); + } + break; + } + + // case PLUGIN_WRITE: + // { + // P138_data_struct *P138_data = static_cast(getPluginTaskData(event->TaskIndex)); + + // if (nullptr != P138_data) { + // success = P138_data->plugin_write(event, string); + // } + // break; + // } + + case PLUGIN_GET_CONFIG_VALUE: + { + P138_data_struct *P138_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P138_data) { + success = P138_data->plugin_get_config_value(event, string); // GetConfig operation, handle variables + } + break; + } + } + + return success; +} + +#endif // USES_P138 diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 06eab61ff..1b11c59f4 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -1228,6 +1228,9 @@ To create/register a plugin, you have to : #define USES_P081 // Cron #define USES_P082 // GPS #define USES_P089 // Ping + #if !defined(USES_P138) && defined(ESP32) + #define USES_P138 // IP5306 + #endif #endif #ifdef PLUGIN_SET_COLLECTION_A @@ -1348,6 +1351,9 @@ To create/register a plugin, you have to : #ifndef USES_P132 #define USES_P132 // INA3221 #endif + #if !defined(USES_P138) && defined(ESP32) + #define USES_P138 // IP5306 + #endif #endif // Collection of all display plugins. (also NeoPixel) @@ -1406,6 +1412,9 @@ To create/register a plugin, you have to : #ifndef USES_P116 #define USES_P116 // ST77xx #endif + #if !defined(USES_P138) && defined(ESP32) + #define USES_P138 // IP5306 + #endif #endif // Collection of all NeoPixel plugins @@ -1444,6 +1453,9 @@ To create/register a plugin, you have to : #undef FEATURE_CHART_JS #define FEATURE_CHART_JS 0 #endif + #if !defined(USES_P138) && defined(ESP32) + #define USES_P138 // IP5306 + #endif #endif #ifdef CONTROLLER_SET_COLLECTION diff --git a/src/src/PluginStructs/P138_data_struct.cpp b/src/src/PluginStructs/P138_data_struct.cpp new file mode 100644 index 000000000..63a053792 --- /dev/null +++ b/src/src/PluginStructs/P138_data_struct.cpp @@ -0,0 +1,152 @@ +#include "../PluginStructs/P138_data_struct.h" + +#ifdef USES_P138 + +// **************************************************************************/ +// toString: convert P138_valueOptions_e enum to value-name or display-name +// **************************************************************************/ +const __FlashStringHelper* toString(const P138_valueOptions_e value, bool displayString) { + switch (value) { + case P138_valueOptions_e::None: return displayString ? F("None") : F("none"); + + // case P138_valueOptions_e::BatteryVoltage: return displayString ? F("Battery voltage") : F("batteryvoltage"); + case P138_valueOptions_e::BatteryCurrent: return displayString ? F("Battery current") : F("batterycurrent"); + case P138_valueOptions_e::ChargeUnderVoltage: return displayString ? F("Charge undervoltage") : F("chargeundervoltage"); + case P138_valueOptions_e::StopVoltage: return displayString ? F("Stop voltage") : F("stopvoltage"); + case P138_valueOptions_e::InCurrent: return displayString ? F("Input current") : F("inputcurrent"); + case P138_valueOptions_e::ChargeLevel: return displayString ? F("Charge level") : F("chargelevel"); + case P138_valueOptions_e::PowerSource: return displayString ? F("Power source") : F("powersource"); + } + return F("*Undefined*"); +} + +// **************************************************************************/ +// Constructor +// **************************************************************************/ +P138_data_struct::P138_data_struct(struct EventStruct *event) { + addLog(LOG_LEVEL_INFO, F("AXP192: Init.")); + + _ip5306 = new (std::nothrow) arduino::ip5306(); // Default address and I2C Wire object +} + +// **************************************************************************/ +// Destructor +// **************************************************************************/ +P138_data_struct::~P138_data_struct() { + delete _ip5306; + _ip5306 = nullptr; +} + +// **************************************************************************/ +// plugin_read: Read the values and send to controller(s) +// **************************************************************************/ +bool P138_data_struct::plugin_read(struct EventStruct *event) { + bool success = true; + + for (uint8_t i = 0; i < P138_NR_OUTPUT_VALUES; i++) { + UserVar[event->BaseVarIndex + i] = read_value(static_cast(PCONFIG(P138_CONFIG_BASE + i))); + } + + return success; +} + +// **************************************************************************/ +// plugin_fifty_per_second: check if the powersource changed and generate an event for that +// **************************************************************************/ +bool P138_data_struct::plugin_fifty_per_second(struct EventStruct *event) { + bool success = true; + + if (bitRead(P138_CONFIG_FLAGS, P138_FLAG_POWERCHANGE) && isInitialized()) { + int8_t src = static_cast(_ip5306->power_source()); + + if (_lastPowerSource != src) { // Changed? + String eventCommand = getTaskDeviceName(event->TaskIndex); + eventCommand += F("#PowerChanged="); + eventCommand += src; // 0 = battery, 1 = Vin + eventQueue.add(eventCommand); + _lastPowerSource = src; // Keep current + } + } + return success; +} + +// **************************************************************************/ +// read_value: Read the requested value +// **************************************************************************/ +float P138_data_struct::read_value(P138_valueOptions_e value) { + if (isInitialized()) { + switch (value) { + case P138_valueOptions_e::None: return 0.0f; + case P138_valueOptions_e::BatteryCurrent: { + const float charge_current[] = { 200.0f, 400.0f, 500.0f, 600.0f }; + return charge_current[static_cast(_ip5306->end_charge_current_detection())]; + } + case P138_valueOptions_e::ChargeUnderVoltage: return _ip5306->charge_under_voltage_loop(); + case P138_valueOptions_e::StopVoltage: { + const float stop_voltage[] = { 4.14f, 4.17f, 4.185f, 4.2f }; + return stop_voltage[static_cast(_ip5306->charging_full_stop_voltage())]; + } + case P138_valueOptions_e::InCurrent: return static_cast(_ip5306->vin_current()); + case P138_valueOptions_e::ChargeLevel: return _ip5306->charge_level() * 100.0f; // Make percentage + case P138_valueOptions_e::PowerSource: return static_cast(_ip5306->power_source()); // 0 = batt, 1 = Vin + } + } + return 0.0f; +} + +// **************************************************************************/ +// plugin_write: Process commands +// **************************************************************************/ +bool P138_data_struct::plugin_write(struct EventStruct *event, + const String & string) { + bool success = false; + + // String cmd = parseString(string, 1); + + // if (isInitialized() && cmd.equals(F("ip5306"))) { // Command trigger + // cmd = parseString(string, 2); // sub command + // const bool empty3 = parseString(string, 3).isEmpty(); + // const bool empty4 = parseString(string, 4).isEmpty(); + // success = true; + + // if (cmd.equals(F("??")) && !empty3) { // ip5306,??, + // } else { + // success = false; + // } + // } + + return success; +} + +/**************************************************************************** + * plugin_get_config_value: Retrieve values like [#] + ***************************************************************************/ +bool P138_data_struct::plugin_get_config_value(struct EventStruct *event, + String & string) { + bool success = true; + String command = parseString(string, 1); + float value; + + if (command.equals(F("batcurrent"))) { // batcurrent + value = read_value(P138_valueOptions_e::BatteryCurrent); + } else if (command.equals(F("chundervolt"))) { // chundervolt + value = read_value(P138_valueOptions_e::ChargeUnderVoltage); + } else if (command.equals(F("stopvolt"))) { // stopvolt + value = read_value(P138_valueOptions_e::StopVoltage); + } else if (command.equals(F("inpcurrent"))) { // inpcurrent + value = read_value(P138_valueOptions_e::InCurrent); + } else if (command.equals(F("chargelvl"))) { // chargelvl + value = read_value(P138_valueOptions_e::ChargeLevel); + } else if (command.equals(F("pwrsource"))) { // pwrsource + value = read_value(P138_valueOptions_e::PowerSource); + } else { + success = false; + } + + if (success) { + string = toString(value, static_cast(P138_CONFIG_DECIMALS)); + } + return success; +} + +#endif // ifdef USES_P138 diff --git a/src/src/PluginStructs/P138_data_struct.h b/src/src/PluginStructs/P138_data_struct.h new file mode 100644 index 000000000..c1ec259a1 --- /dev/null +++ b/src/src/PluginStructs/P138_data_struct.h @@ -0,0 +1,59 @@ +#ifndef PLUGINSTRUCTS_P138_DATA_STRUCT_H +#define PLUGINSTRUCTS_P138_DATA_STRUCT_H + +#include "../../_Plugin_Helper.h" +#ifdef USES_P138 + +# include + +# define P138_DEBUG_LOG // Enable for some (extra) logging + +# define P138_CONFIG_BASE 0 // Uses PCONFIG(0)..PCONFIG(3) to store the selection for 4 output values +# define P138_SENSOR_TYPE_INDEX (P138_CONFIG_BASE + VARS_PER_TASK) +# define P138_NR_OUTPUT_VALUES getValueCountFromSensorType(static_cast(PCONFIG(P138_SENSOR_TYPE_INDEX))) +# define P138_CONFIG_DECIMALS PCONFIG(P138_CONFIG_BASE + VARS_PER_TASK + 1) + +# define P138_CONFIG_FLAGS PCONFIG_ULONG(0) +# define P138_FLAG_POWERCHANGE 0 // Flag 0: Send event on PowerChange event + +enum class P138_valueOptions_e : uint8_t { + None = 0x00, + BatteryCurrent = 0x01, + ChargeUnderVoltage = 0x02, + StopVoltage = 0x03, + InCurrent = 0x04, + ChargeLevel = 0x05, + PowerSource = 0x06, +}; + +const __FlashStringHelper* toString(const P138_valueOptions_e value, + bool displayString = true); + +struct P138_data_struct : public PluginTaskData_base { +public: + + P138_data_struct(struct EventStruct *event); + P138_data_struct() = delete; + ~P138_data_struct(); + + bool plugin_read(struct EventStruct *event); + bool plugin_fifty_per_second(struct EventStruct *event); + bool plugin_write(struct EventStruct *event, + const String & string); + bool plugin_get_config_value(struct EventStruct *event, + String & string); + +private: + + arduino::ip5306 *_ip5306 = nullptr; + + bool isInitialized() { + return nullptr != _ip5306; + } + + float read_value(P138_valueOptions_e value); + int8_t _lastPowerSource = -1; +}; + +#endif // ifdef USES_P138 +#endif // ifndef PLUGINSTRUCTS_P138_DATA_STRUCT_H From 4ef913c3d7239104a8ddc8aaa5a995b858ec35c0 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Tue, 8 Nov 2022 20:31:04 +0100 Subject: [PATCH 2/8] [P138] Add IP5306 library to lib folder --- lib/htcw_ip5306/LICENSE | 21 +++ lib/htcw_ip5306/README.md | 13 ++ lib/htcw_ip5306/include/ip5306.hpp | 108 +++++++++++++ lib/htcw_ip5306/library.json | 18 +++ lib/htcw_ip5306/src/ip5306.cpp | 250 +++++++++++++++++++++++++++++ 5 files changed, 410 insertions(+) create mode 100644 lib/htcw_ip5306/LICENSE create mode 100644 lib/htcw_ip5306/README.md create mode 100644 lib/htcw_ip5306/include/ip5306.hpp create mode 100644 lib/htcw_ip5306/library.json create mode 100644 lib/htcw_ip5306/src/ip5306.cpp diff --git a/lib/htcw_ip5306/LICENSE b/lib/htcw_ip5306/LICENSE new file mode 100644 index 000000000..230ea108b --- /dev/null +++ b/lib/htcw_ip5306/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 honey the codewitch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/htcw_ip5306/README.md b/lib/htcw_ip5306/README.md new file mode 100644 index 000000000..9e67ab85c --- /dev/null +++ b/lib/htcw_ip5306/README.md @@ -0,0 +1,13 @@ +# button + +This library allows you to use the IP5306 power management module + +``` +[env:node32s] +platform = espressif32 +board = node32s +framework = arduino +lib_deps = + codewitch-honey-crisis/htcw_ip5306@^0.1.0 +lib_ldf_mode = deep +``` \ No newline at end of file diff --git a/lib/htcw_ip5306/include/ip5306.hpp b/lib/htcw_ip5306/include/ip5306.hpp new file mode 100644 index 000000000..df892a839 --- /dev/null +++ b/lib/htcw_ip5306/include/ip5306.hpp @@ -0,0 +1,108 @@ +#pragma once +#include +#include +namespace arduino { +enum struct ip5306_shutdown { + after_8s=0, + after_32s=1, + after_16s=2, + after_64s=3 +}; +enum struct ip5306_charging_full_voltage { + at_4_14v=0, + at_4_17v=1, + at_4_185v=2, + at_4_2v=3, +}; +enum struct ip5306_press_time { + press_2_seconds=0, + press_3_seconds=1 +}; +enum struct ip5306_end_charge_current { + at_200mA = 0, + at_400mA = 1, + at_500mA = 2, + at_600mA = 3 +}; +enum struct ip5306_voltage_pressure { + none = 0, + p_14mV=1, + p_28mV=2, + p_42mV=3 +}; +enum struct ip5306_charge_cutoff_voltage { + at_4_2v = 0, + at_4_3v = 1, + at_4_35v = 2, + at_4_4v = 3 +}; +enum struct ip5306_source { + battery = 0, + vin = 1 +}; +enum struct ip5306_load { + heavy = 0, + light = 1 +}; +enum struct ip5306_presses { + short_press_twice = 0, + long_press_once = 1 +}; +class ip5306 { + TwoWire& m_i2c; +public: + constexpr static const uint8_t address = 0x75; + inline ip5306(TwoWire& i2c=Wire) : m_i2c(i2c) { + + } + bool key_off() const; + void key_off(bool value); + bool boost_output() const; + void boost_output(bool value); + bool power_on_load() const; + void power_on_load(bool value); + bool charger() const; + void charger(bool value); + bool boost() const; + void boost(bool value); + bool low_battery_shutdown() const; + void low_battery_shutdown(bool value); + bool boost_after_vin() const; + void boost_after_vin(bool value); + bool short_press_boot_switch() const; + void short_press_boot_switch(bool value); + ip5306_presses flashlight_clicks() const; + void flashlight_clicks(ip5306_presses value); + ip5306_presses boost_off_clicks() const; + void boost_off_clicks(ip5306_presses value); + ip5306_shutdown light_load_shutdown_time() const; + void light_load_shutdown_time(ip5306_shutdown value); + ip5306_press_time long_press_time() const; + void long_press_time(ip5306_press_time value); + ip5306_charging_full_voltage charging_full_stop_voltage() const; + void charging_full_stop_voltage(ip5306_charging_full_voltage value); + float charge_under_voltage_loop() const; + void charge_under_voltage_loop(float value); + ip5306_end_charge_current end_charge_current_detection() const; + void end_charge_current_detection(ip5306_end_charge_current value); + ip5306_voltage_pressure voltage_pressure() const; + void voltage_pressure(ip5306_voltage_pressure value); + ip5306_charge_cutoff_voltage charge_cutoff_voltage() const; + void charge_cutoff_voltage(ip5306_charge_cutoff_voltage value); + ip5306_source charge_cc_loop() const; + void charge_cc_loop(ip5306_source value); + unsigned vin_current() const; + void vin_current(unsigned value); + bool short_press_detected() const; + void clear_short_press_detected(); + bool long_press_detected() const; + void clear_long_press_detected(); + bool double_click_detected() const; + void clear_double_click_detected(); + ip5306_source power_source() const; + bool battery_full() const; + ip5306_load output_load() const; + float charge_level() const; + +}; +} \ No newline at end of file diff --git a/lib/htcw_ip5306/library.json b/lib/htcw_ip5306/library.json new file mode 100644 index 000000000..d45768b78 --- /dev/null +++ b/lib/htcw_ip5306/library.json @@ -0,0 +1,18 @@ +{ + "name": "htcw_ip5306", + "version": "0.1.0", + "description": "Provides support for the IP5306 power module", + "keywords": ["power", "battery", "sleep"], + "authors": { + "name":"honey the codewitch", + "homepage": "https://www.codeproject.com/Members/code-witch" + }, + "license": "MIT", + "frameworks": ["arduino"], + "platforms": "*", + "repository": + { + "type": "git", + "url": "https://github.com/codewitch-honey-crisis/htcw_ip5306.git" + } +} \ No newline at end of file diff --git a/lib/htcw_ip5306/src/ip5306.cpp b/lib/htcw_ip5306/src/ip5306.cpp new file mode 100644 index 000000000..376593b68 --- /dev/null +++ b/lib/htcw_ip5306/src/ip5306.cpp @@ -0,0 +1,250 @@ +#include +namespace arduino { +// based on +// https://gist.github.com/me-no-dev/7702f08dd578de5efa47caf322250b57 + +/* +** IP5306 Power Module +*/ + +/* M5 Defaults +KeyOff: Enabled +BoostOutput: Disabled +PowerOnLoad: Enabled +Charger: Enabled +Boost: Enabled +LowBatShutdown: Enabled +ShortPressBoostSwitch: Disabled +FlashlightClicks: Double Press +BoostOffClicks: Long Press +BoostAfterVin: Open +LongPressTime: 2s +ChargeUnderVoltageLoop: 4.55V +ChargeCCLoop: Vin +VinCurrent: 2250mA +VoltagePressure: 28mV +ChargingFullStopVoltage: 4.17V +LightLoadShutdownTime: 32s +EndChargeCurrentDetection: 500mA +ChargeCutoffVoltage: 4.2V +*/ + +#define IP5306_REG_SYS_0 0x00 +#define IP5306_REG_SYS_1 0x01 +#define IP5306_REG_SYS_2 0x02 +#define IP5306_REG_CHG_0 0x20 +#define IP5306_REG_CHG_1 0x21 +#define IP5306_REG_CHG_2 0x22 +#define IP5306_REG_CHG_3 0x23 +#define IP5306_REG_CHG_4 0x24 +#define IP5306_REG_READ_0 0x70 +#define IP5306_REG_READ_1 0x71 +#define IP5306_REG_READ_2 0x72 +#define IP5306_REG_READ_3 0x77 +#define IP5306_REG_READ_4 0x78 + +#define IP5306_LEDS2PCT(byte) \ + ((byte & 0x01 ? 25 : 0) + \ + (byte & 0x02 ? 25 : 0) + \ + (byte & 0x04 ? 25 : 0) + \ + (byte & 0x08 ? 25 : 0)) + +int ip5306_get_reg(TwoWire& i2c, uint8_t reg){ + i2c.beginTransmission(ip5306::address); + i2c.write(reg); + if(i2c.endTransmission(false) == 0 && i2c.requestFrom(0x75, 1)){ + return i2c.read(); + } + return -1; +} + +int ip5306_set_reg(TwoWire& i2c, uint8_t reg, uint8_t value){ + i2c.beginTransmission(ip5306::address); + i2c.write(reg); + i2c.write(value); + if(i2c.endTransmission(true) == 0){ + return 0; + } + return -1; +} + +uint8_t ip5306_get_bits(TwoWire& i2c, uint8_t reg, uint8_t index, uint8_t bits){ + int value = ip5306_get_reg(i2c,reg); + if(value < 0){ + Serial.printf("ip5306_get_bits fail: 0x%02x\n", reg); + return 0; + } + return (value >> index) & ((1 << bits)-1); +} + +void ip5306_set_bits(TwoWire& i2c, uint8_t reg, uint8_t index, uint8_t bits, uint8_t value){ + uint8_t mask = (1 << bits) - 1; + int v = ip5306_get_reg(i2c,reg); + if(v < 0){ + Serial.printf("ip5306_get_reg fail: 0x%02x\n", reg); + return; + } + v &= ~(mask << index); + v |= ((value & mask) << index); + if(ip5306_set_reg(i2c,reg, v)){ + Serial.printf("ip5306_set_bits fail: 0x%02x\n", reg); + } +} + +bool ip5306::key_off() const { + return ip5306_get_bits(m_i2c,IP5306_REG_SYS_0, 0, 1); +} +void ip5306::key_off(bool value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_0, 0, 1, value); +} +bool ip5306::boost_output() const { + return ip5306_get_bits(m_i2c,IP5306_REG_SYS_0, 1, 1); +} +void ip5306::boost_output(bool value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_0, 1, 1, value); +} + +bool ip5306::power_on_load() const { + return ip5306_get_bits(m_i2c,IP5306_REG_SYS_0, 2, 1); +} +void ip5306::power_on_load(bool value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_0, 2, 1, value); +} +bool ip5306::charger() const { + return ip5306_get_bits(m_i2c,IP5306_REG_SYS_0, 4, 1); + +} +void ip5306::charger(bool value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_0, 4, 1, value); +} +bool ip5306::boost() const { + return ip5306_get_bits(m_i2c,IP5306_REG_SYS_0, 5, 1); +} +void ip5306::boost(bool value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_0, 5, 1, value); +} +bool ip5306::low_battery_shutdown() const { + return ip5306_get_bits(m_i2c,IP5306_REG_SYS_1, 0, 1); +} +void ip5306::low_battery_shutdown(bool value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_1, 0, 1, value); +} +bool ip5306::boost_after_vin() const { + return ip5306_get_bits(m_i2c,IP5306_REG_SYS_1, 2, 1); +} +void ip5306::boost_after_vin(bool value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_1, 2, 1, value); +} +bool ip5306::short_press_boot_switch() const { + return ip5306_get_bits(m_i2c,IP5306_REG_SYS_1, 5, 1); +} +void ip5306::short_press_boot_switch(bool value) { + return ip5306_set_bits(m_i2c,IP5306_REG_SYS_1, 5, 1, value); +} +ip5306_presses ip5306::flashlight_clicks() const { + return (ip5306_presses)ip5306_get_bits(m_i2c,IP5306_REG_SYS_1, 6, 1); +} +void ip5306::flashlight_clicks(ip5306_presses value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_1, 6, 1, (int)value); +} +ip5306_presses ip5306::boost_off_clicks() const { + return (ip5306_presses)(1-ip5306_get_bits(m_i2c,IP5306_REG_SYS_1, 7, 1)); +} +void ip5306::boost_off_clicks(ip5306_presses value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_1, 7, 1, 1-((int)value)); +} +ip5306_shutdown ip5306::light_load_shutdown_time() const { + return (ip5306_shutdown)ip5306_get_bits(m_i2c,IP5306_REG_SYS_2, 2, 2); +} +void ip5306::light_load_shutdown_time(ip5306_shutdown value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_2, 2, 2, (int)value); +} +ip5306_press_time ip5306::long_press_time() const { + return (ip5306_press_time)ip5306_get_bits(m_i2c,IP5306_REG_SYS_2, 4, 1); +} +void ip5306::long_press_time(ip5306_press_time value) { + ip5306_set_bits(m_i2c,IP5306_REG_SYS_2, 4, 1, (int)value); +} +ip5306_charging_full_voltage ip5306::charging_full_stop_voltage() const { + return (ip5306_charging_full_voltage)ip5306_get_bits(m_i2c,IP5306_REG_CHG_0, 0, 2); +} +void ip5306::charging_full_stop_voltage(ip5306_charging_full_voltage value) { + ip5306_set_bits(m_i2c,IP5306_REG_CHG_0, 0, 2, (int)value); +} +float ip5306::charge_under_voltage_loop() const { + //Automatically adjust the charging current when the voltage of VOUT is greater than the set value + //Vout=4.45V + (v * 0.05V) (default 4.55V) + //When charging at the maximum current, the charge is less than the set value. Slowly reducing the charging current to maintain this voltage + int v = ip5306_get_bits(m_i2c,IP5306_REG_CHG_1, 2, 3); + return 4.45+(v*.05); +} +void ip5306::charge_under_voltage_loop(float value) { + value-=4.45; + int i = value/.05; + ip5306_set_bits(m_i2c,IP5306_REG_CHG_1, 2, 3, i); +} +ip5306_end_charge_current ip5306::end_charge_current_detection() const { + return (ip5306_end_charge_current)ip5306_get_bits(m_i2c,IP5306_REG_CHG_1, 6, 2); +} +void ip5306::end_charge_current_detection(ip5306_end_charge_current value) { + ip5306_set_bits(m_i2c,IP5306_REG_CHG_1, 6, 2, (int)value); +} +ip5306_voltage_pressure ip5306::voltage_pressure() const { + return (ip5306_voltage_pressure)ip5306_get_bits(m_i2c,IP5306_REG_CHG_2, 0, 2); +} +void ip5306::voltage_pressure(ip5306_voltage_pressure value) { + ip5306_set_bits(m_i2c,IP5306_REG_CHG_2, 0, 2, (int)value); +} +ip5306_charge_cutoff_voltage ip5306::charge_cutoff_voltage() const { + return (ip5306_charge_cutoff_voltage)ip5306_get_bits(m_i2c,IP5306_REG_CHG_2, 2, 2); +} +void ip5306::charge_cutoff_voltage(ip5306_charge_cutoff_voltage value) { + ip5306_set_bits(m_i2c,IP5306_REG_CHG_2, 2, 2, (int)value); +} +ip5306_source ip5306::charge_cc_loop() const { + return (ip5306_source)ip5306_get_bits(m_i2c,IP5306_REG_CHG_3, 5, 1); +} +void ip5306::charge_cc_loop(ip5306_source value) { + ip5306_set_bits(m_i2c,IP5306_REG_CHG_3, 5, 1, (int)value); +} +unsigned ip5306::vin_current() const { + int v = ip5306_get_bits(m_i2c,IP5306_REG_CHG_4, 0, 5); + return (v*100)+50; +} +void ip5306::vin_current(unsigned value) { + //ImA=(v*100)+50 (default 2250mA) + ip5306_set_bits(m_i2c,IP5306_REG_CHG_4, 0, 5, (value-50)/100); +} +bool ip5306::short_press_detected() const { + return ip5306_get_bits(m_i2c,IP5306_REG_READ_3, 0, 1); +} +void ip5306::clear_short_press_detected() { + ip5306_set_bits(m_i2c,IP5306_REG_READ_3, 0, 1, 1); +} +bool ip5306::long_press_detected() const { + return ip5306_get_bits(m_i2c,IP5306_REG_READ_3, 1, 1); +} +void ip5306::clear_long_press_detected() { + ip5306_set_bits(m_i2c,IP5306_REG_READ_3, 1, 1, 1); +} +bool ip5306::double_click_detected() const { + return ip5306_get_bits(m_i2c,IP5306_REG_READ_3, 2, 1); +} +void ip5306::clear_double_click_detected() { + ip5306_set_bits(m_i2c,IP5306_REG_READ_3, 2, 1, 1); +} +ip5306_source ip5306::power_source() const { + return (ip5306_source)ip5306_get_bits(m_i2c,IP5306_REG_READ_0, 3, 1); +} +bool ip5306::battery_full() const { + return ip5306_get_bits(m_i2c,IP5306_REG_READ_1, 3, 1); +} +ip5306_load ip5306::output_load() const { + return (ip5306_load)ip5306_get_bits(m_i2c,IP5306_REG_READ_2, 2, 1); +} +float ip5306::charge_level() const { + // LED[0-4] State (inverted) + return IP5306_LEDS2PCT(((~ip5306_get_bits(m_i2c,IP5306_REG_READ_4, 4, 4)) & 0x0F))/100.0; +} + +} \ No newline at end of file From d5b1f5860186d7dd9c5d852942dc61b93756eb7c Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Tue, 8 Nov 2022 21:01:53 +0100 Subject: [PATCH 3/8] [P138] Fix some typos, clean up some obsolete comments --- src/_P138_IP5306.ino | 9 +++------ src/src/PluginStructs/P138_data_struct.cpp | 4 +--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/_P138_IP5306.ino b/src/_P138_IP5306.ino index 135686287..2a3b5d4fe 100644 --- a/src/_P138_IP5306.ino +++ b/src/_P138_IP5306.ino @@ -7,7 +7,8 @@ /** * Changelog: - * 2022-08-236 tonhuisman: Initial plugin development, using codewitch-honey-crisis/htcw_ip5306 library + * 2022-11-08 tonhuisman: Fix a few typos, cleanup some comments + * 2022-08-26 tonhuisman: Initial plugin development, using codewitch-honey-crisis/htcw_ip5306 library **/ /** @@ -94,7 +95,7 @@ boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_I2C_HAS_ADDRESS: { - success = event->Par1 == 0x75; + success = event->Par1 == 0x75; break; } @@ -116,8 +117,6 @@ boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *valOptions[] = { toString(P138_valueOptions_e::None), - - // toString(P138_valueOptions_e::BatteryVoltage), toString(P138_valueOptions_e::BatteryCurrent), toString(P138_valueOptions_e::ChargeUnderVoltage), toString(P138_valueOptions_e::StopVoltage), @@ -127,8 +126,6 @@ boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) }; const int valValues[] = { static_cast(P138_valueOptions_e::None), - - // static_cast(P138_valueOptions_e::BatteryVoltage), static_cast(P138_valueOptions_e::BatteryCurrent), static_cast(P138_valueOptions_e::ChargeUnderVoltage), static_cast(P138_valueOptions_e::StopVoltage), diff --git a/src/src/PluginStructs/P138_data_struct.cpp b/src/src/PluginStructs/P138_data_struct.cpp index 63a053792..7c4d80d56 100644 --- a/src/src/PluginStructs/P138_data_struct.cpp +++ b/src/src/PluginStructs/P138_data_struct.cpp @@ -8,8 +8,6 @@ const __FlashStringHelper* toString(const P138_valueOptions_e value, bool displayString) { switch (value) { case P138_valueOptions_e::None: return displayString ? F("None") : F("none"); - - // case P138_valueOptions_e::BatteryVoltage: return displayString ? F("Battery voltage") : F("batteryvoltage"); case P138_valueOptions_e::BatteryCurrent: return displayString ? F("Battery current") : F("batterycurrent"); case P138_valueOptions_e::ChargeUnderVoltage: return displayString ? F("Charge undervoltage") : F("chargeundervoltage"); case P138_valueOptions_e::StopVoltage: return displayString ? F("Stop voltage") : F("stopvoltage"); @@ -24,7 +22,7 @@ const __FlashStringHelper* toString(const P138_valueOptions_e value, bool displa // Constructor // **************************************************************************/ P138_data_struct::P138_data_struct(struct EventStruct *event) { - addLog(LOG_LEVEL_INFO, F("AXP192: Init.")); + addLog(LOG_LEVEL_INFO, F("IP5306: Init.")); _ip5306 = new (std::nothrow) arduino::ip5306(); // Default address and I2C Wire object } From 9f9d18030b584d695424a80c854fea7cf291f3c6 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Mon, 5 Dec 2022 20:44:00 +0100 Subject: [PATCH 4/8] [P138] Remove [Testing] tag --- src/_P138_IP5306.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_P138_IP5306.ino b/src/_P138_IP5306.ino index 2a3b5d4fe..1d438500c 100644 --- a/src/_P138_IP5306.ino +++ b/src/_P138_IP5306.ino @@ -7,6 +7,7 @@ /** * Changelog: + * 2022-12-05 tonhuisman: Remove [Testing] tag * 2022-11-08 tonhuisman: Fix a few typos, cleanup some comments * 2022-08-26 tonhuisman: Initial plugin development, using codewitch-honey-crisis/htcw_ip5306 library **/ @@ -33,7 +34,7 @@ # define PLUGIN_138 # define PLUGIN_ID_138 138 -# define PLUGIN_NAME_138 "Power mgt - IP5306 Power management [TESTING]" +# define PLUGIN_NAME_138 "Power mgt - IP5306 Power management" # include "./src/PluginStructs/P138_data_struct.h" From d62b3b978c8a8526a13a1f184fb2128f61fb42b6 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Mon, 5 Dec 2022 22:10:50 +0100 Subject: [PATCH 5/8] [P138] Add to I2C scanner --- src/src/WebServer/I2C_Scanner.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/src/WebServer/I2C_Scanner.cpp b/src/src/WebServer/I2C_Scanner.cpp index 5c308fd9f..2da85a6d3 100644 --- a/src/src/WebServer/I2C_Scanner.cpp +++ b/src/src/WebServer/I2C_Scanner.cpp @@ -316,9 +316,11 @@ String getKnownI2Cdevice(uint8_t address) { result += F("HT16K33,TCA9543a/6a/8a I2C multiplexer"); break; case 0x74: - case 0x75: result += F("HT16K33,TCA9546a/8a I2C multiplexer"); break; + case 0x75: + result += F("HT16K33,TCA9546a/8a I2C multiplexer,IP5306"); + break; case 0x76: result += F("BMP280,BME280,BME680,MS5607,MS5611,HT16K33,TCA9546a/8a I2C multiplexer"); break; From c5b0c296d04ea2df952a11ccb3fe1e7c2beeba0a Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Tue, 6 Dec 2022 22:08:51 +0100 Subject: [PATCH 6/8] [P138] Reorder Device configuration, enable PluginStats option --- src/_P138_IP5306.ino | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/_P138_IP5306.ino b/src/_P138_IP5306.ino index 1d438500c..eaf28b756 100644 --- a/src/_P138_IP5306.ino +++ b/src/_P138_IP5306.ino @@ -7,6 +7,8 @@ /** * Changelog: + * 2022-12-06 tonhuisman: Reorder Device configuration because of added PLUGIN_WEBFORM_LOAD_OUTPUT_SELECTOR state + * Enable PluginStats option * 2022-12-05 tonhuisman: Remove [Testing] tag * 2022-11-08 tonhuisman: Fix a few typos, cleanup some comments * 2022-08-26 tonhuisman: Initial plugin development, using codewitch-honey-crisis/htcw_ip5306 library @@ -55,6 +57,7 @@ boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) Device[deviceCount].SendDataOption = true; Device[deviceCount].TimerOption = true; Device[deviceCount].TimerOptional = true; + Device[deviceCount].PluginStats = true; break; } @@ -113,7 +116,7 @@ boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) break; } - case PLUGIN_WEBFORM_LOAD: + case PLUGIN_WEBFORM_LOAD_OUTPUT_SELECTOR: { { const __FlashStringHelper *valOptions[] = { @@ -144,7 +147,13 @@ boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) valValues); } } + success = true; + break; + } + + case PLUGIN_WEBFORM_LOAD: + { addFormNumericBox(F("Decimals for config values"), F("decimals"), P138_CONFIG_DECIMALS, 0, 4); addFormCheckBox(F("Event on PowerSource change"), F("eventpwrchg"), bitRead(P138_CONFIG_FLAGS, P138_FLAG_POWERCHANGE)); From 30899184573ccfc318116187de39426189b5a8c7 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Tue, 6 Dec 2022 22:10:30 +0100 Subject: [PATCH 7/8] [P138] Add documentation --- docs/source/Plugin/P138.rst | 120 ++++++++++++++++++ .../Plugin/P138_DeviceConfiguration.png | Bin 0 -> 58872 bytes .../Plugin/P138_NumberOutputValuesOptions.png | Bin 0 -> 13328 bytes docs/source/Plugin/P138_ValueOptions.png | Bin 0 -> 13089 bytes docs/source/Plugin/P138_events.repl | 12 ++ docs/source/Plugin/P138_values.repl | 34 +++++ docs/source/Plugin/_Plugin.rst | 6 + docs/source/Plugin/_plugin_categories.repl | 1 + .../Plugin/_plugin_substitutions_p13x.repl | 13 ++ docs/source/Reference/Events.rst | 5 + 10 files changed, 191 insertions(+) create mode 100644 docs/source/Plugin/P138.rst create mode 100644 docs/source/Plugin/P138_DeviceConfiguration.png create mode 100644 docs/source/Plugin/P138_NumberOutputValuesOptions.png create mode 100644 docs/source/Plugin/P138_ValueOptions.png create mode 100644 docs/source/Plugin/P138_events.repl create mode 100644 docs/source/Plugin/P138_values.repl diff --git a/docs/source/Plugin/P138.rst b/docs/source/Plugin/P138.rst new file mode 100644 index 000000000..2fe25a207 --- /dev/null +++ b/docs/source/Plugin/P138.rst @@ -0,0 +1,120 @@ +.. include:: ../Plugin/_plugin_substitutions_p13x.repl +.. _P138_page: + +|P138_typename| +================================================== + +|P138_shortinfo| + +Plugin details +-------------- + +Type: |P138_type| + +Name: |P138_name| + +Status: |P138_status| + +GitHub: |P138_github|_ + +Maintainer: |P138_maintainer| + +Used libraries: |P138_usedlibraries| + +Description +----------- + +I2C Power management controller. As found in some ESP32 models of M5Stack and TTGO. + +Plugin is only available in ESP32 builds, as this controller is currently only found to be used with ESP32 boards. It can be used on ESP8266, though untested. + +Configuration +-------------- + +.. image:: P138_DeviceConfiguration.png + :alt: Device configuration + +* **Name** A unique name should be entered here. + +* **Enabled** The device can be disabled or enabled. When not enabled the device should not use any resources. + +I2C Options +^^^^^^^^^^^^ + +The available settings here depend on the build used. At least the **Force Slow I2C speed** option is available, but selections for the I2C Multiplexer can also be shown. For details see the :ref:`Hardware_page` + +Device Settings +^^^^^^^^^^^^^^^^ + +* **Decimals for config values**: The number of decimals to use for presenting the Config values (see below for a list of available values). + +* **Event on PowerSource change**: When checked the plugin will generate an event ``#PowerChanged`` with argument 0 or 1 for battery or external power (the new state). + +Output Configuration +^^^^^^^^^^^^^^^^^^^^ + +* **Number Output Values**: Select the number of values that have to be available. The default is set to *Quad*, as there are far more than 4 values available for display. + +.. image:: P138_NumberOutputValuesOptions.png + +Available options: *Single* (1), *Dual* (2), *Triple* (3) and *Quad* (4). + +* **Value 1..4**: Select the desired value to be available in the Values fields. The name of the Values will be set to a matching default automatically, but can be changed afterward. + +.. image:: P138_ValueOptions.png + +Available options: + +* *None*: To leave the value empty/0.00 + +* *Battery current*: The current measured at the Battery connection. + +* *Charge undervoltage*: The (fixed) voltage at which charging of the battery is started by the controller. + +* *Stop voltage*: The (fixed) configured voltage at which the battery is no longer being charged. + +* *Input current*: The input current used by the controller. + +* *Charge level*: The charge level of the battery. + +* *Power source*: The power source used by the ESP, 0 = battery, 1 = External (USB) power. + +Data Acquisition +^^^^^^^^^^^^^^^^ + +This group of settings, **Single event with all values**, **Send to Controller** and **Interval** settings are standard available configuration items. Send to Controller is only visible when one or more Controllers are configured. + +**Interval** By default, Interval will be set to 0 sec. as it is optional. When set > 0 it is the frequency used to read sensor values and send these to any Controllers configured for this device. + +Values +^^^^^^ + +The measured values are available in variables, where the names are determined by the selected **Value 1..4** settings. A formula can be set to recalculate. The number of decimals can be set as desired, and defaults to 2. + +.. Commands +.. ~~~~~~~~ + +.. .. include:: P138_commands.repl + + +Extra values +~~~~~~~~~~~~ + +As this plugin has more values available than can be set to the regular Values outputs, all values are also available from the Get Config feature. + +.. include:: P138_values.repl + +Extra events +~~~~~~~~~~~~ + +Besides the regular events, of ``#=`` or ``#All=,..`` when the **Interval** is set, there can be an extra event generated: + +.. include:: P138_events.repl + + +Change log +---------- + +.. versionchanged:: 2.0 + + |added| 2022-08-26 Initially added. diff --git a/docs/source/Plugin/P138_DeviceConfiguration.png b/docs/source/Plugin/P138_DeviceConfiguration.png new file mode 100644 index 0000000000000000000000000000000000000000..124aefbc477252c2770803f6cfd20684a48b6fd0 GIT binary patch literal 58872 zcmd?QcUV(d+b)jIs52HEQ9-1{VS=Diq)3rADu|(q^codIlK`QYKxSkF1472ogisU| z6cD6^5+EuiLMS2vh5%7Qks3p2A?<7wo%cJx?|sktuJh+_Ul%0Vd+oLNYR_{&_j51w zWeekdyN~V`5)#@6xny`nNa#m2@W=jXCve98?{k^J$Ik1f#)iNraIh~BP{7B}0hb(u zgoK1!H~+S!of4J+PC5r0IRqQRg4_eW1A@K%{e;}T0{!8zeY;O zRpsnyt+S`q_wBy$ud@=jP)LxYrJB9ryaXiEK?lVRqXt zBg3!9M0Gw`9W|Ljl4w{Gj%5Pr}TDN(6Y7~{wv zAQnrz9KO_%V>s6xUE5`j7|?%{W{FFASGELi$mC!1Nm z%}{>`KHBwsr6>RS=Z={ojr`G!AJPpoUxp{`dGsK!?Bt!ugsuL%cflA^ZCr_cqHH`k zX=eMtclZ4brH9Rzj;0zCYfoG%R{lHplGB^Ji#8_sUn6{jet4UX!P#=OM&i2Nap#|) ze5>+sA$yyxpF)jmdb;sSQU|yC%u!UfPrAb--+X*j%kj_3E3}0aBs;hvIrBys&9_O- z^Rcp<@D-7L*p(3Sr@lDaWw(!g|UHMR5%ycUkWniPgWL>p!-{= z=ioC{GnPBs$PaALWNNAwBIlryrQJN3lhfmDUOTUYE=J@I3vWHYJ}}iV>XDN25(fS3 zMw^vQhFm|?Pw!qm2K!jn^z{AX7H|Dbc~`IS6%^4+73-7AVMm7g!~zq)Hv6^h<~$04 zEVo>KTiW^eyt{LVwyFXOi~SVO4qO61HnA&geO0vaX)s)SKFVH03Nz|(Qa&O6H zk!?c8bD+lcjLBZ!a(RY;OXP#dAP$pd^|M-L#@2Q(p2Gw6mU-(k`=?UvBoscX7 z;`&S_xEt9mr5mpROGe-Ti);k>QAjeU`7RrS;u39*$V%*k2J9SsDti{%h%R|gQSmz{ z^y1gHGx`%fL5s+Emxu`Ir6V(g@-<}cNe&gTC;9fHzfzpV!de9?y!N&OHx$QV+@0;=dcIs~a zf=^yqts`36m?QV2mG7-nq5PDb#rHF&ndJfm&&8~2#Dh&3hT%d_ptI%)=0ZY4*96!n z4ZqLq&VOmtw(j4~N=)lBvZ<3V=6mRsR&7uji`x}MAunDGCUOwheo1`K-YyeSdUCHv z=S1jI*c_qGMNzJ?(094*qJy2z!g__z>gRjqiR5m5OU7Kx>IwA4a)0(;YD+_tJ}NCk z!_Q#v{*vk~SeFXJO^<6>>WbE?Ns_eehGL{c!kppQk(`yq_Xbiq)+^y{2sCm3fI1_W zXvX(Vo?i5d;?Q0e(N%7e!qk&jR=btLTut;x@3Oo=4MVY+lb(ET0Xc`bHtiqH@@qHX zwk(x&1hsHIiL1nFGHpPgTCL96oQffJ=OOBRiMauZj_`-~T$b+^{*0Q_YxwDYU7e$; zl8gyn`09W>qRDi_qlg4R)RAd>*bS(RCnGEt_M{^tcqC?$r&mExg0A8 z;Uw~;%#$oP8Z;u6++5044UTurL7~E}l%1Tqv37@C7*$JM)1qK{BU;?o-v0UW+>=G8 z***7Px))UJo&Fdp6HYbN zy8UWosq7+Vn2**X0)%G|(AFg;cNwrpi_J30vx_+kAf21(R0Whh$G89O*OC4ByR22< z+V7srQwDCw+BAn-5^!tw*>;>|T^=7B-DMIV z6R{F1Y?f^Oeic0vhiYzhAJYws(U&AJq4JMV8n-Kw$X!y4x(S@jGL*VGU+mX{Xj2SS zS5uUG8-ll_s950rL+cNsR!Q`OsIe))=Goq>R5WFPH!v~FAsngS2~O4Kf_2PAmI8a- zIVE~?;huE?TzT`KU4p@=oE3@JOo>h(wk<@RwG$O!Wh2-8bm!nyOjw*))IqT|`kpD~ zZ9kUIC@Q!pMxXe=*T(4W#GHjP;SY1Ah7@>`SW|`2{Sk(q4d?B%lA~+Ko!7M89(cYw zQY3ppe1TpJF3xal(l_4IThIZQPG))O;G(q{`bX3B3=oopXi!>G5S7-MUbCQk)H%Z! zejajY$RNTmq|H)GtgziL*talUTe8ZRQx)W1S1L>1=RTG=ZNZJe8QnI+p`4rDdRG`^ z2DfP)nG38;r)G0=J8Dfe*r&2rW1EmmJkKy=VkkDWps{U;W!28l6RrobkXjF8d>TU ztjedPDNyRZZjIXha%txrC$U)AU*}~fE}G2ZCWoP~Aa8ezyB3Ozkk9F3kE9>BwI-YtZ*-_Yxx4XGS%@3A>ofxqG0*%kQe z=1POFuQWrW4&`fYh{sHkRPGO#SNJ-1+)qlTwnj*{|K=(P$U+BQBVxVCh}VNPPr$>K zBlErMB6wwX1a6WhU=?zEKuXH)S@Rs80lD^Rho5X;GxbNI04cyR*!jEAaim56uw9Jv zEX}%D!q4NCRf%zZT)O7;O6U#$^*`?!iJ@eP&wW9{#G%o)skS!uR9Lw)DWdL=E~vHN zqWgJz<-@#3lsqYud?_1_s!CxRdgdY-hdVyjboltuqziVU%l%za@sH{1Dy}u$#TCK$ z^(xB}9=w_EQ zEDLd`%&s9;B(ZX3xtb&$Mf|LDkC|2NK6K$aD9{;xmvyhp+_Z8z=%~Gmk~>W z?r@J(yC=>EI=f4_K8I2wYM+69fHpqO!(IB~#GD$<;i0F{tD~Ea^t7|cHrjA%Tk^TpJ(^7ES$r^@;Tz@Any-)Z?@(_M zaren$BHRLE=EJ3vYSnPcI-avv5b$70I8>E%0KeIu#6 zCzi-k-|_d{%=G8O&n*0k-?U}&=s)@g-HuF$>AhlhBxW*j#P#(=sl^e;bdLxWyEaCy z%%@`ReW74UnHy$547B)ywa7L(8GWba9p4yisMqyE$no7^amcq(#3~ zC~_RLm7)WNL=ubrN$Xdp`}y56$JSnU9JI^Ax>`Mq&ix=K@UnRYd=RPnW4bh;JZkhyb!F!P6gl#9x4~h-kO9hR z)0Hok5Sf~tJkHvXcZ{F3e=e~Db%no)*RDdpLuLRt0}t8!|MgS?_9x)SANkD4bo*OEsla+;D^jV3#{Q2hMF`wP};n#kX zk%>3AK2%@ulaN-ZiHz2@ZsV>jojc=gcY(V#dh-nY4I+061$3nv2E58*kUt+#J8*B# zlI28goZ2oVsU~|M`}tI&E&Vo7+{H3$$VKQ6_d@WkgM~oYUtho3$L>YIPkbGCV?I01hE_t699X@kOM8=Y zttE>uH#z5X^uRqF2Ixbr&??!!{=_Mnxki`fgx*HhY-Ki)AVdg1nkTfFa4N&l5z?Qg z*OLE<9CffiIo;rX5huds(6i3GZg=K15dDUPP@l?+-23g$m%8?tKdZfp6(B zoJ{il-A`0!X%N-CPDjfJ4ihjtG0zq+b}s4<>xxc$Tf+%=UN0DKMim5@Y#$+;L`4H# zGwpg4Qmu3|ix3s6?0p@PN=vG42=WTq^>$U&#Bf5R02uP*(N*jxZlwzz)@LNXa?TO* zPEUjDcJCvrT&b5jsR!qy0PjKfT?pd2cjTD1ygJGG$%WI{zB@EfPu4122|4uU?@w!iE%DJ~LQ&^`NWUDljDdPDi?;-1{~pcGql%3-5e$FOC)*J*R8^n$I(ih&%tr+NR+4vPTDS>fUWwH4tF z`Cd7}lvosR-lYG|oe|__0A4{Y2cL{as44ighaGvg$QKs`t#Z;0=SVxnVk(aLU**~5I6aQkWhf8 zJo>|5XP_EVIDhZ6>`+=0E27jcXzPP4Hs%icyF;z0qE)Rga5fb_YeEaL`H>oG! zNGGM9p3b)Z0YSL|R@C&qea56N@&;TB0u^z^3uu;VN=cPiuQSl*F24lZ6V+p73JEO>JBj4vizE?WM{@6#IV=Y6PfjQ({_LHUq333SAM2Ka zEL^8no`e=+?^qXY`ql@vP2hw!i()|?<#WXhgO|Ax?%)JYV;aA_*#Bt9WgRPRhIDU+ zb`w0nDCm3=iP*`tuuQvYV~(XmnWu3~W3@Gjc9AHQ^vhF>YzBm)5FS?u@2?{W-( zFirot$OP~LLccTOO!5a%(=@3=#1t=XdFBe)f|w%DR-LzVmS$VXyubLpl%FH8=sz>7 zthT+=)o}34Rvr_t&hlI|t>(>noZcj=gnsvrf~arg=KUSQtZV{12^w>WCqmo9mX~+D z>HjF^9FINuWxZ1mGaQNsqY;kLBVA#K5D8yf;bAKCfwS;3cGu)2Im5Odm}vl(+b<;a zV)OyvfxoTa;;&Q9O<%xe)tLZ;lbj07o%hsQe=>j(N^VX6!v0i%=?tSqi`oAS+MTt% zVi!Olz8KwfeL%xDTPO6#mj(Pk0YJb_LMHYidQq#TTLkl+*E1LYVK4tl9{fXpzE=B( z>D0CU&WirK(^b!8`@|+&)&TmC;>iBM{LCax##Rl`OB(IR|9=0P2i33mL)fZn9BT5%v~Mo2m9TEHqKxA{<2ul zY3!5w-#n4VZ#=R>KB~%NJla^7 zr{JTa$0<_!6kV#?8C0XY_w|MlN)>y32#bBfFMF)?aHONCq*fMi+_Z05gF7Q;t4ipL zAi~k;zkDKdVKaL&W*F<@8HR|44Q7r>{yO4$$V{~}M4gSOb2$IKjptTRp?8AHkBTZs zU*D!?qQe+5E~|X?xMQ>-#VeZ`_S+=jJHH+yZlTKPIKka$yY08VFUr0R7;|Xf8|X@d zsE>@zRs`cbn^U~--~q=Rt>&U8R>=v-b0z3`#D=L`+5Op3JLD&NEF|y>i|XXzn$ngO8?~1 zF8{Lt{(Ju4?E6HN>HU|qz`veuz&_brZ~7?iExWs_kS61x2L6o4~7_uw@BJ3aHF z?WA?XFE7%F#IP)Oo^HgIvF2zAd!X!#d)9!-;7sBCI}404o%YaZTeoJUV>54+3PfoF z07EQ&{@Aj#u`*Y85~w*D@L(1WLA$K1e`%|n{>3{%ChQPU%ZSuJ!N~QOL3eaf{6^j< zao~n8ZqI=wb>5zLhhmd8sX^Wa_+-D!n?X&p@7Z*nc(W=bP;PN2;9yUGaU^=*zco>? zpJv(|wRLcvfJ^k$I$GX288I@(3S<}OP9eD;&O|vWjls!nULR)RQU(T}fzTqJep-9M zwQr$6hlbJlYV!dz9USB6S9!6%!S+CqsB?Ug*h3rbIP8;CcjDY#;GTkjE5R#|t+LmZ ztVBjne)VMxDCAwb0^8Ms&eOhyeWG}2T*?BWL)|rd>xrh-$x(5WeCNksyjR$BtbB|* z9N9-p{cU=3DbUty?;ebO#&iMuy7$36n%(iz!d}z-ic;|G;&~^}=h>xCAksHU*8+c| z=NQ(9g3f22sqHGVwp?kD@y_|EvXEF@M8{OZN+dw^((2vxj2xYhzXge9RDhi{E=tCI zK@VfwO!E0UA=e*Xfv%I5JZ#VI1v#4!iD{O+^1OU8c*g|=?8Tk3t;oJ#O!6lRoaqZC z)kz9&Du zw-YwgGl<&tHofw?I-{=o^;%6c2WETJwJ}OpVH)Xt@9ll*_zt+A*>!AYv(nb6;D2K-j0&a_dpUXUooeQ+*!ng6lAsrP9T# z;^_xNysc*jT`dnXZv1Q@2QzPqUWi>-ilk1Em;$R$g%8>MAr0pl( zVU0faT}8N#>+-J>qp1(S>rS)_=Uq1uq!IgbQz`eSFi_LlHFiGAFW=CS*3oaS6Ov)x zNS8b1sxdk67Ar?3bvL*1a$Wch4o4?q0%r!N?dBFFYu_ z1rtO9Z)2Y*g|$z%osK?{nx-5=u{kW?LOQRpqtioMg@X4NnUY9%3hHm01eJn2t0?ho zjL>Soc~VCHH?d140GXV`e)}l=V4e`RK^knkVw>!{sFZc;@*uTB3D&@Vg}*_yhokbU zAN(BlD~z0gk>#k4{%fJKe%W7B+Hp08vNQy8P(;lK(UCu*NE# zVcl7@H3#ll_l(K*O+^K0JZ^7zb7}Et*2y!KWisAPaUld112e%Y#t@(`TW`6S>HQ7F>IYgs%7c}nzh#SwHrrZU%q zOw_kqaIS0yJ9dazi`l!5yIzW&DT#J*5P3|RXj&^4fjdYhRnd(ZTm3l!2FBVe-}jCY zcQXg3Z%^N;ZVMp_MFcBc6xXX)=LYX;=!%diLZ<< zCOK`@^Qa>odns9wLgE(gKK`x6j{&GqV-x1HPjzk7^cw_K15UQxFuHf^+gvI8<)7f@ z9~G71{~6o;zd$|!ObLC7PlbN}V)p+N8dTQ&+oSXw9NZ5evlq_*WQOL%8mz}Ied;S% z8nB0^Whg__{fRs~zhm7F#BgT5E^_@j5@4{I&w(e6Xni3@g!2oJCG3bB@y*JAEoB7M z0|#K`&o}k2500EWWV)xG@*NSrfCDiqfc?Zs#$A2}-6~$mn^Ec3$=|g_MFVxb|2btX zB4xR0=wHBbis)Ro?6j&X1+hu*?Db!A-CSsuy8yl03K-{ z1D}MHavp#itV~VwZO<*ouqWpD70P5iqrP)rVq-t5o2-@lV!eA2_#}z2-y~n6rWCx< zfL!7`MhH^MNf=aw@*(5Ew9S0MA5=Ub$jI1hNpAa0m!E08mUZpd(vz@N*I#=| z(!lPp)Iwm~+!5M}O`0KMBbcD0*58hqPQsUDGDfR2cpd7IE5Deq7(|Ct}3G&@;!pK(GF|I?pYYP&3O?1Y4@#i_dIBykgdRRvb^Dy{onV&DZ2&qpKf3Si_gl}9zPgt1C<~`DKd7f= zF^6zcew14{9Pc2~hH%VKfNbmUB*E1O5ji~8KqQc08)rUiKfOq9#pmXiq#BlB9*mxX z9`Ef~{4!N*7k10`t#6O9SuIUUd^9VZD}M^zo^;+;wQc;@rr*G+KejBqu8m4`2(^(l z6a*-Q&3fktbB2z0COy}i(QjKR;yizlok@w0Z0gV!!3dhED%QGf-m?q&wJ6Ah4q901 z>(C3^h?u8}!5kvZEUVH}4e7TY2!0y=@DPoCP;v6i#)Pbu0je>|a}ax_P({IGJm>6F z-@N$3To4BC)INVjq-{D9A#RoJ@3FBmYJr#!Q$SCVVj2x}r054Lppfc~WSOu7QW~2O z`UBn-&=iP@@<`8)tIDItcL-kp3M9tGc@6P9x(y-KStpQ|SKNF{VX{^l7E$Sj{YLHY zSjJaGZZACP$vfv*rQ|!_0A!7^L1oP5gNOIz)(0NfA4()&@@>x_8(c;v z%ng?Sro620mOD}g7@9+dL*ie12ng@TgP7B4Orse6?iXo*Xn;M{x9aW*EQ+^^L4|uE ziAj+geSD>p=;J13HR$Q8wbSM({ zR^`ZW=v~X!rOif+ZZ)DD>lJbhr2L#fP}?cCJm4zr`seAByW_;z_DbmUf4=d`pty`o z$(qz8Ehw;K%G+)|hB5-QM&{^^+HR>jE`ADUL;`Q{77HYsx{sW?Q>ONHoPdy|A#oj1m~d;o zNtqIi$Z{}rc?=#lQyY%EY|$nHbJgwgTl>AHCyg0?TSPJabkNR8NP`}e{rp#iz^P&x z&G{QndvNt;9=Q;*Oc!SyJ$m@koXYOW>ov)zdkHg@yu@iAT@7k7LI;&S^P|E^bTj`^ zqrp)EVlg_i>o*YeN0@*OsKXA1GI-ldgH{kne8?a}LC&iSB=n{Yt{cvZKVLuc03vayzQv&cF z?2dTQW)fEDgYcL1?53Y%AKa6BVPcm7e{@Mx(3A2HUHhH=h?z8o*8C^_+!8$FS!T)TKYQVFH+V!6KvVKOSzT{S`0z)-&SY&%d`pvc3 zrA8OsB+S?!o3y`ptgTWf-1qHu3O)~-jx&hVoB@0UF(+tQson(g?vP$`>Zvbogd zdx5|Y5VPdHPo@v~wGc>39E4A9-dTQ})nxx6I~x zdNCUK2Uh-+*6=Pe`-4o~Mz}Tihz)eR?c-Nha~&?-XqarRe4ykVC-!+oJ*_^3G>wN} zID#{Oc^c{Ka>T~{0I3|OFCA}=u3RX9@ie+h-Mt~|N2#Itk;oP#b*?z);D83)OA=dP*0|I;T*Y@QyHC~L)PIxpA|u=meR#~byP?YQ@) z)BPxJA~icMq@R0uAo14f!-3JW3*Zh`Qs0iqsF#w9rFU3ud8e4yn^57pP$wVQ94N~r zOu;_g_d*@($*H8CUUv#$!>^ChZ~az}dwP(8_r7ATSs_?aak?S`BUQMqI=NgdQVNK} zkA|dx;(fcuRonX&9D2IyN~fteLFG_DccT9IvO)rXOu%RC3{pJxZERPuUVS@!8~>IT z6ZJmPf5gqD*Tt(`OafJAc376aAaU5CsdVJXtnx+`I4s|n8W-xzk@6noEfV7~`vg&a z>*j}~-D7oJhJ9DVVx&fcO_QxuyC*7jQhMdcPSnuGhUg^HwT7$N#)Va#siiOFZjp-Oy@0qG-ZA9j& z4sH7dYI=0zHfvcc=pkMoQ6RY3FBmQ7Gkh90l@kDinH-yD*iw0{M>9gK?Q&=zXwRMX zAQ)dMw=c&WK@ z*UK9YZ5$5|yEyGJvg(_)gN&Z$m;kb?I*jJkGO*7QlsgD2E#i3!h6K)fM8&V|rU%IO zZRD@#D?yGceKLlbUs19VV=|{r>YP1!pTnEy6w&GMmIh?FrrV~}es>}3dGtZ5#u(-i zxOh-|P@2Z?K!@Dz`O`ORwStY6&++#fXD@55;OD84NYBokU}pkixa|u%$!k@ z#B)Gg_4bgFU_!txm}Sat*`r+w=!QLGQ?In@kN9PrY5Y4`jIAa%4Cp*7l@v9^R$RT+ z-eZFnE?MXQ0Ob*+^~wc=r0Xch7>V z;5Y^|Q!jajk73jeH=}BNa%1!s%=UEV_@FfCM90NjlXnMo*0o(%{W#&H0Hm|uvQF>a zL_%bL&vK|<4zp|}=^!Es66vKbmz45{$oCzLOK8dZA5U_J0i9Jk+^bEbFqo=QAyq{O z)CM&TD_zoro^Yv-(7Wjax}ZUv6v<+QUmcz~LL4c)KM$~A!BQ>J7o|og4k*my%7&E8Y~`q!s~zbvIMK4>csxRuENH-Y89bIhq_;KqSuX9!qYv5>o6eQvLYSdW_eJvro%LW8NUAV&-S(9r8;B)z-^5P zMkGn09NH;R%z>iATTdnYZ6w=AZ?3*n<*D)}!(zxmWQE$)1m10A-gPGZjIGLwpX(g6 zxqW3ZC*;>h-(Hrj54#CbS5RpW8&D5R35K=n8}%MYGsKDbUPj)P#&BZlN=a)+_B>Q@ z{7wUe={o~Ecn+kBDdMI%0NRYa+nL7<9vD>{U5aPvOPi}%jqL?=^rH%toO1`m>bu5v zR1Ghd9!m(bZ)1x4(Zf-k=ng!hrYu)W0xOI4_dxf|EN($cD;25eGwB4PaO9Q+v>-4Xqsom}WkSy^or z@lFkOWd|0T)ISFLOL74R|xPT#K!7Ez@Di_B9;3&-b$8 z*1db1FLTQCEe5|YA+dPkz5=?vzdLOod)30TDk=8-4L^xp{V-NLQ=%I;GMbV^E_2U= zQv>*=txtz^1UZJlo~J_RJWF0M#aMLLB;}R+H>SnD7m;rGQ1Z@W2)Dl5%nDJ5^|HR& z3TuZa7}P@WD#_5Z{;GDAV0QC6chEFhgrPC~3|u@^Zz4%VHXseQUUcHD8dStqOb~MY z5fwpDi>9eJYQo0GjE=x1B6&ThtY;;#iZdff=KHVF^U7A_qZSi9F=DGk@FW_Z!^K(X? z1TwGd!RhyAd3u1QqZT@g{Q~Jwkv}kqkp(ttk<4CujG<9R@aK!&8p0-z>*2b;LsAt{ z>khUeaPfX0HXQrPBf!(DY0OuUQUP7h0lencY^Qb)VxM$8S9p4G@r8K07^HH0e)leB zUc!EH(Vd7ftIGWAX-rqemc4t*!3SX`Y4!P@>KZ!fh8@l7k zem2-AnQ?A$B;%5^4qPrH6jxw)PjWi_eYyBKVO zkEq*+i2nW#KgWt)p1Ceq|GEw_gJ#f>nrIrFc$mra6G9 z29Rz2p{07#c0o5C%efAa~9wBAW*^onf+dkMx~rTQBgP6&CsSwkDct)%sl z4sOI4DQL_#q2%O$lDT^%4jjNw4q`0rl|MBdqsJ4&(ie|g`GH@ zQ}65kz<%kvT`E+x zoGO|zjVp3RRCE>x%#iQS_B@Ue&nOWviaH{bn535T_xgQlkx-9>v}dxH6_9pD z4K}RU(*kauJw_9Arnij*?79V}NG%{jOFO&|kUJJk?%kcb{@$aoO!8>zo{AAKkWZm_ zsewhm*fHnfIN31ryjyx}-mbPw*&a?+&qAfa2jV8{)TIpBdDBbcp zJ5HKmiHuxKmqH=$J*DA;Bf!Mv5naX3&xN$*5hn4ldz%tcdGnv&H7;_W8mtsuG_qpR zy4|~j9IYOG8KPH!kNE6+HYwUPpDlBp=Kz&7LskT8m@A0l(~e~pS6?b!Euc-w!XR92 z8iN@lSqAPTdDe{bmZ+2Oe$YBv1;|T+n_A#yq}#X}D3Hq%=~Qc`dYyy36aAe@xZB=e z-Dcew`;_Ac24?(-O_u5>OMZue_Q`~}9ab!t(2UL4O)E6fG(Tk98!?FrAqN+cq@s?+ zk*9keJQ@)%Rd)8vK0eyqihVnIRo2Qjd2ixFU@I|i1MrWxUHxsZu26_zr$Cp%unbr~ zVj;O0eDpZ-k?)!ARw=XQ6rkn5R>%+A{qlttAo*?TZcX#>KWa5#y&Qb^Ryjjb;g;1m z9j^$G{jydwt3(hfGRm%Z&3({3tW5_kDwWahHM(alKK6Y%IO{~%PI1~w)uT<7ow|IS zoj}jl0!9`+P|x3+n14KIht($K6fh4Eh9;0+}@#P_ZW4&J9-@kI(YDBcGEk@R=(Nx}a&Gj4sDQCs0sHn%_ z>VbwND@R*ZKRf30by@WQNaCkY{6SwAk=ucf2_J}&kVE7|T2Grh1FTXI6`(cmlKOqRs$Lb*+SypIP-01iQ%5rU4SrfX8yNrPvfM?& zpIM|~5pSDyaDTka3B}wEOb#FbJfJ&a#Wp%uER0CpX@Ym&cMVeb9r@XlE8 zvMVA7<(i<9V@m;Tpk?3L>YX#|tx2fVBKZR=395T=`&{R6*B=x+HQ= zBxpmWESVOW6`32EHyeEflo6T7slcpN9tM5W0)$;g=mDgBvsBvoIZ_-=R((UuDa`oI zgAd+&@;(Lw8%NjI9S!nOqh^MS0beZzpfARqzlw}D;QD12z7wZCtVBVo+2K?VO04+V zIc&aZ6CB`c)9M;$*qXN;QVKtKO-t1}6u=p4%)q*21jlAjw(|qqr?K*t-$mPD-(2y9 z3p(cV{NfO03d5tgo-VRhLG4ZAD#;1cO=PWbpY_hG6y$qZe^U2O$i>SaHLGg);Y8-t zyc@d`YO#K0E-G)mF7wVv(l<3TB6@1KR^16eMKbj^^?YogvEfAP7iE18_EWk%T5IQ! zGobc+efo=GK7sZ_WAC^>_^`#uYXz^~bl7u_22l^We zH9#ssfOs;%{tF2p^sfZx|JAOMO<3@sCC)&B|E$8im9oOJL^W|Y$_-8$L`mg&a~qKx zb3`}kNlS|jc9At%=dYnjPfQkEdZIs%gtp_XeDa(e)^L|AfschqhOKOPVs?@OL*|c@ zK1}EJNUr_R@O0(Jl8Pg_a`x1?xwA#M1v3j;51vL`47(P&&3&O_y;>oA}yCzD2pRwN6opRee;cm;E*L2Dbm z_1dIm{sVs1tV3^q7)p8{Y5s3gMTFE@EPdNu07-!1W4c9Rh$xretNp{v=Js!`gSeLDsRlMq2;nT>)L$rXqwAK~UqGz|j z{)dXkNUaAqbwF2~S8w(v=FSbr%Zi=qZ?mwEQyeQ(bPqC5pQn#n(I_>&Hzzbq+kHFK zOj#o1_Vul5GO0=dEv#6A*l@Jh5Ux?hg$7UY4Z6u{ z_o~W{%(kP_^l19pF&7T6`SYgy>-cqxXiQCO1=TB;Hc#JpUo&^dU4nLhims#2$34MhB?k|1Xkx~qHR zx;L3G{D@i`gKXq})E>Uk2tm;3y-5?g@0SRKtQ&P>OpPHx;Sra^1xz>l0peT^wRs&h4Bid38P0H;jFBiSo+ zW8CGN1@t_gv{I&^e`3V|6`hOMF0UlX4dor}?O*JPGz)u^1PeKPrtKyaK8X`zI zn5w=Olyx4sDUVIk@nZ#u|u-{ zJ{y`{bCg1*lT-6rmZ)vKPkkP_h>v|1hte|}XT%#3v!GN)5@UTvh8k1oiS2~5&@AKex_0(> zOlzJq9qzP5kQkCcfu=&H$whg7$qOIOyH`u8O&iygQ`(%ej~C~bleGMdCCgW|wOAW} z=M>R-XmXdYQbRk*r!IGaXg|loM>Nff9U?tEJB8p>El63aN!Kpc&t{|D4PtmbitB18 zMw=^q=EskiHM$L=?B>@u>L!lZj<1s<((n2U9Gc)kq#DQGPcDvnPDw_(JLz;#1|fRy z(vV=CBVKE805doH^4VN@TL`>oh|TsHsMkCcvsO&M&#kW-CRx&Q;(18k&9?#6S1Jwx zG5*mDiSEu#etVZ0dtNyV%n2p`2?RE8K6PK_>?9_BKEPY4x zXO2L?{`eAlhSE)bSd~+IWR{i%9XUX^kB>b_ZdY)& zl#v)R2~{~dEeuOy|s)806i`kWy(0 zQ0&JTPbyBaNM$6MiKNr-DF(6Ded;M%eub2n+~rERYbD?7dhYBQFEkpqvUA!2IqE7Q zRpeWW4cS{;bGE0&d!xdZHx@RI|moT&!`)Gf`{9kMImrn0-&v2{WTliF2V*^qdGC3Ra zPRwTjv70RIZ@hF|MH@9P@gf)(@2^joDXPpmqmzrS{`~VRjUl>CG2M2drB!0QPdkg( zd}GccIS7tKzJ)KQOOgDm_A!qr>(-V`hWt#`@gAVIujGrys$+8wI-k!C(@^;lYp5z)S*e$+s8&x0G{E$rDKR6vaIT122A zC8%+jc#I?EtY;<2tcE*2cJ{3FPhnvO^RnG3&B9QSm~_EC-^>dsz45dX-+6qKKCHZ) z5@=`Xn|#h;(Mwk>>E*~AYHj$BR1d^=Ckd)dsEm$5Z`Qv^CvG zKDh(#&jPKYhUy*)OrGh&%qjxO?xY zrqaG$m?_HGU_=Bdf}JY7pM>eU6o!X}U@pW-=!l8a>cc z9Y7Pp;F2lo>L#`9U4%16ryk?RsMifj)<`mscW*T2Z`Al)>``Xe=O}3o`&X90MAmmb z^*QC@#;Y$0{rdty14e!HfILf#}(}R*5}%g`H{wD?EKq9H|@aiP0Z^xtZ+!DQ-RgF-BoJW#dFllL^+Re<;?2 zX2p=?Aqu;kDedj?pts|ah6~e)`XoNoEsczfj;bu$T@zZ3zf~zG@W-f)C&)*Grf~grQefffN zW*F(ypQ{qqihG$7b%DS1C2gKeKGUSRP}q>;qNoN#Z(w|SC!ZwGd{r|Xeh@6!)1RwO zU!xv#VAKU&np%0XbVkY=CdG%@BX_=|Mxvo6DGWDTv|2KGC!89YHFyeDtC59rxmo?( z!I!+cax>ER2Na-UiCm<_c0?78F;XpQ58ZZpoW35Gi0V4MFc9MRCCZlwakpjoXCv1CC~iBeC_nsna**0Z0IU_43jl8p}J3A4%Ki=tE_@&2tbSJ*3po;w)t@LCt(3FyE#5l=bF&IQt8{LUqF!`!aNvz!|8%j3a~ecn~;S5g7dqd}EX_A~i6 zopSf6dxRF3OIPUQgtFBXm!F5>mM{S}!Qr9RXJ2`nYh!3R$~|e-SA)tYM;Fa^u(vy4 zgbtGqnH?3#1a@wqkw!(#@4myFX_CqhT7x66Hn4rZ3osZj?)ZsD()j3m4=eIYW2B=l zCX2>8dr|3cskA2k7-V$#rqm$gJ)w2%6E{&aq0||F=^7h`+b0SEXe&t z+$NCTc@))ZB}^JWL$v+z2{{$Vt!bt3S_k(KI|I7vNtCR>mz~HqLVxB-#(=G#PPorm zp~nzADSv)Y^?+oyo3_<%oWF1T#Qt_b`c|UqXL);BPe|Bax;KNWJavb2E8 z+CHEgFclzp!fm7*K^;HRbZAJr@17X@mjeu|fg-!{__%&ib-xH68Fk{W1M5TtGI}c{ zf3rUje^B73>SoK}J7(fQ1^tbS<9t6!PwUR^LFoy6LGfBh?y*k55);>`+X8^74pF;X zZ)dOR)lbtO%&>}hG64QBuv+ZFW{e87UCMf>uR}&DB_;wt7aZ0g^lCijVl>Zl8iX#nK|lXE*U?q`m{FY z-l=*&z3m+lyh)~3-n*3NC;BrtjbDVIb=!xg+tQ~&$v;Obw>6|&HLn%LfRQ#=Egs7c za})PZwe#V7+6YBQ+b?%W4xGJf%a^P)sd#2{MfOmWH{NitpcB&csz39p@L8GJku4wBFv@iI6)ld!ZB0rzvYv7-S{_XVnOX z54_(i$TX&^rN@1jnl_bS><<$$Vk`Dq zY$}e>eOL1SDm)QIblGp&3kTgM7Ukem!lq#c*49JvDNV&D#YtigP1g^QXcZ~b5_!&R za^BstrES{KY-3a*QQG=Z+(B&2 z_F;=e{B#6fCP;2B-pLbN9^-B9Fen3m#BUsUBz<8N4kfQW742haYG%SKPHQs@jvtIN zwdOKZxQT}hmm)vH zvVP3>Y=t^9V(wLVxr0agsLVY#{URt@R%v<2KNoxa=+h@oZdoQ;Y+^N{xe||n9wy7{ zX8P>6MLt}-a3SITZA6Md%%y36v?05}5tgsgzgyCkGtLf0adv`B&JbCMC|LgdQ5>OIw zewhcw<9Dz#u4}^!pPLeg9!A);92KW_j(nmfyx%!!SOg~mSpl+&qh4@8ODJTVb2;r1 zzstd`0Xn*X`Hxe@W$464I6^D(AKBrV_VPL?a9$`8YJGIex6AzJ`1euFYrY3!`gd#% z%xe7OgX;xAy}BDi1*&U6te`s{s0VE*?bj*7n4&_m!YBD_fRsoH5E3u;j$ zN%hEWQ7BVx1dx#VYr^pJ#ZkMPr@y_QwHrBA`>!lLFL6VnOS`62iG`JG_N=T@tiBeewxW1Xi+QJ79P9N0w+w zaE{>bpS|-R-=1PBPk}$s8VCRWdVq9g`R{n?bq-i+2_DJNm}?0ViP;&4fSrf~r@`DB zaQfXT_TVglYSD#Vz@-k3jLZdAsdO8(Gq&lpsFNqBu5Y=o6IX{vJEC?!0?sxX1+<^u zfY!yye#pe1@GE68)3$B~y=+Fn>UNA5l{fFl;mvpg^ z=gQ0Mh4Fe+zclCv6oG$|K#bXYs)P=hx6z-E{{aJ=2ep{;egtkKZ_J_!g|7&lpV8xfJ%T_5DvFAl_Jv4~cu!>+>^TlbVX z{ggzHhOVkYK^~YPrFG|((k9Sn3fd2CpfBWk_+@%13{+8!0)Ts94!fb=Zxe?#xl>kATR{ZEHxqkNzi1j~OGC|kER}jhF1|@3(gR6wcP{uR_tPiSjIDC^gK8fC2%&X!O_Wib7*%|Tn7Z4PK;(@KV4eekHh z;aX#FP&85jYb5(T zZyc~uQ{#unWNCGwODs9M?=90_otZWO-s#Rma3&UU)@J+w$Jch7#t9DmiwKuCXgq%l zAnHKpxV*GESA;4s;@KQ7{J~gw#4W!|QY?m3>(#pu>G&QvT>LkHt3|Kg;ue1LKExRL zPaaYx{%})PMicyWv1wyg>fOnEx>tWRI16N4o24o&-@Y>wrQ0w4iV)(x^M))&=X#Rz zi@m8l_yHc6%BH76`gy6P&2tqFd%=+JjR4$t;mA=&>hya}TSpr0`FDp-dSkW#*0r67 z3cXq7?@>Kw?Z7dZCDpLNm!PT9(JaK92Y>VG*n|n8=~1*~@A3z`tLe<1C>y|!lu^F> zlK<63tJ{xj$5+!fOZS;wLbdgRgW^tgUUx;Bc)}!08lp%@objM~enI=m7_H*=OuE)w zcwARHL^1<23s|WsZFYhIDik0W=>xF~ks`gu#79CIXwS4bE%dK1V zgd9;Q9=>RP$du~yB73ue>5p0yQol^l5P$T(oGnq`Xb^c#~q}A)4x*)xJgG{^cfS6eF!RZyG z{se?0ZfGrSF~e%M|M2iraV9`t=?WYigz0@YXIs*k^p*Vg2X;@>i|8)>r*(@0ecVWZ zM+%Syy!s0F8oexqEhY z51a;J7K$k__?JG;pCGRPYyTo9kmLLp7J%iyi(bd3?$T0mdlnT5$ zuuJ?k(T7Z>AED!uneM(tG*Fv)ftlB4OUi8@s1g3X{gzFIKojyH5THi!_+CDBvSn{+ zc$%7XjK%-`!3WqYdQJg-l$PwJVW2s99cT`Mm;*!??f(>l{QVF>1{~CHD47_4?8S)? zatcM(NE?@`M4Co>dvW!*-xF(>+eN#d zFt$n`Y1{$IJcEgpwVo=}GUj~Xr2{8|aNsDOZCE;s}k|z!p61&KDM0dogt)%QJMIj9+?XfPc|2nZNUtLC$Zm5(Q}Z?Xd8Fj zj>r(0Ra5788%?y5Yf*EoYko2u=Gio8yp6t@F;gr8`S)Dd` z`j*Tl+-P@#HdtF#Vlm{X#Hd(|8s&3{AFmokb%iuI#GN9FpXbh$K~iOD05;K$*{`A6 zMXP;tpz*0?ZN-(6?zzA{iOi!Lpq;z_;-0>c8jW4&e@pHF;7hqHj=3}q}7*t$eD&ggPp#7t08Y&j_%3H zhdE>Pve2QT#YN?UY9Y@B7j3fe4fCXT*DhvWBjAgKc*Q~=R(q8wNV@fH-MP7Ut2R=D z(>_)b5FO<`iI6DC&Q80B`HQuaam?^YI#y$UDebE1n9QTCpoR(%tuvD=vG~TeqEgCb ztaMwZR;)zE!ym>4;g_yRf6f;+UDhvZlzf?Wda(Iyb|m z(NOX1H*dV~2*s-J{=!L5gJi3t-AK$H#*cJd&Yt6hfMCmckF>~Nk;I!xnBj8<+_k>BzdG;5f_Z<=<;$IFLL}`DR z5FWV^uW087Hsrd=zh-ST!Fy~z282BAj+x5$#Z#B7q#OP&&`3`Na5@{-Z$f8=XG#igK8bUmf5TJfy1C9n+- z@x#(JKZ-rHUm%T3=(Gy9J0Lry)TbBQ0!}~|%Capx?(=jiI*iL_8WBccK$kzPv@F&) zf$1Y%yCo0`_jHLt5nauqPxYkAqi;UCS?GHN9KZ`xq!INepHv*ErUo;kaa~YcpzB3| z=e}ik%;zSNLgFwP;7iN@_NAY8WPr338%FJk=b`dtQ^0(O~ z0X3&>>OK*D2Y{$ZdG5o7#kwg1-6>8WJ1GKYnY20A7L1?o`15tZ_Phuj$uEDWaxFmr z@kLu09zmCAvIWABq%3MquBL6!)ol`PW{&_YK7gmaUQZ~B##+-mlBiwf0I5s|c~Ep> zj>IFD-%|dAE+kMBX8KbmOcS`k1C<~a;IP00mj8~Il!;)e+qB(NPHPeV-tsD6^&kGszxH=!XPqye4`856Xey2(e}l#`8#Z)sZE zjK`ZlC=I!rgWI1iqQ8GnGUZ@8G?hOzkG0M=!yS%4jL7#bP={gz_NT88B~p~c`$1zS z8tZ*_UOxo`e5TaFO=jOAq~GG$D-w-4)L+4>1QEG!aHXh13}A)5oOwQfDyR^O4A7i= zkFT*!VNFpg9!U;nXzymH-VFf8XcFM&z-^hFsby3XlnobB_zFGaVb;d8Wq7t*(`ldRcqnW;HT^z0!t=lWE z_HVZZyp9&lZzl$1#rJ-v1DBj3TWl*D>FUhJncVwNM259FWhMz zA6xSdSrIPXnM^IhPJ@%q@fG0D(?DM2d|9rbWR{0Z_8I3G1Muul^VQZMKs4 z%ZrVpJNa~N#k(s~4r8Cm4oqNfa>Pe-_PTx$fk(@VCXf%ALJ^@E2WaMCIpL8|$ab)% z+nnnp;HMOS^nXgm6j-!yR^J9K_UwMi_=n3kB!7!sgZ|uRAR3>*QDRn}-fbY6+PZd2 z0H4x!7WFCkVX?7YiIYmhU4GyKQZD{$H4|;2-aW3ixckVmt6SoCP|l1LiH}Xn(8?f) z$KU=4s>JQ5y{@>nm~)9U-;;uJ>LVnbmT}eN)YNVDHV1J*=#(MslIF8~8+kU63hHM3 z2gm5ADWU(|TSj=qibuX^3o}J~xAq;l8EaU?WWzfp!xFwPyV4nxsTD9w6f-CayrLc1 zl-^xY#g%-WnO7G}{KJQHrE7VZZ*ew7jUR(=>OXx6QaYpOI(u1TItZ3>I(;Pl34tXU znE9gDFV(oAr|yDD5DqzGbD@f+9OHgG$B=sRTeiOjJs7xMsFP3<*x9z+YC&iFm>MuJ z0IGOyfhzyVLo0!Uz{ z)(kE0K|fRtg(OgW8<#~0$~073mkp%kRL7j3%2xM?B%Jq09KKB13})J`?`ud#*TKjuVQ)+6P~cx zReQWdPF4oHRcXb3tOwlQEfe3$Jpp<@+G(!J#Is#C`c47zJ>Z*!{$0zYd@(3OD>iJ_ zY+1?x|M)E)XZlCM7;w_<$%bIoQXKE!=_CSNt@B$o2R{D_Gq+)yejsea#k8`u3;&X> z0E$dD(D!x7A7G}Q#Eq%CZ6JlScNsv1Z!)u)`HrY8;3gn{zCNh5@Pb`X4hnToU{)4dT0?N)M*S`a z9XiSK^*@Ou{1*$CFM(K&MojKs45y{==YP=?PoDfwY^J4`|KMd7ivL5W@_+O68jvma zA)`TQFli~#5A)R^4Mou=H-<+yMN_o>IyER)Xg7IQYKdKwaNH%$yd8C`Ce7#q4Qz@C zql0&|ZhMD4fd4Nl-^{9=u<4MyBjaYooYur4RHuHCa!QiPK5>Li%@V~frkj;MggcHMQ-gVO;MtHKUDoRe7p81~iTUQhd! zf$J@s*H0>i&-ptbENU+PxnkQ@eqqz%pTzVNqQ5Dxk#In%tG-3s)BW^FV>#DiA$RzX$93$woEi5iz*X zy3Lw-3#FRimu~h+!5H3_)|X0xSX5$BF$7&%Iu*6iE^O-Bg7GTHR)n@$UuJKJz$YWK zZGRqy-w`yVPHW$g43Er_j(7h3WB=WN%Ym8(7VN;mK!<_alabu(+dxO(q%-`z0?}M4`ESP-c*S2dJ749YaMT35L@4mz- zwDSvpo)=L*uDRMeN7IWoczC3T{0ObtJK8~wctg^T}zIVQPxBgJ?=Qsqb z_Kjt(nvejqytsUaUq)p#oEObnPD>8WG-*$zoto&Ml6M|4%hYn}jI5qBM4EA^7uYB{ z?Yn%(JvsLti*EmGNFBkoL?|_K3Y54G{sKFSgmUBm{_@8_NeIYE{&~+Yo%sia`u~mJ zw}&l^R;~ym_V?d7l?FVL62y`_14w*_uk)GIbwiGcX zMljEqPy1a4ZIJGJ?t&4djj8nsIdF6hHm14XSGqqGl{jU!6;9j(4EQ}|&`tv3bKc|S zA&oQ?Q&1ZP1lpOZ?x6hxT-l%hbMF+2+&MR=rlKc815E^n6Ne*Hec|d*O7G`4L6OXI zj-Ha>@zU+fQJ_L3FlpKXeTb2PFJ!3|3~KnFoY81a^57Q%-i3vwU@i4aFU~@Y(_{!f zJLEco3$9t+;D!X+#W#81WU|EwZ7M66HPm(-ad=q|rC+7D@gXb&OfzyNI<}UporC`}e-}cz$N~3DNi%CsepGumsgDxS|Iig9f>qen%?T~oW z8IpTMgkF6xt+DHL|A&`&$1bCrhze&Fbo9H`uJM5JHM;|GB$g{+DM-7VwuZ_;4ozh- zKZD=sN5a%zI&z#oMQ9|sC=9G9bO$HQd~FRZvnw1F ze*__GxlVmNZJviBV}&Z=&eS}#@KD#%xOR7VUr2MikWDRALfh;zJcA~YsT2Sc?>R|& z(-(-C2;;{qd=rV6v*vImi09|m-YLs}hjPB{&mnm1sqY_z)Uqo>p{)UGd^@YGnDX>P zu^dHP(Tb9so})*WQSZYQovl+*5pr{q2~WvnF_a)`GF#$W`60tIyP$*}?L)k2ha~h> zD&xTy54niOm-kP>v#i9=ihaAXQ>k|^%yW!szM0<=>NMl$>^iRhhZV1P62sSwSLSZs1@xTyYHFvbEThCg{!&1iG-&& zCA*96WYaRW1}_cP6N4fBospF}#?s-64|)z|Xgw>lPL@fEYD>KvN#mMn%(>lQRc?ah zdm$O$hZ`3{bkT#%`vcB?Q{UaN)9tQZ@}neK>|`GY2Fa1RJ- zgU|5JuQcHFs9L{YmNhh$t{g+vDK;LDwe7A&q&M4V9vkPlAnj5mI#n#RKH*iE;!B@) zZRhDPPZW(`uU04A*Xm-hO|8|z5IG~9HD$1 z2XkOtN2DmiEuk2t4MgAir;$cpl+?S1vaKo_qt;YsTHm zGGp{i=Zbf8QM28Ndg$?_D471$TKD2v5i4_qB8V0Mm+W~X%j zwtIG_U|`FY33aaO=2~g~n17Uc12VaGz>|$ zxKgF5vc9{JoQzkSe<5fxyt31_fD++FGJKs?LhEdlN;ON=AJ_US;1`OY2+vIA37UlE zGTh)_+!;j0wR;n&Zsn+yjaQG^r!%SlLoRtY@CAPUyGf4N|DzfM?ndUy3f<**xk ziqy9LhZJ4FzG~R9cvC8Mx1w)mIa>Noo_$F>YuSa9RyY+vm!T0391g=W9Nr>PG_n@Ndiba&tJU^N{S<@^5C2W!R(^ElYMs*H?`Ip|cv1swCk%0MF04KQ z?dF(IYMNIV#~Sq-9sFpEi4g{M7zxy=)g}^juy3bk3Z6GcLJe+X7OYi3!-HEyALxF?Mbd-0dB+S~L#|FCoF2*RkYnZ;_9jwo>fKfktxk4m4PVx>`?}WW z%%l%NW37W#5&O#i@yi%_X~$1Zhewl+VAk=v%Nh;5&f7s{F}L?(G{lE&^M|NVc^bXo zQ_97r>$7lf@0n({i@W$C|NXqCU>Ho`vI;&R&nU*SdwJvCWYjKnzx163*zR3l0$IrXiOUW(EDJvw*{w^f!n#$}%fNI$2 zl$yYV>5e*g_fBqiNM3?#SqCB;)jYR4|HH9HCqh^aJh)4~DdI$l#gwj6UL>71d7NwV zst;{~#Ml$4iY8f1bl>LV?DM%atJxni8#8|b0*RTcTtzkt4*JF^Gl(;ah}bDw+n%b) z^LPK;yfbl0si?u=DsqVus{BTE!0tZKj~4w#Sp9AMNrmw_U8BA^?oVnzES>f z3MrOspZWsEnEx2%&{HKl@67ywdhuN$*khDla|=#Iu%jL2`9#WZ)`<o#oXE{vY(jd?=gL{nrs{mLnr?WpEY2&~gIK{A(dC?Nu_NTJ)+!-rsO-YXT2 zC%6nRY(gZs_vsrGg9CK?f?c}%s4sqaU1I_$jP1AVTJuAN5y(aN_1b0j%nekx#+7K; zxbaf|j@3*`52@uy!;V=*C5h*>reMF*Lu?RP{e!w@%?Zq&O+f2lC^n^3v4c*o#C6Su zKAL%nblAf7?bx;>YBew}0X%&;`vfd9#$SEjStIwmw^u5qD4#<4B03eU9ySluF}HnM zk&n&Xo*sH7U|x}HAd0`livBE6<85O_M`tTkvFlcoJ)ROc;;xn7316A+XW~sOyw%1*B>%6R;h5nw) zstgSJJ0N9?6}~(bSI2vHT7}5Ui@LDr1|`C_;@Mz z#KLVshi2-VBAPOy?hQ$Bri2hwq$t>RiavcMzPu~RyG|4_>Ne#?oX?JCe?e~FZgR4> zb0pv^Yo#bNk#8u~G3N#ucSBrlGJF(fO)@*&L^s(-_K0b&L*yC)rl$4Pd{ZZOF8yct6$e?AW>cOGFohx{inl@ z*)FUui^q^8$BFLr=ybCRM(1O)XlI0mF5MvH#eqA%-E8* z`>KnphUHp`h3YS5>%-=*f_E2)-N8C0!CtJ}G$*bh#`g_rPXZc39QP#?h;_zwMm?lA z$$|Ui(R{d$9lW5gacb%-t;L(+I~g{s6a}wy!MbhHS|%8Fe49;Ogo(*vw`?-8n~a5N zO4@;YO_kj&W;ib5OpKqx%OS7Q&_G-GNW=7{hTRWeG;E@Lc3J}Gjyu{c=#1k)`3C9W ziC^n$1$^A+{f+u~8bocGGqwGngXDah zUi$E@Hq{Ou?s~V#+GQAn8XTthPwzwsW?wP3QkN%L%ZBEgZ_30vWkPi-lVA_ux&mxr z&C8ga>dtI&ks}vG+PY+@{vYh99c}C1nU*SlDT|(plOb+>7ArgZ%23*C@Sf9j>>qB~ z;lI^<-f`*T#NL@-x)Lvv;?h-xYdwL!@>36~>#ZBPJASk%U|<*)B6tK$ABCx1n2{09 zbh_mi-5oeFiSrle3QU3OcoQ|O%CZ-pGNOIv;$k{GVJ8OJM$eAzHd?^;rY2LW;K!n2 zLkN_mPc$v&8HxHyLmr_z!lN3H7X_EHg~jfo-YyIB<`_GnX%;gg66N^izFypR`&eB3 zOeK9^uH(d{>xkR3aVP6alas1rKn^DA>6W#59)sSD-g?}NS(EXD&V6>36T#;qM&J-oM$m*>D4v-e7)5%u(tNLAb&feX`vdP2s1H$-sqQ!^^ae#ze3x$t1ajv zSDrApRjLE_Iuvi>^+wOahi|YF`Q}n$Ch}IEu@7Bm!7*T}RhJc8qahgUgm(9^ux1%+ zT%*d4ue!g254W>=V#`PZkBV>coA@xKci${Fdse@!LaG%GE=2GzD@tjY*mOml@x@GU z_eZda6P5V=Vl;UX)q%F$Gqu@6skm1(N>DS~I%Rb1ig$fApS_>KN=L!a?S0JZuVYC~ zk@-K9D5N*N81yv#61B42P(*XuQL`aLp!8T46AJ6LefuIzui&iKINK$%Bc1T8I@AgA zPNtp2;zE&WTQQIw@(c1;0wz4hl-qGHp!037iO<}-A5xw9Gh7p^>k5Vv6uoUA9 zoo>{pVYgH_!+(Pq)+z6KHyO<;arwl~hqtbQsO9M_JBsaVTg>z9ltUORS;n~2;prb{ zs8Qy5$>stZgT5H@cU#$Ru(GPOz-eqq{S<+ZC%^&e+4Fdl^a(`ZDX*-srVZmt9|(~ewY=fnQ9yH76R z`YyR(&f0c%&xERvOmAgTJo8h~QDx^lOR{&B3-(lGoz-#8`Q4r4zNPd|Gh6O%3bMAc z`_l62&=>G)_zwIUGQyvJoD{fw+EG7Grk8v*aJO|@@9RoP5bMtv^tKoArXymndsgEU zpGm|Y{Hrh3&e^Fe*LWun>S^aM^j-D$p>rF$#5_$4QhfdOGon*11eCRRW7Vv}YDeyb z@|eZ&9iK3Q`i}f=58^X>+qq^htXCxeu~k@yy*Sq0HR$!M1flksvFa&+bj zqN4AL^eSvAN?vq#cV4zyFon`TMNP_J?O2v}&}>a!DRk77-QySAE$$0*s&O#;1hc8b zBkKZCyI3;bmu9#z+To)Zy^v09CsLYgpPy*b!^NmH`HhpF=ipxLP~@VyxQTzTzVt@D zqK->M9F-#ql$dYEhM1#{bh$LC4fsd&dq`3`^QlSiOEj)89tDV$+m4>B1FuywL{?FE zBYt_aY-JXFbGeO!jadvPz0>2*H(xH#TDRat-EHu#jJy7%noWg-4vgQ5s)2TM_$z~o z$ty7L_}uG8w3Oh{BIBSy+=Z3({mKQM_Cp_AV*%lS3G?`u8H4{*#R2fW|AsO-B|PE> zB?7?4x4#y*eViYR&+BQ%Na_~?2DJueM*mrWKOZ<~CTGJ`%4YFbJE#i%e@Qn0t6=$m zOl^qTLa_^ej8lXqnQV=O{~LO=A!rLL2s)sk%gHSQ&i3{1W*h-*)gSTn72CJk5sU(xvA|V_s`i+YoEt$`)S6TY%e)oWc@S*kSW)v0#tE+8zX7KQ8HMf zw_3+ez0Jdpq$YHV`)K)TEf_g*J5e(^g@N`ioc%5I%htGfOVT5e0m^#-BDRFMy_(g| z46Ri=Y7AN*gTZ>+OQdxzO_Gd>uVZk)M>*SXtb@VfJr>)$37J-i;NlU7izh25mL2-? z`@xL)Z0N3QbH~P#$wxR%7nVlHv(I&&+!AptSy+o_v+3+!DMDEGVg@npEs2u2I}x1u zEG+zayK@g`>t;zBv-6>pH@Ec09QNystKY>p^$woC800#ZCIV15D#>oNx#+JitW&x#;mG#L zPJ71)TK);*Q`@YLfS&K&l&it!FOjS}=o>YxbENoTB@OD={o4X)>bnTLRia>O?iYWt zc(#6RKXz*YiZocq9k7mBw}z#oxoG{o@Cq9U+v#Fm>kV(j&FS=CpD!C#4S1F|@R+C$ z+%g@@up$sH*NuKk{}pR3ky&leO50zb7`^>_TYypJLQZO#)#Qb0xGn24UcpD!n!~6n z3Nfpl#bI3E6f`n(JrmV=jOF#^956%EM(pOSn_}SUp{Fd?861o2>0eumE_n#pasM0w zrq;s3*e6$OMkQB+uh!Pw;oWfp;^xQ->`T%oFtW`{M8D{XYjsEGr^c&3u$vq)RO#0A z=Gs%Z@y-Pp{++~L329^vy?q{5;oXKK0B*{N?PI>((M0DnQwoqq{P!%cPiITTE24YH zSKfKm-(GVpFmE#}H7n;7?!NJ+=45|%P3;9XCHdCl76v7zj)hDVrx(^Ec>eJ62*5Yd z$eV;kEGQmqL{1~pKWRWhi_|SSEJC-@o^6$F#qw;9E#m(0Ouv-IbFDk!OMWVT2=9eM zEWb&-($*V0Wt?AvkOo|X@AHs#Iadk!hzw&(-$t+!+>9(IkrJJnWG>v4x#(6S~eUQZq^Gm&B9 zZl@!8?UAP--)8`X?9LB>9k-3zZj)iW5d9rg)HU~IX`3klYW%6)#qS=sfSs<=FXBv? zG^XT|)Ngg5McEZBS2l02k-`HQI?JTm70)8RT}RHYe$rn{0sCg2TWOr$DpDb0x%lFx z8T6e8=L0?B=holK5=CMN_|3(&<=*m9zY`|MvkYBe!Xux^XFEgNg?OWAUtffJ=moE& zxOdTuAm2CaFRzxa5gmI_umDBl6C=-TZS*&CB~(Y|8-;i&`Ckx)-sWmZcY`Jr##SW5 zwtqITaoBDO+;%LG+wDU7_Lt2vk1fYTBu!hLB1Oy_wl1)Z(mTW~bJ5P^7nOk@C%Fvr z2$CJ@FA5yaAlm1Iq_TSi42pbbX{f|4?;;_a6B>0fKvAj|4!Z$|BotZw{Fg;6E`En# z?hLxFd@JJeCAx;yLZfw5;BcldyYNW&Y9Gm-g{Ap>&{Wj7)j2L}*7(jgxz7xAj@Q*2 z1yHelmqsE5qC{ey)MoNObuWvqw8^O?yMo3&e?`{hgt?cpV@-RWbiCztLmzm28YbXx zE1!(TnvBY5GV-?D7K?&jXJ&G=t@Ih!?^<$%X!{t`Xe}lNO>wDT&_S-uU%K7z`>8*1 z?P22B*RJy^WyM7Q_5LQQc+c*g^+l5B+s1l<7+Rs^oPd5&;&28I$kqBE0zgr;ne(LG zR6MCs*c7MVx#@}AROqfMq%;Lb?JchVr#D)HH@58Ax+J5OI!WFHQaAuBYP{79V*nQN zNx`&&KUV}I%2(~_pDu%+QHM5Q6+v}i?MND~$Vvd$zl9r_w`uImeP8898T!XkxQgHT zGPk-W_3qc}SRWm_Mb{pN=rzZ_()7R_heC%n%#rRUKJ!&cm>FJD`|}nALy~WVZO-Ze zI)$Y1AG=S~=GCB?GYFy7L?#jZHx~e({Ppb^Zh;&B78q6uD2?T__lIXZ#*Rp@redd(z29!o%hQ zZgm=}%aKxXQ|(aMQid(r(L^GJ8v_ee92~usb6gh<=p1Xnhj$;@(%AY7qNFE#RWDeX z39j-t!}fnNa& z^(~OL#n*hnst1j9^RVK<(DgOYKB|y_4MkzCp)mp`0t;Y2}BZ690YQ?e%;$6Oe^!(88yqpcZc9an+f@KlnV6Z~C}E z%{E3g8Wqxot3}vMI*UXXcr#(wMdAGTTq;>j0P-_#Nef{e}LyFNldF z!Z$@^9HF$Q={(4{rE(5^#UcB0JLF0pUDv|e_0YqJx7u`_bjg&3(eHtH@BpA1&t#Vv zBrkgPU3)1hF)iWRNkNF+%zaX6kb^kG>u|dMPW!Tj(Rjf2;W8P&=MpcRO%+~s+LZEy z@hhfWsBXIY#F7(o+Puq9eNwK$8-N%1x%c@@Yt^78$H1Keh~yc<2E?zyVk0sa)*-L& z&y==S#E}o_EGwmuF*X|Wi_xV1ob{@^8I#@uf?WC*9U-HquX$AjEJX-pdXMiv>RIvH zx#eT8<@$@_r4R{T|22SK?r2(gl)AhIHIV>>ys%aPr^p5)r7vib)gb!b3E6~&k2!6r zC5p*L`}Kq26wDW-Z!~}LR(bJd+FKC@gT6;>SEz8cdVhQ+!mvh?FAefjm60P&!Q$F? zkPD7X{F*A>PpfxpPhAQGOjCFCZXw^gt|X+>$911WN{^#VjY}1iN$`imDYz^1bgT}_ z)YDh4f?NK2##-2^_oI9*t)5`gn8S~Q>6!)lCzUSkGKUcPR{?JR&X#jY`WHunY-ET& zj34vhW<-T0@^cQKpDUfB{r-#c!`y4`);XM|$Xo}?+Z_un976_X;8A|RyfS6zZLOCt zZ_w}$;8>G0BoMQl79l7lp%;>!eqr|3qmTPGmA79UN6pAs9)@s@mz+e+u$fD_d!m(z zYSkrSit{02@(u|nD3ybk(jc-%zA4F8h9|~Xj)3DSU$o8A!aUHn?yD3?Ue=;sUDxk5 zZ7UakEJC+W3M&a0OMJ4|c6|^)wld5vFU(1~xf8h(ON&x?1{itc>?Md5k>M__Bl4Z< zN|?6J3?vw)>nuk@`f~Ke8b{a``qw-PQ)(7nMiiVYvpvWAegy~p+zhDkM$axg z(EatK167+7m=OCLLBb>JeO!m$?u^^TFP>~EI{dHQN6G(`lQ9rHypH|_Db_W{4{ z_0Io&re+3WW=0%CMuQC;`1MKa3@yeak`6;-z(W@PCl-3!UwRn=f?)6}iYaup9qI z{>x&%6-)p#0Z0G?Kn{GI2Szb|{&+w@0Fn|{IgcH0nO!P+f0{Ya(c*wu-juy8@yOZZ zmnojK(A zgL}SOVAfDXN$>@P5YJ=cyI{!P7&G!9{2Ta+-No(mXYT_pwz2U?y)4@liLUnuKn-Rx z9YSYr#|^LAtF?4YZ5n8pKo-t6!QaKPVmty>GprvkA`ycXU^P?^2R@`p>((8Lt4Cr2&apYHZXu1kr6VE0 zu_tVPuhmcgbu*6rmWE}{v@ek62jG8QZx6j~G(EX)cc*H*nX!klU3RGrLg?zXD`DP{G47bf7>`i6BVd9rLo~-Yea#Jj9X;Q_u^4G> z!{mRMwRBXr-}8 z<;;=F|5tnO9?x|DH;%hHA1Q=#SZYOxbU=<*4n@V1kmHILVV1LD)TIbHMCi&Xt56Qh zX~VEe>|!B_Va>{!ndLBJv+ety4%dBu?(2JhfA{Zk{~nLuHshjlvrf(w#Q?x~&y(oOL|zWdkTT>X&9 z(OVe9^Nc4(q7q`$F&lBkvv#79+8Z$}iH%QyChB2824)e}aV(<}b)B7Bq~8qamYN{u&mK|Z0IPllT&s)fp)0DPi@&ywKqr)(}2u! zX>^m@I##-vbNQI=%%FQSHg8$saLexIAdn;`nMU$6AhV14Q9JgO4g1p)yVbDn<&jR+ z7bQf#{KdE+es}H5(BEZZ<2rFM8w;wV-?h0n2r6X60=1(Th_Vp5TZRX^zFq_1n{(JL zY4*F841_ly=;^D=ntP(lcyh>fpmP!Z$@7yTsEMKDbasV@fqo9 zHlS|9VpEmnrkmGR+!S#(`u+S>XV%*4$+SNj7YUbw0r%v-v*@PQnFH2bhm%XwbXiro zu)O5`&CMVBLUmc=bfs|w(}qf^$0ZWjx)`(axBKk&Nd;ozL)s5k4v5aJV z-m7G-d6y)Da@@f&OekoZI8f=_5!jiT)U)W&D^j+ij^WAUYl&|9eszZr>{P>*fajWe zG9S!mn4+k0{`39z8i);V$AhV#LxCs@`4Amz(4n{(+HbQXjTgmx8bdg=t6Lj8U)rBK zd>Ex${dG97^3BS9l+uRg#tVWDp!5!>?yYCwt(uwW)}x5eVG0Q_0C~Dt5W6G8wG@p``ts9+32|R#^q4Pzg?}@N2n5TpRJ)_;e+>O$#@F zKc|Ro7$Th*@NAuRjxUSP+_Jw`8YWeqP(J5HQ%oYF<`i_84ED%yc2=F3TD zrCUzP_+jVjOD-%IFrA zj%kmf*W~c8;e$bq#ePgiv^OgdMI8R!%di4o?R2(Jg->|z}tw(k|OFge8kNz!_VcxW2Jxi8XlY@0p;Zm z1zUZTritb`Nt**n36b|O#b&<%@qYy*Uz|pqET($(%3{w6PNb(!P&6{OXI9p}eBtWI z+FE+BP5I|+&;L9Wce+eQB|iJ?sZZBk_U*y|_Q2BEEcuZ8zk1hSvj8x|@rI4$8S0US zeJ_-6sSF>Ad9fYG$FuR~v*ieaOb3K@R_Vu-J9m>JEG|i^&oYlh*!KmV^Z=4oj>#UB zvVdpstx|u!W=X{p@D_Vf+qT?72*DC6x!x*kD_{mCSRU7Mo~4-mJd2ChtSvri_%<$~ zR}#^dr;b^R6W{_zZ<}6X=~HY3kC3E|LS1qQ8Hm%N63h| zQ463Iv%1+#!BL))V3fK55pY~NQ^lCx)~Ipf{5-N|$q}f|vx~t)%#L`o52+*M z(c*YX07b~EKc_qEw1bxw#fp*|?bKSv36`05W?e>{1VL4H%)NUN4}XGeJy+_6cReMU zMy#x3l^m4^)>x`Avsl1QGQ0nbTEZ{TD+y7&5J8IIY?J`!r?a#6eIT>BQrm-rhbHTj z8xh0afQnZJ9dPfpj>_X>L)(8FBS&REM$FD}dHStJx;arcfFo+$LLm=SDb)|*Yen4R zHPLu=GS^wl-vqc2qx`gk$Vi%Z(44ileDxVn;+rqUU2ogg7mOtM+} zOi9o(pBQ>{xb^*bW~atHD@L2T8)B+27-E|m0vWjUCu}yAHJjnQR!^J!W=~;*)|hX{ z8wmeK`SgfYV5w2dVv1+OZ1LJ^{hK(?TMwkCw7@DF*Npe2j<61a_f&Al>3Gba)qL}y zVwb1{Ob%+os4VRoUURQw_tyB{^p-{f&DqAc^~9?H5A&*P@v(MyOiLBJrpymRj0G>y zX!TavN@;N*x})i6R57@<*iTm6(r^BzyVcF%Z}h17a5!WqZ#J(q=}TTAlRrXx)=5~> z;*DNb>SIw@AhJb8m)Z^oC?3n4ue>s@VuB8pUx~dDzBMpmv2g5*VQ!~^qIKlAjWT*V z7P+5f#7Cpjq7|)YHO(Te9SOBFZF3NJa*!A7Pt93E+`3$FYvO(rw2o5D$pF1fKA3mS z;7w4_oNU?PXI$OY7wL??Mz;=yI=_1q*-Yj)#0mp45Sid9Ar4<2qvQ0V(SmOwf?2en z#ws<@PB1pl9!+QSsHyEXr_;mPEbh0Vx(A1g^-=wSjQY*R#A|S#qvJHBUhHMh=2JGa z;I21hZioE%b265Y+Me6i9$HdK|X7O$P1)4a>0o%4s3#^c@ny4XvG z{r76DQoxA!`LeMe2ey+_8K3P+yBi#mLGdG>#z^hXmuUdJWmKJQ?Ul`z7F60274i`i zDae!lt@DZCOW|a=5eGLZa4H$@{3ynceBRMkMk^CSUmC;yl78Vyuz_PE6V!-+s$pF8 zqf$$*1O204 zO7fIbwY~WTb9ugH#-s%2*_e4URywEsE}`ZKEX|D39Sih?_6^_p*-EAQXezicaH*j1 zX||w3o4zc|>50gsJ!FkloaNU0I@m?Z9Mb|17{xLdpC%isyv?Bkr{e+TXW5!BBrG&{ z*F?|>^9`8^v;*;U@X5Dcx;u=&1m&!l^s%a+%;gfc>3ZF6O}aIbJyY8PFUu;1QxzUF z5IW5jjKk-5k4Of^yW8WjZA%i1!-}?l#mh^G z^S%TP3O4dbAl*?8FEUq=*1u$yiGMn0dbR#wY2qoHou^0Gv$J6*E5lcE$ZurCn^Bw9 zrY@~{6wi&$M#0jDYuNPl^$*{J%(KfZ^wy;AyDt-Z^w5z6u~1bq5S#X>a#$u%Eyo!5q150f|?`f7#~xXwRB_M~5yki`4N~ zjDt_KqSWPh;I1;+JB|)0ZahnJ-isszgkVv%EiUpw<5H8qgC)VjRKde<`@K;;V>JAh zGjh-K8rMs?{toyTm4$L4MG0pi( zhZQ%}#U<{qrA^)Wh=1)tQjyM|8|vAy$(Gbc^Yg@CP6H#)%8uvyl=*Nh(VLCYjIc@( zPtT4d%sgDSzIKAbqq|cH#!_o@Z6=`F`;(7zABKc8UfyX^{A;Ey{!4yung8||EZfo$ z^$;J@;!WG6rm?VwVRnoc=oKc(Hp0b~NNJ0YeB5ykE~?6QKPzjD?m1m1I^=&;1tQ)$ zud^^#%{C8XSfKw1y*jXK)Aon3G^gaHmdD`M){=%dWqQZqqXiT!S>IdO}&I? z&-BDW2qh#HaxN$Kuk&iRH>9? z&!YPtcC0DbA{DIhR^u!h~iG*0i+qfm$t0K3ny@! z_D!FBSC&^ss1Z#aVO%mdO$A%HK8PB{@T3zku{=CYfZl{^>8plDv`?Ev`N@M@DKAp) z0jtz&2{;J#HMu5v%2NYD418pKqeUvt?)&_Sd=||)!nTB)h~^nxZ>TCJ_dp|>&;M?k zDqZ+}v>P5&Ig`6(>TTZ4=6ooRFX-JG6UpKVBCH1wGpB-B?jUe0>B4t#fTkAED7H4U zkT8ogvLMXj^PVLeay;GHb*jt^uE&hUT*WT&2f{bExVSnZ72IlTzAD=R`c==SRYNkM zwXAA7fYOvA)N+82g*lL<3Vd#XfBf>h_^P!Tcy#lRF)4Qdm!a@uer#(TP){JskUL$u zAS_(dbq4eR47n0wiQ+8W5Y~OGpB{?W98VpYJTX2bneCONrQo-za&w%pri~#`Ib@;7 z9{SuK>>XCE*GC={zND#s{P*C!)yt#<)GY?H$DHq9 zojS>p8}@7alE6sXy!oyv7zxWA-o9omS_q>R0OJvs94cv6hhu zs8BW{Xn<&zA#?EXWgTjRprq(bstrZ=)R&_tsoCdJKNp^qc7GI>WJnCn4$JHFr7t7I z;u?{uGgM?syx_m$X*`K&O=jYo z|2Cy>~lTFbo8108v z8IUdTwT~kwE{a_r;;`?UHrLs6>s*-^K6F#Y^Y@nSIr5<1ZuN-a00z!U0*D&(0zlOJ z#AtRaLOka)fMW^9=#C|d3BEBBTjCU>z44A|!(QbL`pY(E>2Ub=xG=(*sx5&P9|{e? zQ=mL_=ZD-8R=*JMZsY+-L-hK!4Ppa@ZJjOOLV=S%yfx0Be7j3)rRc6{_3iYHzq3+` zeDIU_CHONcM4Z*wt5pM^Wwk{c@4LFAm5R06QFC523z#kT?@c|!OuOZIR5+JtoGuqK z`;I0WkD1pxOtAPAuIst$^=AU8>GADb9-k26w!Q2~UUlV8g2knEmsN)e?@rIXTsI>IT@SdR3NSI3ccem6dnC5^=!wp11#nSj{my8hq;m< z|A}xXCJ@gK5CYM-f@iQV=SNF7$9W0XT^Usk1=n^8Z&B+>V4-@g_F9=HVH`-YJtp2S za0@;X&qwTG>W#V6S?1<}PR3|<^&Q*aP5tXjCDy5@1#|!u4=x0*5Rz9Qt>G#;JRvEp z(TM`8Px+;%4Woz=J`D;kD1f_=uhZAvCcOjhsMD11AB4~jr{>4T`bR;2``sH7YWe$mCqB?>`n zOf0V3dB=2q*6yyUjiKF{)X!mMXA(6*Kj^WaGF8Hi+Ba$3GSkApARIIv`iEztSmD^$ zM<2qZ6uTZK_dEdOa_QFY?>7pG^ZhaB*ReJMe&;<65>kqWzyDkYIx#a?vii_g;32E0 zC#5Hbn_eJw4p!w_nt$rr{zUzT{$jaq>PYWNeXsk=R{^fk?cK5dEWpSZO)ri;itVLt zyi@vKe~-+Js64@y2|A!*?shWCbtv^W1}e4gv?r(~Ym-RBbE z*YF6qU}Jw@Fq;ifpOEwB%HVyis`GM)9Y6Rgpgv5=cd2@WZfZmOp9+#45o<*a6_bx zY3s}wYsb&Ko~`je#62~qyh=VQ0YX0a$KP)U=T>dGH)Cj}L53xS+n?$>1n|=)#V&2g z#|Az2$23dhsu9vgMIGJW+&6SA(yw=Z7E zY(8CayLwx2#RX4@c~xne*udG3{odVs#P7oU_1&cTzuTb@>;`ASb*MHkGpLQX7n!(9 zdk4k<+I#5l%^*&9b53ni?7HD&AOLJSJ@y~0R#27L+csix9LT$c=tr=d;wBG1%%r4v z?w!0(_uL#83>OS|{jmq@SBt4GeCBo!>y5W?jb5dlSm3abTZHuXQ^3N>mf^45O9bt) zuK=d_DRwykEhH4g8C%?9Qi*006$(B8C+_*ZV4M%9*cO81dfq;(@C|~xD@#Jt>d*e? zJe{T>emL^!!~$ezP}TNqnJ3#~)wIRMZ8_AsC`xe8i@T=F%*{QKPDOQ=nv(Gt3)koW z2;C`e72m)WvNPvX?>tRP+)`%8uh{_cYDcf!9`R-^12%$Erdyp-6p>nl_|L)X;)3@+ ze&0J!Fakf;**oPatE2h*Zczuv$TUx7k%0_Gkpxt__m7+&iBnHa&@$>Qt`kmL{DIGR zsYpvG73KeuisY&xYtR3X= zeE;P+sI49t{1Wb73jz#|rT=)=?Lq(nk%+J#%sFaMbNg1&Q}~y6A~2n6ld-1k?%|-z zl53tO7AwVO1S_7M4(~z8RAqhffU#QheH@s$lwhAIfWDLoJU1*p1?-u9VyR@9kpDe{ z1A=m{@!xk83z>D&&VJiFZzLm*njdl15Sire%{i*;C95+`6;Murk*HPp3WQ?$^Iuv+ zIV?|$Ch~GBl79)nm^UdC2XE}wi4_u|kE`7L62PJ=J^}K$e#Fudfc(CcIaBzGj-v|- zesI`3LUrTc&-`_=yKu5OLAqH-_pUJ7CNGMQbRHcErD=kkFlVIY0afwbDy{+7qW+{1 za{=-%q~tSz*T$Qasy;Q|75oovb3w?^+F@d5L}%#$={J z3?1~B1EwRW)lAMLN7(k-xhHWi_;E5$1^jq!m5l}%0BrQi59P~bGFN%3#Y*~Uu=Zl? z05IqzQNq+aLg$1S@lJ2$rnrKLk|b~~%Q<#K7_f`Et^w*7<~S^G zkX6nb{i+$my*@BNTVLhFHEIz$LGucG9Jl_rsLKBpzWkqP-2Y*kkME6z4N3|+4Y_It z06w4qB^=x;(dS~52Nd5ECeUc$YutpaHLSf>XMN%0r-^6e-U1s!#y|^!nzF}*Z9*n{ zitUAIM&AcQ>q8$X7=%3(I!iSOHO9c;lZj)_awI_YJ()aGf$Wu0lc>=D00^VCAt^89!L zMDpe;(*=&yP0gmGYkW`g52mXFh-cy3&Y}UkL* z;3{-3Wul)a#yz-h_orD!jkZovf~+) z&PlP4nGNJZvG{=vNhuRPx`rcW-*q#gHdXlH*Si3^xyoLZnXdI_g;lH-=BBvD^J0eC z55pTwC$bhsT-Ee)v9~Kl;}kUbcq?h|{H}fL+NOLqI-OTy7C;PZDaBcAGE*rAOkIpn z4zHK1r!>wKdNeQ`O6U2Nmi;863Eg=E?c^1}7PJ}*(3{BpBvzdfG!vyG8e-4D8)cj2 zu|WtnqOx(+Pc^x@trm46t91zlT{E6d^jbPAkU0OmH^uI8S_g| zrR3xx-LG5UCRskNkvX4!rBFM?j!}_PP-KI=czyQ{*loyzYh^g4;>v+s*MZ%D{WKh6 zUL9-d7f!xvMPR&cv|m&;Qef$hf)2M*Zv4}#q3;b3&-mRnRjOpIByWiuB6nJuQC=Tf zo7@4@sSrJ$5j3>_hLCF}?06=%D9P}GM#+YGd9oLq7cCXLI);xp+xdiiW_Q#Gs&&DL z(tpGYA=_t;3fVqZh#I6q%b9HcA#@V<_OTtWw&_2{(!K4t#^|t`iZYzuw@KXgwc&`q zj|$?=y0A9gl{3{77@Xx*=v~thvsDAojej|8g?dP{HZm00F~VW+z^fHYw4Rt1SIwI8 z`bF$fO|WC6?Mu+M<_pS=Ns8tx^0|!wGj~Ov@Og0uB1`}6gSDb{IZqXsyk}rl%m3HO zt02YPu7R~;`T(OeIto5pTo`Y~)yS^io_+hmL9rulHRVTRjAw(ko!XEGo;vx;fX+AC zHi6D-xO&b&L{|koz>Ylt-iPVib8WR z-rc@BU`GUzx8m)RqZx6iWW8Q-MVF#A%*dPJO;qz8e?7YwsrQdE^)JQ$rujm9S|GD& zb39EgYlv7(0VG)M7_G0(UOV7xl9xCrKC2SGJ0-kiFpiPA zyvZZjlX90v-hjQ7f62x#1*k=?LI0C!UZZt+nF|mKzBnR9Kwb*>SN0X0QndCEgzlnz z5*Obt2TH|t|I^Nu!}Ho=WkbUNYSWQYqW08O6+S_>r?XUqMx zESRR+|Brd#f6N1`c7^|cng_OSi4$^m<}-XU)GnjFdERH3L=5T9!6$c<+K#4@JytL6 zaiLgm_Dg&C;TkYf0dwZwdlhnsDA%f<`P3V^riV^l3zSI=QOj@|T(}KOCo1yNF>~D#Y6(L8~NZw{ZRBzXdTZ zhK*koKG2UgW4L$?V44Lfp0g(^H$roPZX2YVfRzDz$SGz&=>v=#I&kok!(BC`vW;k! z?Q4HQ{}ih(?})kdZ`O9$&G)e|(kK7^9qCq+R!zBM zjJ#4^TDdKWliyiq71ciwX#~qz%l$?)^Z!RpFm%bVXNH8l56CtU^99Q=f2LI(`GD!< zdqwMr)WVx*Qf#)H$26jCCp{*-q03s^;ZSB*Z9VhrDMH^^5YjmWVE{*M`gv@Rg_aA8 zzmIJrGmQq;tp(=x5OTfnh6@ubz`Sk;apE)e8YbvL=FZYKZ-}_OlsF8<{=8FsSCD-R zhEVEC##VdEa(4VgqknaG0CxT!AldKgCI!ID1ejffUZ&E<>)0`1_EC$R#Pplvs7we!$A)vKyP@{P0US?;{M6eA=e<}n}C@mTCr>B5PIoaTT5hU zpqk}c59Ol%%bP<6V?~NM$3ISad*F@HUJgr^=zIpfw2}siXuEOKh2F@_Jay@uP`R&N zJ;?&$Ns9k%YbipB@38a&Al??|mCdq1v*{NKR(6h$?tOVjm9F*G0$mRnvpiUPJ=`NM zdd{;dzG3dMjI%juKn(vV;k=zdacbHdX4Y3p5L4Xw!wE$f3hIEW_`_-Ui}3^M?3D9{ zz4R+eAXCj-4vzXaB%<^tOt_IXHq1hwa3h0a{XZpf2!Vvf*Ns&Pw~A2t%5IB6(N#r$UTE#}7ov$U5eMVipwiNHXqv;|5N^~nA0?NP_bXZ#)0yVi zx7;%yJiR&uC-jDH1_p#tEo?6G_C&a!tYV<2UrjYJiL~5s?le5G(*)L7t@vpo7n$FFxONt)$K_ z>2(esPURR%L)+Dz&S@?V-jS~ z`7&158V1%XAN>JWCjeKdP3uS0JC6Q);E#`laM+P3^&?4szxD`RGB} zJL#Zl5a8RB))Opub|Z*k;VTSG)NKCOyyu`x8S);;naFP(pwofTeU@kdsGJ{4E6|9E zM33JZ{#>im>rM$CUuNY!9F^ECT;q|E^e*wk(Qz{T662?XmVvvEzo!BKY+NQrVJB1- zGC}n-XNl_#yYHI5Y1X2>1^nnASlbm{IQJ!K+cP;(Mg8B{YH?V1Do(yf=V7IM3J*x=y1 zJ^sS?W6O;@PV6GOdOB^5%YYmxZRI9FiSIjFb6Ilxg%DohJDZzV)zA8hZ8rX^ob$K` z%bPkKi5hl6o;?(Ek@R{Wez!)ht8NGI-mx{?UD`xS5Z>kw!-&d}IbJp%5~r{Ic3N#K zhC4oUF&E6Klk;xY+2TGQ4l|cb4p=_%woU7J$+(O#c~oS6+}Idh4vlS#j%nK-;1OBb zsC};pBX|g{1zsqsXm&C?sRn9xq4JfKc(Z%2kyW*>+3Rw3%AH-(3gUNp30Ftn?f|ol z(K1I%r`a~XCZw>WRr}_Vs5_?7@OjxuhJ-q-0TUY?-)tHDd__cv2~016_Cu({fUJ1) zhp*wqNA^V=C|%rDHB@Y4zgwK4kk#-C9u(n44E#EzQ%V}vsw(|=plVl+CWbConbto@ z%D3325~E{zt33I#;8|Hz@%0H+=+?WY@D{&a(*_Nd+m*bx#hRK-i^j!x3h;ZRgs%(W zCm0-m%6RhThns)dNYY<>?y}0(DJrT3ruZZZB2*t%w0@qHQiNc}<>i<6!(lg~8VlJ84O!npypM<>MkaR{+(-JvM=lt3!btN!oaIsj6mo;D;+O<`|>y(K? zSc&iBkk6sSTkgwsE7V*YgB;;Y?#MLS= zrjR`MXctfNw<|E&J-q?nZ~1b7H4q)gVvb*Xc*=5gb6lVL;5%u8-lYu^Sy!%^)ebgM zfn$Ev99eMt$(3D=r4x(QOAYyAjK~yF+J{aHAaK)OfTbI@0C+asj@7dXIE*9 zo2)=F+c+1I-Vfe{1;heYTj{&4BnctizrJdo-Q6RG!ho_CYYbif847-Y|gSUASW^ z@vU9j$SS0f9aP6|?i@l7FLf205kd_4H#i5?Wm_|&zOgDWiI|U><^$(? ziGmJLePRNDHJjQl6kYeJ&T^%|EZm``tbKmrsx4A}NW|UI3KtXu?dc@r^hG&-SXT5~ z<7k3Pxs`Q(k&QcfuCKAE0|5;7?#;c|MNedrcvM`yvxoK5%dRgf@|_HKh&Nb@g(<#e zY?TNrS(B0f<@#>@6&(YleCGY}hlFTWbV&fA=H?WzxU&NzuBp!L-t<@y1~*D~A*NU{m3 zZ7!WsK#w=0^!!o5Xmdjj`fM!Edu$_4u8!iW2AO1`^%r-Oj^S+EVCS@L!vaacv8Kz3 zqx8Ij@bYQwO}a5!{nMtae{q&TJFz~wd#7@m)N~$y`P^%g)wCNVUdm=3A7?LWe#1qe z=YJEaarQ!Jd6T5hZ5#}3F^msx&~Bv!^Z4j$T?dMS9}2I`rI%{=wmM>g1h#UPpUyJU zdDlY6aN{Vq`BRPHeA-i1dMgcB|&Q}?wz+lV%U5(`8-X82|h3y-xkHZdEX5mET#lZn`=ul(} zdDl?zD5e?B_eLViE zbcK%Icx5JHn}Jx9S>13&k&ckRQtG@>$Bf&fIk?UM>O6(K1lS}| zH}M)p4rh>o;3UDeYPTOX#+Nc`1~|cR+Dl^xrAz&<+^HrHDYDq- z6@!sk7mOCmeO?tNrZ+d&_a(@G+d7GJb5BN_ zbQ?Xl#o4jKt{NY>qLSQ{fdxcFSD(djW$={EI-rKw{{4CDWT&ILBd>s@)H|(rF5OA- zj9PB<$tnaKIoL%mXwUc|S&&itR777MXmt44)-Nr+8pb)_aJ3HnZvLa>sHYAeYN(y| zlOW7uIG!+zkOoS=j3B_V?^QfTS%yP&TZ^u;5(ym4w$F61%oh_}UXQCOE_dlw9qcKv zsx7->(qMZRT~9t!LZb)RRAu!s4Kowl<_70@JoVy-qsw#A6RZd9+7}lN(JK+iDEWSR zvjEF50sf%{_g-k5iwyUj(%wP2E=9s6a$xD$KW`Xlo*Nu0 zYYBG1gr3QAA^BH?G2Ss4xa83+#_HbpCKi*h^rFMbDBt$5zKjse%OKA5ONq>8mM`^q zk(yI2Bluj21lL=!Y=5{*u?>tiH?=&`eb`$pE;1(bjqwS@8G2>aZGfkrzbxg%(X#`H(g4X5&5&j=#K?h|kOxyq4Q^cwv;N$o5r zAmk%=rWlkdRwf2)`a?vpx35YjEI)ZE%vOAW#ifbUt3NU^*PVDM(y{rO;0sj=EgMwl zbc_Gs)Bou6h@k$Cph&H6U|g1BARCkiGJ0Hzk;Rud@@9jLeVLZe&-Q0T$f_o&((fhU zNU_QQDaeF1Xmwd;xhzm5VF{VlhOzW* zBBIUeRs z*C4rrvf>?(gHZT#o$_Ksaz*mNxghp{eVZ)q#w%A$G9R7ujz2^TDbE69Wj6 z#)~Qjo1hlY;si~h*!{K`T**g7=ad#RpB(8@b(mrq#iI zc4|bpw7gtD^faCSE{ru?dHJJLFCDK;BMd4a@s`%ph0sE0DD6$aK(S3ftv;`$-!+V$ zoZyB;$uDCsksI9QPc|EFSEFl`F38jEIMnL0)chcicR`}*hou*K34v6wFZp*+LnA4Y zLn51%Gf@vw_xI6aM&mr`m=$PNn1==M-JPF8|98v z@m2Gl4u883p7*+zObrdzeomMDbXUbzgdrlbjw-ARK$q<@puhb5$qw;Z`;u?qa3b=_ zrpWl9vb7kH1}PSMqWZ2WEXBG)W80yA>6mR1?W$X!#qZ6>@!^liVr)QesQy-1hp-gx zzqJCTO^a1@KQkLOte;e>6FfvOXARSr*cAw5gv+N+dPxgA$#1hrjlxUBX;qR`!Z027 z9GyIu=+$3VV&eck27^Xl>UHvkmUdh{&VazO=G-++9h7LvYq5lnWuN&M3O^pKK)Stg#RFR5 zRGmBCpNcf1peypI4^i7LIzVe(s&#kGHL4K(Z7&}3Rzf(P_!LJ60Nc*NBpCX))g^qq zY{Wc-}gNAg6>6h*3PYLp@J*c{{5I!3t=)9a8 zFG~U>(9!F9_*v+nBm%)9eYo;P`-+!#b-r56X zt8H*80}gjQbJ_>5a+uN_mOl5~L8G}MouYz|W5gS(jOJTe_Xc5o4 z#ca97QUetqChOjQ0M<}p>Cjm5JQ;SkLcj8~edPGOhJbuIw@sF$XgqP@6I4T^DLHii zfY>ILQ#SRrook8)E!pw#C?j8>H?6|To20#-m5upI7c;8vn#yaw+RR&go6fOOhZSAK zNZ)|lPoHBlHGjZtpa-C`Bq=rVm^E(c{B2md3>YqSCob}J$qDoVz& zg|;C`isjY*vKNEFU09*^GQA(0jCu#F4l9qiib>;Cpe=hnFqY5x1)fg5r(rpFx3j!S zm3Ah_SvJS$Pya08VU-{5qW?w4-{`F|U;(o6^B!0h`mDq0>0(5Q3kIYjNm8XQC{KxL z-D9C0+G|RxlN~8n63bRP5G!nUH;$GLvETcuaW`nw?psclqu#dxE$)v^+F}8F2S2^f3Ay{B+vVv=bZDLbD#Sh#8WM0;=8nWK_C#ZstQyG1iFp{{`Muj4gB`1 z9IXc~x2@Ebp}-Y*ohUYk0GB(iD#jil(EZM;;1s^f-F)6#a*g4uV{r621dl@wlhzX<$mDlsN*i7&7pzArnA0+qt-9L0# zjrsT^@A7?0&J02Q=EtO<9nX5nF7M7x0s7@1&jUY?mjzK%yHT?1%!={eRC&$Tu$^02 zn=E!B#Pg=q5RnKXe7ZorbBA0`Kl`ao+v%dM!4Gx?CQ`zi*Wbu7Nx7-Y0GI#%bCm;= z{r5KM{A&mcDWl)-t*!56ruA!|T-vf_FLq)8O>BVhV>9(GqZb!#8qH3Wq_CSytkIjB zPN%;tFV#FeJQDg=))p6mFUmb!Op}n5R1Z1nv$VIfQ_f$gyA#QBeJA#|A-OTRt@{lS z=&7X<)l6*_Asosi^L=saMLApVTfjD1ZTzb0j3_7;!lIz5Aj3ro1Z3> zJM|jsIa=gs3z(w?B36jJqF=PeaQ5SUPU2q96JO91pOAL!uM|vRk2rN0<+hIs=4GFe ze%;|~)FAydA(N+$nI{@aa`T3343GDr)6Lq{5LkC&Hn&9nlB3q|>wd%_kVzyFH!}I$ zeVF&ns~=}?6?&5K9I8jooOH}M@h($}GF}M$FytH9^5aJUqAzd+^E_8Ms1SMum-*%v$oeC z^jSy8&Kn;1+h;1C+0-%LYGry?XJUlgTg`cU@3#5q&-Uj#PVZoqvv_`JPrEwK>m(&; zJFL)fj2mfkQ{7w8=X;{MbM1)K{XVl{r=UFH)3mb?8vnmc0`CqFcnq15px3K=C-_WV z(N9rQLqj{ScKuerA(!&CMPE{4hP~+#aYK{_cW;i6-Q#+4%4N~z7t;7XF-xcmt~y@o z|2!_{p?F*$uHIA&{5K|uOk8wp&)YnPsqdipa(2WC+pcbNxpGN~&W3-2(5A$j50cN_ zN>6T4gTiHGu-0=rXgc9y#EV= zJp7x!68PP@L!~s&8(xarj;jzlOHve(GEoDYLyxMA^Hta>tO0kzzfQoo$6?J};khlx z4rKP?aL<*lJPG*zX3YDS;asN;Q)rd1`1)?aCfQZ5fd0^xK_htS+V(dx|Lwc7Bxrs> zi%FzX5v~Un@GdWU|^mntIkFa31^}9DhU*rzkh=Sc3c`w zj`=Xs6%Qo(C%^JM%fB<-MH41ivpGFE zGjjt}LsmtcNsywUM8wk3-Y0cBg0Qlc2^Pf%b<+G!O-I2m#yF}XcT zxYlphe`oQ%Nc3#x2e9%)kE~%lgetn*75DKhcWBGn0nU5U$lBfecH3o3sd0krfQSnz zbd9Pz(o$u*W-SF@qw+3ysJi8YDo>{15tQ^SN#>_*+uCr9WZTpB5SFC%V}W3ro zKxh)VE5=#HBs5~y$Vi6C47o7QUrLJMhQ;pgQjud88$+Mm{JzNRK?T2eCxUeNTw<#( z@0kHFlKyKO>aWn5KzMOv%g(7StTN8_?wR9)?5;&yd#pfOyQ$G1bmmuvW$c1LyM|}_ znjJFu-Jb>a)0EB1eXN)Z)Yub4v2L6KjYTCIymU2ea;?KG;WiLKJ7&% z?D^w-PjXwK(9W_yYHPx4wr|gs=bPh(2GkQzo3TSQfrARiCFzmX;hH+-klx%bY`lDe z-)TgmIHRSMTT)P5vczh9NdG8B63i~;BqWgBM7F&@Phbr(H+U|4SE%@SiE(v@S{v7P z4J5Z0>o*2NS~aU!!{Ja7el^u6*GCFJAQ16M8a6`frRS262ZdBZ3tHH$<{b!u z>>g@=a{8-+>(c-grJ|n@2s1S~2?CA1c2wWg5_H3v^@$%vFa{T@QJKmELJ>kgz0=@G zR0Hn5+7(47A};=b9GbEph=nd_{Fs;+3a_nw43ZYorQ$gJm80Fy!yL_j${S;b*nLM|;h#k8K~&Hl zybflKjE%1WS-hWQ0J;j}Do9foFK~DMyHQfHZ#~#3dU^U5zUq>)Frt*wA*Z96Ye(&ut*bumXXfzWvzdiZqHp-jko)|EyDmhu zsD2c`XpFno->v3tPyJXAKD^ndkRcY-0F}~}oVS_d-;$&}>s4L)B<8Yq@N2@;-(Ri5 zqV>Ds3Lh`;nj2~;LprCeO=bf?I&}X2{vZ$|nGivmSekIAY>1Ywu5N-_o~PEzd9Q2v zN}8#*v18Jsf0`pqp$}|8z`Vtq=LXIP4Ahpse~(M*@Ric)>+AFXQyU;006>_PpR+yU z2_EZ#Ef0*Nu3DEiyW3{E$bqgRMbpWvtY z?Rnmp^CoSCCW*I$5AI*7ER>lpSUeYU+QsIsT}%XT=F@_%sG3CnLwqK@HenSvxe$3xX~yJ@bZjXa8*U;(MTv?; zKNAPBdv&3cMu;%Tbf5LJb}TlT<028oXw1@Z=?n`qG8W=Jw_|2NGk$&osMYng{vuNJ)@4pX$;Z z1X`4GgH=u!TX8*4z#~l{|7s6<1<~(ng%;p+XS=x-M{dMfb8}5|wfQFqgNmESFuC75 zK_rZE?`(?5Aor$Hh5w=DB7lkUMEKdD16X>9kL}Jl4;N~CE#2c*4VhBA2-V=75s$7R zSssK%{YOGzNvR`Wd9~3;XvL=(Wc?kFELn3_~h)eJb`5XNMTjI|!IE z_#9rw%98-g8vy~wJe8*EngP=BxGEL!B+YtZA92Rvi+TP{M=n*fzL8V4RY&wBv?cTo z2;_7dZ`KyIu(egr`u+^vWZ%t8<-B9a6gVSWE^*o=`0lelR*qlxI5*x>fI02T?-0zl zKI_b}B!@@#J^?7v2?MTV^IS*nkx(?vrczg0B)f_Tq3nikQHtb4*mi~Rb)Wzw6!vz{Tz$I%iBsn)$*GtoNH#?nwGpfygHEOQh z+a(hEIxdx;QZ=_VmGU5ZQn*qX{N&p&4ya?HS5>IsXGl4(z-Vvp z-7=w)B>mnM_nN_7?6-zyt?l z+j|4j@#Mcz2aiom`-*JGw9D0;-Kj;17BZ-081_CYm-YSfsIQ~yct&T2F`JmV!~Mx@ zz-DL6nuDZ9gyA-2cSnvQU&)m`s(?J?xlE@`>42@eINj^_m^X`VR>qps535mA8C|9j8Ix6cNFuqmUGEGd ze*gl#?)r0ddGY|WEQsv30;2|W9fPA+AMb6PG$dj2Gz?HPUAJRQXYaAWRp;H4gw#<9 z27S3>$rlNyDHdj9?kVtJpZEQKPSlw3uW#5&IQ_6RG8*3Qo-s1%eVWwV=|$a8Bw7_n z+hZ01xYGb3*PE3Op+;KZO+A9`dCFC7oP(RM#$6vV*ErQ;sEDA1*5B5!{Xg>5e|3YJ z6aTZ}@$bHn)mv`P&Pl5;?Ciaj1SLys1eFlDQ1bToJRhurzwQ`_bTgW1)>up~wburRv&M ztYXe3Oj5jS#g3*)k=>cpKy@srB;MAV|4op!ZU>{DqnYb-Wt^t+?1dSmSM1aBNFP6E2!zf7yaU#4ahb2t}1tUBN95? z<7miWZ6;B8ZK+iv(h-AXOSVeA(HrD{2J@b`*p{bf(M2%l}z0ET_`pdbCwG>?)BQ$vX{ zQUMza)iP;mI&g5F*vZQgp=rtC6UhpPo2MYh)BpK}-gdd|ubuUft+Yy%v|$_hhKid}{00 z6;aUKAwIF`U$;zQymX9`ilOMY832o~_O7_XMm(hntf)O@>7L^@vdNUf$~bO^eypHL z6-2(EXN}Rk*Cn=V)P2*C!bxASJTvSnA`)_iu6%GeQX^kE?)>)9IJC&E6yof>=0HiM zNxXrug%=uHMcS_IIzA-rdc0YjP7$q%D@xm1})(CoG%8c ztLcAl|4KO!e^6S?*12G$t8T2u|6;8to)ds1ck*DBhvoPW^k@KvH#`GioU`>@?I$aF zjbH0_RmMCBx|-VBGM64ZXH30vK=Ue9@T_p>H>^$p*|%gnRyo=E?=!+araw(jQf97i zZA#7<#+>+hP}8&xFjjQOR8iIePOCJu*Tfct(d~@+_NZ82U;ohSoH~!g~l;n}V@JHJLzV=&l{rH=!I2>DyU$mvqe9Y0r z6vvgNp8jVkf1s+S(}Dyl`d+*%vK6dX;^7v2tN>=MaDan7csB5*H<9HVpqX35Ky)z! z0|ib1Fa8#M#b$6|W_GSWt}v-u$A|n2OSd%iyahvO!4$~7u*YXAzP+c-^X9ZNbm)#0 z8{((O+s+p6;(#1q;|z;|^0N&b<&^|_fCTRnI@H+V7CUAd;FC}6Avac_ong6+0b$)G zW2WGh#NN~_AtO@x(Z`!=S&gG8T`$ij^rrv+PPbtUon9z*xvTN)V?aQikM};ce^RF+ z-y5Y}qe(688@ugvDSLA3tu{u_6!E z>P=u|08}|}9rR)!@f6!m6?{jK-#6v`V5T@5-0_)Sg2hPT_NF*A!y0$8TENoxKWP;h ztK^%a40NI()AGG_=rsyVcMPNQfBF0i+P=czz9GfY0EWj8zOQb@o~YnA{|GuHi1~nr z+`dY85F6_~W;zE!I4=i6299&d0TchTWIgo8H(NdP!y`B_kEYN0vb|{F-Fjg@q$3wZ0qHm6& zvGLK{R#cHJ0Q6zZgiH$}^RCvt17ayP#AZ1jt7L|NB$aSX6B(C6+}+&^y1C2_TC`#q zq>*ew|Me=$)5R*&Ag4{4C@*P4ZqzQl-n|D`*y|cIT?WZiBu`?e8Z@>!y$mvKDpCoV zehCz6AW$lb5~E`%?Xd+&SXFFP1~K4930=u|LqSxEvFh4Y)LC3wLR$TF=3Vs;JeL6c z@Hi6q4B^;v0EPuHtFuBYk8Ngd;Wm$VkGIau$S*hl0tojZ7bnuLako*&I028gYPg~r zXi2L^RBe{|I1%L#HPwA{Y+R<}*_TLk05cIMcUzDiADV`vAxF*iDB<+VVa(`(x^gRV z861ROvlw=tUj|>LSU@ZZ;L%a!u!XTF|EwVc?D2ZGqUaOGs+}YXj9PPgpJtSGbGo>( zbl~x$IBaoF17ssW*s{^2AwpPyV#B}gDB%9q`tQxULxh#D-|XcB&@jL2U@h8Sz`h8d zICPKz6T4DCI&e#bW6gLZng@Y_jznvF!bTouVi8CejRjYD!V;bgX0fVf_s4&U+x&hR zD@@R++fP>bMOCUB(93d_0pj6opZKKDiU&K|NQ-L451L`eO$qC|>L(R?V7oYCqw3&j zEMh$n1}99@24k9j9(+Tu&As^i&{O*c$mAgq{N6;0h%i=-7;qzWz(5{NqJT~D{U*Z% zJ|01rAd}Z$qCW?*zQHW08&XOS-2ln)FvCV#cN^mx!9451NqBO<@**WFr?*fzzaDYh zVgY+p)LJm*jMz;y8S~{)AojLt5rnFQgR1#Mczks02Mm%WCh8}&wy9}41HA@pcjq_2 z0o9O~L#ByLo`_BO%l8@Ez%!BqCx_8A!Enc?<@A0XYh8UEYKGl}PG_90F|-$Re#8I_ zfnHAJU~dOlpndXMP!YI&Nn17dvu` za>xMOesTKi>IqA`21SrwuZ~~g-H;9b7mWkhTLJ*dlzM(L6!N1n*~3*jAL~#InWh*g zk^Mt=n=|J;8r-EkH8I~V##!vMo%V2G+vX?q=x5l^zh{d+e`&XUKUZfwWX_11OCfF<#9NuOfxEw5))?Mxy=J6}<1sD6aWi#{tC?4djQ1L9Fl7`J)V*|Q zjt>j_%BjtVc-gpoLt=I&f3D1H+GJ=Xf4aSFK(lp$x2i&`qpFZ3L7Hh0!SLpZI`$n$ zEOD(4oYz1T2p`ef`v`QvFPZ^UTL(ZGXJ7ywl0WW%$%2 z+Q7i@x&c=KgK){l&aV4Apr)+(sHJOC+0Xz@(J+u6Vzl5(HqDtWmUvKBI?}sK%V$T~ z_iJO(ad^5(;<*!7wjN8*cyEri*Q18JzWwct8+WsczzxyMAP|N0)hvKPmFw2+-y>}j zt`W*o4Z06&CX{Fnj#ZL6#njmR%-In$z`Xe@+z17aT~5f7dEFawB;LeM%1)7YtpIJB~`1dfkqS53czZF)KTDk z9aS|pD-l^)_3CP25n+vr-rGSA_SR9-r|eWM^8v~>U|t0N^^Qfb~v$r!eu_yE$$Fa8}Rfl-v1_g^#idc z3*AdrSZuqED!gWyA~`vE$oMMvEh`|=lCWrPuy}zfTq?#5Df%AL=2zD2e3bCHY$eIT z!A%}vq0zI@5~t8Hn-;XjUu!AOvhF1Wtu2w#aFhk&+*C`}^?j)$W){g}X6j0PW64Tt%T^5miEMFMHOj+HOjimfpWy%Ae*Te$)#< z=oIxza(Jl$)yj#gRnAkml#B?vAvF)i{;KlCI5i~$-J{ALOtGwX*k$kO`SzWqR6(}g z4UtE~%0WS`V-v5|wtwmFkIG$wh!16Tr3${jd5%%{KXiPbL83jZ&K?s#S}j7YOWu(6 z_E8@6QC_fiA%3;M!C$F$0!I@S#j`_it2Dk%@gm(fP6uUd;$|CL!WnT^Gep@le$STL zD&b>B)`QxMvB|~waRqOieE6hn!9Qzj8X-~Yc;#dkoh{RPvBM7L(; zIY9+wm3DBEhd%Z8(#d)3RG3DF4;D9oO9&cK_^n-MlNwx>qRneQN4C%67y;tSnI)>cZGAJ&?-J{%Iw1=mB1 z3l~8Jld|5M*jamgIwXl+V`D=WLRdEFs_*N<*N~ntdnCX zTr0MtPZiE9rd0`y5^$nK`FH4%jPoV&gX?!5Zk5FMp5C>kjt3i}pNLK@M~0oc#6X!~G=qrdk^KX2qJhmwQ8$i+aF58uu#x^ zv^|{O?6Y<_*X((eK@Kl}>U~t~^=^IT_}&2f_XK0(f&nL1q_Ua*>`Zog6#a@2m&yA9 zok0K4RSr)3;1@|$3 z-0<`9ieO4r8vx(a-axV7E&NuhwZS|o>OjBB@jYa>bA0yix#(K({8a8i;=MeIJrQAX zCDx$``z-A{^P|oiI_Sx-=*gXr3_S3_{Xa5u?cJ16cI1RHdBw=Vs|Bud9^)3xdS{s| zNgsyMzh~+Df8b)$>w#+K($Zt26N;@jHaHE*0?OFtN8@~d4e~YleQMOK-=57mBVi~x z@K1Q!mKD3>kcy&)#`3)FmSTS5BkSTc{BC-i*YZG0R&gigfm(kzBwg)Sk$+wNiB%GX zhaeFnkSfrF|LwGn8WW6Wb-Nesp0Pr!+TXH`3jWs_RH!L~q|Pkfig(T|rWp9j?^ITy zBbuH&*$(u@2AS$tn8?xwQGiyE|t9Q`a4Za9CJ-> z$y>9*Hcgp~-lNN$X7JzH&g@9-Gn(46HvWy@>sj4(smF`_b8UT9G%C{$?#@FJGQL*Ml5A4OJ@^)fCLVvK3!` zjC4>kO`GsNDA`ElhbRpex@vAG`?Opj#9~w2qBd*i_b| zBr>>-f9v(h!oMA_WiOFQ2ksm7*m8P#9~G`dtYP}xQd6Twzo8|*{F8|w43dS8+>r91?0h~2WfFbZSo|^Pw^b_no`;CE zxTG;@l6sEg?p+Ir&D=1br6fA@*B$~=>!q$ zQ^SPB(v11c?CFXE8Kc6rTZ?=08;lzT^Iv5)9xU#lkn;@TCiO8D!3Z|mGqZlU6=~zoCS(+ zTC%EGRht`S^^obFIyyciZzy~7$GnzXF^X0XJWUI%M-FBq3A2n=VN7MQD?pIKJSl-> zcp>Ti?iXu;LkxKSAh<2{ah1rKnpji)ssxZDEsgJpEdPtMt+?!}C*t$_iYFx-i|r>Uhi+BueR8Wh^aG4_fgXFsl@ zlp#R1Bj=Wqk&?2qgQuegpQNgA^&VI|e?NET6`lO!o$(@xXJ5ZA1;BW|uAtm}cQ?~D z+ZOg{or+|?9R8>)=U~`*XkKGfyrPJX^aGRGkxYGIt8)9H2zFY6up^~p4b5SKq%H1N zUFO4ncS@n)JhO|k;ns9Z0V9s~Xkn$Q*$WWpi=QsgrkFFPWk<>Yr9O8%M8`F5l#^fB z0B(6LsFT9gWpwpaqHNcbHiegu&-QwfJ;LQz^3u!!hD)Xb7wfVvCao!~i*%q;Z5y|Y zTiOA$$2q9+KjOlK`j>XV){`hz8KYU(_XLSU5eLi`;y*2VxX5oH;>r8unpzF!AY189ubY!6-_BK#? zSL?uQRI_ZMBdne>3i{o5p>Xx=-{n->E5E+i%`L7R5`aL1pMXf*8kO0SmA8&A)bjY+ z^IO^DmWYphH7^4r*N6@${lT>cq58%iAKynlev`9CVn?1=} zitkAmpKk~EFXtTE`@|%R569J0n;{xYeoRg2@AiCtTbwB=m4U3coq8<0sj+fWoK?nl zn?NqaNCp)6RHkJj?kt)F_i4iaa^d#e=*f+BHI`yTq(t~X$FQ-zPFA@u< z&}&QmDp{eWV^+Jo@h}8(L))~2Q$Pl>Lx7_&`I(!q?KrF1&nae+95OMKGNIraKFmNb z!*t4IG(sekdy!5OTEt)VD0nd}N!InN{3yW&Co@7eCpGek$3G9yMWQQGC*#n^VsO5F zGQy06FFNS8Uj|9z3VHyr+SDjR`zG;Z4zVEbDXW0RXDL3-f5zi%37b0iqiLJ@o_Sx) zH6N{hBO?e-lU)~I!#A8w#>s-hUuOLshRK>Sy>I$vw7+<6w&wf-cTJAzWhC|zEhjo? zK#Ey7Uljvb0x|}154`@^cl==9nz2Q1uJ-j6vnZLAPMWJW%vE-9sk~DUq(O@@Dk@mC zJLePK*1b&J-E$hfKj`x;o{;o zNI0S{dyfJZP=T*#JLQhUa>LZ%W^&GueT z@VnFpM9fH0++7PP&M()|{zt;HK#Sz+hOHUaz zmO8>MZpp@Lxr_L8=<*B_*U#NW_So{R%?O$7eJV*~Sk12ea+C5S)){$#!X3WtTHfmQ z%fJFGPA#Sg&g1RfBV`>j&XtnUx_*~UZ4SBO9|nW7A`OUeu| zc5Yu4MgO-_2P}TaO(<>|>=zo?=5u!0BucL8c(v{Zelj+eEZxKDF+d2^ps~_&-t+cX zYp?y^+8?^$&2-~^+~HCvRsETGe9u#fbPk4+a|Z{tngWja=UV)9J4V;^dVv`?_1(Wm3z>-RwzKl*X3gGZFE0LW zhuruIOh8oBL4%`XuAN+(Y1>Gaa0FMK* zi5|Rolfgy<@;PTaKa2+tg5|1tzd>5{{L03}^&pbT0$^ zLPb2iu(b3;tCuf}A@T9?c2-taXtw3$W!M8cI!Ov(Qt)wywe%1X!Vlsg^W?8%&-XwOb7Nf#(O~UI!VyMGAYr26Mlp3RWnlnX{r@< zB@n+6_8ogHv99Q>ef7&!XKj0KI$5zEm&$)=7vi@$O|~2G-kvuPWUztY3gUCDY8tIUd_$ zzn8}Y%-P{)UzQ-GL}vjz?QteGEj<954rZ@E5UaD$dj77B3+F-J1ad(PMa6J_n*!aWl*WmP*A7);%;}+^Nu$Mjl zEHmnlvEC-c|2-UM$p-xXS7&@xQ$ysxz<@6828G1we?) z=KnpEJN7!BWiJf6n(5E7$AVWIOsQ+0Dq}lc)k-jwG<0VM+9d9AM%r-P@ugN~@M1#c S_ATHngH&N!&~k-mq5ludJX1pe literal 0 HcmV?d00001 diff --git a/docs/source/Plugin/P138_ValueOptions.png b/docs/source/Plugin/P138_ValueOptions.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a45ae386bfab5279f2c67e6445103ea6af264a GIT binary patch literal 13089 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 literal 0 HcmV?d00001 diff --git a/docs/source/Plugin/P138_events.repl b/docs/source/Plugin/P138_events.repl new file mode 100644 index 000000000..72327d677 --- /dev/null +++ b/docs/source/Plugin/P138_events.repl @@ -0,0 +1,12 @@ +.. csv-table:: + :header: "Event", "Extra information" + :widths: 20, 30 + + " + | ``#PowerChanged=`` + + | ``source``: ``0`` (Battery power) or ``1`` (External / USB power). + + "," + | Event generated when the **Event on PowerSource change** is enabled. + " diff --git a/docs/source/Plugin/P138_values.repl b/docs/source/Plugin/P138_values.repl new file mode 100644 index 000000000..1cab53a47 --- /dev/null +++ b/docs/source/Plugin/P138_values.repl @@ -0,0 +1,34 @@ +.. csv-table:: + :escape: ^ + :widths: 20, 30 + + " + ``[#batterycurrent]`` + "," + The current measured at the Battery connection. + " + " + ``[#chargeundervoltage]`` + "," + The (fixed) voltage at which charging of the battery is started by the controller. + " + " + ``[#stopvoltage]`` + "," + The (fixed) configured voltage at which the battery is no longer being charged. + " + " + ``[#inputcurrent]`` + "," + The input current used by the controller. + " + " + ``[#chargelevel]`` + "," + The charge level of the battery. + " + " + ``[#powersource]`` + "," + The power source used by the ESP, 0 = battery, 1 = External (USB) power. + " diff --git a/docs/source/Plugin/_Plugin.rst b/docs/source/Plugin/_Plugin.rst index 30d87d72f..47338a8ad 100644 --- a/docs/source/Plugin/_Plugin.rst +++ b/docs/source/Plugin/_Plugin.rst @@ -362,6 +362,7 @@ There are different released versions of ESP Easy: ":ref:`P133_page`","|P133_status|","P133" ":ref:`P134_page`","|P134_status|","P134" ":ref:`P135_page`","|P135_status|","P135" + ":ref:`P138_page`","|P138_status|","P138" ":ref:`P141_page`","|P141_status|","P141" @@ -509,6 +510,11 @@ Plugins: |Plugin_Position| Hardware: |P013_usedby|, |P082_usedby| +Power management +---------------- + +Plugins: |Plugin_Powermanagement| + Regulator --------- diff --git a/docs/source/Plugin/_plugin_categories.repl b/docs/source/Plugin/_plugin_categories.repl index 0ffb7696e..303eecc54 100644 --- a/docs/source/Plugin/_plugin_categories.repl +++ b/docs/source/Plugin/_plugin_categories.repl @@ -23,6 +23,7 @@ .. |Plugin_Notify| replace:: :ref:`P055_page`, :ref:`P065_page` .. |Plugin_Output| replace:: :ref:`P029_page`, :ref:`P038_page`, :ref:`P041_page`, :ref:`P042_page`, :ref:`P043_page`, :ref:`P070_page`, :ref:`P124_page`, :ref:`P126_page`, :ref:`P128_page` .. |Plugin_Position| replace:: :ref:`P013_page`, :ref:`P082_page`, :ref:`P121_page` +.. |Plugin_Powermanagement| replace:: :ref:`P138_page` .. |Plugin_Regulator| replace:: :ref:`P021_page` .. |Plugin_RFID| replace:: :ref:`P008_page`, :ref:`P017_page`, :ref:`P040_page`, :ref:`P111_page` .. |Plugin_Switch_input| replace:: :ref:`P001_page`, :ref:`P009_page`, :ref:`P019_page`, :ref:`P059_page`, :ref:`P080_page`, :ref:`P091_page`, :ref:`P097_page` diff --git a/docs/source/Plugin/_plugin_substitutions_p13x.repl b/docs/source/Plugin/_plugin_substitutions_p13x.repl index bdf9ca8ec..4e131c3eb 100644 --- a/docs/source/Plugin/_plugin_substitutions_p13x.repl +++ b/docs/source/Plugin/_plugin_substitutions_p13x.repl @@ -62,3 +62,16 @@ .. |P135_maintainer| replace:: `tonhuisman` .. |P135_compileinfo| replace:: `.` .. |P135_usedlibraries| replace:: `https://github.com/sparkfun/SparkFun_SCD4x_Arduino_Library` + +.. |P138_name| replace:: :cyan:`IP5306 Power management` +.. |P138_type| replace:: :cyan:`Power mgt` +.. |P138_typename| replace:: :cyan:`Power mgt - IP5306 Power management` +.. |P138_porttype| replace:: `.` +.. |P138_status| replace:: :yellow:`COLLECTION` :yellow:`DISPLAY` :yellow:`ENERGY` :yellow:`NEOPIXEL` +.. |P138_github| replace:: P138_IP5306.ino +.. _P138_github: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P138_IP5306.ino +.. |P138_usedby| replace:: `.` +.. |P138_shortinfo| replace:: `Power management controller` +.. |P138_maintainer| replace:: `tonhuisman` +.. |P138_compileinfo| replace:: `.` +.. |P138_usedlibraries| replace:: `https://github.com/codewitch-honey-crisis/htcw_ip5306` diff --git a/docs/source/Reference/Events.rst b/docs/source/Reference/Events.rst index 8594b4c7d..e2e623f02 100644 --- a/docs/source/Reference/Events.rst +++ b/docs/source/Reference/Events.rst @@ -527,3 +527,8 @@ P129 :ref:`P129_page` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. include:: ../Plugin/P129_events.repl + +P138 :ref:`P138_page` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../Plugin/P138_events.repl From 1a18d051997957a0b526df63194c723a7c7b45d4 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Wed, 7 Dec 2022 21:40:55 +0100 Subject: [PATCH 8/8] [P138] Use same term for PowerMgt as in P137 docs --- docs/source/Plugin/_Plugin.rst | 2 +- docs/source/Plugin/_plugin_categories.repl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/Plugin/_Plugin.rst b/docs/source/Plugin/_Plugin.rst index 47338a8ad..581e3316e 100644 --- a/docs/source/Plugin/_Plugin.rst +++ b/docs/source/Plugin/_Plugin.rst @@ -513,7 +513,7 @@ Hardware: |P013_usedby|, |P082_usedby| Power management ---------------- -Plugins: |Plugin_Powermanagement| +Plugins: |Plugin_PowerMgt| Regulator --------- diff --git a/docs/source/Plugin/_plugin_categories.repl b/docs/source/Plugin/_plugin_categories.repl index 303eecc54..bb3148fa8 100644 --- a/docs/source/Plugin/_plugin_categories.repl +++ b/docs/source/Plugin/_plugin_categories.repl @@ -23,7 +23,7 @@ .. |Plugin_Notify| replace:: :ref:`P055_page`, :ref:`P065_page` .. |Plugin_Output| replace:: :ref:`P029_page`, :ref:`P038_page`, :ref:`P041_page`, :ref:`P042_page`, :ref:`P043_page`, :ref:`P070_page`, :ref:`P124_page`, :ref:`P126_page`, :ref:`P128_page` .. |Plugin_Position| replace:: :ref:`P013_page`, :ref:`P082_page`, :ref:`P121_page` -.. |Plugin_Powermanagement| replace:: :ref:`P138_page` +.. |Plugin_PowerMgt| replace:: :ref:`P138_page` .. |Plugin_Regulator| replace:: :ref:`P021_page` .. |Plugin_RFID| replace:: :ref:`P008_page`, :ref:`P017_page`, :ref:`P040_page`, :ref:`P111_page` .. |Plugin_Switch_input| replace:: :ref:`P001_page`, :ref:`P009_page`, :ref:`P019_page`, :ref:`P059_page`, :ref:`P080_page`, :ref:`P091_page`, :ref:`P097_page`