From bc55ccd987ca3d701eaf400d3ed2d3e74b2b02c1 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 10 Mar 2021 09:17:54 -0800 Subject: [PATCH] Reorganize architecture section (#839) --- docs/architecture/devices-and-services.md | 57 ++++++++++++++++++ docs/architecture_components.md | 26 ++++---- docs/area_registry_index.md | 1 - docs/config_entries_index.md | 1 - docs/core/entity.md | 39 +----------- docs/data_entry_flow_index.md | 5 +- docs/device_registry_index.md | 3 +- docs/entity_registry_index.md | 1 - sidebars.js | 17 ++++-- .../en/architecture/entities_architecture.png | Bin 34546 -> 0 bytes .../architecture/entity-core-interaction.svg | 1 + .../en/architecture/entity-data-hierarchy.svg | 1 + .../integrating-devices-services.svg | 1 + 13 files changed, 89 insertions(+), 64 deletions(-) create mode 100644 docs/architecture/devices-and-services.md delete mode 100644 static/img/en/architecture/entities_architecture.png create mode 100644 static/img/en/architecture/entity-core-interaction.svg create mode 100644 static/img/en/architecture/entity-data-hierarchy.svg create mode 100644 static/img/en/architecture/integrating-devices-services.svg diff --git a/docs/architecture/devices-and-services.md b/docs/architecture/devices-and-services.md new file mode 100644 index 00000000..dc62ff3f --- /dev/null +++ b/docs/architecture/devices-and-services.md @@ -0,0 +1,57 @@ +--- +title: "Entities: integrating devices & services" +sidebar_label: "Introduction" +--- + +Integrations can represent devices & services in Home Assistant. The data points are represented as entities. Entities are standardized by other integrations like `light`, `switch`, etc. Standardized entities come with services for control, but an integration can also provide their own services in case something is not standardized. + +An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. + +Integrating devices & services + + + +Configuration is provided by the user via a [Config Entry](../config_entries_index.md) or in special/legacy cases via [configuration.yaml](../configuration_yaml_index.md). + +The device integration (i.e. `hue`) will use this configuration to set up a connection with the device/service. It will forward the config entry (legacy uses discovery helper) to set up its entities in their respective integrations (light, switch). The device integration can also register their own services for things that are not made standardized. These services are published under the integration's domain, ie `hue.activate_scene`. + +The entity integration (i.e. `light`) is responsible for defining the abstract entity class and services to control the entities. + +The Entity Component helper is responsible for distributing the configuration to the platforms, forward discovery and collect entities for service calls. + +The Entity Platform helper manages all entities for the platform and polls them for updates if necessary. When adding entities, the Entity Platform is responsible for registering the entity with the device and entity registries. + +Integration Platform (i.e. `hue.light`) uses configuration to query the external device/service and create entities to be added. It is also possible for integration platforms to register entity services. These services will work on all entities of the device integration for the entity integration (i.e. all Hue light entities). These services are published under the device integration domain. + +## Entity interaction with Home Assistant Core + +The integration entity class that inherits from the entity base class is responsible for fetching the data and handle the service calls. If polling is disabled, it is also responsible for telling Home Assistant when data is available. + +Entities interacting with core + + + +The entity base class (defined by the entity integration) is responsible for formatting the data and writing it to the state machine. + +The entity registry will write an `unavailable` state for any registered entity that is not currently backed by an entity object. + +## Entity data hierarchy + +Entity hierarchy + + + +Delete, disable or re-enable any object and all objects below will be adjusted accordingly. diff --git a/docs/architecture_components.md b/docs/architecture_components.md index 98fe0d53..840f3040 100644 --- a/docs/architecture_components.md +++ b/docs/architecture_components.md @@ -1,29 +1,29 @@ --- -title: "Components Architecture" -sidebar_label: "Components" +title: "Integration Architecture" +sidebar_label: "Integrations" --- -Home Assistant can be extended with **components**. Each component is responsible for a specific domain within Home Assistant. Components can listen for or trigger events, offer services, and maintain states. Components are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in components](https://www.home-assistant.io/integrations/). +Home Assistant can be extended with **integrations**. Each integration is responsible for a specific domain within Home Assistant. Integrations can listen for or trigger events, offer services, and maintain states. Integrations are made up of a component (the base logic) and platforms (bits that integrate with other integrations). Integrations are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in integrations](https://www.home-assistant.io/integrations/). +alt='Diagram showing interaction between integrations and the Home Assistant core.' /> -There are two types of components within Home Assistant: components that interact with an Internet of Things domain, and components that respond to events that happen within Home Assistant. Read on to learn about each type! +There are two types of integrations within Home Assistant: integrations that interact with an Internet of Things domain, and integrations that respond to events that happen within Home Assistant. Read on to learn about each type! -## Components that interact with an Internet-of-Things domain +## Integrations that interact with an Internet-of-Things domain -These components track devices within a specific domain and consist of a core part and platform-specific logic. These components make their information available via the State Machine and the Event Bus. The components also register services in the Service Registry to expose control of the devices. +These integrations track devices within a specific domain and consist of a core part and platform-specific logic. These integrations make their information available via the State Machine and the Event Bus. The integrations also register services in the Service Registry to expose control of the devices. -For example, the built-in [`switch` component](https://www.home-assistant.io/components/switch/) is responsible for interaction with different types of switches. A platform provides support for a particular kind or brand of device. For example, a switch could use a WeMo or Orvibo platform and a light component might interact with the Hue or LIFX platform. +For example, the built-in [`switch` component](https://www.home-assistant.io/integrations/switch/) is responsible for interaction with different types of switches. A platform provides support for a particular kind or brand of device. For example, a switch could use a WeMo or Orvibo platform and a light component might interact with the Hue or LIFX platform. If you want to add support for a new platform, check out the [add new platform section](creating_platform_index.md). -## Components that respond to events that happen within Home Assistant +## Integrations that respond to events that happen within Home Assistant -These components provide small pieces of home automation logic or involve services that do common tasks within your house. +These integrations provide small pieces of home automation logic or involve services that do common tasks within your house. -For example, the [`device_sun_light_trigger` component](https://www.home-assistant.io/components/device_sun_light_trigger/) tracks the state of devices and the sun to make sure that the lights are turned on when it gets dark and people are home. The component uses logic like this: +For example, the [`device_sun_light_trigger` component](https://www.home-assistant.io/integrations/device_sun_light_trigger/) tracks the state of devices and the sun to make sure that the lights are turned on when it gets dark and people are home. The component uses logic like this: ```text In the event that device 'Paulus Nexus 5' changes to the 'Home' state: @@ -49,7 +49,7 @@ When we put all the different pieces of Home Assistant together, it's a close ma Overview of the full Home Assistant architecture with a couple of loaded components and platforms -The platform logic for components uses third-party Python libraries to communicate with the devices. Through this, we can leverage some of the best libraries in the Python community. +The platform logic for integrations uses third-party Python libraries to communicate with the devices. Through this, we can leverage some of the best libraries in the Python community. diff --git a/docs/area_registry_index.md b/docs/area_registry_index.md index 5629441b..de3c29ad 100644 --- a/docs/area_registry_index.md +++ b/docs/area_registry_index.md @@ -1,6 +1,5 @@ --- title: Area Registry -sidebar_label: Introduction --- The area registry is a registry where Home Assistant keeps track of areas. An area represents a physical location for Home Assistant. It can be used to place devices in different areas. diff --git a/docs/config_entries_index.md b/docs/config_entries_index.md index 316eb6fe..5d3b42b0 100644 --- a/docs/config_entries_index.md +++ b/docs/config_entries_index.md @@ -1,6 +1,5 @@ --- title: Config Entries -sidebar_label: Introduction --- Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. Config entries can also have an extra [options flow handler](config_entries_options_flow_handler.md), also defined by the component. diff --git a/docs/core/entity.md b/docs/core/entity.md index 505be272..c114af38 100644 --- a/docs/core/entity.md +++ b/docs/core/entity.md @@ -3,46 +3,9 @@ title: Entity sidebar_label: Introduction --- -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. +For a generic introduction of entities, see [entities architecture](../architecture/devices-and-services.md). -Architecture Overview of Home Assistant -## Configuration - -Configuration is provided by the [configuration.yaml file](configuration_yaml_index.md) or by a [Config Entry](config_entries_index.md). - -## Component - -Examples of components: `light`, `switch`. - -The component is responsible for defining the Abstract Entity Class and services to control the entities. - -## Entity Component - -The Entity Component is responsible for: - -- Distributing the configuration to the platforms -- Forward config entries and discoveries -- Collect entities for service calls -- Optionally maintain a group of all entities - -## Entity Platform - -The Entity Platform manages all entities for the platform and polls them for updates if necessary. - -When adding entities, the Entity Platform will query the Entity Registry to make sure that the entities to be added have the correct entity IDs. - -## Entity Registry - -The [Entity Registry](entity_registry_index.md) will track entities and allows users to store extra settings for an entity. - -## Platform - -Examples of platforms: `light.hue`, `switch.wemo`. - -Platform uses configuration to query the external device/service and add entities to the entity platform. ## Basic implementation diff --git a/docs/data_entry_flow_index.md b/docs/data_entry_flow_index.md index 92feee76..00600c9c 100644 --- a/docs/data_entry_flow_index.md +++ b/docs/data_entry_flow_index.md @@ -1,6 +1,5 @@ --- title: Data Entry Flow -sidebar_label: Introduction --- Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager manages all flows that are in progress and handles creation of new flows. @@ -309,10 +308,10 @@ class TestFlow(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 task_one = None task_two = None - + async def _async_do_task(self, task): await task # A task that take some time to complete. - + # Continue the flow after show progress when the task is done. # To avoid a potential deadlock we create a new task that continues the flow. # The task must be completely done so the flow can await the task diff --git a/docs/device_registry_index.md b/docs/device_registry_index.md index 9cba8edf..61138654 100644 --- a/docs/device_registry_index.md +++ b/docs/device_registry_index.md @@ -1,6 +1,5 @@ --- title: Device Registry -sidebar_label: Introduction --- The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and humidity sensor might expose entities for temperature, humidity and battery level. @@ -80,7 +79,7 @@ device_registry.async_get_or_create( connections={(dr.CONNECTION_NETWORK_MAC, config.mac)}, identifiers={(DOMAIN, config.bridgeid)}, manufacturer="Signify", - suggested_area="Kitchen", + suggested_area="Kitchen", name=config.name, model=config.modelid, sw_version=config.swversion, diff --git a/docs/entity_registry_index.md b/docs/entity_registry_index.md index 11bfd795..12132cf3 100644 --- a/docs/entity_registry_index.md +++ b/docs/entity_registry_index.md @@ -1,6 +1,5 @@ --- title: Entity Registry -sidebar_label: Introduction --- The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant which specifies the [`unique_id` attribute](/core/entity.md#generic-properties) will be registered in the registry. diff --git a/sidebars.js b/sidebars.js index 9c204e29..9b906a3f 100644 --- a/sidebars.js +++ b/sidebars.js @@ -93,11 +93,18 @@ module.exports = { "auth_auth_provider", "auth_auth_module", ], - "Config Entries": ["config_entries_index"], - "Data Entry Flow": ["data_entry_flow_index"], - "Entity Registry": ["entity_registry_index", "entity_registry_disabled_by"], - "Device Registry": ["device_registry_index"], - "Area Registry": ["area_registry_index"], + Configuration: [ + "config_entries_index", + "data_entry_flow_index" + ], + "Integrating devices & services": [ + "architecture/devices-and-services", + "entity_registry_index", + "entity_registry_disabled_by", + "device_registry_index", + "area_registry_index" + ] + }, Core: { "Development Workflow": [ diff --git a/static/img/en/architecture/entities_architecture.png b/static/img/en/architecture/entities_architecture.png deleted file mode 100644 index 68dac7802b1d3ef2839c19d6e4b7a59f789a3f5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34546 zcmce;cT`hZ`!9}Va4d+LQ97t#upkf+5NSFfMIwl(^cs3EQbWKp0vVe0(1IXMK}zT) z1O-D0MQZ2~A+!V{HBv%;Cpa_jyx)8Oxp%GKJ!`Sn$vOL+{p`J;{glt=IUpbCXmA|k zJ;uhy#-XLD_K=P3Fqn<);Duk=fh%#r^;kBxXKY$(cOLnVQYScH=Mv2(x2ii1IgP=j zzqSWP9_f310Q{x~tZshz+A!oI^mfa!NF+5f{(0)X1kAB(hBuF0wqpBy33TA9iLK4W zBl4Hk^8U~kdjTEFMp-86nSN?RcK$h$^+49zK_?csY*O0o0>WexAyPI$e$E;DU; zE2t2?*hoV#)9F}x}M$bBQ=| zy=sO0C_UAHY2qjF_1m|zCF5%*CA$qu`)vnH0zL$K91mCxVZLnT3U`>Uq#d_lyfEor z)P%MBg*kX9kkaZ;dc^Xq$K(58%!S%tE{^(>>9fVnsPop)XOKHBD7GfnsU$c&9P*KM z#%2jU1p)70{CS@n#2cv=c@%&6Gz82I0?ybXk6y$d-ap;H$oBWG7S#T;rCO#ky-FEw zne$G`p^!WO^{mT{R#9WrJQAs+yWXbOlVlsC^VE`Kr?Hk>0C@H^?8UxFuovNw=eAME z>50|1Af@D+ZrMs)HMD+P(*JDpm`*{U3X}UJKs}?32Smct)ETLBQ zY-@CEY7qARGn~KP;CV7ecO6=PC?d(#Lt}B}}U* zZtxw)ZMQRhrlvEMmjWdLT`(!o7h-;XMe`?A9%n9o4Dr-U5G88{JS?uG_DbU#zYoV} z`mb#0?se{To7h)w*Xpa(f8QYa4}NmS%^&A#Tyxc6EXzG0(PMCaQ!Qh-2#BX6ABe~? zr^~f{+o-D0#P130+bo9q-fauezMt~99IK;0&s4S_Elj2cwtvcG#z~m__ov}pr?`SQ z_BfO_cY?P?&&31~RB8kCyEjOT&DL|`^;FC&`uLV^x8vbl$m_LYqGjK&=085tcboD; z&IxU|9pQ>$Zu*&*tTdr&<|C0e8p7OC8+Or+)UVG!tDEyuC;_@oA^9fn5`@WGwW+k} z>_rMKfH>A;VlT5jFB%*$Wh)UflJhX+^EV%z<`G)(^t#HPuDjulXWXFV90k6f7#S#QJha_868*G1j!45_udH4<-9XMmE;jXkNcW!f! z6VAm);dA6|`O)Ud-0DGC>UYb`#eKyoFSzg>3SsWx?5Cnbe0M(8(|%0deS48OLu;IF z$qPP*TQ56uu5p>K*iBXjF+Aj{zzwQB=UNh4$qTAw z+U#`Iak*`5z@V1#QAqpHwY9s7eLNhh5Rr#OMT^L=e)2}VZQ4s=tS}~1fq+5r%iz?i z5T(>YafK;itDhFb@FPmoazb2pS}AHK;`$rYh*g_vSLh5g-6HVnI;C+XjXC$3KGY|Z z#tl;FMWKddlxZKT;Jdyu;J^=qr~;yFb2~Snctv~$iRPz1=oEkPzA)Q@{cIR6@7blM z(NX29`{xOI4YtTnm#F%!8?*ap;jU+Ck$0!Yr=P~G>>e!pBtkRhg{lRkt~Ymj}30qMAyw8weEa=ISO4STGoCf)`}DI zAbPjb-TX&cW>61iy4oAPHO8KAw25PoGHeR4_ofl1@tc9`2ZFklh+oqh$$VV&WbbZ!>CFH#wn)FEb-0#gN-4nP zz>};5l7+V4ez6)RS1lW zbQHg^yy@y#H|_0S(x~a_a@nH(o%c)kpF|i=I z5P)rqGZD_zUCw>S>9xCUj?J`X%2x-4tkyAH?BuIA1}} z%z&lLP6uT4nat6JzBkB+_#5Gvk_3CI;+Z#gLQ9y#wXU@W4?8k8yo>nDlgedm-;d~# z2shUclOXr}wP%m7NYIu+3W3 z`9OM&@P))1NiVZxe_xx3YCpAh9+&76Z@Y!VN#vBFN%toUIp|cJt0Iwx2*I_Lne>;Y z9^Wzx+T#k^`=(4mTw|6Dq1vz|uES4Y7j4_i%6oR*47NFD=@~xdX4fsu4a#NJJBDd0 zb6--~DkFVVt~6I%u=1IpRwv2KJuJBkN0f`TcC1jaxx9K?xJgcLQdeUr*#3dQdxH{h z<>rQB`pRw>oKZ`@iAAO%?1U=2+v#sUXm7)xZl-N425f{LgB|?Ki%EvUt@dSBK7SAuRo0Wu zPFa%A6}`tevACgo9_`%My{OmvVXgt#w#cX(;MIgW8TK`Wg^&oD5!b-`ol*(HxWdgH z)2J3%PF3E|wH6iF@;=KRni4IF2ebs*8LbhdO!!>Ds|A-VASDf+aM%E(&IicqrGTs&rIX{|c-i)&ALmWbLi{O#w?CE8Hv(l2tZmo>Vt zQ=&6Wie0hMBL+j-8GS>dkhC$HVF!w6G`TtRPDyr@#__M2i$XrF?4oQsn#pit8cz1N z_19$)NZ$u7*0#L^udn0P4lb7ETUJ_SE{!4RAH4$4Khl50*#a7l_Bq`x>-d|<51|gR zLykr3&Dv+w@(&E8ax4vR*X>nIUGTw2RdpUk!N3DPJ3ZOxp5cM#@~wf_DUCa7xmTRK zMLA9azRVgMiQGjSfBqx<^r^?H5Dvy(wP{yv6@AbPujXu7L0Supc}Gt#Gje$kd6?Ni z2V0UH1o?cufT<$==vERX0O}Ua1KJ3_xw#Y5o=RWz2sOskkg^+zI$or3+P{`^ey4pg~L`KENV+^l<~NYK-$OxAf&R z14OhCBT_^@`7nmDve;iUTKW#(GR(buc(szh(gZ%{K~ag=4$RF0SK6xyG*4W$>$qn& z2m~3(;~C-=%6dJBEV;ElAKb~gHo6Mw^PXQ#>P#|&_ExsLHI6tW$UoSE8saV?B-hUs zeMYfNRnZU%W!E%het4-8MOL)aQct;X#+9?w%BDa&FkQ^PYDU_<$B*hy$S{$qT&yM6 zC&J11<{pO~j>0BSN-xcQMzI0WD=S)ck%ncbvTZm%K3JD(VGVVCvWGh3b5nztf%rNh zciWDm*!ff@n}5*>*Cx}<&imR4vUx80t;)o;Zsqs#ki5i5`1TK-VhEXBwj zmd#YeM!)NF==KV7+PkXD4^jx}&1@e2QoFlJ>_@f9SJHDKu#4EKP}{h`JbS1@eE;yuV(p;d zbzlJkM`qv^eE}P-OJV4W=3jY0Y(OB#vKOv4(18mFm%c~TxfDSpWpnKX8ecbIIDg+^ z*AzIeC|j-`>N-I7Y17E;#IScUz9Xx+G*ncZD#V8>!!)j&-2YuJDL>oQ<+?p|V0j7R z*Qe=RLK(K#^H!^XH5N)0H;R|&zHP;i#vs5fqi@Fz+VIo2pXc5&D*;q!>%^!{n5%L` zg8}G{TN0#~#05L2b8Y$_UJWZ0&7n$(k1!91^m0Cbhb4^mIHIJSwV&Lyf9J0uKA+%aM2RR>C6BR#H&GZPi zDbGQ)e^+E}e&I;u=w*StPUz|BY(~ZhJjx+6ubMJM(oo28E{{YiCYCgpdu0~j2+B-+ zQMuPZifAAF&EB53KzYxQWX&nS8y2<_HhQohRC*loYF$&Y=Agm!0@bhEJ>{Fql&FPU zgnMweTKoKB2e|UUt^5p65g)CtBaf1El{+Zu8cM;-WgF5C@%B=z5F(?*N+f20V7|Bd z3b(#3C$`(B8}v2ZXYCe^#PDVYni0N7)0nZJ8M7!L$oCW9UDr@vEVqJweJBkMymSis zw!X*1oUg&Bd;3OExf|l5%ysRZ;rOyLc1_+Njzt4f1Bg~d2YLo$sFqr;1C8CybS>0+ z{U*SeIO+6zOL~E{S4Bs_Mt?N8w3q@e=wj;ed6WPOySxNz{vFS2eg&4%SE|%=nCz+> zb@C=1 z#wMxZUPT7D*~$nd(I8+$m|El2(7u~7tW`_E(UH+n z6K;uXM$3Vb*ko6)=qscOiXJ@5Cd0v{>L8$8-+n(U?U75{tgs1(_5WT)8relJN`^bq zUy*}_HsB=Ekx`Os)l!(?0GW{D2OFD}8{RvqpH~#WqrQA#W3qA_;Yl6Usi#%om}R65 zu{nrcMGg?K!mzh6-CkHF>k7PS$6PYn32`#k7o`~;TbFHNpX=?c!d!1Gpied)nH*NS zMTz0CC&*v-6S4*745>YcYWp5pHg(p*dytQd#7wdHF~}hU&P#mG4XQaDiOhI^3Zt!I!asvX+o(XK*;c+TU zhj=noGYx-?5lJ-;HbKpUAwHgr7?qWs2wKM8K!~Y-zn`GVkGkd%ThB4vZfJ>F5Tj{9 zSA2ZsBd5e(Cb?wWyTp7~Wyg`85p>RdtC+$?_;H`KP2`$nOmd=$j6}mqTlMuuy5Hmq=Q%<$!zQ4^G&zLYkDG(D6!TQ?pZFFuQb%Xq zu{wK-Q*?U;dD2`APz25VouJi&73CLB!M>f50(-@5ThT9DQWo#vTef*XDn6u_5j1=M z)*G;It;*jexXdxm#BUz2QEZMg_8BEX6BI6G&)Jk$7F#nkv1R79#zmh9g0#z9@R!cL z)sQ6Ix5UiqAIw-e?AB*Q>mO~6Fk{m-0e7PtGEM>Iv^w(%AX*QOOduzRFsjYPXk1+( z3*RsaA5QAE%R+=P_mhaL^x=Db?Sjb56rO?a!MqFk@N=yp6Z7?w?0 zU3a(^g-peruQm2vy-@{h2?#Kfz>qDa+3G6~4pkKh+CYmkAuF@h*Sk=U?Azy~kf=kD z-=xyimoD^z%Y%A$RGxlRmG9e`@|H+5frgJPD=6_}f>$lq@hxQ_xpbJ}z$%{V&=tC# zUI13Br>%E#%bu?l1#oeK5HW`;gDGPfPEeCH}N(c5H20QV6V7ho&kw9KkV3Ikg=Ojv*4H2 z<9HdU1czND^h;l82IE(?2GHlYtf4lBcavhezQj&)!yCUop5p;A=9FFMwakJEt~4e0 zTLX@^BEW_N@Sf9~iC>v}eLiae)!Cof#B?K+m3!;Kb+>d~B|`Z@YRQ%{$nm#(vue0U zfxZl`>dThSi+7a3L&|0j385i@=PQ(s<;ko|iwUd$9_m%GB{F0U9Y91T$_HFtHHXFy zq2`Gu?WlPI#*_#76FZD7YyIG`%L{;s;(yL0|GhH?`9M74vFgE(Nr$X!L-*=~=QX&J zZEtEsMxsv3WRZaoqd~_!yv)l6Hv$g*6^NZaqTZw=EQ~!BP%eZt#rk%_>SG9cSoV#W>r^pkHQYJ!K`<q~JV|Du!JxT9ZDf=F0CQ&;h-PD@U&an)i+}PwwM)X$)O@B%jQ2hE% zgcU8m+U~9vF!NvHLQH*nYah&rYdl#i$I;~?z+A3YNg_>r8q;YQr2hdqzniWg?T3w?bVDZ3N&8*8(|UUc_& zsjMR+u$Nc};wKb0U>>UlnSAj=tJlQ0@+(+Y7Z{#Bt0lU9pqc@YRqB_oamgi8-l0SlN%WUbdRi z$P*m3Q)VhPH*IpdTY7tr^`&tV605~a$b&1vxTxRw9 z4gCmd?a*ALt@6qy&6sLEAvYXj!K^-)95VA($oxliwQ2oL_FEsT3Hc7aa@or4$EBtqY>fI;C}bOwd(6Z^TI-a!lFI|NYE4Z{LtjuklmS{ z2KN=_IxoRTtQ4 z;It)gq0T^gyUaEFPE>*X3rvtOhaLVf3zuPGj2ufBz8qQBiz`I15DjbH=ZE_o*A2Y0 zQbCYo7%_FViDec-#>Gb;(KrZb5JtktG$|h)kipi#{w+X4_0m2(cH?XxT$o_&eR0f= z-)ArHKN(x@;eyLa*D~lLByy<f8|F{tWQ;}t_NwCns$PIpnFq22Z z=W!HNEab|zkuQGv5=5%JXft@8W;SS8K(8*#GVfnDtE3w#P;Fee)t5e(#X(M!C;4D_ zV8H>awNEb%C+YWWOr!b_SzVs~P_9$B9>0Zp|0acd0{@S3Tj($)T^@nki zQ52AOvF>dMw^NFp4A?6pk9-_JJpRT##&|$J z0q95I;iW|NJ1S&{z=tP*=#x(xyogz^;#N=}<2EV;oU_2fb3Jb(sPt_+2v{T;_S0$- zBY8kZPuAok-_e#HM}27^($iCc=pVP`*jk{}I@FBPl&Bn6_3r5!==yNr6JP;Y3>wSg z`c|B2h)Fr>6Rx2k9+>O-)lp<%Wf<{Q#SS_kPSmoj?%N|eK?mGOu9(`g4S@Nvb~q90 z#j@mS%8wnEufcE(RBAc(ZI`I@5?#qx0(nPLTjJe@Bv`6JB*1gj^c*!zhV0g97_}hWhqZTjLhQ$oHVe!GtocfArDwaB5*Hw?yz>mD_q->3jC;oYwvCkW%cnPjWn~{b!Xtt1 zSL?ba^l2~4c|kH;~qrPX`>O@uIoiN%;pWx zDD3+#oyuMkeX-;9`&&`=2npQMdec3@^ihSY^rFo@i0kYdk*N>Z_lv945}l2a)aosq zS(UjG7}K*ZQrIs;yb^5>0XuP4_~JzX0`#xNsfx0`EutwTeSLNEL0-MKWF`|NMtt|< z{ejo!AlH(YMI`n;h@?|?d)5MP2A!g8ZI|QhyQkaphwo^ERfZRIV4Cw%h&nW3*W!Kx zkPN$y{|W@tk;tycC&I`1Cil82J#Y!7^NWZ}^ynh4$8Rf7PPM@|(1YDoz2LIZiNM0#*{P=ef^?)V;MQscU2x+4E3x&P0=}&)uR`Ss8qlE_{6KS z;&G#D3p4_MTdM@AxB%tpn{N-iVuJWRmB>J?D&D_8{YFCWrxu{t`s1F=%B5UzT!=c` zoW)qmi&b8lg!t0#^+ZrbcPKOgEuEAd{pFVo$=Bm5qdRS4^kOlgG2P`>d7WtDF2!u+Gj+iM_2o>s8#N zp|U~%Ahv%na73bL*in}q(O1wk-RmdmZQm2i@+M&WIb_!9J}CCrF8POD zXKCVJxAxEe)qbCSe+C%p^DMFdH{AXH#lP+DKD5h{Pw#2o=^!#biK{y4dRa^v2V!v4uK^(#R~_Rn~8zYFZ2+OalDTz*CSAI%*SKKbom`lmVDKmGjEob8`}{%KzNoSHgc2PEN7 zBh;^m$I_ZsRx>j5oQW%je$c0DCny4_`RB;u^;nir!_YpqI``~WaG*_gJ@{4yvNgmb z`xO$MG2e@!<^dHH74~7W_sX!t;k2fORcwgYpKiEk2tmOlXw;tH+OC?e55bK;sWUc- zaxcYg^XDs1^yyDc=6NPCX%g%okAnop{*dAqZ^h*&kmg!J0 zTmePJBB^pl?uUOhN&02bSytD19yvGob#wwkbRCPvhs7csJ>EO}=XgHVsCHe_2{v(T zij>I-y~6Qs^n9ItPH$3vQ_oY1eOs&d{pLR*&oi8$iUz?kM>=TqcdI+2`oU>oX{0Wn z=32bDGju?ZLzh!K!1g4keH0b~%NArVW6al^Jc4!erOEVwjZzyObN%R8+j_(+mLTin zhP>xA49dDxKbzi!h;3jrU(Od#QTxXyQT}x|9)3#9eIA!z>}_krDcKtCU- zURzZxs@$2dB9S>iH8n2U73`g3iDQfiPO&B*DnsVL?B8A7JmC;vtrBB#o(0!gILU>+2B~gCG3hM!{Q}Zwnk}`9C(?hw@Z3gJ(_cl?q=u?`_{3#y@~00k{==8%gf!{dx!HVYe;;Sz(cL* zpvmDSXX9xHDhdb;D(&%xQabpe;%UMhnC(9D#J?z?9F0q?uDIK@X*2$VeQ8OzAT zIE!V$?)$+;`4{*pWggZyi8I5RFl$a${sZ7hCpqlHyu@0AMyi;IN#iQqkO9k9HKA5s zH=IhDbgy0bUDr424NRCaIUy4&`w3Nm+$*+Yb(szE^iYR=i#;2Od_5wI78tP)bsT6( z(;)cD`B28&_KjC5e|3Vos>;ONq?Kclf8ND$i=?G1QSs7bMn@KAav>Jq8^{Y9As)}Y zFbE#1Pk}slb%Um(v(qGi@{{6`xut8|p#0GCeukh49;JD(bFPEN>|Rv}_P9x`iLBl7 z7$G5Sw=&3+-&-s%v&`AEE7Yq|;jgT3jw|#Y$~_&&uAUk4Ew%59e_avWA|S(2k<+CV za@wi-yC`8r=!&fs)KY;LI!s@v71r!|%*(2;gqh~_Q!nUAY{ffxw) z$tY@hG2FdY_fh;?+ApV@CGF;5T`S(5*hXcbTec?`IU;w`*n5|n{l$^5-zn4FhOj<4 zQ=YDnV|mxz>;JHj!HA`!tYv4~m*06&>+i|)0PN{sMmwzxZewJ}R#49VAIo^bCNi)t zG?TwO+JGb{=5x2FG+y-|1L`8egA)XO+vAnYUvTH`wRBU}$3z6-uH)9oM zvNb&cbgu#k{8R+jlUNtnTuuWt!4%Nm_e6<58BGc#&n*Qch0B_k1a~LNl+qcz4&L8^gZHH~tfFA=d)p7(6v;Eo@ ze%OW$__270?b)+P;K#GT*Wm*%+1L*7#6CL#{LlnKkW;Tu13v%(es=ob(g30@-nqz< z6L|AM42Na#FH6Sx)1CL9=Il-^Q#0q^yFMJc2EO%gS?Udq4DYOQIrvg3NfU;fe%|FS zenx(D*?PN}1n-gRjwRp3wTb!zwxbHxB1Gq_^TGxiT`*Mo4$V44SNy$GW>AhqJO&@=TK%=d&OHNSJ z%O+OPf+NVk#(A{O_Ya6CNzLzsw)}Cy^!awApis9!s;34-1k+vzyz47tZU-5wj;OikF&gcWyy#iW``QMtg==ri+*Bl+897 zng&(Cntm`OT@-l!0lB5@3Y^gRsBCV=l0ZQGNM;PMuo&TGjW= z;&RmJXj5apW6&JanQ!{dX7sShB)mopUenOMYC^y`Yw))BaP+U~rHhRz8FU2Hp^mAt zOlpG>ZFzNjsu&XN-d}^OEu4AN%6sD(9r}!hv@bV6?on*>BM)%h+fWk?=Ft>4~bVOVT{TMk7fJE5gUDz*_*|VL`jR2u_ zYz#G5We3y}+Iu_(c_WdiGrGSCf7_g*o=Q71Jj&CrojvPb zvwbiMY0|N(dd(%o-pHN#3ol41OnYn03REZqcH_l|B^TLV*63KDPmpTW3`qa)m!vwC z>s;C%DD~QVDA?VM0kDID zazh~Em9{t$PGxS-`rD`4uH^>lo+uZ^K_y}cX|9=9c3gU{s6GSSv9%s=(qY|{#k?Zj_T_o(Ek%-tY z#ojc@u?Nv8o*v&;|Dc;V`%f8NJE8`X;7=11%FbS0d&b>dFsrOFBC6KI)(_naYu;)$ z1H4nX@?Hx~Vz)yyWG?$k55N)zObsLXh7dR*<&BkBB?`be8aNnqsEc|m;JrXG`jc!F3H^8V8wtsHw7}*;* z)(DAHgt)sm7Yo+=pH;E9J+>Vqdl{SR4UJTP+8gbe_qakV_KIEutfa=KETwX6In4`g zQ1oEPacnsgW2#gWy$vVr93l)M98F7zWqpPr?Zsw%b~;dnWCKR6fy6!!`r~s9W5;`l z^y~Cj7H{*)pka0GocZQzvP1*9zSyD$pfm~u_4mhJ=-er)sbwjh$9=4D!u}vyxj_4N z(pTyPjqz1p>4euVzx~_pO9vhv%su>yMcVTD3V3HU&c2ru9|sC1wqFz*bcp{7dhL4A z(Z;^*&4?oFVj(gCK@AY|WzV~#s_meAwl9iJ11zl3ebg7Mwt zy)fl62k34t5jT~+dx9Hu5OZHd>9;u1sa|WS%TWB*y03rTyba`{ROH2Gc|pM^I*ms+ zzJ_vxxU9iIk>&9G&YsuYLqfulLwt@54C$}l+xR>k^4S3E1{9?O1kZ8i_aPyR zU6rlNqthxL+wlWN{uVR~(x~j$E(C(mzuYo%Ko#5TlPv43tPNnYOi)@^*pG)DS!&)I&@!Plk)% z(Ze?0%j#UvuDhpSeoeiv>>GO7rVX#3dtwXT>aq77WXj(O0e26X)mGb23>>JAEucJ!anAKsWVv9OrY##bh~2n1vME* zQ&s5!dVAwx0&dfcl5<-$oB z30pSU!)9AJ_C!Q9a#PC)8ZM^r{j5c;KVxxgNYucn+PuVgGZ4F|UmO^e zrE*IgU$;Ia71Fz#jE=7n8?z0FOqC7MNV@cOEX&Lgrnx(y79!PaAC^19!{#E!v$z(t z)y0@qBi_GJ4ftj5M%adhg>LT0@yUp_M=FFd!IMC_EszCz(HTxn)f=iZl(AhX;EkNH zLnm#iK!L=`kw%$g54q;jVHlQ6RHBcXV89*F2~=PO_^@l&k20GK`LL?wyY~ww(oQV| zJd6SX;T(`9tJ;wrI9~FauA6C5R%OS20OsN{2UV=3`RbXRnT>n>X&l1s5^GN{>FSTZ zk(zt`%z=9J5ftfEF|ZodCDL~!5#S)JMui`-Ovd)N^aF2PX-Dn$t`~qYIf$WWv=(uay8C-W%#j?;L8Txy>UL!yJRmkWA4@y{2)N?S8MD%cypEW z7h_nydHvokiDZy4LBBd?-kQf8Mj+@Ufpf2yuCae+N{MYG{ZRE2wrp-k%*Kdr53A8q=NFNi)CxgR zz^L*Q=7&eRQP(XBfts@;LwMiC2yQY@oyP^RHuO1vKJByQ(3cqGsrdR?eW$QA(*j6r zR6lq+c2EnqS;KdL zuN$3V%2_Pi+G5888VuKc+n74NBpGgWKdGwQae_E|sVa6{dWYXhAt7-Yy3>xy1Vy z51|S|wL4Rt&|=BIJ-W?)Td77V5_!T3nvr}{wp~REp}wCw9gCr`yY0Fn7_w8r2JICu=$%Dt z-0f;5Ri|(F@P7aaa1#oZ3cL6|Y8_BGpL<=3r{8^SGdyKrAK&&MtcZ9-yuIrIAITYF zBt^EL)V|nRCx$(b5o;HB-a{rpY~ACnhm3AKTsDm;5a?0pLbcVBwG6tmcrT7rEth0) zh|F1(SRtgU;vjmNvK-PPzno>|;KkytYWEu(cwyPIj|%8Bfht0UDr4_5cLY!SfTOMO zIe2FoaG$f)W$Yn+UGlio*0xv7AdQfiHB>3D9wqvanH%iFar`gY4WCq60dKna+vBed*4@hp3tvg`2nk9eS7_meqC~&=-nhD|EYlA2Tw+5o`0O_@_5h)5_&e& zOXSD<_U6UCuvoVb3y<|kg&zli>Rb5IlY7Umva)^Ci6Z_Db5;lJsxkv(+jd2JMOx@F zSmlNeFS8shV_pb3Evy8-1K*R6F{W24ooijBCw53aAB z#j!TFf+Iab*=42^$^5F<2F+jueWHzTL_xQU%!fUwd*fy!X-FQ@G&ZhTp02GBKXh*^ ze!EU;F5auc$7;e|p>WWUp{&ib8oanpRTP0@c3Iof4_d%4Z>j~_B=sZ?X zsUiv)dh*T=0NCObyR-tFelL~PZLw1(Ykx@< zE6q@|HFd^ML`O+ux$z=&m}_;mhE^TD`&N?S&%K(E^|C!mGKm6IhX0lS{Rh|4WHr(J z3HUrpQadOG{Q3*>`S-1G;K#qA5MUXQKd~SnMgMgOPc)@{aN4_ z#(yxIzi%Dj`9Bua_o75VdvU%*8vM#>*HCfz0*jJcykiXTaNf#vPO~Gx(z6bekB!LS z5CAURhXvVOWaV_%?LlU95BKjr>zaLsJO|#+(cb61*kt2{n~h-Kq(K5twe}k{*?BV6 zn8Z>WXpnEVkl)`IU*{xCK-Z6e7`7?P+FK_iy1w-{%2N$F%Vy8C#W*C3j~Qd~1ICCszqCVn$@UmZsL=`Ev41taqwIZErV{tYHfG$ym3klq?(L~pce zk6fsxb;T5l2EI3;?OC;ZIF@wj+XkfZv4}~Qw>)8Lz}qiZY)z7(HM@Qm(bRoW-+?g! zzHFWOa1$^*&ABe^7G?Pm-n>H zJU7DSPi>wk=L6CG2-2M*O1IEXNwyg%QO1|obwR}q-79FmPTqZ$Z<2ROfOuvXsSHVf zH4LCRRMVREqXQ;RkbyGbw6KNpr=3m!Mgx3EPR6E6WN#*+Xpacqca3Q49#;D0`)??H zn^IY3+Vuy;-W2DKs^%A`O_-Vkp9Jt*SQ)_^wpO=?rgpOg5-WiZO>ROIH#z3!8s;DO zAb%=*)34>SNhRF)F!lAQ&0GAiTEXKQq2=x3CgoEe)ssMUydCHg%Bq}+)6G74T>f!~ za$f48zc$MLv(li?{k9A{iNTpxcxGXnnZKrrB;Ti-Ty6xQH{JnPbAximb144Ps{7X>Dt*v`;K;} z{^orS_N~lqtg|ULCxcUl;M9$TO(=T_xH)#m{ymC9N3r}^L`c7b?%UmBOib{xF92;i zvlg6p0*ghR>EW0=xib7K%o>19I&bPnGnz_mo&Xb@L)A^dv_=M0xsYbNhRufFmHX%L z(-T~EA;3R^01iVHShma&!K-5c#kX3RUzBFfPEXqCPGEBSQuwcM&{g%5gp90=uIne! z`+dPib8mBtAjgVLUqNCqlQ+duBuDl>S}CU3cOp$vHw3SYRjQg>e;c2p>{BC6wbYsX zAFx`<&6C=B&0gS-yOK(+Kh2b(hA##ZD|p5g9X5k4P}M6ova8>E{?}0RN`cRyQD@pW zUXP#Rv5Or)2jO?Ku=@A?evni*r*=6~B!Jx2ycHmZZ+rAc%R1mg$d=fbeL@bFnd`P1jWm)n zlr54-%fcoG(aDs+@xSi^>D{d8sFD~tx+XB20=^}QnFMl=v$>~(a;Sw;21B^FE^xDQ zgqN1-<0O(^5^ZU-zOcxPj?5BCypJ}B;$necHbAurF?@u$tNE(h9Xq;>dU-!)9ikd4jyP4jDGomEuYw)VZm zuqE(S+i<;Tpwmq`V)KMFH_KkPmC{5tcz+me&a1`9P%6k+ zpKPvFgrWg2x!Q-2DZ&2f-pn|9xg!xK#9v#?nYb#Ju$F-@_QLK^{40#|%?V@b#RR1& z9w}e!T)p##hxZ4a1g1N+8jQVGNa%u%prmm#On=G}1t*6qry(Ug3dD)LV??$y@(zI(O z+?5Njg(bqF6<{sw6F6bRzvfzhhV8_mU>%l#&!S|(%kxQ(`=^k$z}KTn@_k>6qrNqF zVG_Nd>$+sxRl<(d8G{6}pU>R(OnBAUAbbLT$q(7H80_ES>33HD+du*xz0}dmc|Qdo z6@`=}T~UGvE=D4!rA?d30Cwo?<7&j*UajN3Ew^=LUkj=_P&FT%n_^_v`zdc`6$<); zmCH{8(1bjXliQzNvfx<*Nj@~Sc&7-jrnGz`V-omUtvD!n@NliqP27=RSYooJ0XBS4 zMrS89IFz^H0dM)5aMU-z9`_UjqT+r5*7Iy<=m~^>5C^_xWy+-_{z;hZN7Sz}J$Joy zatu0}gVk9tdG_H3IPU98tu61iOtM-g%o@le`#-18dtVq3-HCB|4$ueDQ;lZ82SX-}Jg9L1OVvX^I$~vjHS24n`_pRz@vM7s9d4zIWYr zWKfzH)S54bv(4#kNWr(XU*Xt;t5;vq(&#>=-P&k@?A^ zYVNP#${LzuuNHb?#xbC7UB!ZzutvDC-X9)Zcf(rfG8kWOYk@da$14z%$e^0BMz=Mq zN@nPjHyF*e;0`-p&_bDB{t8syO`uzc7|`10gSE%^e03O^>$g?e;zwU5M6>!W6;sgf z@L&}>49%wQd*f1ohTzRfaa--hECDqF{VwQv=&RR?AbJw}cbKiv5kep_>c(#7Wy&Ce zdYxjf@UR%gNlXr1kN?b8V|6pc_{&(BcYcRyaf7P-kQafo*aJJ;u_Abdd`rfw7$EMD zkAqGcBsd${i?lP7{p?gX10GjTR5+uY>Hf8o$t4~it{R*y=eV}7DVAnY$ary{(A+Gk zh3n;GKMh;aFZjbxw9ok4U2aE+@2i952T8ExwH*TelG3F(A)Cod`wtf-0+AZz(#d+8 zWU-X9GsRYp?5|&n@0)B(CI7yCeFx&@U;eSwEIbc5N^ODvYrs1Gx90r68Vz3o{!>81 zVzmnMF+5WkD4ui1`R`3H-vapPq2lC5Dw)~k^8f(!eSh8mH$KXnnP`*q*--|;?)z<6 zT<$){_Mfch-!wP$u9nF8=2sYa_FIrZ=Db(3>c6rf--S|Vz^K>3vvS(f&}ZxVXYLv}sKe9Fa1qiA^0tnN(fXGhRnqcLI>Suz8ie}4 zZCN!C)u1n%K?3QRrCl{Rfw@Dd3#;?-P2NCXO_iWL@y?mhAfQ<_T!B6+-pUXEE)M`| z07f>aK3YSm8LN96&3#{@WqHVn%?~-lUa7}KbN^<9zQ9X=N@#n!2%%+Q3iH0w__c9gt2$r94=Ue>+6!QU@PDGp11%ll+ZNWx0qtz>3^J+ ze>_4!1M;K-{U@&>sfjC7+Q+&5*kvdbiP;4;s7(bXcNT|FkYx+~Lf<%?V7QF7pw6VpI!ISc&WPoWpwQCmATiI_2nDEwC#9 zcG-m^T6?dz<+YWg5mKt{?qdIz2*>E)v$^XM*diJGkC;G|z&`|B!O|CG>{G&7!JACe z9BKSttuAvjU!wMZ|78plf5f>P_2zRmaEkt$I|8s$grb;dI`bJ72I3yj0!PXgQ(#72 z@>ecMCn{u>a{tVje^Xul7x^qg26bC))7l41VP4L&_oenW^vQ4xm3l?l^94{{%}YYN z=C2pYmd6Z7jX!(N`ii)`fc(yEJDfjZWDHtAtMIAWj4tv#{W!{jkoj$I=ri~G>)7_2xo~^k1B~H0mkTaT z$;epc%+ZPqgvR=ZI+#@*s zC#I=#KYQKN;SU|9m^*6yT%LVXVwX?In z@9hAk^uS7a>@OZ`C-0XSNbStECQMaRenH|=c4uS8r>ZPWN>?(no80P7lWvhEp3VQn z;h?`O4c!iksz-P?V$B)W_T0QS8-gaCLE=-Jg$#OnJniQUKEL3&x+?9x$5Fjsn?@zy8FL}J+02xXQpasTO&;;nXKoYu3E8jQc~%+++8+5F zk{DLK;o251;?XRTdrV-%<^&W?%GuwWx0Tmd+gMw=uDbEfC8_A(^Dx)?c0%oLQ40SZ zW)~ov6=ItMg z2RsBIogVv|7JE*97A4vzB#N%06D0k->hu|sj z3OP5(E~^*JSLU>|Pk%+Q@OISpS24Aq94BbgN$jkO{#s>S!H#@8(H>goS7<8^t2F3N zm2xe7E=W^s7n-okCjgN)D>Nhyv*AC#U+eXH@}z5}>sc{`5&zewA*2$K<|o#M)9Zxc zibNHu9Q-UJfBVdn;pK#3f&G^EI8E9bohr%F02`2JaXz4|@KH1>@%GvugocUxa*HJ@ zGmnaIjaJfYc`nH1S=IB--~rZAZmh;i1ttEPpYN*J28LEmYiK2Ac(lwQk`jN^(BQj* zaEU=^^do+3jICp0{y2S}LBgsSfpVy3k&}_i?mQhO277U9M+j`9 zTG0Z3H+02glw0-`TG6Jk+=27{2e-5e$BJ)}HWW!uO~x#(9+O}YE- z#q*-)&u}#}B_2*}n{5pe`{4QPjSb9IkknOVJCxRSm)0&9X zAsNyAG6SUz->*k(62wPGxzsmo>Eh4T4Y6-*l~Fbc9_3ut!SB8z%|^qJGlt3h+X{lj zN686meki?h%G+ySSKLxV_=^qb4Vb-oqwoPVWu#eW?O;+ol`<>1tAOOtbsF(bTEa|f zhpC2StaxDNtDw;GufRQ&Cdt7vDDrFSL&3KN_0}}MWQh`W`aemYKEoS!8!k|e8hguY zx>hx`2N1FpD{bt!NzzzR7K%~RhDjv9{{qf+6&11GS#_+2t0j)5A>$rCYXL6@Fl(SA zAUny@Yk%Plb<2|I_lZs|giDj7x|{jwKv2KG(F@S0^{OJ><*iz~VE4XQQyuP*F|jmi zv8B7@B^fEd1*Vh4Z{*ad$M6#tD^*qRiLBQ7d^=N8j==nmmUP91PANg-BWScB&h4ej88($0Hx8O7V#a08)RHY}k#(-`iDy>wlj%XBZirWnbEhcl`DNDE(1n zS#NgLp!xk<;_@49$i*xKOXj z4Bv9#B$OQjO3Y}RceEcN*E7q!b8C2TJh9vqAf;1~&0O$RvBB@RU-^b#1#`sVBW*rf zYj3|P{p=oR6&9q8AiTtbNi;cjEGLzS?n|WVz9z`cE(01q z_19W$Y(i#+Wa7&LC^YJX65(R2;VA+X5dn%k(B(fGa^_5Tr5PB^7NTm1=Z@`fZZMmS zf9(Y%Ih1u+Ak+9`mZ~IOJ}VakNr6`P`@SL!EoNHKw{goZkk@ZAl%wMYdF{B|9NqrX ziM~Lfe)47}psrL~$007~WW5l{`i%i)fU-t!4h;WUk;`wB3&*`r5aP^_xN67 z%q%a@8)FyiLfw50F$otJ93AU2mnfI4}tcA7h@vzRHKWxvsKvpyy3nV=Zxi6UxcjrUR zo@CT27S8s1}; zi*7+7{t;npF6tU#(@Oa9w(8w_u{wmT2CXtEy#QB_bwHZ=>DDr+`|=@H$8;fV;QMZ6 z5x|{ySL<$ME$M!gbwL*9zM3hWVq|W?m&~dn|9D_OLw-ip5B>QX-YF=3mk;uJsW-;j zrYyJ;nTO`GRVl_{n-*)(KK71fNiEO;%P+-E?fsHIUUJ~IHaG5Qi~2))egd^!1Tt1i z2W4VGslpJexoU|QDZd=^zfTEZMwYJkrpPV(yXySXDQap}N*XRqkabHqZ~{tyMLqDB z@ysWlvGVpL4n575Uhs&KWN9F2z%G}z3o{uWXCRe#Gw&XT650xKMT+4XU zGmW8e&kRq>7I&Han*G#0zE4uZGFDkpW0c$83C@hpa~ckNt~s`zUZ~~ivm>KbT<86{ z1fa}H;^koqj#sOShSrYwFh{{$Jx5fLw7aH&Z&4u&9lp=8iv}D(QOB{T=XzH~_V)^u zn&IyL!6W3($Z4HYl_-~7zhnDXtD1-{E@A!`?ePec$*+%GbWXp;ALYjLx${)SIp&`v zy(rAT&y?1Thp3@Y8?uD{7};7yR3N*l#YzdD?G4gMULG%AWCEpAfE4Dp9u6G4llDH? zAbuyCeJ5?ZGLlOsHjt?bxT?1vn_#u&3}T^8wJ^-!lJi zLOHMUUC``tT6f_72TIhR@K`ABFgP-l+Ar=nn+NKl9B;(x3+a+SkbKU=NA+4lc4p}I%uyC$Hw_6?EDpO6?7F6j(xQ82nS;t zA=)B8MS@QMzyJ)gk@w7baRhe0fdeAbK}l>KK=K1hT#%D$%O4jEvSFmkBKMm;L!B*r z8PNUxgKs5;GREJzv0OyFmkA^x)H}${f@ehd+9Yk7CMFow19$#~3m3gKErK?_gZBkjkqi${4{s^y<1F=3fkXdOV*+Nj1-}Nh2>5nAK3>_a ziw-nzgMClOBLH!FwA-i-Tx?uv4GJ9r3HX8q|`sdpf^d zmiY6_=z}WWk0zi-2QZ53d|cSm%y1v)gy@>J+1DGFZ9sx9&~~$mwbJEfJ5xBYC)%D^ zW;Z$J-CVLwb_{}eMnM-Tp8|TKoGhVU zCTSe5o9<@va`0HnJHo_Sl-KcW=q|)3Iu6LBB?ihjuTnhPU~Uo@ycoL+E?D=2<+&pd zvrl75gPJ6&LUHF2Ej=816K{kX2RF||U@9qyCxv^fJHE;%84J`ryl4X$s<<|$3ML?p z(&L66#xYTD>pAlV4A{uxhAjINhvmc)$LY_lzhVn(L`nZ_iEa(1i>meuQ}#(1hjt( znROb#;Nj(m1MooKiv6pX%ZF~2ixnsXz`|Y2CSE$H>WOjgau0|(p%U7^3A2a-;{(6@ zk;HN!e^pL-S2(nxp>HQGj1;F-JrRIr3*=rllQ~1{lYxT9i6XzEO}Q`?*|hdkEtRd@ z!+@j6)%1dbjpZjq->7|!n`aATlf8m>zg-r{DZ7_G^C5h{kZog)km*DX1cFRLrb59tr*kYE9tAaiia!y zDC=)S*--AHfp}OyA>o(J1Q;2R=~O^@y+w8^fg@znuVFNqv_Q!X(%e6JoV#7fxxv6N zde&B$TwUdPK015yARNfHSn~*r<}37{_x13e_wp#g9JKxcG6~o8Bevx?BIM$?KTD`8 z1*0jnz2)5WN!?^yk(1CAp4YIBT8i=A;p&v-)8=p|2|>89H{d_CewVW5V&W)xjaJ$~ zQNabstZOVDg~0UgLzh|&D3d&uS_AQbihWU(;FD56KbV;@A7!0XAIv$5S`=wmtoPcsZqlgNhS!g70Ex2?CW2-b!gw=k-L(uDYl% zX94BQsj}WUiqs81dHz{+nv$r~qIkGXVj()~lr zD|kY_`kB7ZOx=Ox88?`o7wyA$_5GL<1Q=);N9T}C3z#XBm{*-*%eA_U;H9ryQ~Pd6 ziZ{Kd)OAJlqmwtHj{c+;8yIA>)&s%Mo_DwCKB#z-i>q~_p!jAR4rSTWhFMkZp2zXl zjvjGyv@3h=j#L2s0D_RvCnGU;(j4T|>y2Lf<*=?2&ID+hJ)nsSz~dm%hKZ*E0pD1B ze-1h1Tq6Nc^+|y%cq5#MG*dU|tz?dP(-)zLhEZBjPn1h?5)i&o-p$Un-Cr-DDrKJWF3M3o8ObYt zeh+H#-nu}de2L-*gCc%AXm3o-PE?b# zYFWZ*8M^n%EChwp2k$nCyO-N|K4_q@GVo7OoJ=^Kcrhh5BCtuO+&clJ2o*Gp&eD=a zA0b~hqsuJ;3`nD73QZcCXdPpIusFw*!U3#jje5DO$#nA%M^N($O3B6I7fTLMAf&}9 zGxd?IZQ^u|FH|*~b}hRv5vc4PvW?(~`lj@BY(F%INN~UBP4|+^>q+?riLCltnBDcQ z^IR&a6kNebDj>oul!^grBhq=iHa0OFj@oZnGp&g>exKfO$e%E;m+~-00$3HTN+Ds5 zHF-Jjzn+e0UZqqI#uepC&#Aas$l$)w9WLwWaZh}*Kr2$OtO1`QC6NmHV4WTcjVP_^ zp7~moN2u=q2(~-)O8oqZpxB;Z$Z>i{;&zScsrSuY^sOG@qLrv5Ia%uCb01GEK8K>_ z^dD8#FDG|-jh-I+!h*rM*T9rxkAM9-2;LE{F6Mm_Uta zM4Utjt@e#AB#VOiT8QnS(G&FqE5C3^M&|PZOGi&BPps#31-5IoyT)z5cCso(d8^CQ z&DC{bbu@_|>xFgm#*z_IgPvQz5$~r4u`2UILakQrm*jM&h7YPo+~HS$UfXLUV5MZS zuW-J3wpZUPTut8D_e{&{B&PkIyWMFMLHu6+ z39|s$ykEXcU?bO%=b>f!${NkGV6|kM4y5jJMY0tswN%}xHyOqpSt{z>rcO>Cj!GPx zdYfWJ%6-nq?w<5EGBE^;;=#A9AkP}Fp_V$)+A&WmF1bL2cEVHheR}_c}#Jehw z`y5DDF&rnv!eKCih9BEUu8i%^|4`<^;=g4xI-eP9RP4kC1~$K^6`*KmBLjoM#UwW@ zy^87HCcko#CluEPI}5B-1O>LP!w|+IFe_f$S7DkDfM22y88sMm&MRU}iT7 zt|=;2{Pu<8Z$*5(M(h`4qQlL~0WLnUfCmN!wstaJOF6;gWY}fTlgW~gp)^e{@Q)2_ zHBN^D5`fhSL09>&s{dBYlQEO8XnYth$_-@)7r(i@cVH%Wx1fo!SDd0)-2~N}B6QJc zaoJe*>bCq7#f8)Dog zDLy32F45E_urrtwdNlBP-M(`iuvqQOb}Hfz@>U9t9W}tyL#3Z|<~wg!G_%M)h54u9 z46j(Rwb);0(ETe<`W28(>Ny?^ecS*JHxl6TZ1 z3(^Ag{c5D-Gk(_?$lpzy4t%TrX;(aI5%<2WZ)^HfeJ%cMC}7<`jkBrlS+<|gyT&GV zS7=h$13AIK=wKI?!Mu95Z`OrA2y0Fh2j-4b&)qH^dem|Jw~7^Tae0(tFujGIu?8$A z)>CWOr%R{L2r#2K^=`w#^gNI1)4IS_`alox5o*wR-2!gF0q!7d=5&Vy#{e%oPKNRm zb9x=oHq2Gnxz*l!i1;R8$Kj?8mbPGURnoM`X|Q4SVn$?&W>6+m*rR1Fxth(t&OLvk zSWjbjzl!M8%&(_pubht{!j4m?JAN-7+)p}~<`LOyHLTfOO!u)wawaQD&2?^!t%y`t zFE&PcuiC5TCiN;B)?&$Z>By-%i&FNsqBqW0N}lD?sqmXye`P>+LY0qe9)9Du>QWF5 zrgb|Z>N(KWurhDlHOpfHQ-hva!Y$wrGocSIE^*#Z?HS?;TP8FWni_?(QQ!~Mpuc|y z+zB+o1Rzm;=wE0R;QHe7Hn2S5{sY_>LKH%jiM#Kj)5|_C`^P;CXvQ^OKI8wPo6BaL z02d-W`2UcvEWZeemE&+j9A9eHS zNKu2p|IsfXqFFYLQdabJ6s%CgH2tII%M01v#e(I{%30-YkM&yeZROT)4s;0VWm1? zjTW&X#%)-!pEtb&;E1*B0+1L5N_9g4$4<>f>Sbg27>!{~m$kg_j zQ@5`B%7#AlD7J3;VBx#%8=g}wFn6+BBYC=yq1)8;m7-U$&E#RjH-8o>S3A5@YOoyM zJb;$c01N2*`z^;josTwRZ!wE7F@9*I6g6Hn;8rS;gEfufxAj#Ha=Qxr;6Ev-L1hig~5>!2udAct# zOAsF+J(T!e`LaJNA`K@PRY{O^2>l8X7p&cix`eyW7!%1 zQTV?{3adOpYK6eBZ;2c6ej%BApy)v%s7iesCVpF#-0Al_d!+pxu6lv6zAuaXkic#u zLwK0fd0rij?eWm`c}M&BG!kR+K@NT!nA-n6Fhxc%)5~>G2_6#|{CRf&d?t)+^t_PA z2Wi3>b3ZaxXi;&0WA>Ba9WA20kdS)|q3PdnQErNCS-* z$74<6RwI#BX|(I7%fc<(r){1PIvLAL1Nhr{T>23(c-tI4^9j`4QvD;fL-Dy{Vl2G- zJq=$96cvGwlaMXDL)#gx;?u3r!|}HREE6oirvbzI2jYfI4>LW_fASyaMIj zxhJGpP2#r^cvf-t!S7#hdHyyGL1CZ}`LsR%peg6pM6-oQ8}Fs-cUuw{N)Zf42du;V z&FV3haUcwKrBCT(y&`N=bS=>O!gT^lF?kh21V^E-4kK3=ROhcMgmNQSOanN{1UaA< zGkTpqoZr>y`4l$Zix$(V%C;LyeKQeD0k(Yz%w{Q|$M* zub?Y@zhWE;SL`cJKTb0ZV@kn4MF^=@MeSlEuKVzRP!Mz^2U;~B8tsqAisGheS@H1L^iN@sO_ zuM~UCOXqh*Y<${t@LT!`dFQ^_w0MEZ2ZCdxP={pU+C$s)I*?gc|BEw#GY9_ZyY1-R zu2g2Z*Ky|~`g(QU89eIxAg1xo>`4^A`vZ~t__ROk*qD?(I-FE|s`pJjl?-`&+*b?v zqFORePIToy%-19a1>ReZcYJ-O&|%Bco{@YOQS5#8!;fZRrX<91b5dpR2x&9NpFz8- zC~8-Gy1pBjQ0!%TY60g=f!4b;?mutTG@K$dr~~Ge?MNszej1FwO{TX!E8`tx;%d%N zs60mQU2-@X(=Rg;u!icM*+4T_OszP6O+xl(8S$w#AMICbB8=rd(LJ%5N9}ulLg95# zogA8}6zdPjc30M)Cv4+!-24wyBIh2Y>A32Wk^+W_;_eOYJW34$yfolYp(@12OL+Yc z)^+(lggT6>X7YFTs}RgNTcAGA*#C^{fQ6yJMq+eReQ!T)i#4JbJsevZ(YDMb2*Xfh zyP`qmRCtPj(WmYX4`oqNf`09Xw`2(ko-DL(Q&AC{e2J7EWJaWMNdf=JL{u ziPr8OtCI~_j*V=MW!Q<*4-1>lc(rvv?Wi7y5NSIjd_8H0udQ9pG8-1iS0KA$HW?bT z{J|pWX(7+i`_dAxy$0xCF|GkU=yYy;Ki@(`v%td?i!C=gQe~{kME@dMqMD39GvAGXfjF=@>8&h{Imo_iHo{X2zwv{157)%x8fH#pNP2g8*2H(rcA19m#SXc2e?xj!km z9J(vzDsTRQ6s5k zS5CS&21Mf%KKPtPtRq{Gtt@wzk@cDLkWw z*Z7HR9<=^#T+XM7ai{5VrO=$$9llP<9-leZ`pb{sOhPd9wQ+ab%g@R5ub={mF!+(^ ztWjCrAx#5GU9C8au*xxwNBp~u4zRH|ZSSe~-v za47}5HQ-+Rs6pjp2~@C*hVem>mQu?5e3Qao7_8tk#%^>@)WGWs@O_7;OeXq*08dvC zLir_jL52+;RIE4GF4cxM`lv;^w^!(a(Oal)IE$z))M{2i%xL9hk-|*nM4n5a=7gYmIfYRTkpIa3oTVw zZHHBeDrNmOFj>}@)Y2Ya6;{q`#VuD)0IDs>->kKVB2B*tnq6J3-Tf0iV{Zo* zdj)sES46ukcsMn*KV#8_LYhgOm+PBcgNYugR*-KC3r{{0fVwEL2K{rTtN?$jFNt72dK}6`0gh$kENt*EzE{)er zTL&nYZ_9k*_^#dEP=}GBjfmnqP=2zv<1`ZENwV-k}JZ?(%kT(icAD(Ea z-wdP5m1U;#F^|8wOUv)Ok+e@zvwyLpf@RM8e?pAyJ`(oJlJ7+Snm%gtJk*eU@S}tm zVjMiM?h^|Q4?P6FBgh<{|2$z0j+uezEC8W0i>L~!G6XyWJ|JD&z;`W?^sewG->Vt3 zY)1>61?sw_+h?YTA9j3;XAaSCn_PaFuT2S>8!LSZSo5`Cf2N;3`7z)g$0Lt;;u;Bk z*Q;V6SF!Qho|~k4$JD~mQQ{X*>)W_<#A39n8f^kjamQI?#85~C!q=PZ)NiX+yc_+A zC+3DfOoce^YQ)_#UR@ExQS-%wc4?xOPrh14+dyanDb*{8p=ndsq1ghS9f@i}1*lq7`tpWy7gmyVd($ zl%R<(<=R8Xg9N_>fMQfi&MI5)v+3uZ|FW|JRAi%dvcNlANpM^-WAQeg-YvDujU`#9;E9V$@VklL`i zmSgXhIOXFg3DI(1p=FOuo_1_!yHQkJvGS3UFfb!+UrFk=tN9eVKcmeD_UyMz;mi-H zg-Mc&p}d%^#t=%v#5K&Fx6H7#KRu3W+FK>LF*g!{1U%w1O2+p)uS-l-dT1LwZig@4 z)bo)934gPpF@`fUCnazTzlzd?$FuhuBp<1`%IUgwBq?fU3;!h>-I6b*YzhA*mo7ma;h8EYaM=P;MEhYgx?8(o{-9B$!?y*?QX4Zosi zd2_Jex^h9hm`l-KaIG)Hy-%lmZ2;%mKJ?}0kKggubvg58zRj_(_`6)ew#79BRm$d~ zy%Z%pt{0siEIAeom7e@_s0ec5Z-&K171?EXwB82`)1iY~)-H?KV$Jt`XuHU4PYp}A|{@$&syzHD^{S7@POZA6x zS&mV3yVse6j|fKB}nbt}0BgwGJ10x1W);o?zZxVSztVWc}q6^g&e{ z`V*4PNumjDw5b<>iS1A|elqXD$;9FQFuaCY zw{`0xd=+dOE# z=BG!n4LzvPa^>3BmGb)Wc+mszBU@&sCHj5v?s12!|0$cyFtmejC+-N%k{F8^BH|W> z_%pTtDf#ep7(c8Sj=rG}F>BZLwhIQz92WL;SeuTr5pMMSsNuO{uOAk<99^f*y;snY z>_NG&ABE-0_Hw8l6ZyTt%~T;SM-l9XvFpbLzfk&V%x`~Ev6fOq`tm-q!z&-$F7@7- z&1Xu3@+sFOu}U?aB~=n>HYCBKmTNl(uJIe zai&m(54_f?a5JkBhweU3+bPV95(K8#zapTxNUCw}&Ka43u+C|KX5+y*XUrC)=nnp$ z*B!6zn#39FMe^J~;X;28MS1h?+wPAr)7BpDRS{A>8W?}k{f~Mq0dT2B#nv{@G6$>!z?&f`P=HBmMC3>AOKdgv2%iGU@s%kaKv>T} z6vM(J!K~v~>_+D|M;7wisP55gH!Z5P2fZ|$w>(d|z5`qB{|p^-7D2xr^^(Qa{#g>M z6NzUJXFcW_cRI58;j{X>rHBX7ep9zPmZk47_6GhL*YmeQJjjlA!oov`_1Ee9n?7Jx z1J7>vba|3cg+`fR5`rD#5qA>5`QrUmAOXrmVe16hki8ccDlX0Oje+2rMt?gVJEUUG)J);H+yiQ z(!XC~ajCi}r8t6=H)Kw6`px{uz^erFaYGJ3@Gm4wannASXsYKtF5(B{u?)lc{E_FV zaKG>~#BU&~SmM}Jn>U>8z9}sF(DpI0L(ziyj?2QFA|t2veX2urK9AKtN7bMo+S-M>c@A& zEx`&vpc6&?F#D;|4d!Ql!<1jJUNHFWq+ft5F@Rr#iL!YH-|i$K{)?8irJ3``od;W~ z;`GQVZiMglwi{SJkgshgj2n>_`t}p4@sNrzW*}tX)wBlazlHgQe#uUb`N&2}yooY4 z+En)WatD8n8v$0OATC7-w7#ttfGjWF(^rQsZ@aL}HQxCVJR@-fpRr%onEN(Vl_4mX zjgk&Ef;NF~#__U>+$X<3pq!Ni>_RD6q<08+brwn&KLeYU{~SK>MC#oFcIo*m%6n9A z_+3(0YLI?bU~M7g(gEMpwj`7ANz zv>^1=xIJmn*0AtgIy3`J!-((WDrkt&Bwrjwh=pb zAZiBV{$RRhjhkH;p5_wl0lp15L&^U(_vX$qFW8tm3g3%hakb$`BI^mV`I;>L@vz^f zqam0~gteCt14YDaQk%~1^4T{sBYfwK@t9GpvezI)?$C&t68KS^C403}Ton+`44*HO zkJ}PGh@C?y-KOd_hkx|+a~cdMkIJ?m1Q3h=p?r4e7w&AXC}Wx;)A+_xfpxTkPQ|3t zZMOQ??IsCO6%pa0KR&^Jg{{G><66nIQtqskz{lPCa(AInf#qlwoR|DhSNCMi@s<2- zmU`#AY0yBOPd#GH-I0AXEmkc#g2EW|2z`c*>gn{uXfu~G#uK`vl Op2AZlSm6^R-~S7Z*vY~G diff --git a/static/img/en/architecture/entity-core-interaction.svg b/static/img/en/architecture/entity-core-interaction.svg new file mode 100644 index 00000000..04774b60 --- /dev/null +++ b/static/img/en/architecture/entity-core-interaction.svg @@ -0,0 +1 @@ + diff --git a/static/img/en/architecture/entity-data-hierarchy.svg b/static/img/en/architecture/entity-data-hierarchy.svg new file mode 100644 index 00000000..c1fa8462 --- /dev/null +++ b/static/img/en/architecture/entity-data-hierarchy.svg @@ -0,0 +1 @@ + diff --git a/static/img/en/architecture/integrating-devices-services.svg b/static/img/en/architecture/integrating-devices-services.svg new file mode 100644 index 00000000..604ef036 --- /dev/null +++ b/static/img/en/architecture/integrating-devices-services.svg @@ -0,0 +1 @@ +