962e5b10815a38e218d35f81a6b4781e8da996a0
[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 from typing import Any, cast
21
22 import network_generation.model.python.hexagon as Hexagon
23 from network_generation.model.python.geo_location import (
24     GeoLocation,
25     IGeoLocation,
26 )
27 from network_generation.model.python.hexagon import Layout
28 from network_generation.model.python.o_ran_object import (
29     IORanObject,
30     ORanObject,
31 )
32 from network_generation.model.python.o_ran_smo import ORanSmo
33 from network_generation.model.python.o_ran_spiral_radius_profile import (
34     SpiralRadiusProfile,
35 )
36 from network_generation.model.python.point import Point
37
38 # Define the "IORanNetwork" interface
39 IORanNetwork = IORanObject
40
41
42 class ORanNetwork(ORanObject):
43     """
44     Class representing an O-RAN Network object.
45     """
46
47     __my_default_value: IORanNetwork = cast(IORanNetwork, ORanObject.default())
48
49     # constructor
50     def __init__(
51         self,
52         configuration: dict[str, dict],
53         data: dict[str, Any] = cast(dict[str, Any], __my_default_value),
54         **kwargs: dict[str, Any]
55     ) -> None:
56         o_ran_network_data: IORanNetwork = self._to_o_ran_network_data(data)
57         super().__init__(cast(dict[str, Any], o_ran_network_data), **kwargs)
58         self.__configuration = configuration
59
60         self.name = str(configuration["name"])
61         self._center: IGeoLocation = cast(
62             IGeoLocation, configuration["center"]
63         )
64
65         size: int = int(
66             int(configuration["pattern"]["nrCellDu"]["maxReach"])
67             / (
68                 1
69                 + int(
70                     configuration["pattern"]["nrCellDu"][
71                         "cellScaleFactorForHandoverArea"
72                     ]
73                 )
74                 / 100
75             )
76         )
77         layout = Layout(
78             Hexagon.layout_flat, Point(size, size), Point(0, 0)
79         )  # 1 pixel = 1 meter
80         self._spiral_radius_profile: SpiralRadiusProfile = SpiralRadiusProfile(
81             {
82                 "oRanSmoSpiralRadiusOfNearRtRics": configuration["pattern"][
83                     "smo"
84                 ]["nearRtRicSpiralRadius"],
85                 "oRanNearRtRicSpiralRadiusOfOCus": configuration["pattern"][
86                     "nearRtRic"
87                 ]["oRanCuSpiralRadius"],
88                 "oRanCuSpiralRadiusOfODus": configuration["pattern"][
89                     "oRanCu"
90                 ]["oRanDuSpiralRadius"],
91                 "oRanDuSpiralRadiusOfTowers": configuration["pattern"][
92                     "oRanDu"
93                 ]["towerSpiralRadius"],
94             }
95         )
96         self._o_ran_smo = ORanSmo(
97             {
98                 "name": "O-RAN-SMO",
99                 "geoLocation": self.center,
100                 "layout": layout,
101                 "parent": self,
102             }
103         )
104
105     def _to_o_ran_network_data(self, data: dict[str, Any]) -> IORanNetwork:
106         result: IORanNetwork = self.__my_default_value
107         for key, key_type in IORanNetwork.__annotations__.items():
108             if key in data:
109                 result[key] = data[key]  # type: ignore
110         return result
111
112     @property
113     def center(self) -> GeoLocation:
114         """
115         Getter for a json object representing the O-RAN Network.
116         :return O-RAN Network as json object.
117         """
118         return GeoLocation(self._center)
119
120     @property
121     def spiral_radius_profile(self) -> SpiralRadiusProfile:
122         """
123         Getter for a json object representing the SpiralRadiusProfile.
124         :return SpiralRadiusProfile.
125         """
126         return self._spiral_radius_profile
127
128     @property
129     def configuration(self) -> dict[str, Any]:
130         """
131         Getter for a json object representing the O-RAN Network.
132         :return O-RAN Network as json object.
133         """
134         return self.__configuration
135
136     def to_topology(self) -> dict[str, Any]:
137         nodes: list[dict[str, Any]] = self._o_ran_smo.to_topology_nodes()
138         links: list[dict[str, Any]] = self._o_ran_smo.to_topology_links()
139         return {
140             "ietf-network:networks": {
141                 "network": [
142                     {
143                         "network-id": self.id,
144                         "node": nodes,
145                         "ietf-network-topology:link": links,
146                     }
147                 ],
148             }
149         }
150
151     def toKml(self) -> ET.Element:
152         root: ET.Element = ET.Element(
153             "kml", xmlns="http://www.opengis.net/kml/2.2"
154         )
155         document = ET.SubElement(root, "Document")
156         open: ET.Element = ET.SubElement(document, "open")
157         open.text = "1"
158         name: ET.Element = ET.SubElement(document, "name")
159         name.text = self.name
160
161         document.append(self._o_ran_smo.toKml())
162
163         return root
164
165     def toSvg(self) -> ET.Element:
166         """
167         Getter for a xml/svg Element object representing the Network.
168         :return Network as SVG object.
169         """
170         root: ET.Element = ET.Element(
171             "svg",
172             # width=str(self.__svg_width()),
173             # height=str(self.__svg_height()),
174             # viewBox=" ".join([
175             #     str(-3*self.FONTSIZE),
176             #     str(-3*self.FONTSIZE),
177             #     str(self.__svg_width()),
178             #     str(self.__svg_height())]
179             # ),
180             xmlns="http://www.w3.org/2000/svg",
181         )
182         desc = ET.Element("desc")
183         desc.text = "\n context: " + self.id + "\n name: " + self.name
184         root.append(desc)
185
186         title = ET.Element("title")
187         title.text = str(self.configuration["name"])
188         root.append(title)
189
190         # root.append(self.__context.svg(x, y))
191         return root
192
193     def json(self) -> dict[str, Any]:
194         return super().json()