From f7a4ac60506d27affe197fa650916ba00ddb38cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E6=B3=93=E9=93=AE?= Date: Thu, 17 Jul 2025 14:46:50 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uixt/ai/wings_service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uixt/ai/wings_service.go b/uixt/ai/wings_service.go index 9c0615ee..4b4ddde9 100644 --- a/uixt/ai/wings_service.go +++ b/uixt/ai/wings_service.go @@ -419,7 +419,7 @@ func (w *WingsService) callWingsAPI(ctx context.Context, request WingsActionRequ // Execute HTTP request client := &http.Client{ - Timeout: 30 * time.Second, + Timeout: 60 * time.Second, } resp, err := client.Do(httpReq) From c3fba110869bd7e02fef2171dcb1364ec6946607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E6=B3=93=E9=93=AE?= Date: Thu, 17 Jul 2025 14:47:33 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E8=AE=BF?= =?UTF-8?q?=E9=97=AEwings=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uixt/ai/wings_service.go | 1 + 1 file changed, 1 insertion(+) diff --git a/uixt/ai/wings_service.go b/uixt/ai/wings_service.go index 4b4ddde9..5dea7484 100644 --- a/uixt/ai/wings_service.go +++ b/uixt/ai/wings_service.go @@ -160,6 +160,7 @@ func (w *WingsService) Assert(ctx context.Context, opts *AssertOptions) (*Assert LogID: generateWingsUUID(), }, } + log.Info().Interface("apiRequest", apiRequest).Msg("Wings API request") // Call Wings API startTime := time.Now() From d4dff22dd833251a534d4ef9dc8111ddf1ed2356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E6=B3=93=E9=93=AE?= Date: Thu, 17 Jul 2025 16:49:26 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=88=AA=E5=9B=BE?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uixt/driver_session.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/uixt/driver_session.go b/uixt/driver_session.go index 66b83962..43bc1491 100644 --- a/uixt/driver_session.go +++ b/uixt/driver_session.go @@ -308,6 +308,9 @@ func (s *DriverSession) Request(method string, urlStr string, rawBody []byte, op } if err = rawResp.CheckErr(); err != nil { + if resp.StatusCode == http.StatusOK { + return rawResp, nil + } return nil, err } From 984edf3f3c456630201700b8e62ac4a4b0829e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E6=B3=93=E9=93=AE?= Date: Fri, 18 Jul 2025 12:12:10 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96ios=20forward?= =?UTF-8?q?=E9=93=BE=E8=B7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uixt/ios_device.go | 54 ++++++++++++++++++++++++++++++++---------- uixt/ios_driver_wda.go | 35 +++++++-------------------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/uixt/ios_device.go b/uixt/ios_device.go index fbd712df..484eec18 100644 --- a/uixt/ios_device.go +++ b/uixt/ios_device.go @@ -106,7 +106,10 @@ func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error) device = &IOSDevice{ DeviceEntry: *iosDevice, Options: deviceOptions, - listeners: make(map[int]*forward.ConnListener), + listeners: make(map[int]struct { + listener *forward.ConnListener + localPort int + }), } log.Info().Str("udid", device.Options.UDID).Msg("init ios device") @@ -119,8 +122,12 @@ func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error) type IOSDevice struct { ios.DeviceEntry - Options *option.IOSDeviceOptions - listeners map[int]*forward.ConnListener + Options *option.IOSDeviceOptions + // 键为remotePort,值为对应的listener和localPort + listeners map[int]struct { + listener *forward.ConnListener + localPort int + } } type DeviceDetail struct { @@ -197,8 +204,10 @@ func (dev *IOSDevice) IsHealthy() (bool, error) { } func (dev *IOSDevice) Teardown() error { - for _, listener := range dev.listeners { - _ = listener.Close() + for _, forwardInfo := range dev.listeners { + if forwardInfo.listener != nil { + _ = forwardInfo.listener.Close() + } } return nil } @@ -287,18 +296,37 @@ func (dev *IOSDevice) Uninstall(bundleId string) error { return nil } -func (dev *IOSDevice) Forward(localPort, remotePort int) error { - if dev.listeners[localPort] != nil { - log.Warn().Msg(fmt.Sprintf("local port :%d is already in use", localPort)) - _ = dev.listeners[localPort].Close() +func (dev *IOSDevice) Forward(remotePort int) (int, error) { + // 检查remotePort是否已经被转发 + if forwardInfo, exists := dev.listeners[remotePort]; exists && forwardInfo.listener != nil { + log.Info().Msg(fmt.Sprintf("remote port :%d is already forwarded to local port :%d", remotePort, forwardInfo.localPort)) + return forwardInfo.localPort, nil } + + // 获取一个空闲的本地端口 + localPort, err := builtin.GetFreePort() + if err != nil { + log.Error().Err(err).Msg("failed to get free port") + return 0, err + } + listener, err := forward.Forward(dev.DeviceEntry, uint16(localPort), uint16(remotePort)) if err != nil { - log.Error().Err(err).Msg(fmt.Sprintf("failed to forward %d to %d", localPort, remotePort)) - return err + log.Error().Err(err).Msg(fmt.Sprintf("failed to forward local port :%d to remote port :%d", localPort, remotePort)) + return 0, err } - dev.listeners[localPort] = listener - return nil + + // 保存转发信息,以remotePort为键 + dev.listeners[remotePort] = struct { + listener *forward.ConnListener + localPort int + }{ + listener: listener, + localPort: localPort, + } + + log.Info().Msg(fmt.Sprintf("forwarded local port :%d to remote port :%d", localPort, remotePort)) + return localPort, nil } func (dev *IOSDevice) GetDeviceInfo() (*DeviceDetail, error) { diff --git a/uixt/ios_driver_wda.go b/uixt/ios_driver_wda.go index 724b1357..2358c3bc 100644 --- a/uixt/ios_driver_wda.go +++ b/uixt/ios_driver_wda.go @@ -13,7 +13,6 @@ import ( "os/exec" "path" "path/filepath" - "strconv" "strings" "syscall" "time" @@ -60,40 +59,22 @@ type WDADriver struct { } func (wd *WDADriver) getLocalPort() (int, error) { - localPort, err := strconv.Atoi(os.Getenv("WDA_LOCAL_PORT")) + localPort, err := wd.Device.Forward(wd.Device.Options.WDAPort) if err != nil { - localPort, err = builtin.GetFreePort() - if err != nil { - return 0, errors.Wrap(code.DeviceHTTPDriverError, - fmt.Sprintf("get free port failed: %v", err)) - } - // forward local port to device - if err = wd.Device.Forward(localPort, wd.Device.Options.WDAPort); err != nil { - return 0, errors.Wrap(code.DeviceHTTPDriverError, - fmt.Sprintf("forward tcp port failed: %v", err)) - } - } else { - log.Info().Int("WDA_LOCAL_PORT", localPort).Msg("reuse WDA local port") + return 0, errors.Wrap(code.DeviceHTTPDriverError, + fmt.Sprintf("forward tcp port failed: %v", err)) } return localPort, nil } func (wd *WDADriver) getMjpegLocalPort() (int, error) { - localMjpegPort, err := strconv.Atoi(os.Getenv("WDA_LOCAL_MJPEG_PORT")) + localMjpegPort, err := wd.Device.Forward(wd.Device.Options.WDAMjpegPort) if err != nil { - localMjpegPort, err = builtin.GetFreePort() - if err != nil { - return 0, errors.Wrap(code.DeviceHTTPDriverError, - fmt.Sprintf("get free port failed: %v", err)) - } - if err = wd.Device.Forward(localMjpegPort, wd.Device.Options.WDAMjpegPort); err != nil { - return 0, errors.Wrap(code.DeviceHTTPDriverError, - fmt.Sprintf("forward tcp port failed: %v", err)) - } - } else { - log.Info().Int("WDA_LOCAL_MJPEG_PORT", localMjpegPort). - Msg("reuse WDA local mjpeg port") + return 0, errors.Wrap(code.DeviceHTTPDriverError, + fmt.Sprintf("forward tcp port failed: %v", err)) } + log.Info().Int("WDA_LOCAL_MJPEG_PORT", localMjpegPort). + Msg("reuse WDA local mjpeg port") return localMjpegPort, nil }