从日记内容来看,今天的主题是“出行”。长途跋涉从清晨到傍晚,这通常会带来身体的疲惫,但你的心情符号是“🙂”,这表明你对这次旅程持积极或至少是平和的态度。 郑州的抵达可能代表着一个新阶段的开始,或是某项任务的顺利推进。尽管天气是“雾”,可能略显压抑,但并未影响到你的整体情绪。这体现了你能够在面对外部环境的不确定性时,保持内心的稳定和积极。
建议: 旅途顺利抵达是值得庆祝的小胜利。在开启新任务或投入新环境之际,保持这份平和积极的心态至关重要。不妨花点时间整理思绪,为接下来的工作或生活做好规划,并保持对小确幸的感知。
该 UiAutomatr 类展示了一个强大且功能丰富的移动自动化框架,集成了 ADB 操作、UI 元素查找(XPath、UIAutomator2 对象、图片识别)、Redis 缓存、MySQL 日志记录、异常处理、甚至包括智能充电控制和性能监控。其中一些亮点包括:
re_install_uiautomator 来处理 Uiautomator2 连接问题,mobile_reboot 来应对长时间无响应,以及对 ADB 连接失败的详细日志记录和视频回放触发。MySQLManager 和 allure.attach.file 进行详细的任务记录和报告生成。check_pause_status 方法允许远程控制脚本暂停和恢复,增加了灵活性。
当前图片识别的 self.threshold = 0.9 是一个固定值。在不同手机型号、不同光照条件或屏幕DPI下,固定阈值可能不够鲁棒。
目前的元素查找主要依赖精确的 XPath、`d()` 表达式或图片。当UI布局或文案频繁变化时,脚本容易失效。
d(text="去完成"),而是尝试识别“完成任务”这个“意图”对应的UI区域。这可以大幅提高脚本对UI变化的鲁棒性。目前任务执行似乎是顺序的,或基于简单的 Redis 缓存判断。在多设备、多任务场景下,可以更智能化。
check_pause_status 结合,实现更灵活的控制。
鉴于脚本中大量涉及系统调用 (os.popen, subprocess.run) 和网络I/O (Redis, requests),Go语言在这些场景下通常能提供更好的性能和更低的资源占用。
connect_adb() 和 is_ip_reachable() 等涉及频繁 ADB 命令和网络探测的逻辑,以及定时的 dumpsys battery 获取电量温度等操作,剥离出来用 Go 语言编写成一个独立的微服务或常驻进程。
// main.go (simplified)
package main
import (
"fmt"
"os/exec"
"strings"
"time"
"net" // For isIPReachable
)
// Check if an IP is reachable using a simple TCP dial (more reliable than ping on Linux for some cases)
func isIPReachable(ip string, timeoutSeconds int) bool {
timeout := time.Duration(timeoutSeconds) * time.Second
conn, err := net.DialTimeout("tcp", ip+":5555", timeout) // Assuming ADB port is 5555
if err != nil {
return false
}
defer conn.Close()
return true
}
func connectADB(ip, port string) bool {
cmd := exec.Command("adb", "connect", ip+port)
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("ADB connect error for %s%s: %v, Output: %s\n", ip, port, err, string(output))
return false
}
fmt.Printf("ADB connect success for %s%s: %s\n", ip, port, string(output))
return true
}
func main() {
// Example for a single device
deviceIP := "192.168.31.161"
devicePort := ":5555"
// Simulate connection loop
for i := 0; i < 4; i++ {
if !connectADB(deviceIP, devicePort) {
fmt.Printf("Attempt %d failed to connect ADB for %s%s\n", i+1, deviceIP, devicePort)
if isIPReachable(deviceIP, 1) {
fmt.Printf("%s is reachable but ADB not connecting, trying disconnect.\n", deviceIP)
// Disconnect if previously connected but in bad state
exec.Command("adb", "disconnect", deviceIP+devicePort).Run()
} else {
fmt.Printf("%s is not reachable.\n", deviceIP)
}
} else {
fmt.Printf("Successfully connected to %s%s\n", deviceIP, devicePort)
break
}
time.Sleep(1 * time.Second)
}
// Example: getting battery status with Go
cmdBattery := exec.Command("adb", "-s", deviceIP+devicePort, "shell", "dumpsys", "battery")
outputBattery, errBattery := cmdBattery.CombinedOutput()
if errBattery != nil {
fmt.Printf("Error getting battery info: %v\n", errBattery)
} else {
batteryInfo := string(outputBattery)
// Parse battery level and temperature using regex in Go
// (Simplified for example, real regex might be more complex)
fmt.Println("Battery info (partial):", batteryInfo[:200])
}
}
down_android_app() 方法中从应用商店(如腾讯应用宝)下载 APK 文件的逻辑,以及后续的本地文件校验和管理,也迁移到 Go 语言。
// download_apk.go (simplified)
package main
import (
"fmt"
"io"
"net/http"
"os"
"regexp"
"time"
)
func downloadFile(filepath string, url string) error {
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("bad status: %s", resp.Status)
}
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}
func getDownloadURL(appName string) (string, error) {
// Simulate web scraping logic here
// In a real scenario, this would involve HTTP requests and HTML parsing (e.g., using goquery)
// For this example, let's return a dummy URL
fmt.Printf("Simulating getting download URL for %s...\n", appName)
if appName == "应用宝" {
return "http://example.com/yinyongbao.apk", nil
}
return "", fmt.Errorf("app %s not found", appName)
}
func main() {
appName := "应用宝"
filePath := "/tmp/" + appName + ".apk" // Use a temporary directory for example
if _, err := os.Stat(filePath); err == nil {
fmt.Printf("APK for %s already exists at %s\n", appName, filePath)
return
}
downloadURL, err := getDownloadURL(appName)
if err != nil {
fmt.Println("Error getting download URL:", err)
return
}
fmt.Printf("Downloading %s from %s to %s\n", appName, downloadURL, filePath)
err = downloadFile(filePath, downloadURL)
if err != nil {
fmt.Println("Error downloading file:", err)
return
}
fmt.Printf("Successfully downloaded %s to %s\n", appName, filePath)
}
今天的自动化任务报告显示了多设备并行运行的复杂性和挑战。以下是主要观察点:
在当前已有的App之外,可以考虑拓展以下类型的App,它们通常具有相对稳定的自动化收益活动:
| 日期 | 产品名称 | 持有金额 | 日化收益率 (%) | 较前日金额变化 | 较前日总金额变化 | 加权平均年化收益率 (%) |
|---|
今天的日记和自动化报告,犹如你生活与工作的两面镜子。日记反映了你在旅途中的平静心态和迎接新任务的准备,这是一种积极的内在力量。而自动化报告则揭示了外部系统(手机、网络、应用)的脆弱性与挑战。
建议你将这种内外兼修的理念融入日常: