Skip to content

Commit

Permalink
Use someip data processor in client instance
Browse files Browse the repository at this point in the history
  • Loading branch information
chrizog committed Aug 12, 2024
1 parent 58f123a commit 53d5fb6
Show file tree
Hide file tree
Showing 24 changed files with 450 additions and 213 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# someipy - A Python Library for the SOME/IP Protocol
# someipy - A Python Library implementing the SOME/IP Protocol

## Get in Contact :postbox:

Expand Down Expand Up @@ -53,11 +53,11 @@ The library is still under development. The current major limitations and deviat

### SOME/IP

- Calling methods via TCP is not supported yet. Only method calls via UDP are supported.
- Only unicast services are supported.
- SOME/IP-TP is not supported.
- IPv6 endpoints are not supported.
- Session handling is supported only for SOME/IP-SD and not for SOME/IP messages transporting events.
- Session handling is supported only for SOME/IP-SD and not for SOME/IP messages transporting events or methods.
- SOME/IP fields are not supported.

### Service Discovery

Expand Down
4 changes: 3 additions & 1 deletion example_apps/addition_method_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# but this way the code is more readable and the types are more descriptive and extensible, i.e.
# you could other information such as version or metadata to the method parameters.


@dataclass
class Addends(SomeIpPayload):
addend1: Sint16
Expand All @@ -19,9 +20,10 @@ def __init__(self, addend1: int = 0, addend2: int = 0):
self.addend1 = Sint16(addend1)
self.addend2 = Sint16(addend2)


@dataclass
class Sum(SomeIpPayload):
value: Sint32

def __init__(self):
self.value = Sint32()
self.value = Sint32()
34 changes: 23 additions & 11 deletions example_apps/call_method_tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import logging

from someipy import TransportLayerProtocol
from someipy.client_service_instance import MethodResult, construct_client_service_instance
from someipy.client_service_instance import (
MethodResult,
construct_client_service_instance,
)
from someipy.service import ServiceBuilder
from someipy.service_discovery import construct_service_discovery
from someipy.logging import set_someipy_log_level
Expand All @@ -17,6 +20,7 @@
SAMPLE_INSTANCE_ID = 0x5678
SAMPLE_METHOD_ID = 0x0123


async def main():

# It's possible to configure the logging level of the someipy library, e.g. logging.INFO, logging.DEBUG, logging.WARN, ..
Expand All @@ -25,8 +29,10 @@ async def main():
# Since the construction of the class ServiceDiscoveryProtocol is not trivial and would require an async __init__ function
# use the construct_service_discovery function
# The local interface IP address needs to be passed so that the src-address of all SD UDP packets is correctly set
service_discovery = await construct_service_discovery(SD_MULTICAST_GROUP, SD_PORT, INTERFACE_IP)

service_discovery = await construct_service_discovery(
SD_MULTICAST_GROUP, SD_PORT, INTERFACE_IP
)

addition_service = (
ServiceBuilder()
.with_service_id(SAMPLE_SERVICE_ID)
Expand All @@ -41,7 +47,7 @@ async def main():
endpoint=(ipaddress.IPv4Address(INTERFACE_IP), 3002),
ttl=5,
sd_sender=service_discovery,
protocol=TransportLayerProtocol.TCP
protocol=TransportLayerProtocol.TCP,
)

# The service instance has to be attached always to the ServiceDiscoveryProtocol object, so that the service instance
Expand All @@ -50,11 +56,18 @@ async def main():

try:
while True:

method_parameter = Addends(addend1=1, addend2=2)
method_success, method_result = await client_instance_addition.call_method(SAMPLE_METHOD_ID, method_parameter.serialize())

# The call method function returns a tuple with the first element being a MethodResult enum
method_success, method_result = await client_instance_addition.call_method(
SAMPLE_METHOD_ID, method_parameter.serialize()
)
# Check the result of the method call and handle it accordingly
if method_success == MethodResult.SUCCESS:
print(f"Received result for method: {' '.join(f'0x{b:02x}' for b in method_result)}")
print(
f"Received result for method: {' '.join(f'0x{b:02x}' for b in method_result)}"
)
try:
sum = Sum().deserialize(method_result)
print(f"Sum: {sum.value.value}")
Expand All @@ -68,6 +81,8 @@ async def main():
print("Service not yet available..")

await asyncio.sleep(2)

# When the application is canceled by the user, the asyncio.CancelledError is raised
except asyncio.CancelledError:
print("Shutdown..")
finally:
Expand All @@ -81,7 +96,4 @@ async def main():


if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
asyncio.run(main())
32 changes: 21 additions & 11 deletions example_apps/call_method_udp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import logging

