265e6f45f2fbf3f1d9af215a1b5dfa3d5122fbed
[oam.git] / code / network-generator / network_generation / model / python / o_ran_ru.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 """
18 A Class representing an O-RAN radio unit (ORanRu)
19 """
20 import xml.etree.ElementTree as ET
21 from typing import Any, cast
22
23 from network_generation.model.python.nr_cell_du import NrCellDu
24 from network_generation.model.python.o_ran_du import ORanDu
25 from network_generation.model.python.o_ran_node import IORanNode, ORanNode
26 from network_generation.model.python.o_ran_termination_point import (
27     ORanTerminationPoint,
28 )
29
30
31 # Define the "IORanRu" interface
32 class IORanRu(IORanNode):
33     cellCount: int
34     ruAngle: int
35     ruAzimuth: int
36
37
38 default_value: IORanRu = cast(
39     IORanRu,
40     {
41         **ORanNode.default(),
42         **{"cellCount": 1, "ruAngle": 120, "ruAzimuth": 0},
43     },
44 )
45
46
47 # Define an abstract O-RAN Node class
48 class ORanRu(ORanNode):
49     def __init__(
50         self,
51         data: dict[str, Any] = cast(dict[str, Any], default_value),
52         **kwargs: dict[str, Any]
53     ) -> None:
54         o_ran_ru_data: IORanRu = self._to_o_ran_ru_data(data)
55         super().__init__(cast(dict[str, Any], o_ran_ru_data), **kwargs)
56         self._cell_count: int = (
57             int(str(o_ran_ru_data["cellCount"]))
58             if o_ran_ru_data and "cellCount" in o_ran_ru_data
59             else 1
60         )
61         self._ru_angle: int = (
62             int(str(o_ran_ru_data["ruAngle"]))
63             if o_ran_ru_data and "ruAngle" in o_ran_ru_data
64             else 120
65         )
66         self._ru_azimuth: int = (
67             int(str(o_ran_ru_data["ruAzimuth"]))
68             if o_ran_ru_data and "ruAzimuth" in o_ran_ru_data
69             else 0
70         )
71         self._cells: list[NrCellDu] = self._create_cells()
72         name: str = self.name.replace("RU", "DU")
73
74         o_ran_du_data: dict[str, Any] = {
75             "name": name,
76             "geoLocation": self.parent.geo_location,
77             "position": self.parent.position,
78             "layout": self.layout,
79             "parent": self.parent.parent.parent,
80         }
81         self._oRanDu: ORanDu = ORanDu(o_ran_du_data)
82
83     def _to_o_ran_ru_data(self, data: dict[str, Any]) -> IORanRu:
84         result: IORanRu = default_value
85         for key, key_type in IORanRu.__annotations__.items():
86             if key in data:
87                 result[key] = data[key]  # type: ignore
88         return result
89
90     def _create_cells(self) -> list[NrCellDu]:
91         result: list[NrCellDu] = []
92         cell_config: dict = (
93             self.parent.parent.parent.parent.parent.parent
94             .configuration["pattern"]["nrCellDu"]
95         )
96         cell_angle: int = cell_config["cellAngle"]
97         cell_scale_factor: int = (
98             cell_config["cellScaleFactorForHandoverArea"]
99         )
100         maxReach: int = cell_config["maxReach"]
101         for index in range(self._cell_count):
102             s: str = "00" + str(index)
103             name: str = "-".join(
104                 [self.name.replace("RU", "NRCellDu"), s[len(s) - 2: len(s)]]
105             )
106             azimuth: int = index * cell_angle + self._ru_azimuth
107             result.append(
108                 NrCellDu(
109                     {
110                         "name": name,
111                         "geoLocation": self.geo_location,
112                         "position": self.position,
113                         "layout": self.layout,
114                         "parent": self,
115                         "cellAngle": cell_angle,
116                         "cellScaleFactorForHandoverArea": cell_scale_factor,
117                         "maxReach": maxReach,
118                         "azimuth": azimuth,
119                     }
120                 )
121             )
122         return result
123
124     @property
125     def cells(self) -> list[NrCellDu]:
126         return self._cells
127
128     @property
129     def oRanDu(self) -> ORanDu:
130         return self._oRanDu
131
132     def termination_points(self) -> list[ORanTerminationPoint]:
133         result: list[ORanTerminationPoint] = super().termination_points()
134         phy_tp: str = "-".join([self.name, "phy".upper()])
135         result.append(ORanTerminationPoint({"id": phy_tp, "name": phy_tp}))
136         for interface in ["ofhm", "ofhc", "ofhu", "ofhs"]:
137             id: str = "-".join([self.name, interface.upper()])
138             result.append(
139                 ORanTerminationPoint(
140                     {"id": id, "name": id, "supporter": phy_tp, "parent": self}
141                 )
142             )
143         for cell in self.cells:
144             result.extend(cell.termination_points())
145         return result
146
147     def to_topology_nodes(self) -> list[dict[str, Any]]:
148         result: list[dict[str, Any]] = super().to_topology_nodes()
149         result.extend(self.oRanDu.to_topology_nodes())
150         return result
151
152     def to_topology_links(self) -> list[dict[str, Any]]:
153         result: list[dict[str, Any]] = super().to_topology_links()
154         result.extend(self.oRanDu.to_topology_links())
155         for interface in ["phy", "ofhm", "ofhc", "ofhu", "ofhs"]:
156             link_id: str = "".join(
157                 [interface, ":", self.name, "<->", self.oRanDu.name]
158             )
159             source_tp: str = "-".join([self.name, interface.upper()])
160             dest_tp: str = "-".join([self.oRanDu.name, interface.upper()])
161             result.append(
162                 {
163                     "link-id": link_id,
164                     "source": {
165                         "source-node": self.name,
166                         "source-tp": source_tp,
167                     },
168                     "destination": {
169                         "dest-node": self.oRanDu.name,
170                         "dest-tp": dest_tp,
171                     },
172                 }
173             )
174         return result
175
176     def toKml(self) -> ET.Element:
177         o_ran_ru: ET.Element = ET.Element("Folder")
178         open: ET.Element = ET.SubElement(o_ran_ru, "open")
179         open.text = "1"
180         name: ET.Element = ET.SubElement(o_ran_ru, "name")
181         name.text = self.name
182         for cell in self.cells:
183             o_ran_ru.append(cell.toKml())
184         return o_ran_ru
185
186     def toSvg(self) -> ET.Element:
187         return ET.Element("to-be-implemented")