linting ...
[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_angle: int = (
93             self.parent.parent.parent.parent.parent.parent.configuration[
94                 "pattern"
95             ]["nr-cell-du"]["cell-angle"]
96         )
97         for index in range(self._cell_count):
98             s: str = "00" + str(index)
99             name: str = "-".join(
100                 [self.name.replace("RU", "NRCellDu"), s[len(s) - 2: len(s)]]
101             )
102             azimuth: int = index * cell_angle + self._ru_azimuth
103             result.append(
104                 NrCellDu(
105                     {
106                         "name": name,
107                         "geoLocation": self.geo_location,
108                         "position": self.position,
109                         "layout": self.layout,
110                         "parent": self,
111                         "cellAngle": cell_angle,
112                         "azimuth": azimuth,
113                     }
114                 )
115             )
116         return result
117
118     @property
119     def cells(self) -> list[NrCellDu]:
120         return self._cells
121
122     @property
123     def oRanDu(self) -> ORanDu:
124         return self._oRanDu
125
126     def termination_points(self) -> list[ORanTerminationPoint]:
127         result: list[ORanTerminationPoint] = super().termination_points()
128         phy_tp: str = "-".join([self.name, "phy".upper()])
129         result.append(ORanTerminationPoint({"id": phy_tp, "name": phy_tp}))
130         for interface in ["ofhm", "ofhc", "ofhu", "ofhs"]:
131             id: str = "-".join([self.name, interface.upper()])
132             result.append(
133                 ORanTerminationPoint(
134                     {"id": id, "name": id, "supporter": phy_tp, "parent": self}
135                 )
136             )
137         for cell in self.cells:
138             result.extend(cell.termination_points())
139         return result
140
141     def to_topology_nodes(self) -> list[dict[str, Any]]:
142         result: list[dict[str, Any]] = super().to_topology_nodes()
143         result.extend(self.oRanDu.to_topology_nodes())
144         return result
145
146     def to_topology_links(self) -> list[dict[str, Any]]:
147         result: list[dict[str, Any]] = super().to_topology_links()
148         result.extend(self.oRanDu.to_topology_links())
149         for interface in ["phy", "ofhm", "ofhc", "ofhu", "ofhs"]:
150             link_id: str = "".join(
151                 [interface, ":", self.name, "<->", self.oRanDu.name]
152             )
153             source_tp: str = "-".join([self.name, interface.upper()])
154             dest_tp: str = "-".join([self.oRanDu.name, interface.upper()])
155             result.append(
156                 {
157                     "link-id": link_id,
158                     "source": {
159                         "source-node": self.name,
160                         "source-tp": source_tp,
161                     },
162                     "destination": {
163                         "dest-node": self.oRanDu.name,
164                         "dest-tp": dest_tp,
165                     },
166                 }
167             )
168         return result
169
170     def toKml(self) -> ET.Element:
171         o_ran_ru: ET.Element = ET.Element("Folder")
172         open: ET.Element = ET.SubElement(o_ran_ru, "open")
173         open.text = "1"
174         name: ET.Element = ET.SubElement(o_ran_ru, "name")
175         name.text = self.name
176         for cell in self.cells:
177             o_ran_ru.append(cell.toKml())
178         return o_ran_ru
179
180     def toSvg(self) -> ET.Element:
181         return ET.Element("to-be-implemented")