Skip to content

MCCU API Client

Bases: BaseAPIClient

API client for MCCU API.

This client provides a Python class to communicate with the Operating Point API.

This API reads the nameplate information (ratings) of the 'ABB' made motor. The API is only available from the ABB network.

Source code in reportconnectors/api_client/mccu_api_client.py
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
class MccuAPIClient(BaseAPIClient):
    """
    API client for MCCU API.

    This client provides a Python class to communicate with the Operating Point API.

    This API reads the nameplate information (ratings) of the 'ABB' made motor.
    The API is only available from the ABB network.
    """

    __version__ = "0.3.0"
    api_key: Optional[str] = None

    class KeyNames(BaseAPIClient.KeyNames):
        API_KEY_HEADER = "Api-Key"

    def authenticate(self, key: str) -> bool:
        """
        Authenticate to MCCU API using Api-Key.

        Args:
            key: API key for MCCU

        Returns:
            True, if the client is already logged in or authentication went successfully.
            False if no key is provided.
        """

        if key is not None:
            self.api_key = key
        return self.is_logged

    def _add_authorization_to_request(self, request: requests.Request) -> requests.Request:
        if self.api_key is not None and self.KeyNames.API_KEY_HEADER not in request.headers:
            request.headers[self.KeyNames.API_KEY_HEADER] = self.api_key
        return request

    @property
    def is_logged(self) -> bool:
        """Simple check if client api_key is available."""
        return self.api_key is not None

    def get_motor_nameplate(self, serial_number: str) -> Dict:
        """
        Gets the complete nameplate of the ABB produced motor based on its serial number.

        Args:
            serial_number: Serial number of the motor.

        Returns:
            Dict containing information about motor's nameplate.
        """

        _endpoint = "ratings"
        params = {"serialno": str(serial_number)}
        response = self._make_request(method="GET", endpoint=_endpoint, params=params)
        decoded_response: Dict = self._decode_response(response=response, default={})
        return decoded_response

    def get_shaft_power_map(
        self,
        serial_number: str,
        nominal_voltage: Optional[float] = None,
        nominal_line_frequency: Optional[float] = None,
        nominal_speed: Optional[float] = None,
        nominal_power: Optional[float] = None,
        connection: Optional[StatorConnection] = None,
    ) -> Dict:
        """
        Gets the shaft power map for motor identified by provided serial number.

        Voltage [V], line frequency [Hz], speed [RPM], power [kW] and connection type are required
        to get the shaft power map. However, all of them can be read from the `get_motor_nameplate` endpoint.

        Therefore, this method operates in two modes:

        1. If all optional parameters are provided, it will use them to get the shaft power map.
        2. If any of the optional parameters are not provided, it will first make the call to get the use the nameplate
            and then use it to get the shaft power map.

        Args:
            serial_number: Serial number of the motor. Required
            nominal_voltage: Nominal voltage of the motor. [V]
            nominal_line_frequency: Nominal line frequency of the motor. [Hz]
            nominal_speed: Nominal speed of the motor. [RPM]
            nominal_power: Nominal power of the motor. [W]
            connection: Stator connection type of the motor. [delta=0, star=1]

        Returns:
            Dict with motor ratings, number_of_poles and shaft power map as base64-encoded CSV.
        """

        _endpoint = "shaftPowerMap"

        if (
            nominal_voltage is None
            or nominal_line_frequency is None
            or nominal_speed is None
            or nominal_power is None
            or connection is None
        ):
            ratings = self._get_motor_ratings(serial_number=serial_number)
        else:
            ratings = dict(
                voltage=nominal_voltage,
                frequency=nominal_line_frequency,
                speed=nominal_speed,
                power=nominal_power,
                connection=int(connection),
            )

        json_data = {"ratings": {"serial_number": str(serial_number), **ratings}}
        response = self._make_request(method="POST", endpoint=_endpoint, json_data=json_data)
        decoded_response: Dict = self._decode_response(response=response, default={})
        return decoded_response

    def _get_motor_ratings(self, serial_number: str) -> Dict:
        """
        Get ratings for shaft power map request from mccu nameplate details.

        It returns the ratings as dict with following keys and values in units:

        * voltage [V]
        * frequency [Hz]
        * speed [RPM]
        * power [W]
        * connection [0/1]

        Returns:
            Dict containing all ratings needed by shaft power map endpoint.
        """

        rad_sec_2_rpm = 9.5493

        response = self.get_motor_nameplate(serial_number=serial_number)
        if "payload" not in response:
            return {}
        mccu_nameplate_data = response["payload"]
        output_dict = {
            "voltage": mccu_nameplate_data.get("voltage", 0),
            "frequency": mccu_nameplate_data.get("frequency", 0),
            "speed": mccu_nameplate_data.get("speed", 0) * rad_sec_2_rpm,
            "power": mccu_nameplate_data.get("power", 0),
            "connection": mccu_nameplate_data.get("stator_connection", 0),
        }
        return output_dict

