chore(deps): bump github.com/unpoller/unifi/v6 to v6.3.1

v6.3.1 reports U-LTE state as a string and cellular SNR as FlexFloat.
Keep exporting those readings with the new types.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Cody Lee
2026-10-07 09:40:34 -05:00
co-authored by Cursor
parent ed58dc7f3f
commit 7714a4bfaa
10 changed files with 63 additions and 46 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ require (
github.com/prometheus/common v0.72.0
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.12.1
github.com/unpoller/unifi/v6 v6.3.0
github.com/unpoller/unifi/v6 v6.3.1
go.opentelemetry.io/otel v1.46.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.46.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.46.0
+2 -2
View File
@@ -121,8 +121,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
github.com/unpoller/unifi/v6 v6.3.0 h1:J7etDpdkarEG9sOiSORtzZB93RDyzXu9KqZ4cWoBYcQ=
github.com/unpoller/unifi/v6 v6.3.0/go.mod h1:fJ1lU/mpKrQ8Jv3b2yq399ATlrUuiOZAMbKWcw/1GaU=
github.com/unpoller/unifi/v6 v6.3.1 h1:gUBOYmSl/kmTAlSVfTEaDYqGU6iao5biMDeuQcCZmLE=
github.com/unpoller/unifi/v6 v6.3.1/go.mod h1:fJ1lU/mpKrQ8Jv3b2yq399ATlrUuiOZAMbKWcw/1GaU=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
+2 -2
View File
@@ -146,7 +146,7 @@ func (u *DatadogUnifi) batchLTE(r report, s *unifi.UAP) {
"name": s.Name,
"model": s.Model,
"type": s.Type,
"state": s.LteState.Txt,
"state": s.LteState,
"failover_mode": s.LteFailoverMode,
"signal": s.LteSignal,
"rat": s.LteRat,
@@ -171,7 +171,7 @@ func (u *DatadogUnifi) batchLTE(r report, s *unifi.UAP) {
// hasLTEStatus reports whether this access point is a cellular backup module.
// U-LTE and U-LTE-Pro are typed as UAPs; their live modem status arrives as lte_* fields.
func hasLTEStatus(d *unifi.UAP) bool {
return d.LteState.Txt != "" || d.LteFailoverMode != "" || d.LteRat != "" ||
return d.LteState != "" || d.LteFailoverMode != "" || d.LteRat != "" ||
d.LteNetworkOperator != "" || d.LteSignal != "" || d.LteConnected.Txt != ""
}
+10 -2
View File
@@ -105,10 +105,8 @@ func mbbOptional(rad unifi.MBBRadio) map[string]float64 {
for k, v := range map[string]unifi.FlexInt{
"rsrp": rad.Rsrp,
"rsrq": rad.Rsrq,
"snr": rad.Snr,
"nr_rsrp": rad.RsrpNr,
"nr_rsrq": rad.RsrqNr,
"nr_snr": rad.SnrNr,
"signal": rad.Signal,
"signal_percent": rad.SignalPercent,
"lte_max_bitrate_dl": rad.MaxBitrateDl,
@@ -121,6 +119,16 @@ func mbbOptional(rad unifi.MBBRadio) map[string]float64 {
}
}
// SNR is a fractional dB reading, so the library decodes it as FlexFloat.
for k, v := range map[string]unifi.FlexFloat{
"snr": rad.Snr,
"nr_snr": rad.SnrNr,
} {
if v.Txt != "" {
out[k] = v.Val
}
}
return out
}
+2 -2
View File
@@ -142,7 +142,7 @@ func (u *InfluxUnifi) batchLTE(r report, s *unifi.UAP) {
"name": s.Name,
"model": s.Model,
"type": s.Type,
"state": s.LteState.Txt,
"state": s.LteState,
"failover_mode": s.LteFailoverMode,
"signal": s.LteSignal,
"rat": s.LteRat,
@@ -166,7 +166,7 @@ func (u *InfluxUnifi) batchLTE(r report, s *unifi.UAP) {
// hasLTEStatus reports whether this access point is a cellular backup module.
// U-LTE and U-LTE-Pro are typed as UAPs; their live modem status arrives as lte_* fields.
func hasLTEStatus(d *unifi.UAP) bool {
return d.LteState.Txt != "" || d.LteFailoverMode != "" || d.LteRat != "" ||
return d.LteState != "" || d.LteFailoverMode != "" || d.LteRat != "" ||
d.LteNetworkOperator != "" || d.LteSignal != "" || d.LteConnected.Txt != ""
}
+10 -2
View File
@@ -114,10 +114,8 @@ func mbbOptional(rad unifi.MBBRadio) map[string]float64 {
for k, v := range map[string]unifi.FlexInt{
"rsrp": rad.Rsrp,
"rsrq": rad.Rsrq,
"snr": rad.Snr,
"nr_rsrp": rad.RsrpNr,
"nr_rsrq": rad.RsrqNr,
"nr_snr": rad.SnrNr,
"signal": rad.Signal,
"signal_percent": rad.SignalPercent,
"lte_max_bitrate_dl": rad.MaxBitrateDl,
@@ -130,6 +128,16 @@ func mbbOptional(rad unifi.MBBRadio) map[string]float64 {
}
}
// SNR is a fractional dB reading, so the library decodes it as FlexFloat.
for k, v := range map[string]unifi.FlexFloat{
"snr": rad.Snr,
"nr_snr": rad.SnrNr,
} {
if v.Txt != "" {
out[k] = v.Val
}
}
return out
}
+2 -2
View File
@@ -91,7 +91,7 @@ func (u *OtelOutput) exportUAP(ctx context.Context, meter metric.Meter, r *Repor
// hasLTEStatus reports whether this access point is a cellular backup module.
// U-LTE and U-LTE-Pro are typed as UAPs; their live modem status arrives as lte_* fields.
func hasLTEStatus(d *unifi.UAP) bool {
return d.LteState.Txt != "" || d.LteFailoverMode != "" || d.LteRat != "" ||
return d.LteState != "" || d.LteFailoverMode != "" || d.LteRat != "" ||
d.LteNetworkOperator != "" || d.LteSignal != "" || d.LteConnected.Txt != ""
}
@@ -108,7 +108,7 @@ func (u *OtelOutput) exportLTE(ctx context.Context, meter metric.Meter, r *Repor
attribute.String("name", s.Name),
attribute.String("model", s.Model),
attribute.String("type", s.Type),
attribute.String("lte_state", s.LteState.Txt),
attribute.String("lte_state", s.LteState),
attribute.String("lte_failover_mode", s.LteFailoverMode),
attribute.String("lte_signal", s.LteSignal),
attribute.String("lte_rat", s.LteRat),
+16 -16
View File
@@ -53,24 +53,24 @@ func (u *OtelOutput) exportUMBB(ctx context.Context, meter metric.Meter, r *Repo
// Signal readings and bitrates are left out when the modem does not report them,
// so a missing reading is not mistaken for 0 dBm.
for _, g := range []struct {
name, desc string
val unifi.FlexInt
name, desc, txt string
val float64
}{
{"unifi_device_umbb_rsrp_dbm", "Cellular RSRP of the serving cell in dBm. LTE anchor in 5G NSA mode", rad.Rsrp},
{"unifi_device_umbb_rsrq_db", "Cellular RSRQ of the serving cell in dB. LTE anchor in 5G NSA mode", rad.Rsrq},
{"unifi_device_umbb_snr_db", "Cellular signal-to-noise ratio of the serving cell in dB. LTE anchor in 5G NSA mode", rad.Snr},
{"unifi_device_umbb_nr_rsrp_dbm", "5G NR RSRP in dBm", rad.RsrpNr},
{"unifi_device_umbb_nr_rsrq_db", "5G NR RSRQ in dB", rad.RsrqNr},
{"unifi_device_umbb_nr_snr_db", "5G NR signal-to-noise ratio in dB", rad.SnrNr},
{"unifi_device_umbb_signal_bars", "Cellular signal strength in bars, as shown by the controller", rad.Signal},
{"unifi_device_umbb_signal_percent", "Cellular signal strength percentage (0-100)", rad.SignalPercent},
{"unifi_device_umbb_lte_max_bitrate_dl_bps", "Maximum LTE downlink bitrate in bits per second", rad.MaxBitrateDl},
{"unifi_device_umbb_lte_max_bitrate_ul_bps", "Maximum LTE uplink bitrate in bits per second", rad.MaxBitrateUl},
{"unifi_device_umbb_nr_max_bitrate_dl_bps", "Maximum 5G NR downlink bitrate in bits per second", rad.MaxBitrateDlNr},
{"unifi_device_umbb_nr_max_bitrate_ul_bps", "Maximum 5G NR uplink bitrate in bits per second", rad.MaxBitrateUlNr},
{"unifi_device_umbb_rsrp_dbm", "Cellular RSRP of the serving cell in dBm. LTE anchor in 5G NSA mode", rad.Rsrp.Txt, rad.Rsrp.Val},
{"unifi_device_umbb_rsrq_db", "Cellular RSRQ of the serving cell in dB. LTE anchor in 5G NSA mode", rad.Rsrq.Txt, rad.Rsrq.Val},
{"unifi_device_umbb_snr_db", "Cellular signal-to-noise ratio of the serving cell in dB. LTE anchor in 5G NSA mode", rad.Snr.Txt, rad.Snr.Val},
{"unifi_device_umbb_nr_rsrp_dbm", "5G NR RSRP in dBm", rad.RsrpNr.Txt, rad.RsrpNr.Val},
{"unifi_device_umbb_nr_rsrq_db", "5G NR RSRQ in dB", rad.RsrqNr.Txt, rad.RsrqNr.Val},
{"unifi_device_umbb_nr_snr_db", "5G NR signal-to-noise ratio in dB", rad.SnrNr.Txt, rad.SnrNr.Val},
{"unifi_device_umbb_signal_bars", "Cellular signal strength in bars, as shown by the controller", rad.Signal.Txt, rad.Signal.Val},
{"unifi_device_umbb_signal_percent", "Cellular signal strength percentage (0-100)", rad.SignalPercent.Txt, rad.SignalPercent.Val},
{"unifi_device_umbb_lte_max_bitrate_dl_bps", "Maximum LTE downlink bitrate in bits per second", rad.MaxBitrateDl.Txt, rad.MaxBitrateDl.Val},
{"unifi_device_umbb_lte_max_bitrate_ul_bps", "Maximum LTE uplink bitrate in bits per second", rad.MaxBitrateUl.Txt, rad.MaxBitrateUl.Val},
{"unifi_device_umbb_nr_max_bitrate_dl_bps", "Maximum 5G NR downlink bitrate in bits per second", rad.MaxBitrateDlNr.Txt, rad.MaxBitrateDlNr.Val},
{"unifi_device_umbb_nr_max_bitrate_ul_bps", "Maximum 5G NR uplink bitrate in bits per second", rad.MaxBitrateUlNr.Txt, rad.MaxBitrateUlNr.Val},
} {
if g.val.Txt != "" {
u.recordGauge(ctx, meter, r, g.name, g.desc, g.val.Val, attrs)
if g.txt != "" {
u.recordGauge(ctx, meter, r, g.name, g.desc, g.val, attrs)
}
}
+2 -2
View File
@@ -429,7 +429,7 @@ func (u *promUnifi) exportRADtable(r report, labels []string, rt unifi.RadioTabl
// U-LTE and U-LTE-Pro are typed as UAPs; their live modem status arrives as lte_* fields
// on the device list, not on the gateway WAN ports.
func hasLTEStatus(d *unifi.UAP) bool {
return d.LteState.Txt != "" || d.LteFailoverMode != "" || d.LteRat != "" ||
return d.LteState != "" || d.LteFailoverMode != "" || d.LteRat != "" ||
d.LteNetworkOperator != "" || d.LteSignal != "" || d.LteConnected.Txt != ""
}
@@ -439,7 +439,7 @@ func (u *promUnifi) exportLTE(r report, d *unifi.UAP, labels []string) {
}
info := append(append([]string{}, labels...),
d.LteState.Txt,
d.LteState,
d.LteFailoverMode,
d.LteSignal,
d.LteRat,
+16 -15
View File
@@ -135,24 +135,25 @@ func (u *promUnifi) exportMBB(r report, labels []string, d *unifi.UMBB) {
// so a missing reading is not mistaken for 0 dBm.
for _, s := range []struct {
desc *prometheus.Desc
val unifi.FlexInt
txt string
val float64
dims []string
}{
{u.UMBB.Rsrp, rad.Rsrp, nil},
{u.UMBB.Rsrq, rad.Rsrq, nil},
{u.UMBB.Snr, rad.Snr, nil},
{u.UMBB.RsrpNr, rad.RsrpNr, nil},
{u.UMBB.RsrqNr, rad.RsrqNr, nil},
{u.UMBB.SnrNr, rad.SnrNr, nil},
{u.UMBB.SignalBars, rad.Signal, nil},
{u.UMBB.SignalPercent, rad.SignalPercent, nil},
{u.UMBB.MaxBitrate, rad.MaxBitrateDl, []string{"lte", "dl"}},
{u.UMBB.MaxBitrate, rad.MaxBitrateUl, []string{"lte", "ul"}},
{u.UMBB.MaxBitrate, rad.MaxBitrateDlNr, []string{"nr", "dl"}},
{u.UMBB.MaxBitrate, rad.MaxBitrateUlNr, []string{"nr", "ul"}},
{u.UMBB.Rsrp, rad.Rsrp.Txt, rad.Rsrp.Val, nil},
{u.UMBB.Rsrq, rad.Rsrq.Txt, rad.Rsrq.Val, nil},
{u.UMBB.Snr, rad.Snr.Txt, rad.Snr.Val, nil},
{u.UMBB.RsrpNr, rad.RsrpNr.Txt, rad.RsrpNr.Val, nil},
{u.UMBB.RsrqNr, rad.RsrqNr.Txt, rad.RsrqNr.Val, nil},
{u.UMBB.SnrNr, rad.SnrNr.Txt, rad.SnrNr.Val, nil},
{u.UMBB.SignalBars, rad.Signal.Txt, rad.Signal.Val, nil},
{u.UMBB.SignalPercent, rad.SignalPercent.Txt, rad.SignalPercent.Val, nil},
{u.UMBB.MaxBitrate, rad.MaxBitrateDl.Txt, rad.MaxBitrateDl.Val, []string{"lte", "dl"}},
{u.UMBB.MaxBitrate, rad.MaxBitrateUl.Txt, rad.MaxBitrateUl.Val, []string{"lte", "ul"}},
{u.UMBB.MaxBitrate, rad.MaxBitrateDlNr.Txt, rad.MaxBitrateDlNr.Val, []string{"nr", "dl"}},
{u.UMBB.MaxBitrate, rad.MaxBitrateUlNr.Txt, rad.MaxBitrateUlNr.Val, []string{"nr", "ul"}},
} {
if s.val.Txt != "" {
r.send([]*metric{{s.desc, gauge, s.val.Val, append(append([]string{}, labels...), s.dims...)}})
if s.txt != "" {
r.send([]*metric{{s.desc, gauge, s.val, append(append([]string{}, labels...), s.dims...)}})
}
}