dd1eb70196270e5c994fdc31333a40ac93960820
[oam.git] / code / network-generator / network_generation / model / python / tower.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 a Tower to mount O-RAN RUs
19 It can be interpreted as 'resource pool' for physical network
20 functions.
21 """
22 import xml.etree.ElementTree as ET
23 from typing import Any, cast
24
25 from network_generation.model.python.o_ran_node import IORanNode, ORanNode
26 from network_generation.model.python.o_ran_ru import ORanRu
27 from network_generation.model.python.o_ran_termination_point import (
28     ORanTerminationPoint,
29 )
30
31
32 # Define the "IoRanDu" interface
33 class ITower(IORanNode):
34     o_ran_ru_count: int
35
36
37 default_value: ITower = cast(
38     ITower,
39     {
40         **ORanNode.default(),
41         **{
42             "o_ran_ru_count": 1,
43         },
44     },
45 )
46
47
48 # Implement a concrete O-RAN Node class
49 class Tower(ORanNode):
50     def __init__(
51         self,
52         data: dict[str, Any] = cast(dict[str, Any], default_value),
53         **kwargs: dict[str, Any]
54     ) -> None:
55         tower_data: ITower = self._to_tower_data(data)
56         super().__init__(cast(dict[str, Any], tower_data), **kwargs)
57         self._o_ran_ru_count: int = (
58             int(str(tower_data["oRanRuCount"]))
59             if tower_data and "oRanRuCount" in tower_data
60             else 3
61         )
62         self._o_ran_rus: list[ORanRu] = self._create_o_ran_rus()
63
64     def _to_tower_data(self, data: dict[str, Any]) -> ITower:
65         result: ITower = default_value
66         for key, key_type in ITower.__annotations__.items():
67             if key in data:
68                 result[key] = data[key]  # type: ignore
69         return result
70
71     def _create_o_ran_rus(self) -> list[ORanRu]:
72         result: list[ORanRu] = []
73         for index in range(self._o_ran_ru_count):
74             s: str = "00" + str(index)
75             name: str = "-".join(
76                 [self.name.replace("Tower", "RU"), s[len(s) - 2: len(s)]]
77             )
78             cell_count: int = (
79                 self.parent.parent.parent.parent.parent.configuration[
80                     "pattern"
81                 ]["oRanRu"]["nrCellDuCount"]
82             )
83             cell_angle: int = (
84                 self.parent.parent.parent.parent.parent.configuration[
85                     "pattern"
86                 ]["nrCellDu"]["cellAngle"]
87             )
88             ru_angle: int = cell_count * cell_angle
89             ru_azimuth: int = index * ru_angle
90             result.append(
91                 ORanRu(
92                     {
93                         "name": name,
94                         "geoLocation": self.geo_location,
95                         "position": self.position,
96                         "layout": self.layout,
97                         "parent": self,
98                         "cellCount": cell_count,
99                         "ruAngle": ru_angle,
100                         "ruAzimuth": ru_azimuth,
101                     }
102                 )
103             )
104         return result
105
106     @property
107     def o_ran_rus(self) -> list[ORanRu]:
108         return self._o_ran_rus
109
110     def termination_points(self) -> list[ORanTerminationPoint]:
111         result: list[ORanTerminationPoint] = super().termination_points()
112         phy_tp: str = "-".join([self.name, "phy".upper()])
113         result.append(ORanTerminationPoint({"tp-id": phy_tp}))
114         for interface in ["e2", "o1", "ofhm", "ofhc", "ofhu", "ofhs"]:
115             result.append(
116                 ORanTerminationPoint(
117                     {
118                         "tp-id": "-".join([self.name, interface.upper()]),
119                         "supporting-termination-point": [
120                             {
121                                 "network-ref": type(
122                                     self.parent.parent.parent.parent
123                                 ),
124                                 "node-ref": self.name,
125                                 "tp-ref": phy_tp,
126                             }
127                         ],
128                     }
129                 )
130             )
131         return result
132
133     def to_topology_nodes(self) -> list[dict[str, Any]]:
134         result: list[dict[str, Any]] = super().to_topology_nodes()
135         for o_ran_ru in self.o_ran_rus:
136             result.extend(o_ran_ru.to_topology_nodes())
137         return result
138
139     def to_topology_links(self) -> list[dict[str, Any]]:
140         result: list[dict[str, Any]] = super().to_topology_links()
141         for o_ran_ru in self.o_ran_rus:
142             result.extend(o_ran_ru.to_topology_links())
143         return result
144
145     def toKml(self) -> ET.Element:
146         tower: ET.Element = ET.Element("Folder")
147         open: ET.Element = ET.SubElement(tower, "open")
148         open.text = "1"
149         name: ET.Element = ET.SubElement(tower, "name")
150         name.text = self.name
151         for o_ran_ru in self.o_ran_rus:
152             tower.append(o_ran_ru.toKml())
153         return tower
154
155     def toSvg(self) -> ET.Element:
156         return ET.Element("to-be-implemented")