diff --git a/hrp/cmd/ios/devices.go b/hrp/cmd/ios/devices.go new file mode 100644 index 00000000..8286d6ef --- /dev/null +++ b/hrp/cmd/ios/devices.go @@ -0,0 +1,134 @@ +package ios + +import ( + "encoding/json" + "fmt" + "os" + "strings" + + giDevice "github.com/electricbubble/gidevice" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +func wrapError(err error, msg string) error { + if strings.HasSuffix(err.Error(), "InvalidService") { + msg += ", check if Developer Disk Image mounted" + } + return errors.Wrap(err, msg) +} + +type DeviceList []Device + +type Device struct { + d giDevice.Device + UDID string `json:"UDID"` + Status string `json:"status"` + ConnectionType string `json:"connectionType"` + ConnectionSpeed int `json:"connectionSpeed"` + DeviceDetail *DeviceDetail `json:"deviceDetail,omitempty"` +} + +type DeviceDetail struct { + DeviceName string `json:"deviceName,omitempty"` + DeviceClass string `json:"deviceClass,omitempty"` + ProductVersion string `json:"productVersion,omitempty"` + ProductType string `json:"productType,omitempty"` + ProductName string `json:"productName,omitempty"` + PasswordProtected bool `json:"passwordProtected,omitempty"` + ModelNumber string `json:"modelNumber,omitempty"` + SerialNumber string `json:"serialNumber,omitempty"` + SIMStatus string `json:"simStatus,omitempty"` + PhoneNumber string `json:"phoneNumber,omitempty"` + CPUArchitecture string `json:"cpuArchitecture,omitempty"` + ProtocolVersion string `json:"protocolVersion,omitempty"` + RegionInfo string `json:"regionInfo,omitempty"` + TimeZone string `json:"timeZone,omitempty"` + UniqueDeviceID string `json:"uniqueDeviceID,omitempty"` + WiFiAddress string `json:"wifiAddress,omitempty"` + BuildVersion string `json:"buildVersion,omitempty"` +} + +func (device *Device) GetDetail() (*DeviceDetail, error) { + value, err := device.d.GetValue("", "") + if err != nil { + return nil, errors.Wrap(err, "get device detail failed") + } + detailByte, _ := json.Marshal(value) + detail := &DeviceDetail{} + json.Unmarshal(detailByte, detail) + return detail, nil +} + +func (device *Device) GetStatus() string { + if device.ConnectionType != "" { + return "online" + } else { + return "offline" + } +} + +func (device *Device) ToFormat() string { + result, _ := json.MarshalIndent(device, "", "\t") + return string(result) +} + +var listIOSDevicesCmd = &cobra.Command{ + Use: "devices", + Short: "List all iOS devices", + RunE: func(cmd *cobra.Command, args []string) error { + usbmux, err := giDevice.NewUsbmux() + if err != nil { + return wrapError(err, "create usbmux failed") + } + + devices, err := usbmux.Devices() + if err != nil { + return wrapError(err, "list ios devices failed") + } + + var deviceList []giDevice.Device + // filter by udid + for _, d := range devices { + if udid != "" && udid != d.Properties().SerialNumber { + continue + } + deviceList = append(deviceList, d) + } + if udid != "" && len(deviceList) == 0 { + fmt.Printf("no device found for udid: %s\n", udid) + os.Exit(1) + } + + for _, d := range deviceList { + deviceByte, _ := json.Marshal(d.Properties()) + device := &Device{ + d: d, + } + json.Unmarshal(deviceByte, device) + device.Status = device.GetStatus() + + if isDetail { + device.DeviceDetail, err = device.GetDetail() + if err != nil { + return err + } + fmt.Println(device.ToFormat()) + } else { + fmt.Println(device.UDID, device.ConnectionType, device.Status) + } + } + return nil + }, +} + +var ( + udid string + isDetail bool +) + +func init() { + listIOSDevicesCmd.Flags().StringVarP(&udid, "udid", "u", "", "filter by device's udid") + listIOSDevicesCmd.Flags().BoolVarP(&isDetail, "detail", "d", false, "print device's detail") + iosRootCmd.AddCommand(listIOSDevicesCmd) +} diff --git a/hrp/cmd/ios/init.go b/hrp/cmd/ios/init.go new file mode 100644 index 00000000..a4110b64 --- /dev/null +++ b/hrp/cmd/ios/init.go @@ -0,0 +1,13 @@ +package ios + +import "github.com/spf13/cobra" + +var iosRootCmd = &cobra.Command{ + Use: "ios", + Short: "simple utils for ios device management", + PersistentPreRun: func(cmd *cobra.Command, args []string) {}, +} + +func Init(rootCmd *cobra.Command) { + rootCmd.AddCommand(iosRootCmd) +} diff --git a/hrp/cmd/root.go b/hrp/cmd/root.go index 4ecb63f8..17ca8ba2 100644 --- a/hrp/cmd/root.go +++ b/hrp/cmd/root.go @@ -9,6 +9,7 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" + "github.com/httprunner/httprunner/v4/hrp/cmd/ios" "github.com/httprunner/httprunner/v4/hrp/internal/version" ) @@ -59,6 +60,7 @@ func Execute() { rootCmd.PersistentFlags().BoolVar(&logJSON, "log-json", false, "set log to json format") rootCmd.PersistentFlags().StringVar(&venv, "venv", "", "specify python3 venv path") + ios.Init(rootCmd) if err := rootCmd.Execute(); err != nil { os.Exit(1) }