package main import ( "encoding/json" "fmt" "git.aiterp.net/lucifer/new-server/models" "io" "sort" "strings" "time" ) func WriteDeviceInfo(w io.Writer, devices []models.Device, fields []string) { if len(fields) == 1 && fields[0] == "all" { fields = allFields } else { fields = append(fields[:0:0], fields...) for i, field := range fields { if aliased, ok := fieldAliases[field]; ok { fields[i] = aliased } } } length := 0 for _, field := range fields { if mlFields[field] { continue } if len(field) > length { length = len(field) } } for i, device := range devices { if i > 0 { fmt.Println() } for _, field := range fields { if formatter, ok := fieldFormatters[field]; ok { _, _ = fmt.Fprintf(w, "%-*s %s\n", length+1, field+":", formatter(&device)) } else { _, _ = fmt.Fprintf(w, "%-*s (unknown field)\n", length+1, field+":") } } } } var allFields = []string{ "id", "name", "icon", "bridgeId", "tags", "buttonNames", "power", "color", "intensity", "temperature", "internalId", "sceneAssignment", "userProperties", "driverProperties", } var mlFields = map[string]bool{ "sceneAssignment": true, "userProperties": true, "driverProperties": true, } var fieldFormatters = map[string]func(d *models.Device) string{ "id": func(d *models.Device) string { return fmt.Sprint(d.ID) }, "internalId": func(d *models.Device) string { return d.InternalID }, "name": func(d *models.Device) string { return d.Name }, "icon": func(d *models.Device) string { return d.Icon }, "bridgeId": func(d *models.Device) string { return fmt.Sprint(d.BridgeID) }, "tags": func(d *models.Device) string { return strings.Join(d.Tags, ", ") }, "buttonNames": func(d *models.Device) string { return strings.Join(d.ButtonNames, ", ") }, "power": func(d *models.Device) string { return fmt.Sprint(d.State.Power) }, "color": func(d *models.Device) string { return d.State.Color.String() }, "intensity": func(d *models.Device) string { return fmt.Sprint(d.State.Intensity) }, "temperature": func(d *models.Device) string { return fmt.Sprint(d.State.Temperature) }, "sceneAssignment": func(d *models.Device) string { str := &strings.Builder{} str.Grow(64) for _, scene := range d.SceneAssignments { _, _ = fmt.Fprintf(str, "\n - id: %d\n", scene.SceneID) _, _ = fmt.Fprintf(str, " duration: %d\n", scene.DurationMS) _, _ = fmt.Fprintf(str, " group: %s\n", scene.Group) _, _ = fmt.Fprintf(str, " startTime: %s", scene.StartTime.Format(time.RFC3339)) } if len(d.SceneAssignments) == 0 { str.Reset() str.WriteString("(none)") } return str.String() }, "userProperties": func(d *models.Device) string { str := &strings.Builder{} str.Grow(64) str.WriteString("\n") keys := make([]string, 0, len(d.UserProperties)) for key := range d.UserProperties { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { _, _ = fmt.Fprintf(str, " %s: %s\n", key, d.UserProperties[key]) } if len(d.UserProperties) == 0 { str.Reset() str.WriteString("(none)") } return str.String() }, "driverProperties": func(d *models.Device) string { str := &strings.Builder{} str.Grow(256) str.WriteString("\n") keys := make([]string, 0, len(d.DriverProperties)) for key := range d.DriverProperties { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { j, _ := json.Marshal(d.DriverProperties[key]) _, _ = fmt.Fprintf(str, " %s: %s\n", key, string(j)) } if len(d.DriverProperties) == 0 { str.Reset() str.WriteString("(none)") } return str.String() }, "capabilities": func(d *models.Device) string { capStr := make([]string, len(d.Capabilities)) for i := range d.Capabilities { capStr[i] = string(d.Capabilities[i]) } return strings.Join(capStr, ", ") }, } var fieldAliases = map[string]string{ "bridge": "bridgeId", "buttons": "buttonNames", "internal": "internalId", "caps": "capabilities", "cap": "capabilities", "userprops": "userProperties", "uprops": "userProperties", "driverprops": "driverProperties", "dprops": "driverProperties", "internalid": "internalId", "bridgeid": "bridgeId", "buttonnames": "buttonNames", "scene": "sceneAssignment", }