Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Userland PM16D17 #582

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions recipes-app/iot2050-event-record/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ To enable them, please create a systemd drop-in for `iot2050-event-record.servic
as follows:

```sh
mkdir -p /etc/systemd/system/iot2050-event-record.service.d/
cp /usr/lib/iot2050/event/iot2050-event-record.conf /etc/systemd/system/iot2050-event-record.service.d/
systemctl daemon-reload
systemctl restart iot2050-event-record.service
```
If changing the tilting threshold and uncovering threshold is expected, please
refer to the ``iot2050-event-record.conf`` for the details.
Expand Down
55 changes: 37 additions & 18 deletions recipes-app/iot2050-event-record/files/iot2050-event-record.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from datetime import datetime
from systemd import journal
from enum import Enum
from pystemd.dbuslib import DBus, DbusMessage
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the event-record an identical user story?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a leakage due to the lack of kernel ABI or userspace API compatibility, which seems to be an unmanageable limitation.

Otherwise, looks good to me.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding our upcoming release, we may need to hold off on merging this PR to avoid involving additional third-party libraries for OSS clearance.

import grpc
from gRPC.EventInterface.iot2050_event_pb2 import (
WriteRequest,
Expand Down Expand Up @@ -127,33 +128,51 @@ def record_eio_events():
time.sleep(5)


class ProximitySensorDBus():
def __init__(self, critical_value: int):
self.critical_value = critical_value

def is_uncovered(self) -> bool:
with DBus() as bus:
res: DbusMessage = bus.call_method(
b"com.siemens.iot2050.pxmt",
b"/com/siemens/iot2050/pxmt",
b"com.siemens.iot2050.pxmt",
b"Retrieve",
[])
lux = int(res.body)
return lux < self.critical_value

return False

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
pass


IIO_IMU_PATH = "/sys/devices/platform/bus@100000/2030000.i2c/i2c-5/5-006a/"
IIO_PRO_PATH = "/sys/devices/platform/bus@100000/2030000.i2c/i2c-5/5-0044/"
def record_sensor_events():
accel_x_raw = "{}/in_accel_x_raw"
accel_y_raw = "{}/in_accel_y_raw"
accel_z_raw = "{}/in_accel_z_raw"
pro_raw = "{}/in_proximity0_raw"
imu_w = os.walk(IIO_IMU_PATH)
pro_w = os.walk(IIO_PRO_PATH)
for (dirpath, dirnames, filenames) in imu_w:
if "in_accel_x_raw" in filenames:
accel_x_raw = accel_x_raw.format(dirpath)
accel_y_raw = accel_y_raw.format(dirpath)
accel_z_raw = accel_z_raw.format(dirpath)
break
for (dirpath, dirnames, filenames) in pro_w:
if "in_proximity0_raw" in filenames:
pro_raw = pro_raw.format(dirpath)
break

lux_critical_value = int(os.getenv('LUX_CRITICAL_VALUE', '100'))
pxmt_sensor = ProximitySensorDBus(critical_value=lux_critical_value)
with open(accel_x_raw, 'r') as x, \
open(accel_y_raw, 'r') as y, \
open(accel_z_raw, 'r') as z, \
open(pro_raw, 'r') as l:
pxmt_sensor as l:
is_uncovered = False
accel_critical_value = int(os.getenv('ACCEL_CRITICAL_VALUE'))
lux_critical_value = int(os.getenv('LUX_CRITICAL_VALUE'))
while True:
# Detect tilt sensor event
x.seek(0)
Expand All @@ -176,15 +195,15 @@ def record_sensor_events():
write_event(EVENT_TYPES["tilt"], tilted_event)

# Detect tamper sensor event
l.seek(0)
lux = int(l.read())
if lux < lux_critical_value and not is_uncovered:
is_uncovered = True
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
uncover_event = EVENT_STRINGS["uncover"].format(now)
write_event(EVENT_TYPES["uncover"], uncover_event)
elif lux > lux_critical_value and is_uncovered:
is_uncovered = False
if is_uncovered:
is_uncovered = l.is_uncovered()
else:
is_uncovered = l.is_uncovered()
if is_uncovered:
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
uncover_event = EVENT_STRINGS["uncover"].format(now)
write_event(EVENT_TYPES["uncover"], uncover_event)


def event_record():
if not is_grpc_servers_ready():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ SRC_URI = " \

S = "${WORKDIR}/src"

DEBIAN_DEPENDS = "python3, python3-grpcio, python3-psutil, python3-systemd"
DEBIAN_DEPENDS = "python3, python3-grpcio, python3-psutil, python3-systemd, python3-pystemd"

do_install() {
install -v -d ${D}/usr/lib/iot2050/event/
Expand Down
1 change: 1 addition & 0 deletions recipes-core/images/iot2050-image-example.bb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ IMAGE_INSTALL += " \
tee-supplicant \
iot2050-event-record \
linux-headers-${KERNEL_NAME} \
iot2050-proximity-driver \
"

IOT2050_NODE_RED_SUPPORT ?= "1"
Expand Down
39 changes: 39 additions & 0 deletions recipes-core/iot2050-proximity-driver/files/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright (c) Siemens AG, 2025
# SPDX-FileContributor: Authored by Su Bao Cheng <[email protected]>

CROSS_COMPILE ?= aarch64-linux-gnu-

CC = $(CROSS_COMPILE)gcc

LDFLAGS = -lsystemd

TARGET = iot2050-pxmtd

INSTALL ?= install

DESTDIR ?= /

SRC = main.c \
dbus-service.c \
sensor.c

.PHONY: all clean install

all: $(TARGET)

$(TARGET): $(SRC)
$(CC) $(CFLAGS) -o $(TARGET) $(SRC) $(LDFLAGS)

clean:
rm -f $(TARGET)

install:
$(INSTALL) -v -d $(DESTDIR)/usr/bin
$(INSTALL) -v -d $(DESTDIR)/etc/dbus-1/system.d
$(INSTALL) -v -m 0755 $(TARGET) $(DESTDIR)/usr/bin
$(INSTALL) -v -m 0644 com.siemens.iot2050.pxmt.conf \
$(DESTDIR)/etc/dbus-1/system.d
$(INSTALL) -v -d ${DESTDIR}/lib/systemd/system/
$(INSTALL) -v -m 0644 iot2050-proximity-driver.service\
${DESTDIR}/lib/systemd/system/
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="com.siemens.iot2050.pxmt"/>
<allow send_interface="com.siemens.iot2050.pxmt"/>
</policy>
</busconfig>
96 changes: 96 additions & 0 deletions recipes-core/iot2050-proximity-driver/files/src/dbus-service.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/* SPDX-License-Identifier: MIT
* SPDX-FileCopyrightText: Copyright (c) Siemens AG, 2025
* SPDX-FileContributor: Authored by Su Bao Cheng <[email protected]>
*/

#include <systemd/sd-bus.h>
#include <errno.h>
#include <sys/capability.h>
#include "dbus-service.h"

typedef int (*retrieve_callback_t)(uint16_t *);

static retrieve_callback_t iot2050_pxmtd_retrieve_cb = NULL;

static int iot2050_pxmtd_retrieve(sd_bus_message *m,
void *userdata,
sd_bus_error *ret_error)
{
if (!iot2050_pxmtd_retrieve_cb)
return -ENXIO;

uint16_t ps_val;
int ret = iot2050_pxmtd_retrieve_cb(&ps_val);
if (ret < 0)
return ret;

return sd_bus_reply_method_return(m, "q", ps_val);
}

static const sd_bus_vtable iot2050_pxmtd_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("Retrieve",
SD_BUS_NO_ARGS,
"q",
iot2050_pxmtd_retrieve,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};

int dbus_serve(retrieve_callback_t cb)
{
sd_bus_slot *slot = NULL;
sd_bus *bus = NULL;
int ret;

ret = sd_bus_open_system(&bus);
if (ret < 0) {
fprintf(stderr, "Failed to connect to system bus: %s\n",
strerror(-ret));
goto out;
}

iot2050_pxmtd_retrieve_cb = cb;

ret = sd_bus_add_object_vtable(bus, &slot,
"/com/siemens/iot2050/pxmt",
"com.siemens.iot2050.pxmt",
iot2050_pxmtd_vtable, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to set dbus service property: %s\n",
strerror(-ret));
goto out;
}

ret = sd_bus_request_name(bus, "com.siemens.iot2050.pxmt", 0);
if (ret < 0) {
fprintf(stderr, "Failed to acquire service name: %s\n",
strerror(-ret));
goto out;
}

for (;;) {
ret = sd_bus_process(bus, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to process bus: %s\n",
strerror(-ret));
goto out;
}
if (ret > 0)
continue;

ret = sd_bus_wait(bus, (uint64_t) -1);
if (ret < 0) {
fprintf(stderr, "Failed to wait on bus: %s\n",
strerror(-ret));
goto out;
}
}

ret = 0;
out:
sd_bus_slot_unref(slot);
sd_bus_unref(bus);

return ret;
}
15 changes: 15 additions & 0 deletions recipes-core/iot2050-proximity-driver/files/src/dbus-service.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: MIT
* SPDX-FileCopyrightText: Copyright (c) Siemens AG, 2025
* SPDX-FileContributor: Authored by Su Bao Cheng <[email protected]>
*/

#ifndef IOT2050_PXMTD_DBUS_SERVICE_H
#define IOT2050_PXMTD_DBUS_SERVICE_H

#include <stdint.h>

typedef int (*retrieve_callback_t)(uint16_t *);

int dbus_serve(retrieve_callback_t cb);

#endif /* IOT2050_PXMTD_DBUS_SERVICE_H */
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright (c) Siemens AG, 2025
# SPDX-FileContributor: Authored by Su Bao Cheng <[email protected]>

[Unit]
Description=Userspace driver for the proximity sensor of IOT2050
# Only run on IOT2050-SM variant
ConditionFirmware=device-tree-compatible(siemens,iot2050-advanced-sm)
ConditionVirtualization=!container

[Service]
Type=dbus
BusName=com.siemens.iot2050.pxmt
ExecStart=/usr/bin/iot2050-pxmtd
Restart=always
RestartSec=5
ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
User=root

[Install]
WantedBy=multi-user.target
Alias=dbus-com.siemens.iot2050.pxmt.service
24 changes: 24 additions & 0 deletions recipes-core/iot2050-proximity-driver/files/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: MIT
* SPDX-FileCopyrightText: Copyright (c) Siemens AG, 2025
* SPDX-FileContributor: Authored by Su Bao Cheng <[email protected]>
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sensor.h"
#include "dbus-service.h"

int main()
{
setbuf(stdout, NULL);

int ret = init_sensor();
if (ret < 0) {
fprintf(stderr, "Failed to initialize the sensor: %s\n",
strerror(-ret));
exit(EXIT_FAILURE);
}

return dbus_serve(retrieve_sensor_data) == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
Loading