Add FlexBool type and output failed payloads in debug mode.
This commit is contained in:
		
							parent
							
								
									2af45c05ee
								
							
						
					
					
						commit
						bd77a2f808
					
				|  | @ -75,6 +75,23 @@ func (f *FlexInt) UnmarshalJSON(b []byte) error { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // FlexBool provides a container and unmarshalling for fields that may be
 | ||||||
|  | // boolean or strings in the Unifi API
 | ||||||
|  | type FlexBool struct { | ||||||
|  | 	Bool   bool | ||||||
|  | 	String string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // UnmarshalJSO method converts armed/disarmed, yes/no, active/inactive or 0/1 to true/false.
 | ||||||
|  | // Really it converts ready, up, t, armed, yes, active, enabled, 1, true to true. Anything else is false.
 | ||||||
|  | func (f *FlexBool) UnmarshalJSON(b []byte) error { | ||||||
|  | 	f.String = strings.Trim(string(b), `"`) | ||||||
|  | 	f.Bool = f.String == "1" || strings.EqualFold(f.String, "true") || strings.EqualFold(f.String, "yes") || | ||||||
|  | 		strings.EqualFold(f.String, "t") || strings.EqualFold(f.String, "armed") || strings.EqualFold(f.String, "active") || | ||||||
|  | 		strings.EqualFold(f.String, "enabled") || strings.EqualFold(f.String, "ready") || strings.EqualFold(f.String, "up") | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // GetController creates a http.Client with authenticated cookies.
 | // GetController creates a http.Client with authenticated cookies.
 | ||||||
| // Used to make additional, authenticated requests to the APIs.
 | // Used to make additional, authenticated requests to the APIs.
 | ||||||
| func GetController(user, pass, url string, verifySSL bool) (*Unifi, error) { | func GetController(user, pass, url string, verifySSL bool) (*Unifi, error) { | ||||||
|  |  | ||||||
|  | @ -58,11 +58,14 @@ func (u *Unifi) GetDevices() (*Devices, error) { | ||||||
| // parseDevices parses the raw JSON from the Unifi Controller into device structures.
 | // parseDevices parses the raw JSON from the Unifi Controller into device structures.
 | ||||||
| func (u *Unifi) parseDevices(data []json.RawMessage) *Devices { | func (u *Unifi) parseDevices(data []json.RawMessage) *Devices { | ||||||
| 	devices := new(Devices) | 	devices := new(Devices) | ||||||
| 	for i, r := range data { | 	for _, r := range data { | ||||||
| 		// Loop each item in the raw JSON message, detect its type and unmarshal it.
 | 		// Loop each item in the raw JSON message, detect its type and unmarshal it.
 | ||||||
| 		var obj map[string]interface{} | 		var obj map[string]interface{} | ||||||
| 		if err := json.Unmarshal(r, &obj); err != nil { | 		var uap UAP | ||||||
| 			u.eLogf("%d: json.Unmarshal(interfce{}): %v", i, err) | 		var usg USG | ||||||
|  | 		var usw USW | ||||||
|  | 
 | ||||||
|  | 		if u.unmarshalDevice("interface{}", &obj, r) != nil { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		assetType := "<missing>" | 		assetType := "<missing>" | ||||||
|  | @ -70,29 +73,19 @@ func (u *Unifi) parseDevices(data []json.RawMessage) *Devices { | ||||||
| 			assetType = t | 			assetType = t | ||||||
| 		} | 		} | ||||||
| 		u.dLogf("Unmarshalling Device Type: %v", assetType) | 		u.dLogf("Unmarshalling Device Type: %v", assetType) | ||||||
| 		// Unmarshal again into the correct type..
 | 		switch assetType { // Unmarshal again into the correct type..
 | ||||||
| 		switch assetType { |  | ||||||
| 		case "uap": | 		case "uap": | ||||||
| 			var uap UAP | 			if u.unmarshalDevice(assetType, &uap, r) == nil { | ||||||
| 			if err := json.Unmarshal(r, &uap); err != nil { |  | ||||||
| 				u.eLogf("%d: json.Unmarshal([]UAP): %v", i, err) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 				devices.UAPs = append(devices.UAPs, uap) | 				devices.UAPs = append(devices.UAPs, uap) | ||||||
|  | 			} | ||||||
| 		case "ugw", "usg": // in case they ever fix the name in the api.
 | 		case "ugw", "usg": // in case they ever fix the name in the api.
 | ||||||
| 			var usg USG | 			if u.unmarshalDevice(assetType, &usg, r) == nil { | ||||||
| 			if err := json.Unmarshal(r, &usg); err != nil { |  | ||||||
| 				u.eLogf("%d: json.Unmarshal([]USG): %v", i, err) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 				devices.USGs = append(devices.USGs, usg) | 				devices.USGs = append(devices.USGs, usg) | ||||||
| 		case "usw": |  | ||||||
| 			var usw USW |  | ||||||
| 			if err := json.Unmarshal(r, &usw); err != nil { |  | ||||||
| 				u.eLogf("%d: json.Unmarshal([]USW): %v", i, err) |  | ||||||
| 				continue |  | ||||||
| 			} | 			} | ||||||
|  | 		case "usw": | ||||||
|  | 			if u.unmarshalDevice(assetType, &usw, r) == nil { | ||||||
| 				devices.USWs = append(devices.USWs, usw) | 				devices.USWs = append(devices.USWs, usw) | ||||||
|  | 			} | ||||||
| 		default: | 		default: | ||||||
| 			u.eLogf("unknown asset type - %v - skipping", assetType) | 			u.eLogf("unknown asset type - %v - skipping", assetType) | ||||||
| 			continue | 			continue | ||||||
|  | @ -100,3 +93,17 @@ func (u *Unifi) parseDevices(data []json.RawMessage) *Devices { | ||||||
| 	} | 	} | ||||||
| 	return devices | 	return devices | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // unmarshalDevice handles logging for the unmarshal operations in parseDevices().
 | ||||||
|  | func (u *Unifi) unmarshalDevice(device string, ptr interface{}, payload json.RawMessage) error { | ||||||
|  | 	err := json.Unmarshal(payload, ptr) | ||||||
|  | 	if err != nil { | ||||||
|  | 		u.eLogf("json.Unmarshal(%v): %v", device, err) | ||||||
|  | 		u.eLogf("Enable Debug Logging to output the failed payload.") | ||||||
|  | 		json, err := payload.MarshalJSON() | ||||||
|  | 		u.dLogf("Failed Payload: %s (marshal err: %v)", json, err) | ||||||
|  | 		u.dLogf("The above payload can prove useful during torubleshooting when you open an Issue:") | ||||||
|  | 		u.dLogf("==- https://github.com/golift/unifi/issues/new -==") | ||||||
|  | 	} | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -92,7 +92,7 @@ func (u USG) Points() ([]*influx.Point, error) { | ||||||
| 		"wan1_rx_packets":         u.Wan1.RxPackets, | 		"wan1_rx_packets":         u.Wan1.RxPackets, | ||||||
| 		"wan1_type":               u.Wan1.Type, | 		"wan1_type":               u.Wan1.Type, | ||||||
| 		"wan1_speed":              u.Wan1.Speed, | 		"wan1_speed":              u.Wan1.Speed, | ||||||
| 		"wan1_up":                 u.Wan1.Up, | 		"wan1_up":                 u.Wan1.Up.Bool, | ||||||
| 		"wan1_tx_bytes":           u.Wan1.TxBytes, | 		"wan1_tx_bytes":           u.Wan1.TxBytes, | ||||||
| 		"wan1_tx_bytes-r":         u.Wan1.TxBytesR, | 		"wan1_tx_bytes-r":         u.Wan1.TxBytesR, | ||||||
| 		"wan1_tx_dropped":         u.Wan1.TxDropped, | 		"wan1_tx_dropped":         u.Wan1.TxDropped, | ||||||
|  | @ -170,7 +170,7 @@ func (u USG) Points() ([]*influx.Point, error) { | ||||||
| 			"rx_packets":             p.RxPackets, | 			"rx_packets":             p.RxPackets, | ||||||
| 			"tx_bytes":               p.TxBytes, | 			"tx_bytes":               p.TxBytes, | ||||||
| 			"tx_packets":             p.TxPackets, | 			"tx_packets":             p.TxPackets, | ||||||
| 			"up":                     p.Up, | 			"up":                     p.Up.String, | ||||||
| 			"vlan":                   p.Vlan, | 			"vlan":                   p.Vlan, | ||||||
| 			"dhcpd_ntp_1":            p.DhcpdNtp1, | 			"dhcpd_ntp_1":            p.DhcpdNtp1, | ||||||
| 			"dhcpd_unifi_controller": p.DhcpdUnifiController, | 			"dhcpd_unifi_controller": p.DhcpdUnifiController, | ||||||
|  |  | ||||||
|  | @ -70,7 +70,7 @@ type USG struct { | ||||||
| 		SiteID                 string      `json:"site_id"` | 		SiteID                 string      `json:"site_id"` | ||||||
| 		TxBytes                float64     `json:"tx_bytes"` | 		TxBytes                float64     `json:"tx_bytes"` | ||||||
| 		TxPackets              float64     `json:"tx_packets"` | 		TxPackets              float64     `json:"tx_packets"` | ||||||
| 		Up                     string      `json:"up"` | 		Up                     FlexBool    `json:"up"` | ||||||
| 		Vlan                   string      `json:"vlan,omitempty"` | 		Vlan                   string      `json:"vlan,omitempty"` | ||||||
| 		VlanEnabled            bool        `json:"vlan_enabled"` | 		VlanEnabled            bool        `json:"vlan_enabled"` | ||||||
| 		DhcpRelayEnabled       bool        `json:"dhcp_relay_enabled,omitempty"` | 		DhcpRelayEnabled       bool        `json:"dhcp_relay_enabled,omitempty"` | ||||||
|  | @ -110,7 +110,7 @@ type USG struct { | ||||||
| 		TxDropped   float64  `json:"tx_dropped"` | 		TxDropped   float64  `json:"tx_dropped"` | ||||||
| 		TxErrors    float64  `json:"tx_errors"` | 		TxErrors    float64  `json:"tx_errors"` | ||||||
| 		TxPackets   float64  `json:"tx_packets"` | 		TxPackets   float64  `json:"tx_packets"` | ||||||
| 		Up          bool     `json:"up"` | 		Up          FlexBool `json:"up"` | ||||||
| 	} `json:"port_table"` | 	} `json:"port_table"` | ||||||
| 	Rollupgrade     bool    `json:"rollupgrade"` | 	Rollupgrade     bool    `json:"rollupgrade"` | ||||||
| 	RxBytes         float64 `json:"rx_bytes"` | 	RxBytes         float64 `json:"rx_bytes"` | ||||||
|  | @ -193,7 +193,7 @@ type USG struct { | ||||||
| 		TxErrors         float64  `json:"tx_errors"` | 		TxErrors         float64  `json:"tx_errors"` | ||||||
| 		TxPackets        float64  `json:"tx_packets"` | 		TxPackets        float64  `json:"tx_packets"` | ||||||
| 		Type             string   `json:"type"` | 		Type             string   `json:"type"` | ||||||
| 		Up               bool     `json:"up"` | 		Up               FlexBool `json:"up"` | ||||||
| 		Uptime           float64  `json:"uptime"` | 		Uptime           float64  `json:"uptime"` | ||||||
| 		XputDown         float64  `json:"xput_down"` | 		XputDown         float64  `json:"xput_down"` | ||||||
| 		XputUp           float64  `json:"xput_up"` | 		XputUp           float64  `json:"xput_up"` | ||||||
|  | @ -228,7 +228,7 @@ type USG struct { | ||||||
| 		TxErrors    float64  `json:"tx_errors"` | 		TxErrors    float64  `json:"tx_errors"` | ||||||
| 		TxPackets   float64  `json:"tx_packets"` | 		TxPackets   float64  `json:"tx_packets"` | ||||||
| 		Type        string   `json:"type"` | 		Type        string   `json:"type"` | ||||||
| 		Up          bool     `json:"up"` | 		Up          FlexBool `json:"up"` | ||||||
| 	} `json:"wan1"` | 	} `json:"wan1"` | ||||||
| 	Wan2 struct { | 	Wan2 struct { | ||||||
| 		BytesR      float64  `json:"bytes-r"` | 		BytesR      float64  `json:"bytes-r"` | ||||||
|  | @ -255,6 +255,6 @@ type USG struct { | ||||||
| 		TxErrors    float64  `json:"tx_errors"` | 		TxErrors    float64  `json:"tx_errors"` | ||||||
| 		TxPackets   float64  `json:"tx_packets"` | 		TxPackets   float64  `json:"tx_packets"` | ||||||
| 		Type        string   `json:"type"` | 		Type        string   `json:"type"` | ||||||
| 		Up          bool     `json:"up"` | 		Up          FlexBool `json:"up"` | ||||||
| 	} `json:"wan2"` | 	} `json:"wan2"` | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue