Zum Inhalt

Dokumentation

LIN aus Python und C verwenden

Anwendungen sprechen über einen lokalen Unix-Socket mit dem HAT – ohne eigenen I²C-Treiber.

LIN aus Python und C verwenden

Empfohlener Anwendungsweg

Normale Anwendungen greifen nicht direkt auf I²C zu.

Python / C / eigene Anwendung
          |
          | Unix SOCK_SEQPACKET
          v
      beiis-lind
          |
          | I²C
          v
        STM32

Dadurch besitzt nur ein Prozess den I²C-Endpunkt und mehrere Anwendungen müssen die Hardwaredetails nicht selbst kennen.

Daemon starten

Für Entwicklung:

source .venv/bin/activate

beiis-lind \
  --bus 1 \
  --address 0x42 \
  --socket /tmp/beiis-lin.sock \
  --lock-file /tmp/beiis-lind.lock

Verbindung prüfen:

beiis-lin --socket /tmp/beiis-lin.sock info

Auf Raspberry Pi Hardware verwendet der Daemon standardmäßig zusätzlich den isolierten GPIO6-Interrupt als Wakeup-Signal.

Python

Die einfachste Integration verwendet DaemonClient:

from beiis_lin.client import DaemonClient

c = DaemonClient("/run/beiis/lin-hat.sock")

c.set_active_instance(0)      # master_tx_query
c.data_send(0, b"\x00")     # Native PING

instance, channel, reply = c.data_recv(
    instance=1,              # master_rx_query
    channel=0,
    timeout=2.0,
)

print(reply.hex(" "))
c.close()

Erwartete Antwort:

00 00

Das erste Byte ist die Operation, das zweite der Status 0 = OK.

Python: LIN-Frame senden

from beiis_lin.client import DaemonClient

c = DaemonClient()

c.set_active_instance(0)

request = bytes.fromhex(
    "02 12 01 04 11 22 33 44"
)
c.data_send(0, request)

_, _, reply = c.data_recv(
    instance=1,
    channel=0,
    timeout=2.0,
)

assert reply == bytes.fromhex("02 00")
c.close()

C

Die Socket-Schnittstelle ist ein normaler Unix-Domain-SOCK_SEQPACKET-Socket.

int fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);

Standardpfad:

/run/beiis/lin-hat.sock

Ein Request ist genau ein UTF-8-JSON-Paket.

Aktive Master-Query wählen:

{"v":1,"id":1,"type":"request","op":"set_active_instance","args":{"instance":0}}

Native PING senden:

{"v":1,"id":2,"type":"request","op":"data_send","args":{"channel":0,"data":"00"}}

Antwort von master_rx_query lesen:

{"v":1,"id":3,"type":"request","op":"data_recv","args":{"instance":1,"channel":0,"timeout":2.0}}

Ein vollständiges minimales C-Beispiel liegt unter:

examples/runtime/c_basic.c

Kompilieren:

cc -O2 -Wall -Wextra examples/runtime/c_basic.c -o /tmp/beiis-runtime-c
/tmp/beiis-runtime-c

Warum Socket statt direktem I²C?

Der Socket trennt die Anwendung von:

  • I²C-Registerdetails,
  • Zugriffssynchronisation,
  • GPIO-IRQ-Behandlung,
  • STM32-Runtime-Framing,
  • Firmware-Recovery und mboot.

Damit kann dieselbe Architektur aus Python, C oder jeder anderen Sprache verwendet werden, die Unix-Sockets und JSON beherrscht.

Wichtig: nur ein I²C-Besitzer

Wenn beiis-lind läuft, sollte keine zweite Anwendung gleichzeitig mit --direct auf dieselbe I²C-Adresse zugreifen.

Für normale Anwendungen gilt deshalb:

Socket benutzen. Direkten I²C-Zugriff nur für Bring-up, Recovery und Low-Level-Debugging verwenden.