from someipy import TransportLayerProtocol
from someipy.client_service_instance import MethodResult, construct_client_service_instance
from someipy.client_service_instance import (
MethodResult,
construct_client_service_instance,
)
from someipy.service import ServiceBuilder
from someipy.service_discovery import construct_service_discovery
from someipy.logging import set_someipy_log_level
Expand All @@ -17,6 +20,7 @@
SAMPLE_INSTANCE_ID = 0x5678
SAMPLE_METHOD_ID = 0x0123


async def main():

# It's possible to configure the logging level of the someipy library, e.g. logging.INFO, logging.DEBUG, logging.WARN, ..
Expand All @@ -25,8 +29,10 @@ async def main():
# Since the construction of the class ServiceDiscoveryProtocol is not trivial and would require an async __init__ function
# use the construct_service_discovery function
# The local interface IP address needs to be passed so that the src-address of all SD UDP packets is correctly set
service_discovery = await construct_service_discovery(SD_MULTICAST_GROUP, SD_PORT, INTERFACE_IP)

service_discovery = await construct_service_discovery(
SD_MULTICAST_GROUP, SD_PORT, INTERFACE_IP
)

addition_service = (
ServiceBuilder()
.with_service_id(SAMPLE_SERVICE_ID)
Expand All @@ -41,7 +47,7 @@ async def main():
endpoint=(ipaddress.IPv4Address(INTERFACE_IP), 3002),
ttl=5,
sd_sender=service_discovery,
protocol=TransportLayerProtocol.UDP
protocol=TransportLayerProtocol.UDP,
)

# The service instance has to be attached always to the ServiceDiscoveryProtocol object, so that the service instance
Expand All @@ -50,11 +56,15 @@ async def main():

try:
while True:

method_parameter = Addends(addend1=1, addend2=2)
method_success, method_result = await client_instance_addition.call_method(SAMPLE_METHOD_ID, method_parameter.serialize())
method_success, method_result = await client_instance_addition.call_method(
SAMPLE_METHOD_ID, method_parameter.serialize()
)
if method_success == MethodResult.SUCCESS:
print(f"Received result for method: {' '.join(f'0x{b:02x}' for b in method_result)}")
print(
f"Received result for method: {' '.join(f'0x{b:02x}' for b in method_result)}"
)
try:
sum = Sum().deserialize(method_result)
print(f"Sum: {sum.value.value}")
Expand All @@ -74,11 +84,11 @@ async def main():
print("Service Discovery close..")
service_discovery.close()

print("Shutdown service instance..")
await client_instance_addition.close()

print("End main task..")


if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
asyncio.run(main())
21 changes: 12 additions & 9 deletions example_apps/offer_method_tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
SAMPLE_INSTANCE_ID = 0x5678
SAMPLE_METHOD_ID = 0x0123


def add_method_handler(input_data: bytes, addr: Tuple[str, int]) -> Tuple[bool, bytes]:
# Process the data and return True/False indicating the success of the operation
# and the result of the method call in serialized form (bytes object)
# If False is returned an error message will be sent back to the client. In that case
# the payload can be an empty bytes-object, e.g. return False, b""

print(f"Received data: {' '.join(f'0x{b:02x}' for b in input_data)} from IP: {addr[0]} Port: {addr[1]}")

print(
f"Received data: {' '.join(f'0x{b:02x}' for b in input_data)} from IP: {addr[0]} Port: {addr[1]}"
)

try:
# Deserialize the input data
Expand All @@ -34,13 +37,14 @@ def add_method_handler(input_data: bytes, addr: Tuple[str, int]) -> Tuple[bool,
except Exception as e:
print(f"Error during deserialization: {e}")
return False, b""

# Perform the addition
sum = Sum()
sum.value = Sint32(addends.addend1.value + addends.addend2.value)
print(f"Send back: {' '.join(f'0x{b:02x}' for b in sum.serialize())}")
return True, sum.serialize()


async def main():

# It's possible to configure the logging level of the someipy library, e.g. logging.INFO, logging.DEBUG, logging.WARN, ..
Expand All @@ -49,7 +53,9 @@ async def main():
# Since the construction of the class ServiceDiscoveryProtocol is not trivial and would require an async __init__ function
# use the construct_service_discovery function
# The local interface IP address needs to be passed so that the src-address of all SD UDP packets is correctly set
service_discovery = await construct_service_discovery(SD_MULTICAST_GROUP, SD_PORT, INTERFACE_IP)
service_discovery = await construct_service_discovery(
SD_MULTICAST_GROUP, SD_PORT, INTERFACE_IP
)

addition_method = Method(id=SAMPLE_METHOD_ID, method_handler=add_method_handler)

Expand All @@ -72,7 +78,7 @@ async def main():
ttl=5,
sd_sender=service_discovery,
cyclic_offer_delay_ms=2000,
protocol=TransportLayerProtocol.TCP
protocol=TransportLayerProtocol.TCP,
)

