diff --git a/hrp/internal/version/VERSION b/hrp/internal/version/VERSION index f091f785..df1b5b93 100644 --- a/hrp/internal/version/VERSION +++ b/hrp/internal/version/VERSION @@ -1 +1 @@ -v4.3.4-beta-2306071815 \ No newline at end of file +v4.3.4-beta-2306212230 \ No newline at end of file diff --git a/hrp/pkg/gadb/device.go b/hrp/pkg/gadb/device.go index 2245c5af..8a953e0b 100644 --- a/hrp/pkg/gadb/device.go +++ b/hrp/pkg/gadb/device.go @@ -264,9 +264,6 @@ func (d *Device) RunShellCommandWithBytes(cmd string, args ...string) ([]byte, e if strings.TrimSpace(cmd) == "" { return nil, errors.New("adb shell: command cannot be empty") } - log.Debug().Str("cmd", - fmt.Sprintf("adb -s %s shell %s", d.serial, cmd)). - Msg("run adb command") raw, err := d.executeCommand(fmt.Sprintf("shell:%s", cmd)) return raw, err } @@ -284,9 +281,7 @@ func (d *Device) RunShellCommandV2WithBytes(cmd string, args ...string) ([]byte, if strings.TrimSpace(cmd) == "" { return nil, errors.New("adb shell: command cannot be empty") } - log.Debug().Str("cmd", - fmt.Sprintf("adb -s %s shell %s", d.serial, cmd)). - Msg("run adb command in v2") + raw, err := d.executeCommand(fmt.Sprintf("shell,v2,raw:%s", cmd)) if err != nil { return raw, err @@ -355,9 +350,6 @@ func (d *Device) EnableAdbOverTCP(port ...int) (err error) { port = []int{AdbDaemonPort} } - log.Info().Str("cmd", - fmt.Sprintf("adb -s %s tcpip %d", d.serial, port[0])). - Msg("enable adb over tcp") _, err = d.executeCommand(fmt.Sprintf("tcpip:%d", port[0]), true) return } @@ -375,6 +367,31 @@ func (d *Device) createDeviceTransport() (tp transport, err error) { } func (d *Device) executeCommand(command string, onlyVerifyResponse ...bool) (raw []byte, err error) { + startTime := time.Now() + defer func() { + // log elapsed seconds for shell execution + elapsed := time.Since(startTime).Seconds() + if strings.HasPrefix(command, "shell,v2,raw:") { + cmd := strings.TrimPrefix(command, "shell,v2,raw:") + log.Debug().Str("cmd", + fmt.Sprintf("adb -s %s shell %s", d.serial, cmd)). + Float64("elapsed(s)", elapsed). + Msg("run adb shell in v2") + } else if strings.HasPrefix(command, "shell:") { + cmd := strings.TrimPrefix(command, "shell:") + log.Debug().Str("cmd", + fmt.Sprintf("adb -s %s shell %s", d.serial, cmd)). + Float64("elapsed(s)", elapsed). + Msg("run adb shell") + } else { + cmd := strings.ReplaceAll(command, ":", " ") + log.Debug().Str("command", + fmt.Sprintf("adb -s %s %s", d.serial, cmd)). + Float64("elapsed(s)", elapsed). + Msg("run adb command") + } + }() + if len(onlyVerifyResponse) == 0 { onlyVerifyResponse = []bool{false} } diff --git a/hrp/pkg/uixt/action.go b/hrp/pkg/uixt/action.go index 025432e8..ee12b7a9 100644 --- a/hrp/pkg/uixt/action.go +++ b/hrp/pkg/uixt/action.go @@ -3,6 +3,7 @@ package uixt import ( "encoding/json" "fmt" + "math" "math/rand" "time" @@ -499,7 +500,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) error { return fmt.Errorf("invalid sleep params: %v(%T)", action.Params, action.Params) case ACTION_SleepRandom: if params, ok := action.Params.([]interface{}); ok { - return sleepRandom(params) + return sleepRandom(time.Now(), params) } return fmt.Errorf("invalid sleep random params: %v(%T)", action.Params, action.Params) case ACTION_ScreenShot: @@ -541,7 +542,9 @@ func convertToFloat64(val interface{}) (float64, error) { } } -func sleepRandom(params []interface{}) error { +// sleepRandom sleeps random time with given params +// startTime is used to correct sleep duration caused by process time +func sleepRandom(startTime time.Time, params []interface{}) error { if len(params) == 1 { // constant sleep time params = append(params, params[0], 1.0) @@ -583,10 +586,20 @@ func sleepRandom(params []interface{}) error { for _, s := range sections { accProb += s.weight / totalProb if r < accProb { - n := s.min + rand.Float64()*(s.max-s.min) - log.Info().Float64("duration", n). - Interface("strategy_params", params).Msg("sleep random seconds") - time.Sleep(time.Duration(n*1000) * time.Millisecond) + elapsed := time.Since(startTime).Seconds() + randomSeconds := s.min + rand.Float64()*(s.max-s.min) + dur := randomSeconds - elapsed + + // if elapsed time is greater than random seconds, skip sleep to reduce deviation caused by process time + if dur <= 0 { + log.Info().Float64("elapsed", elapsed).Float64("randomSeconds", randomSeconds). + Interface("strategy_params", params).Msg("elapsed duration >= random seconds, skip sleep") + } else { + log.Info().Float64("sleepDuration", dur).Float64("elapsed", elapsed).Float64("randomSeconds", randomSeconds). + Interface("strategy_params", params).Msg("sleep remaining random seconds") + time.Sleep(time.Duration(math.Ceil(dur*1000)) * time.Millisecond) + } + return nil } } diff --git a/hrp/pkg/uixt/action_test.go b/hrp/pkg/uixt/action_test.go index aba7dcc5..911c3e13 100644 --- a/hrp/pkg/uixt/action_test.go +++ b/hrp/pkg/uixt/action_test.go @@ -16,20 +16,31 @@ func checkErr(t *testing.T, err error, msg ...string) { } func TestSleepRandom(t *testing.T) { - startTime := time.Now() + startTime1 := time.Now() params := []interface{}{1} - err := sleepRandom(params) + err := sleepRandom(startTime1, params) checkErr(t, err) - dur := time.Since(startTime).Seconds() - if dur < 0.9 || dur > 1.1 { + dur := time.Since(startTime1).Seconds() + t.Log(dur) + if dur < 1 || dur > 1.1 { t.Fatal("sleepRandom failed") } - startTime = time.Now() - params = []interface{}{1, 2} - err = sleepRandom(params) + params = []interface{}{0, 2} + err = sleepRandom(startTime1, params) checkErr(t, err) - dur = time.Since(startTime).Seconds() + dur = time.Since(startTime1).Seconds() + t.Log(dur) + if dur < 1 || dur > 2 { + t.Fatal("sleepRandom failed") + } + + startTime2 := time.Now() + params = []interface{}{1, 2} + err = sleepRandom(startTime2, params) + checkErr(t, err) + dur = time.Since(startTime2).Seconds() + t.Log(dur) if dur < 1 || dur > 2 { t.Fatal("sleepRandom failed") } diff --git a/hrp/pkg/uixt/ocr_vedem.go b/hrp/pkg/uixt/ocr_vedem.go index 7ff0e982..3345428e 100644 --- a/hrp/pkg/uixt/ocr_vedem.go +++ b/hrp/pkg/uixt/ocr_vedem.go @@ -193,6 +193,7 @@ func (s *veDEMImageService) GetImage(imageBuf *bytes.Buffer) ( for _, action := range s.actions { bodyWriter.WriteField("actions", action) } + bodyWriter.WriteField("ocrCluster", "highPrecision") formWriter, err := bodyWriter.CreateFormFile("image", "screenshot.png") if err != nil { @@ -200,6 +201,7 @@ func (s *veDEMImageService) GetImage(imageBuf *bytes.Buffer) ( fmt.Sprintf("create form file error: %v", err)) return } + size, err := formWriter.Write(imageBuf.Bytes()) if err != nil { err = errors.Wrap(code.OCRRequestError, diff --git a/hrp/pkg/uixt/video_crawler.go b/hrp/pkg/uixt/video_crawler.go index 04b4f68e..085bc69b 100644 --- a/hrp/pkg/uixt/video_crawler.go +++ b/hrp/pkg/uixt/video_crawler.go @@ -1,6 +1,7 @@ package uixt import ( + "strings" "time" "github.com/pkg/errors" @@ -244,7 +245,7 @@ func (l *LiveCrawler) Run(driver *DriverExt, enterPoint PointF) error { } // sleep custom random time - if err := sleepRandom(l.configs.Live.SleepRandom); err != nil { + if err := sleepRandom(time.Now(), l.configs.Live.SleepRandom); err != nil { log.Error().Err(err).Msg("sleep random failed") } @@ -352,6 +353,7 @@ func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) { // loop until target count achieved or timeout // the main loop is feed crawler currVideoStat.timer = time.NewTimer(time.Duration(configs.Timeout) * time.Second) + lastSwipeTime := time.Now() for { select { case <-currVideoStat.timer.C: @@ -364,6 +366,9 @@ func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) { // take screenshot and get screen texts by OCR imageResult, err := dExt.GetScreenResult() if err != nil { + if strings.Contains(err.Error(), "connect: connection refused") { + return err + } log.Error().Err(err).Msg("OCR GetTexts failed") time.Sleep(3 * time.Second) continue @@ -400,7 +405,7 @@ func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) { } // sleep custom random time - if err := sleepRandom(configs.Feed.SleepRandom); err != nil { + if err := sleepRandom(lastSwipeTime, configs.Feed.SleepRandom); err != nil { log.Error().Err(err).Msg("sleep random failed") } @@ -416,7 +421,7 @@ func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) { log.Error().Err(err).Msg("swipe up failed") return err } - time.Sleep(1 * time.Second) + lastSwipeTime = time.Now() // check if feed page if err := dExt.Driver.AssertForegroundApp(configs.AppPackageName, "feed"); err != nil {