Skip to content

Commit aa20428

Browse files
authored
Merge pull request #35 from EdgePi-Cloud/add-pwm
Add a service for the PWM module
2 parents 85a48b9 + 9b70df0 commit aa20428

File tree

4 files changed

+242
-0
lines changed

4 files changed

+242
-0
lines changed

edgepi_rpc_client/services/pwm/__init__.py

Whitespace-only changes.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
"""Client for PWM service"""
2+
import logging
3+
from edgepirpc.protos import pwm_pb2 as pwm_pb
4+
from edgepi_rpc_client.client_rpc_channel import ClientRpcChannel
5+
from edgepi_rpc_client.util.helpers import (
6+
filter_arg_values,
7+
create_config_request_from_args,
8+
get_server_response,
9+
)
10+
from edgepi_rpc_client.services.pwm.pwm_pb_enums import PWMPins, Polarity
11+
12+
_logger = logging.getLogger(__name__)
13+
14+
15+
# pylint: disable=no-member
16+
class ClientPWMService:
17+
"""Client Methods for PWM Service"""
18+
19+
def __init__(self, transport):
20+
self.client_rpc_channel = ClientRpcChannel(transport)
21+
self.service_stub = pwm_pb.PWMService_Stub(self.client_rpc_channel)
22+
self.rpc_controller = None
23+
24+
# pylint: disable=unused-argument
25+
def set_config(
26+
self,
27+
pwm_num: PWMPins,
28+
frequency: float = None,
29+
duty_cycle: float = None,
30+
polarity: Polarity = None,
31+
):
32+
"""set_config method for SDK PWM module"""
33+
config_args_dict = filter_arg_values(locals(), "self", None)
34+
config_msg = pwm_pb.Config()
35+
arg_msg = pwm_pb.Config().ConfArg()
36+
request = create_config_request_from_args(config_msg, arg_msg, config_args_dict)
37+
return self.perform_call_from_request(
38+
request, self.service_stub.set_config, pwm_pb.SuccessMsg
39+
).content
40+
41+
def enable(self, pwm_num: PWMPins):
42+
"""enable method for SDK PWM module"""
43+
return self.perform_rpc_call(
44+
pwm_num, self.service_stub.enable, pwm_pb.SuccessMsg
45+
).content
46+
47+
def disable(self, pwm_num: PWMPins):
48+
"""disable method for SDK PWM module"""
49+
return self.perform_rpc_call(
50+
pwm_num, self.service_stub.disable, pwm_pb.SuccessMsg
51+
).content
52+
53+
def close(self, pwm_num: PWMPins):
54+
"""close method for SDK PWM module"""
55+
return self.perform_rpc_call(
56+
pwm_num, self.service_stub.close, pwm_pb.SuccessMsg
57+
).content
58+
59+
def init_pwm(self, pwm_num: PWMPins):
60+
"""init_pwm method for SDK PWM module"""
61+
return self.perform_rpc_call(
62+
pwm_num, self.service_stub.init_pwm, pwm_pb.SuccessMsg
63+
).content
64+
65+
def get_frequency(self, pwm_num: PWMPins):
66+
"""get_frequency method for SDK PWM module"""
67+
return self.perform_rpc_call(
68+
pwm_num, self.service_stub.get_frequency, pwm_pb.GetFrequency
69+
).frequency
70+
71+
def get_duty_cycle(self, pwm_num: PWMPins):
72+
"""get_duty_cycle method for SDK PWM module"""
73+
return self.perform_rpc_call(
74+
pwm_num, self.service_stub.get_duty_cycle, pwm_pb.GetDutyCycle
75+
).duty_cycle
76+
77+
def get_polarity(self, pwm_num: PWMPins):
78+
"""get_polarity method for SDK PWM module"""
79+
polarity = self.perform_rpc_call(
80+
pwm_num, self.service_stub.get_polarity, pwm_pb.GetPolarity
81+
).polarity
82+
return Polarity(polarity)
83+
84+
def get_enabled(self, pwm_num: PWMPins):
85+
"""get_enabled method for SDK PWM module"""
86+
return self.perform_rpc_call(
87+
pwm_num, self.service_stub.get_enabled, pwm_pb.GetEnabled
88+
).enabled
89+
90+
# TODO: Potentially these helpers in other services and put them in a separate file
91+
def perform_rpc_call(self, pwm_num, method, response_type):
92+
"""Performs RPC call with PWM number and specified method"""
93+
request = pwm_pb.PWM(pwm_num=pwm_num.value)
94+
return self.perform_call_from_request(request, method, response_type)
95+
96+
def perform_call_from_request(self, request, method, response_type):
97+
"""Executes RPC call using provided request and method"""
98+
rpc_response = method(self.rpc_controller, request)
99+
return get_server_response(rpc_response, response_type)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Client enums to protobuf PWM enums"""
2+
from enum import Enum
3+
from edgepirpc.protos import pwm_pb2 as pwm_pb
4+
5+
class PWMPins(Enum):
6+
"""PWMPins Enum"""
7+
PWM1 = pwm_pb.PWMPins.PWM1
8+
PWM2 = pwm_pb.PWMPins.PWM2
9+
10+
class Polarity(Enum):
11+
"""Polarity Enum"""
12+
NORMAL = pwm_pb.Polarity.NORMAL
13+
INVERSED = pwm_pb.Polarity.INVERSED

tests/integration/test_pwm_service.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
"""PWMService integration test"""
2+
import pytest
3+
import time
4+
from edgepi_rpc_client.services.pwm.client_pwm_service import ClientPWMService
5+
from edgepi_rpc_client.services.pwm.pwm_pb_enums import PWMPins, Polarity
6+
7+
8+
@pytest.fixture(name="pwm_service")
9+
def fixture_test_pwm_service():
10+
"""Inits new PWM service client for testing"""
11+
return ClientPWMService('tcp://localhost:4444')
12+
13+
@pytest.mark.parametrize(
14+
"args",
15+
[
16+
{"pwm_num": PWMPins.PWM1, "polarity": Polarity.NORMAL},
17+
{"pwm_num": PWMPins.PWM2, "polarity": Polarity.INVERSED},
18+
{"pwm_num": PWMPins.PWM1, "frequency": 1000},
19+
{"pwm_num": PWMPins.PWM1, "duty_cycle": 0},
20+
]
21+
)
22+
def test_set_config(pwm_service, args):
23+
"""Test for set_config"""
24+
response_init = pwm_service.init_pwm(pwm_num=args['pwm_num'])
25+
assert response_init == f"Successfully initialized {args['pwm_num']}."
26+
response_config = pwm_service.set_config(**args)
27+
assert response_config == "Successfully applied pwm configurations."
28+
29+
@pytest.mark.parametrize(
30+
'pwm_num',
31+
[
32+
(PWMPins.PWM1),
33+
(PWMPins.PWM2),
34+
]
35+
)
36+
def test_enable(pwm_service, pwm_num):
37+
"""Test for set_enable"""
38+
pwm_service.init_pwm(pwm_num)
39+
response = pwm_service.enable(pwm_num)
40+
assert response == f"Successfully enabled {pwm_num}."
41+
42+
@pytest.mark.parametrize(
43+
'pwm_num',
44+
[
45+
(PWMPins.PWM1),
46+
(PWMPins.PWM2),
47+
]
48+
)
49+
def test_disable(pwm_service, pwm_num):
50+
"""Test for set_disable"""
51+
pwm_service.init_pwm(pwm_num)
52+
response = pwm_service.disable(pwm_num)
53+
assert response == f"Successfully disabled {pwm_num}."
54+
55+
@pytest.mark.parametrize(
56+
'pwm_num',
57+
[
58+
(PWMPins.PWM1),
59+
(PWMPins.PWM2),
60+
]
61+
)
62+
def test_close(pwm_service, pwm_num):
63+
"""Test for close"""
64+
pwm_service.init_pwm(pwm_num)
65+
response = pwm_service.close(pwm_num)
66+
assert response == f"Successfully closed {pwm_num}."
67+
68+
69+
@pytest.mark.parametrize(
70+
'pwm_num',
71+
[
72+
(PWMPins.PWM1),
73+
(PWMPins.PWM2),
74+
]
75+
)
76+
def test_get_frequency(pwm_service, pwm_num):
77+
"""Test for get_frequency"""
78+
pwm_service.init_pwm(pwm_num)
79+
frequency = pwm_service.get_frequency(pwm_num)
80+
assert isinstance(frequency, float)
81+
82+
@pytest.mark.parametrize(
83+
'pwm_num',
84+
[
85+
(PWMPins.PWM1),
86+
(PWMPins.PWM2),
87+
]
88+
)
89+
def test_get_duty_cycle(pwm_service, pwm_num):
90+
"""Test for get_duty_cycle"""
91+
pwm_service.init_pwm(pwm_num)
92+
duty_cycle = pwm_service.get_duty_cycle(pwm_num)
93+
assert isinstance(duty_cycle, float)
94+
95+
@pytest.mark.parametrize(
96+
'pwm_num',
97+
[
98+
(PWMPins.PWM1),
99+
(PWMPins.PWM2),
100+
]
101+
)
102+
def test_get_polarity(pwm_service, pwm_num):
103+
"""Test for get_polarity"""
104+
pwm_service.init_pwm(pwm_num)
105+
polarity = pwm_service.get_polarity(pwm_num)
106+
assert polarity in Polarity
107+
108+
@pytest.mark.parametrize(
109+
'pwm_num',
110+
[
111+
(PWMPins.PWM1),
112+
(PWMPins.PWM2),
113+
]
114+
)
115+
def test_get_enabled(pwm_service, pwm_num):
116+
"""Test for get_enabled"""
117+
pwm_service.init_pwm(pwm_num)
118+
enabled = pwm_service.get_enabled(pwm_num)
119+
assert isinstance(enabled, bool)
120+
121+
def test_with_edgepi(pwm_service):
122+
"""Manual testing of PWM functionality."""
123+
pwm_service.init_pwm(pwm_num=PWMPins.PWM1)
124+
pwm_service.set_config(pwm_num=PWMPins.PWM1, duty_cycle=0)
125+
pwm_service.enable(PWMPins.PWM1)
126+
time.sleep(3)
127+
pwm_service.set_config(pwm_num=PWMPins.PWM1, duty_cycle=0.5)
128+
time.sleep(3)
129+
pwm_service.set_config(pwm_num=PWMPins.PWM1, duty_cycle=1)
130+

0 commit comments

Comments
 (0)