Working on audit
This commit is contained in:
@@ -112,6 +112,8 @@ func fetchArchiveHistory(ctx context.Context, archiveURL, signal string, start,
|
||||
Timestamp: ts,
|
||||
Data: data,
|
||||
Quality: q,
|
||||
Severity: p.Severity,
|
||||
Status: p.Status,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
//
|
||||
//export goCAMonitorCallback
|
||||
func goCAMonitorCallback(handle C.uintptr_t, dbrType C.int, count C.long,
|
||||
dbr unsafe.Pointer, severity C.int, epicsTimeSecs C.double) {
|
||||
dbr unsafe.Pointer, severity C.int, status C.int, epicsTimeSecs C.double) {
|
||||
|
||||
h := uintptr(handle)
|
||||
|
||||
@@ -79,7 +79,13 @@ func goCAMonitorCallback(handle C.uintptr_t, dbrType C.int, count C.long,
|
||||
data = float64(0)
|
||||
}
|
||||
|
||||
v := datasource.Value{Timestamp: ts, Data: data, Quality: q}
|
||||
v := datasource.Value{
|
||||
Timestamp: ts,
|
||||
Data: data,
|
||||
Quality: q,
|
||||
Severity: int(severity),
|
||||
Status: int(status),
|
||||
}
|
||||
|
||||
// Look up the subscription channel under the global handle table lock and
|
||||
// perform a non-blocking send so we never stall the CA callback thread.
|
||||
@@ -129,6 +135,7 @@ func goCAConnectionCallback(handle C.uintptr_t, connected C.int) {
|
||||
Timestamp: time.Now(),
|
||||
Data: float64(0),
|
||||
Quality: datasource.QualityBad,
|
||||
Severity: 3, // INVALID
|
||||
}
|
||||
select {
|
||||
case ch <- v:
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* goCAConnectionCallback is called when a channel connects or disconnects.
|
||||
*/
|
||||
extern void goCAMonitorCallback(uintptr_t handle, int dbrType, long count,
|
||||
void *dbr, int severity,
|
||||
void *dbr, int severity, int status,
|
||||
double epicsTimeSecs);
|
||||
extern void goCAConnectionCallback(uintptr_t handle, int connected);
|
||||
|
||||
@@ -30,9 +30,10 @@ static void caMonitorCallbackShim(struct event_handler_args args) {
|
||||
|
||||
double timeSecs = 0.0;
|
||||
int severity = 0;
|
||||
int status = 0;
|
||||
|
||||
/*
|
||||
* Determine the timestamp and alarm severity from the DBR type.
|
||||
* Determine the timestamp and alarm severity/status from the DBR type.
|
||||
* We request DBR_TIME_* types so the timestamp is embedded in the value
|
||||
* buffer right after the alarm fields (struct dbr_time_double et al.).
|
||||
*/
|
||||
@@ -41,36 +42,42 @@ static void caMonitorCallbackShim(struct event_handler_args args) {
|
||||
const struct dbr_time_double *p = (const struct dbr_time_double *)args.dbr;
|
||||
timeSecs = (double)p->stamp.secPastEpoch + (double)p->stamp.nsec / 1e9;
|
||||
severity = (int)p->severity;
|
||||
status = (int)p->status;
|
||||
break;
|
||||
}
|
||||
case DBR_TIME_FLOAT: {
|
||||
const struct dbr_time_float *p = (const struct dbr_time_float *)args.dbr;
|
||||
timeSecs = (double)p->stamp.secPastEpoch + (double)p->stamp.nsec / 1e9;
|
||||
severity = (int)p->severity;
|
||||
status = (int)p->status;
|
||||
break;
|
||||
}
|
||||
case DBR_TIME_LONG: {
|
||||
const struct dbr_time_long *p = (const struct dbr_time_long *)args.dbr;
|
||||
timeSecs = (double)p->stamp.secPastEpoch + (double)p->stamp.nsec / 1e9;
|
||||
severity = (int)p->severity;
|
||||
status = (int)p->status;
|
||||
break;
|
||||
}
|
||||
case DBR_TIME_SHORT: {
|
||||
const struct dbr_time_short *p = (const struct dbr_time_short *)args.dbr;
|
||||
timeSecs = (double)p->stamp.secPastEpoch + (double)p->stamp.nsec / 1e9;
|
||||
severity = (int)p->severity;
|
||||
status = (int)p->status;
|
||||
break;
|
||||
}
|
||||
case DBR_TIME_STRING: {
|
||||
const struct dbr_time_string *p = (const struct dbr_time_string *)args.dbr;
|
||||
timeSecs = (double)p->stamp.secPastEpoch + (double)p->stamp.nsec / 1e9;
|
||||
severity = (int)p->severity;
|
||||
status = (int)p->status;
|
||||
break;
|
||||
}
|
||||
case DBR_TIME_ENUM: {
|
||||
const struct dbr_time_enum *p = (const struct dbr_time_enum *)args.dbr;
|
||||
timeSecs = (double)p->stamp.secPastEpoch + (double)p->stamp.nsec / 1e9;
|
||||
severity = (int)p->severity;
|
||||
status = (int)p->status;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -78,7 +85,7 @@ static void caMonitorCallbackShim(struct event_handler_args args) {
|
||||
}
|
||||
|
||||
goCAMonitorCallback((uintptr_t)args.usr, (int)args.type, (long)args.count,
|
||||
(void *)args.dbr, severity, timeSecs);
|
||||
(void *)args.dbr, severity, status, timeSecs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -275,6 +275,8 @@ func (e *EPICS) timeValueToDS(signal string, tv proto.TimeValue) datasource.Valu
|
||||
Timestamp: tv.Timestamp,
|
||||
Data: data,
|
||||
Quality: quality,
|
||||
Severity: int(tv.Severity),
|
||||
Status: int(tv.Status),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ type Value struct {
|
||||
Timestamp time.Time
|
||||
Data any // float64 | []float64 | string | int64 | bool
|
||||
Quality Quality
|
||||
Severity int // raw EPICS alarm severity (0=NO_ALARM,1=MINOR,2=MAJOR,3=INVALID); 0 for sources without alarm info
|
||||
Status int // raw EPICS alarm status (.STAT); 0 for sources without alarm info
|
||||
MetaUpdate bool // if true, metadata was refreshed — dispatcher should re-send meta
|
||||
}
|
||||
|
||||
|
||||
@@ -180,6 +180,7 @@ func structToValue(sv pvdata.StructValue) datasource.Value {
|
||||
val := fieldByName(sv, "value")
|
||||
ts := extractTimestamp(sv)
|
||||
quality := extractQuality(sv)
|
||||
severity, status := extractSeverityStatus(sv)
|
||||
|
||||
var data any
|
||||
if val != nil {
|
||||
@@ -190,6 +191,8 @@ func structToValue(sv pvdata.StructValue) datasource.Value {
|
||||
Timestamp: ts,
|
||||
Data: data,
|
||||
Quality: quality,
|
||||
Severity: severity,
|
||||
Status: status,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +332,26 @@ func extractQuality(sv pvdata.StructValue) datasource.Quality {
|
||||
}
|
||||
}
|
||||
|
||||
// extractSeverityStatus pulls the raw EPICS alarm severity and status from the
|
||||
// NTScalar "alarm" struct. Returns (0, 0) when no alarm struct is present.
|
||||
func extractSeverityStatus(sv pvdata.StructValue) (severity, status int) {
|
||||
alarm := structByName(sv, "alarm")
|
||||
if alarm == nil {
|
||||
return 0, 0
|
||||
}
|
||||
if v := fieldByName(*alarm, "severity"); v != nil {
|
||||
if s, ok := v.(int32); ok {
|
||||
severity = int(s)
|
||||
}
|
||||
}
|
||||
if v := fieldByName(*alarm, "status"); v != nil {
|
||||
if s, ok := v.(int32); ok {
|
||||
status = int(s)
|
||||
}
|
||||
}
|
||||
return severity, status
|
||||
}
|
||||
|
||||
func toFloat64(v any) (float64, bool) {
|
||||
switch x := v.(type) {
|
||||
case float64:
|
||||
|
||||
Reference in New Issue
Block a user