Subscriptions: cyclic data-change (and alarm) notifications
The PLC can push value updates instead of being polled. python-snap7 has a create_subscription() stub (s7/_s7commplus_client.py) but no working notification receive/parse or credit management. Implement the full subscription flow.
Goal
create_subscription(items, cycle_ms) → create a Subscription object on the PLC and register the variables.
receive_notification(timeout) → block for the next pushed update and return the changed values.
- Credit management so the flow doesn't stall.
Approach (mirror C# Notification + AlarmsHandler)
- Create the subscription:
CreateObject of a Subscription (Ids.ClassSubscription = 1001) with SubscriptionReferenceList (1048) = the item address array, SubscriptionCycleTime (1049), SubscriptionCreditLimit (1053). (For alarms the ref list is the alarm subsystem address 0x80010000.)
- Receive notifications: the PLC sends unsolicited Notification PDUs (
Core/Notification.cs::DeserializeFromPdu) carrying NotificationCreditTick, SequenceNumber and the changed P-values. These arrive outside the request/response cycle — the connection needs an unsolicited-PDU path (a receive queue / background reader) that coexists with send_request and the TLS-in-COTP tunnel. Note SystemEvent PDUs use ProtocolVersion 0xfe (header-only) and can report fatal protocol errors.
- Credit: call
SubscriptionSetCreditLimit() shortly before the credit tick expires to keep a constant data flow.
C# reference (thomas-v2/S7CommPlusDriver, LGPL-3.0)
Core/Notification.cs — notification PDU parse
Alarming/AlarmsHandler.cs — subscription create (SubscriptionReferenceList, credit), the notification loop, SubscriptionSetCreditLimit
Core/SystemEvent.cs — the 0xfe path
Already in place
Caveat
The biggest design point is the unsolicited-receive path: today _recv_s7_data/send_request assume strict request→response. Notifications break that, so a small receive loop/queue (thread or selector) feeding decrypted PDUs is needed, careful with the MemoryBIO TLS tunnel.
Validation
Subscribe to a couple of fast-changing tags on a live S7-1500 (e.g. a fast-changing analog value) and confirm periodic pushed updates match direct reads.
Subscriptions: cyclic data-change (and alarm) notifications
The PLC can push value updates instead of being polled. python-snap7 has a
create_subscription()stub (s7/_s7commplus_client.py) but no working notification receive/parse or credit management. Implement the full subscription flow.Goal
create_subscription(items, cycle_ms)→ create a Subscription object on the PLC and register the variables.receive_notification(timeout)→ block for the next pushed update and return the changed values.Approach (mirror C#
Notification+AlarmsHandler)CreateObjectof a Subscription (Ids.ClassSubscription= 1001) withSubscriptionReferenceList(1048) = the item address array,SubscriptionCycleTime(1049),SubscriptionCreditLimit(1053). (For alarms the ref list is the alarm subsystem address0x80010000.)Core/Notification.cs::DeserializeFromPdu) carryingNotificationCreditTick,SequenceNumberand the changed P-values. These arrive outside the request/response cycle — the connection needs an unsolicited-PDU path (a receive queue / background reader) that coexists withsend_requestand the TLS-in-COTP tunnel. Note SystemEvent PDUs use ProtocolVersion0xfe(header-only) and can report fatal protocol errors.SubscriptionSetCreditLimit()shortly before the credit tick expires to keep a constant data flow.C# reference (thomas-v2/S7CommPlusDriver, LGPL-3.0)
Core/Notification.cs— notification PDU parseAlarming/AlarmsHandler.cs— subscription create (SubscriptionReferenceList, credit), the notification loop,SubscriptionSetCreditLimitCore/SystemEvent.cs— the 0xfe pathAlready in place
CLASS_SUBSCRIPTION,SUBSCRIPTION_REFERENCE_LIST,SUBSCRIPTION_CYCLE_TIME,SUBSCRIPTION_CREDIT_LIMIT,SUBSCRIPTION_ACTIVEinprotocol.py;create_subscription()stub.Caveat
The biggest design point is the unsolicited-receive path: today
_recv_s7_data/send_requestassume strict request→response. Notifications break that, so a small receive loop/queue (thread or selector) feeding decrypted PDUs is needed, careful with theMemoryBIOTLS tunnel.Validation
Subscribe to a couple of fast-changing tags on a live S7-1500 (e.g. a fast-changing analog value) and confirm periodic pushed updates match direct reads.