# The service instance has to be attached always to the ServiceDiscoveryProtocol object, so that the service instance
Expand Down Expand Up @@ -101,7 +107,4 @@ async def main():


if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
asyncio.run(main())
21 changes: 12 additions & 9 deletions example_apps/offer_method_udp.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
SAMPLE_INSTANCE_ID = 0x5678
SAMPLE_METHOD_ID = 0x0123


def add_method_handler(input_data: bytes, addr: Tuple[str, int]) -> Tuple[bool, bytes]:
# Process the data and return True/False indicating the success of the operation
# and the result of the method call in serialized form (bytes object)
# If False is returned an error message will be sent back to the client. In that case
# the payload can be an empty bytes-object, e.g. return False, b""

print(f"Received data: {' '.join(f'0x{b:02x}' for b in input_data)} from IP: {addr[0]} Port: {addr[1]}")

print(
f"Received data: {' '.join(f'0x{b:02x}' for b in input_data)} from IP: {addr[0]} Port: {addr[1]}"
)

try:
# Deserialize the input data
Expand All @@ -34,13 +37,14 @@ def add_method_handler(input_data: bytes, addr: Tuple[str, int]) -> Tuple[bool,
except Exception as e:
print(f"Error during deserialization: {e}")
return False, b""

# Perform the addition
sum = Sum()
sum.value = Sint32(addends.addend1.value + addends.addend2.value)
print(f"Send back: {' '.join(f'0x{b:02x}' for b in sum.serialize())}")
return True, sum.serialize()


async def main():

# It's possible to configure the logging level of the someipy library, e.g. logging.INFO, logging.DEBUG, logging.WARN, ..
Expand All @@ -49,7 +53,9 @@ async def main():
# Since the construction of the class ServiceDiscoveryProtocol is not trivial and would require an async __init__ function
# use the construct_service_discovery function
# The local interface IP address needs to be passed so that the src-address of all SD UDP packets is correctly set
service_discovery = await construct_service_discovery(SD_MULTICAST_GROUP, SD_PORT, INTERFACE_IP)
service_discovery = await construct_service_discovery(
SD_MULTICAST_GROUP, SD_PORT, INTERFACE_IP
)

addition_method = Method(id=SAMPLE_METHOD_ID, method_handler=add_method_handler)

Expand All @@ -72,7 +78,7 @@ async def main():
ttl=5,
sd_sender=service_discovery,
cyclic_offer_delay_ms=2000,
protocol=TransportLayerProtocol.UDP
protocol=TransportLayerProtocol.UDP,
)

# The service instance has to be attached always to the ServiceDiscoveryProtocol object, so that the service instance
Expand Down Expand Up @@ -101,7 +107,4 @@ async def main():


if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
asyncio.run(main())
16 changes: 9 additions & 7 deletions example_apps/receive_events_tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
SAMPLE_EVENTGROUP_ID = 0x0321
SAMPLE_EVENT_ID = 0x0123


def temperature_callback(someip_message: SomeIpMessage) -> None:
"""
Callback function that is called when a temperature message is received.
Args:
someip_message (SomeIpMessage): The SomeIpMessage object containing the received message.
Returns:
None: This function does not return anything.
"""
Expand All @@ -34,6 +35,7 @@ def temperature_callback(someip_message: SomeIpMessage) -> None:
except Exception as e:
print(f"Error in deserialization: {e}")


async def main():
# It's possible to configure the logging level of the someipy library, e.g. logging.INFO, logging.DEBUG, logging.WARN, ..
set_someipy_log_level(logging.DEBUG)
Expand Down Expand Up @@ -68,7 +70,7 @@ async def main():
endpoint=(ipaddress.IPv4Address(INTERFACE_IP), 3002),
ttl=5,
sd_sender=service_discovery,
protocol=TransportLayerProtocol.TCP
protocol=TransportLayerProtocol.TCP,
)

# It's possible to optionally register a callback function which will be called when an event from the
Expand All @@ -93,11 +95,11 @@ async def main():
print("Service Discovery close..")
service_discovery.close()

print("Shutdown service instance..")
await service_instance_temperature.close()

print("End main task..")


if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt as e:
pass
asyncio.run(main())
Loading

0 comments on commit 53d5fb6

Please sign in to comment.