epics-base / p4p

Python bindings for the PVAccess network client and server.
BSD 3-Clause "New" or "Revised" License
27 stars 38 forks source link

Value is read as zero when the units change #74

Closed mattclarke closed 3 years ago

mattclarke commented 3 years ago

I am using p4p==4.0.0a1.

When I change the EGU value via pvput, the monitor response I get in p4p has the value field set to 0 even though it isn't. For example:

struct "epics:nt/NTScalar:1.0" {
    double value = 0                       <-- actual value on IOC is 15
    struct "alarm_t" {
        int32_t severity = 0
        int32_t status = 0
        string message = ""
    } alarm
    struct "time_t" {
        int64_t secondsPastEpoch = 1633518144
        int32_t nanoseconds = 934295000
        int32_t userTag = 0
    } timeStamp
    struct {
        double limitLow = 0
        double limitHigh = 0
        string description = ""
        string units = "mph"                  <-- pvput changed this
        int32_t precision = 0
        struct "enum_t" {
            int32_t index = 0
            string[] choices = {?}[]
        } form
    } display
    struct "control_t" {
        double limitLow = 0
        double limitHigh = 0
        double minStep = 0
    } control
    struct "valueAlarm_t" {
        bool active = false
        double lowAlarmLimit = 0
        double lowWarningLimit = 2
        double highWarningLimit = 18
        double highAlarmLimit = 20
        int32_t lowAlarmSeverity = 0
        int32_t lowWarningSeverity = 0
        int32_t highWarningSeverity = 0
        int32_t highAlarmSeverity = 0
        int8_t hysteresis = 0
    } valueAlarm
}

I assume it something to do with only sending the data that has changed, but I thought I would mention it :) Is there an easy way to work out what has changed?

mattclarke commented 3 years ago

BTW: I am using "field(value,timeStamp,alarm,control,display)")

mdavidsaver commented 3 years ago

I assume it something to do with only sending the data that has changed, but I thought I would mention it :)

PVXS handles monitors a little differently in that it passes through deltas from the network, as opposed to pvAccessCPP which always fills in unchanged fields using previously accumulated deltas.

Is there an easy way to work out what has changed?

A Value has methods changed() and changedSet(). So you could do something like

top = Value(...)
if top.changed('value', 'alarm', 'timeStamp'):
    ... This is a data update
elif top.changed('display', 'control', 'valueAlarm'):
    ... meta-data update
mattclarke commented 3 years ago

Thanks, changedSet() is exactly what I needed :D