Offering SOME/IP Events
SOME/IP Events
SOME/IP events implement the publish-subscribe concept in SOME/IP. A server offers a service to which one or more clients can subscribe. In case the server sends an event, all subscribed clients will receive the event.
A SOME/IP event is identified through an event ID which is packed into the header of a SOME/IP message. The event ID can be used by multiple services and does not have to be globally unique. The unique identification of an event comes through the combination of service ID, instance ID and event ID.
A SOME/IP event usually carries a serialized payload. For defining the service interface data types and serializing structured data into bytes
follow the article on SOME/IP Service Interface Data Types.
SOME/IP SD Eventgroups vs. SOME/IP Events
In SOME/IP there is also the term of Eventgroups. It’s important to understand the difference for setting up a proper SOME/IP communication. If eventgroup and event IDs are mixed up, the service discovery will not be able to create the subscription properly.
Eventgroups are only used in service discovery of SOME/IP and group events together for logically subscription. Eventgroups only exist at the service discovery level, but never appear in the actual data sent for an event. Once a client subscribed to a service, eventgroups are obsolete.
Grouping events in eventgroups allows clients to subscribe to multiple events at once reducing the bandwidth used for service discovery. For that purpose you could put all your events into a single eventgroup. Then a client can subscribe to a single eventgroup and will receive notifications for all events. This has the advantage of reduced traffic for service discovery. However, since all events are sent to the client even if he may not need all events for operation, more bandwidth is used for sending the actual data.
If you want to enable clients to subscribe to single events more granularly create multiple eventgroups or even one eventgroup for each event. This will require more service discovery traffic, however it may lead to sending only events that are actually needed by a particular client.
Step 1: Define a Service
In order to offer a service containing a SOME/IP event, we will define a Service
first, which is used afterwards to instantiate a ServerServiceInstance
. The Service
will contain a single event with ID 0x0123 in the eventgroup with ID 0x0321. The ServiceBuilder
class is used to build the Service
object.
SAMPLE_SERVICE_ID = 0x1234
SAMPLE_INSTANCE_ID = 0x5678
SAMPLE_EVENTGROUP_ID = 0x0321
SAMPLE_EVENT_ID = 0x0123
temperature_eventgroup = EventGroup(
id=SAMPLE_EVENTGROUP_ID, event_ids=[SAMPLE_EVENT_ID]
)
temperature_service = (
ServiceBuilder()
.with_service_id(SAMPLE_SERVICE_ID)
.with_major_version(1)
.with_eventgroup(temperature_eventgroup)
.build()
)
Step 2: Instantiate the Service
The previously defined Service
can be instantiated as one or multiple service instances. Since we are offering events as a server, a ServerServiceInstance
object is created using the construct_server_service_instance
function. The construct_server_service_instance
is a coroutine and therefore has to be await
ed.
You can choose to either use UDP or TCP as the transport protocol. Make sure, that the configuration matches with the client subscribing to the service.
# For sending events use a ServerServiceInstance
service_instance_temperature = await construct_server_service_instance(
temperature_service,
instance_id=SAMPLE_INSTANCE_ID,
endpoint=(
ipaddress.IPv4Address(INTERFACE_IP),
3000,
), # src IP and port of the service
ttl=5,
sd_sender=service_discovery,
cyclic_offer_delay_ms=2000,
protocol=TransportLayerProtocol.UDP,
)
The parameters ttl
and cyclic_offer_delay_ms
are described in Service Discovery Configuration Parameters
Multiple service instances: If you want to offer multiple service instances in the same application, you would simply construct another service instance here. Read the example application offer_multiple_services.py for more details.
Step 3: Announce the Service via Service Discovery
At this point, clients are not able to subscribe to the ServerServiceInstance
and to its eventgroup with ID 0x0321
. First, we need to attach the ServerServiceInstance
to service discovery. This will enable the ServerServiceInstance
to be notified about new subscriptions from clients. An observer pattern is implemented in which the ServerServiceInstance
is the observer.
It is assumed that the service_discovery
object was instantiated beforehand. For more information on that topic, read Service Discovery Configuration Parameters.
service_discovery.attach(service_instance_temperature)
The next step is to use start_offer
to announce the service instance to potential clients. The start_offer
function will start an internal timer with a cycle of cyclic_offer_delay_ms
sending service discovery messages with offer entries.
service_instance_temperature.start_offer()
Step 4: Sending Event Notifications to Clients
Now that the service is offered, clients can subscribe to the eventgroup with ID 0x0321
and the server can send events to the clients. The send_event
function expects a bytes
-object which is typically created by serialized structured data:
payload = tmp_msg.serialize()
service_instance_temperature.send_event(
SAMPLE_EVENTGROUP_ID, SAMPLE_EVENT_ID, payload
)
Typical sending strategies for SOME/IP events are cyclic updates or update on change. Update on change means that an event is sent whenever the contained value changes. In a cyclic update the event would be sent even if the contained data has not changed since the last publish.