skilld-labs / telemetry-opcua-exporter

Expose OPCUA nodes to Prometheus
Apache License 2.0
11 stars 5 forks source link

Integer values reported as 0 #6

Open StefanVanDyck opened 8 months ago

StefanVanDyck commented 8 months ago

Thank you so much for writing this tool. It's been super helpful.

Unfortunately we ran into an issue where all our status code, etc. showed up as 0 on our dashboards. The issues seems to be the conversion from the opcua datatype to a float.

I managed fix my local copy by adding this simple switch statement to the GetOpcuaValueFromIndex method.

switch r.Value.Type() {
    case ua.TypeIDInt16:
        fallthrough
    case ua.TypeIDInt32:
        fallthrough
    case ua.TypeIDInt64:
        fallthrough
    case ua.TypeIDUint16:
        fallthrough
    case ua.TypeIDUint32:
        fallthrough
    case ua.TypeIDUint64:
        return float64(r.Value.Int()), nil
    }
    return r.Value.Float(), nil

I'll create a quick PR for you to look at.

StefanVanDyck commented 8 months ago

Opened a PR: https://github.com/skilld-labs/telemetry-opcua-exporter/issues/6

I am not a talented go developer by any means. But the fix seems straightforward enough.

Thanks!

dhia-gharsallaoui commented 3 months ago

Hello @StefanVanDyck :wave:

Thank you for your contribution 🙏 and sorry for the delay.

We have already changed the architecture of this software. I will do my best to update the repository ASAP. Meanwhile, here is the function we use to extract the values. You can use it until the repository is updated.


 func (m Message) Float() (float64, error) {
    v, ok := m.Value.(*ua.Variant)
    if !ok {
        return 0, errors.New("message value can't be parsed as ua.Variant")
    }
    valI := v.Value()
    var val float64

    switch v.Type() {
    case ua.TypeIDSByte:
        val = float64(valI.(int8))
    case ua.TypeIDByte:
        val = float64(valI.(uint8))
    case ua.TypeIDInt16:
        val = float64(valI.(int16))
    case ua.TypeIDUint16:
        val = float64(valI.(uint16))
    case ua.TypeIDInt32:
        val = float64(valI.(int32))
    case ua.TypeIDUint32:
        val = float64(valI.(uint32))
    case ua.TypeIDInt64:
        val = float64(valI.(int64))
    case ua.TypeIDUint64:
        val = float64(valI.(uint64))
    case ua.TypeIDFloat:
        val = float64(valI.(float32))
    case ua.TypeIDDouble:
        val = valI.(float64) //nolint:errcheck
    case ua.TypeIDBoolean:
        if valI.(bool) {
            val = 1
        }
    default:
        return 0, errors.New("not a numeric type")
    }
    return val, nil
}