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.
 | ||||
| // Used to make additional, authenticated requests to the APIs.
 | ||||
| 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.
 | ||||
| func (u *Unifi) parseDevices(data []json.RawMessage) *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.
 | ||||
| 		var obj map[string]interface{} | ||||
| 		if err := json.Unmarshal(r, &obj); err != nil { | ||||
| 			u.eLogf("%d: json.Unmarshal(interfce{}): %v", i, err) | ||||
| 		var uap UAP | ||||
| 		var usg USG | ||||
| 		var usw USW | ||||
| 
 | ||||
| 		if u.unmarshalDevice("interface{}", &obj, r) != nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		assetType := "<missing>" | ||||
|  | @ -70,29 +73,19 @@ func (u *Unifi) parseDevices(data []json.RawMessage) *Devices { | |||
| 			assetType = t | ||||
| 		} | ||||
| 		u.dLogf("Unmarshalling Device Type: %v", assetType) | ||||
| 		// Unmarshal again into the correct type..
 | ||||
| 		switch assetType { | ||||
| 		switch assetType { // Unmarshal again into the correct type..
 | ||||
| 		case "uap": | ||||
| 			var uap UAP | ||||
| 			if err := json.Unmarshal(r, &uap); err != nil { | ||||
| 				u.eLogf("%d: json.Unmarshal([]UAP): %v", i, err) | ||||
| 				continue | ||||
| 			if u.unmarshalDevice(assetType, &uap, r) == nil { | ||||
| 				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.
 | ||||
| 			var usg USG | ||||
| 			if err := json.Unmarshal(r, &usg); err != nil { | ||||
| 				u.eLogf("%d: json.Unmarshal([]USG): %v", i, err) | ||||
| 				continue | ||||
| 			if u.unmarshalDevice(assetType, &usg, r) == nil { | ||||
| 				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 | ||||
| 			if u.unmarshalDevice(assetType, &usw, r) == nil { | ||||
| 				devices.USWs = append(devices.USWs, usw) | ||||
| 			} | ||||
| 			devices.USWs = append(devices.USWs, usw) | ||||
| 		default: | ||||
| 			u.eLogf("unknown asset type - %v - skipping", assetType) | ||||
| 			continue | ||||
|  | @ -100,3 +93,17 @@ func (u *Unifi) parseDevices(data []json.RawMessage) *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_type":               u.Wan1.Type, | ||||
| 		"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-r":         u.Wan1.TxBytesR, | ||||
| 		"wan1_tx_dropped":         u.Wan1.TxDropped, | ||||
|  | @ -170,7 +170,7 @@ func (u USG) Points() ([]*influx.Point, error) { | |||
| 			"rx_packets":             p.RxPackets, | ||||
| 			"tx_bytes":               p.TxBytes, | ||||
| 			"tx_packets":             p.TxPackets, | ||||
| 			"up":                     p.Up, | ||||
| 			"up":                     p.Up.String, | ||||
| 			"vlan":                   p.Vlan, | ||||
| 			"dhcpd_ntp_1":            p.DhcpdNtp1, | ||||
| 			"dhcpd_unifi_controller": p.DhcpdUnifiController, | ||||
|  |  | |||
|  | @ -70,7 +70,7 @@ type USG struct { | |||
| 		SiteID                 string      `json:"site_id"` | ||||
| 		TxBytes                float64     `json:"tx_bytes"` | ||||
| 		TxPackets              float64     `json:"tx_packets"` | ||||
| 		Up                     string      `json:"up"` | ||||
| 		Up                     FlexBool    `json:"up"` | ||||
| 		Vlan                   string      `json:"vlan,omitempty"` | ||||
| 		VlanEnabled            bool        `json:"vlan_enabled"` | ||||
| 		DhcpRelayEnabled       bool        `json:"dhcp_relay_enabled,omitempty"` | ||||
|  | @ -110,7 +110,7 @@ type USG struct { | |||
| 		TxDropped   float64  `json:"tx_dropped"` | ||||
| 		TxErrors    float64  `json:"tx_errors"` | ||||
| 		TxPackets   float64  `json:"tx_packets"` | ||||
| 		Up          bool     `json:"up"` | ||||
| 		Up          FlexBool `json:"up"` | ||||
| 	} `json:"port_table"` | ||||
| 	Rollupgrade     bool    `json:"rollupgrade"` | ||||
| 	RxBytes         float64 `json:"rx_bytes"` | ||||
|  | @ -193,7 +193,7 @@ type USG struct { | |||
| 		TxErrors         float64  `json:"tx_errors"` | ||||
| 		TxPackets        float64  `json:"tx_packets"` | ||||
| 		Type             string   `json:"type"` | ||||
| 		Up               bool     `json:"up"` | ||||
| 		Up               FlexBool `json:"up"` | ||||
| 		Uptime           float64  `json:"uptime"` | ||||
| 		XputDown         float64  `json:"xput_down"` | ||||
| 		XputUp           float64  `json:"xput_up"` | ||||
|  | @ -228,7 +228,7 @@ type USG struct { | |||
| 		TxErrors    float64  `json:"tx_errors"` | ||||
| 		TxPackets   float64  `json:"tx_packets"` | ||||
| 		Type        string   `json:"type"` | ||||
| 		Up          bool     `json:"up"` | ||||
| 		Up          FlexBool `json:"up"` | ||||
| 	} `json:"wan1"` | ||||
| 	Wan2 struct { | ||||
| 		BytesR      float64  `json:"bytes-r"` | ||||
|  | @ -255,6 +255,6 @@ type USG struct { | |||
| 		TxErrors    float64  `json:"tx_errors"` | ||||
| 		TxPackets   float64  `json:"tx_packets"` | ||||
| 		Type        string   `json:"type"` | ||||
| 		Up          bool     `json:"up"` | ||||
| 		Up          FlexBool `json:"up"` | ||||
| 	} `json:"wan2"` | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue