Add to_directory method to relevant object classes
[oam.git] / code / network-generator / network_generation / model / python / o_ran_network.py
1 # Copyright 2023 highstreet technologies GmbH
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # !/usr/bin/python
16 """
17 Module for a class representing a O-RAN Network
18 """
19 import xml.etree.ElementTree as ET
20 import os
21 from typing import Any, cast
22
23 import network_generation.model.python.hexagon as Hexagon
24 from network_generation.model.python.geo_location import (
25     GeoLocation,
26     IGeoLocation,
27 )
28 from network_generation.model.python.hexagon import Layout
29 from network_generation.model.python.o_ran_object import (
30     IORanObject,
31     ORanObject,
32 )
33 from network_generation.model.python.o_ran_smo import ORanSmo
34 from network_generation.model.python.o_ran_spiral_radius_profile import (
35     SpiralRadiusProfile,
36 )
37 from network_generation.model.python.point import Point
38
39 # Define the "IORanNetwork" interface
40 IORanNetwork = IORanObject
41
42
43 class ORanNetwork(ORanObject):
44     """
45     Class representing an O-RAN Network object.
46     """
47
48     __my_default_value: IORanNetwork = cast(IORanNetwork, ORanObject.default())
49
50     # constructor
51     def __init__(
52         self,
53         configuration: dict[str, dict],
54         data: dict[str, Any] = cast(dict[str, Any], __my_default_value),
55         **kwargs: dict[str, Any]
56     ) -> None:
57         o_ran_network_data: IORanNetwork = self._to_o_ran_network_data(data)
58         super().__init__(cast(dict[str, Any], o_ran_network_data), **kwargs)
59         self.__configuration = configuration
60
61         self.name = str(configuration["name"])
62         self._center: IGeoLocation = cast(
63             IGeoLocation, configuration["center"]
64         )
65
66         size: int = int(
67             int(configuration["pattern"]["nrCellDu"]["maxReach"])
68             / (
69                 1
70                 + int(
71                     configuration["pattern"]["nrCellDu"][
72                         "cellScaleFactorForHandoverArea"
73                     ]
74                 )
75                 / 100
76             )
77         )
78         layout = Layout(
79             Hexagon.layout_flat, Point(size, size), Point(0, 0)
80         )  # 1 pixel = 1 meter
81         self._spiral_radius_profile: SpiralRadiusProfile = SpiralRadiusProfile(
82             {
83                 "oRanSmoSpiralRadiusOfNearRtRics": configuration["pattern"][
84                     "smo"
85                 ]["nearRtRicSpiralRadius"],
86                 "oRanNearRtRicSpiralRadiusOfOCus": configuration["pattern"][
87                     "nearRtRic"
88                 ]["oRanCuSpiralRadius"],
89                 "oRanCuSpiralRadiusOfODus": configuration["pattern"][
90                     "oRanCu"
91                 ]["oRanDuSpiralRadius"],
92                 "oRanDuSpiralRadiusOfTowers": configuration["pattern"][
93                     "oRanDu"
94                 ]["towerSpiralRadius"],
95             }
96         )
97         self._o_ran_smo = ORanSmo(
98             {
99                 "name": "O-RAN-SMO",
100                 "geoLocation": self.center,
101                 "layout": layout,
102                 "parent": self,
103             }
104         )
105
106     def _to_o_ran_network_data(self, data: dict[str, Any]) -> IORanNetwork:
107         result: IORanNetwork = self.__my_default_value
108         for key, key_type in IORanNetwork.__annotations__.items():
109             if key in data:
110                 result[key] = data[key]  # type: ignore
111         return result
112
113     @property
114     def center(self) -> GeoLocation:
115         """
116         Getter for a json object representing the O-RAN Network.
117         :return O-RAN Network as json object.
118         """
119         return GeoLocation(self._center)
120
121     @property
122     def spiral_radius_profile(self) -> SpiralRadiusProfile:
123         """
124         Getter for a json object representing the SpiralRadiusProfile.
125         :return SpiralRadiusProfile.
126         """
127         return self._spiral_radius_profile
128
129     @property
130     def configuration(self) -> dict[str, Any]:
131         """
132         Getter for a json object representing the O-RAN Network.
133         :return O-RAN Network as json object.
134         """
135         return self.__configuration
136
137     def to_topology(self) -> dict[str, Any]:
138         nodes: list[dict[str, Any]] = self._o_ran_smo.to_topology_nodes()
139         links: list[dict[str, Any]] = self._o_ran_smo.to_topology_links()
140         return {
141             "ietf-network:networks": {
142                 "network": [
143                     {
144                         "network-id": self.id,
145                         "node": nodes,
146                         "ietf-network-topology:link": links,
147                     }
148                 ],
149             }
150         }
151
152     def to_directory(self, parent_dir: str) -> None:
153         self._o_ran_smo.to_directory(os.path.join(parent_dir, self.id))
154
155     def toKml(self) -> ET.Element:
156         root: ET.Element = ET.Element(
157             "kml", xmlns="http://www.opengis.net/kml/2.2"
158         )
159         document = ET.SubElement(root, "Document")
160         open: ET.Element = ET.SubElement(document, "open")
161         open.text = "1"
162         name: ET.Element = ET.SubElement(document, "name")
163         name.text = self.name
164
165         document.append(self._o_ran_smo.toKml())
166
167         return root
168
169     def toSvg(self) -> ET.Element:
170         """
171         Getter for a xml/svg Element object representing the Network.
172         :return Network as SVG object.
173         """
174         root: ET.Element = ET.Element(
175             "svg",
176             # width=str(self.__svg_width()),
177             # height=str(self.__svg_height()),
178             # viewBox=" ".join([
179             #     str(-3*self.FONTSIZE),
180             #     str(-3*self.FONTSIZE),
181             #     str(self.__svg_width()),
182             #     str(self.__svg_height())]
183             # ),
184             xmlns="http://www.w3.org/2000/svg",
185         )
186         desc = ET.Element("desc")
187         desc.text = "\n context: " + self.id + "\n name: " + self.name
188         root.append(desc)
189
190         title = ET.Element("title")
191         title.text = str(self.configuration["name"])
192         root.append(title)
193
194         # root.append(self.__context.svg(x, y))
195         return root
196
197     def json(self) -> dict[str, Any]:
198         return super().json()