is_logged property

Simple check if client api_key is available.

authenticate(key)

Authenticate to MCCU API using Api-Key.

Parameters:

Name Type Description Default
key str

API key for MCCU

required

Returns:

Type Description
bool

True, if the client is already logged in or authentication went successfully.

bool

False if no key is provided.

Source code in reportconnectors/api_client/mccu_api_client.py
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def authenticate(self, key: str) -> bool:
    """
    Authenticate to MCCU API using Api-Key.

    Args:
        key: API key for MCCU

    Returns:
        True, if the client is already logged in or authentication went successfully.
        False if no key is provided.
    """

    if key is not None:
        self.api_key = key
    return self.is_logged

get_motor_nameplate(serial_number)

Gets the complete nameplate of the ABB produced motor based on its serial number.

Parameters:

Name Type Description Default
serial_number str

Serial number of the motor.

required

Returns:

Type Description
Dict

Dict containing information about motor's nameplate.

Source code in reportconnectors/api_client/mccu_api_client.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
def get_motor_nameplate(self, serial_number: str) -> Dict:
    """
    Gets the complete nameplate of the ABB produced motor based on its serial number.

    Args:
        serial_number: Serial number of the motor.

    Returns:
        Dict containing information about motor's nameplate.
    """

    _endpoint = "ratings"
    params = {"serialno": str(serial_number)}
    response = self._make_request(method="GET", endpoint=_endpoint, params=params)
    decoded_response: Dict = self._decode_response(response=response, default={})
    return decoded_response

get_shaft_power_map(serial_number, nominal_voltage=None, nominal_line_frequency=None, nominal_speed=None, nominal_power=None, connection=None)

Gets the shaft power map for motor identified by provided serial number.

Voltage [V], line frequency [Hz], speed [RPM], power [kW] and connection type are required to get the shaft power map. However, all of them can be read from the get_motor_nameplate endpoint.

Therefore, this method operates in two modes:

  1. If all optional parameters are provided, it will use them to get the shaft power map.
  2. If any of the optional parameters are not provided, it will first make the call to get the use the nameplate and then use it to get the shaft power map.

Parameters:

Name Type Description Default
serial_number str

Serial number of the motor. Required

required
nominal_voltage Optional[float]

Nominal voltage of the motor. [V]

None
nominal_line_frequency Optional[float]

Nominal line frequency of the motor. [Hz]

None
nominal_speed Optional[float]

Nominal speed of the motor. [RPM]

None
nominal_power Optional[float]

Nominal power of the motor. [W]

None
connection Optional[StatorConnection]

Stator connection type of the motor. [delta=0, star=1]

None

Returns:

Type Description
Dict

Dict with motor ratings, number_of_poles and shaft power map as base64-encoded CSV.

Source code in reportconnectors/api_client/mccu_api_client.py
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
def get_shaft_power_map(
    self,
    serial_number: str,
    nominal_voltage: Optional[float] = None,
    nominal_line_frequency: Optional[float] = None,
    nominal_speed: Optional[float] = None,
    nominal_power: Optional[float] = None,
    connection: Optional[StatorConnection] = None,
) -> Dict:
    """
    Gets the shaft power map for motor identified by provided serial number.

    Voltage [V], line frequency [Hz], speed [RPM], power [kW] and connection type are required
    to get the shaft power map. However, all of them can be read from the `get_motor_nameplate` endpoint.

    Therefore, this method operates in two modes:

    1. If all optional parameters are provided, it will use them to get the shaft power map.
    2. If any of the optional parameters are not provided, it will first make the call to get the use the nameplate
        and then use it to get the shaft power map.

    Args:
        serial_number: Serial number of the motor. Required
        nominal_voltage: Nominal voltage of the motor. [V]
        nominal_line_frequency: Nominal line frequency of the motor. [Hz]
        nominal_speed: Nominal speed of the motor. [RPM]
        nominal_power: Nominal power of the motor. [W]
        connection: Stator connection type of the motor. [delta=0, star=1]

    Returns:
        Dict with motor ratings, number_of_poles and shaft power map as base64-encoded CSV.
    """

    _endpoint = "shaftPowerMap"

    if (
        nominal_voltage is None
        or nominal_line_frequency is None
        or nominal_speed is None
        or nominal_power is None
        or connection is None
    ):
        ratings = self._get_motor_ratings(serial_number=serial_number)
    else:
        ratings = dict(
            voltage=nominal_voltage,
            frequency=nominal_line_frequency,
            speed=nominal_speed,
            power=nominal_power,
            connection=int(connection),
        )

    json_data = {"ratings": {"serial_number": str(serial_number), **ratings}}
    response = self._make_request(method="POST", endpoint=_endpoint, json_data=json_data)
    decoded_response: Dict = self._decode_response(response=response, default={})
    return decoded_response