commit a4e596c3aa635f436fe66364112f6cc21db16ba4 Author: 1 <1431729805@qq.com> Date: Thu Aug 13 14:35:17 2026 +0800 Initial commit diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4da40f7 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.sourceDirectory": "E:/car/dev_ws/src/orbbec_camera" +} \ No newline at end of file diff --git a/MobaXterm_25.2_CN.zip b/MobaXterm_25.2_CN.zip new file mode 100644 index 0000000..a361a59 Binary files /dev/null and b/MobaXterm_25.2_CN.zip differ diff --git a/MobaXterm_25.2_CN/CygUtils.plugin b/MobaXterm_25.2_CN/CygUtils.plugin new file mode 100644 index 0000000..13674c9 Binary files /dev/null and b/MobaXterm_25.2_CN/CygUtils.plugin differ diff --git a/MobaXterm_25.2_CN/CygUtils64.plugin b/MobaXterm_25.2_CN/CygUtils64.plugin new file mode 100644 index 0000000..e110f5b Binary files /dev/null and b/MobaXterm_25.2_CN/CygUtils64.plugin differ diff --git a/MobaXterm_25.2_CN/MobaXterm.ini b/MobaXterm_25.2_CN/MobaXterm.ini new file mode 100644 index 0000000..2566793 --- /dev/null +++ b/MobaXterm_25.2_CN/MobaXterm.ini @@ -0,0 +1,406 @@ +[Misc] +PasswordsInRegistry=0 +LocalShell=Bash (32位) +NewTabPosition=1 +SingleClickToRunMacros=0 +LastSession= 10.217.155.242 (root)| #109#0% 10.217.155.242%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +SessionP=330918199908 +StorePasswords=Never +RightClickAction=1 +RightClickAssigned=1 +DefTextEditor= +LogFileFormat= +StoreSSHKeysPassphrases=0 +BackupIni=1 +LogTerminalActivity=0 +LogType=0 +LogFolder= +SkinSat=36 +XAuto=1 +XKeepAlive=1 +BackspaceSendsBS=1 +BSisBS=1 +BoldAsFont=0 +WinPath=1 +ConfirmExit=0 +PromptType=2 +WarnBeforePasteMultipleLines=0 +TransTerm=0 +TransDetachedTabs=0 +X11SharedClipboard2=1 +X11OpenGL=0 +X11DisplayMode=0 +X11AccessControl2=0 +X11DisplayOffset=0 +X11ScreenNumber=1 +X11Keyboard=0 +X11DpiMode=拉伸 +X11Version=MobaX +AdvTermSettings= +HomeDir= +SlashDir= +DefaultHome=<主页 (固定)> +DefaultNewTab=<终端> +ReplaceHomeTab=0 +NoTabClose=0 +AllowMultiInstances=0 + +[Passwords] +mobauser@mobaserver= + +[Macros_1] +SubRep=originbot +ImgNum=41 + +[Macros_2] +SubRep=origincar +ImgNum=41 + +[Macros_3] +SubRep=originman +ImgNum=41 +动作模仿节点=em:/_@5TIVp5QfuyIpgNPtzlPpVeImCJSXe/2nXjanYTInmY42K3T56GtMZTteDNctq5tO7bGnyKUXtEygnM66MHbEoadj6keHw+TPKMUHVfJhXLa1frsWZ/RtRgnze8gb1RqyR+ofz2fcYWyHOEbRsqajXK3vvrehiT/SGkpcM17ZPvEaTqhhdcMFmN4hFvGHP61W+oSx3H4JWkq9qjDv1tshkA3TAT6h6ZrGgbYRTXRcRcWAu79mewS5Xyc8TVCEWckAZ/aHNUYq5fvUP2Q0YN7M2AQeuN4BWspec= +视觉巡线=em:/_@tv64pFTv7TbUCHwqz6X26YAZedCuYFITsV3MLPT2fXG5bu5KXv8lWe/fPcCPTx6Gnn9ABCxCZOVcCVu4Ux4E9E198sU8Hw/OlJ8ST3RLchxw4Cf8gms2QEeRe3bpGVCbk8yBsBYSxDdBIY2CM= +网页=em:/_@eVPtVTf1MxvhBA711KOfN8Gfrt13vBL7kzsQQqo5DzO6deIrYViQMswPNsgQAoJ6snnm2kCBxsWcbYS+5Ybu03xJhbbW2Op002bIGSOzKxwWMnWIBb71qkWl7HYqhBG5lhNmiUFgEoxcoVW5S8Hb8NMPQ6bVgw +语音交互=em:/_@WP5zmHEzp3nIFvGhtBTNceYxdeYVdrdzOzR2jg+19kvBb1QmXNGMaeN3mo+yISeCIdSUNyqPy6W88WOyMflLZtc9Ob4V2juA+c0M3gUtscUZ0x6qFnIYQmHs08gGCt+svgEo0d4AmuBZ/jejx+41brGRWnqtTsN7i7 +语音交互(运动)=em:/_@PKl435owHAgtJgPMj1ttDrb8d5aw3Me7Zk4olkD6HuP3UTDM8A6wRe3t2Ki+yrTvQUadGimEh92CDEY2sPg2sbXGuCOj/G3OkAffF3MfVsmLjjSD6jIu8cjRcPtn+YmbDtC1hONi2dGbdQQs9zz/9EMMVmLM1LfyKL + +[WindowPos_HUANG_3200_2000] +CompactMode=0 +MonitorCount=1 +Left=-13 +Top=-13 +Width=3226 +Height=1930 +Maximized=1 +SidebarVisible=1 +SidebarWidth=437 + +[SSH] +SFTPShowDotFiles=1 +SFTPAsciiMode=0 +MonitorHost=1 +MonitorCPU=1 +MonitorRAM=1 +MonitorNetUp=1 +MonitorNetDown=1 +MonitorProcesses=0 +MonitoFDs=0 +MonitorUptime=1 +MonitorUsers=1 +MonitorPartitions=1 +MonitorNfsPartitions=0 +MonitorNetstat=0 +StrictHostKeyChecking=0 +BrowserSortType=0 +BrowserSortReverse=0 +RemoteMonitoring=1 +LastDownDir_31554@HUANG=C:\Users\31554\Desktop +UseInternalMobAgent=0 +UseExternalPageant=1 +ValidateEachAgentRequest=0 +MobAgentKeys= +DisplaySSHBanner=1 +UseNewMoTTY=1 +GwUse2factor=0 +AutoStartSSHGUI=1 +SSHKeepAlive2=0 +EnableSFTP=1 +ScpPreservesDates=0 +UseGSSAPI=1 +KrbDomain= +GSSAPICustomLib= +GSSAPILibNumber=0 +DefaultLoginName= + +[Display] +SidebarRight=0 +C10Checked=1 +C11Checked=1 +C12Checked=1 +C13Checked=0 +C14Checked=0 +VisibleTabNum=1 +VisibleTabClose=1 +MenuAndButtons=2 +BtnType2=2 +S3Checked=0 +DisableQuickConnect=0 +CustomDPI_3200_192=0 +IconsTheme=0 +RoundedTabs=1 +GraphicCache=1 + +[Recently started] +16=用户会话\COM5 (Silicon Labs CP210x USB to UART Bridge (COM5)) (3) +15=用户会话\COM5 (Silicon Labs CP210x USB to UART Bridge (COM5)) (4) +14=用户会话\COM5 (Silicon Labs CP210x USB to UART Bridge (COM5)) +13=用户会话\COM14 (USB-SERIAL CH340 (COM14)) +12=用户会话\COM5 (Silicon Labs CP210x USB to UART Bridge (COM5)) (5) +11=用户会话\COM14 (USB-SERIAL CH340 (COM14)) (2) +10=用户会话\ubuntu.lan +9=用户会话\COM14 (USB-SERIAL CH340 (COM14)) (1) +8=用户会话\192.168.0.3 (root) +7=用户会话\192.168.127.10 (root) +6=用户会话\COM6 (USB-SERIAL CH340 (COM6)) +5=用户会话\192.168.0.105 (root) +4=用户会话\10.162.10.242 (root) +3=用户会话\COM8 (USB-SERIAL CH340 (COM8)) +2=用户会话\COM7 (USB-SERIAL CH340 (COM7)) +1=用户会话\ 10.217.155.242 (root) + +[CustomIcons] +-3=iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAKx0lEQVR42s1aCViU1Rp+ZweGnWGTMlDKXCuNrOtFLQmsvHVLQVFIkFRQECwEzQx9DMubJuGCpqRZRkAuCOPgrZTAzADJbiAg1i2UfRcYtpn57/ePo3fYBxzN8zyH/2z/Od97zjvfec/54TAMA72H7GwzpKdvAsMsoNwV8PlBWL++QN/DnDp1Chy9A7h4cTTS0nZTyp0iR1PaCguLYCxc+BUkkvb7F8CZM48gK+sLSj2pZfytUAdr67UICDgIkUh5/wHIzR0NqTSRUlMGaNVGcT7WrZNCKFTdPwCys0dBJttHqVl9zHxvEBJJCObPP3KndNIfgE2bXqW/SRT5Or5RB0vLNVi58hC4XOavA9DaCojFgErFwfbtUZDLI6nUQMe3b9IpPFxGfSjuPYDz551w6dIEeHmlExW6UFFhhqSkCDQ2siB4OoOwsQmlPg7Dyqrj3gHIyHBGZuYJ8vNWMDVdidWrj6nLm5oMERMTQqktQwBRDzOzMISFfX5vAOTlOSM19QClZmhKGojHnli16nsyRIG2NgHi4t5Fc/NbVGeo80rw+T4ICUmjCem8ewAyM0U4e/Y4pWb38DaNRIVgokISUYGlkzkSE4NoRcZo2rlRHDFI782wtfUk73SaNj39A8gkQya3tMB4+/ZQym6lKOzRpAZGRkuwZk2aOieXC6BU8tQADh60QkNDDKXnDjDEaUycOD958tUOT8eIdr0CyLsG59Rf8A75l8+XO1ZesDv5ZSRRJIKqRD2aNpBHeZE8y4VenaSmjiH6ySjl1KOGpUwKM3qUT+bzgom5NelxYq7pR97OG46bCa077hhARgmcv7+CA2AwnbKVJiZYPc+iVDby5OEVNMMbe4EQi9cRgA96dVReboj9+z+hlE+Pmq/g4vLW6cfLzQvqzx3SyJAmG9HIyFccww6ZCCw7hw3g/O9w+rYQqdRkvFZxNc8QSyKndckEW7eEUZ41VqAFwIsAJPcBwAAHDuwlz7VYq/Q7jB37ctoz1SOvNOWeo7yVVl2LAKLFIRP2HRsWgIulcE77FXto5t36kAfXiE4BbziU/eggS2TpFHkbhEh0DEuWLKIfdXce19cLcOTIWnpuoBw76HGMGeOX+SxnQm6NjF2ZJ/ryTqZ8yfK5TuFJFiK7Dp0BnL2ChzNLcIiGeWYAbVNFdArzsr4ufSA5fhnlozV0kpMn8ifpfJTkQnfVWVlpgc8+i0B7+yiizZvSSX8YFzdmf6kxvr9x6q1FD66d5xRx0JBvohgUQPYfcJTlI4WSk3RwBNW0Er7vzFR+w3t/yxqSFJs13ok0BhYhKipF3UomE8DDo4v2C3WW2bKFm75Y8khhw3n2x26myz7BVXHnr5q4P43L4TH9Asj5E6NO5SOOZv55HVTlrVDKNUDgYtvSH0Z+8/UajXdiQYQSgFh1i127NhO4i/D2TqUzgbK+s4yfUhob3tBe9d5QZIeFwG7lK46hCZYi+/ZeAM4QbbJKkEDGTx6C8bf3AKJTiLd9RZp9wicsnd6nGKEFYA+qqwVwc1uB6dO71HK0vczs8NUNaxio3h7CeHVWwhGRC52jDgq4ItVtALmlGC39FV+S8U/dgaiuZOkU6SLPMIiLDUNHRx0BOKiuiY/3UQn5yd/OUjkV1GQIVkyIKxDxjNQHmriikGB6jGNBtCmavehpTpE7wDhylk5B43fLvjt9Vsn56b+MmawAiWS8+zBmvme4JjHAopVjrp1HYaEp3N0bbu8nVQkP59WcZgWbs5nQJuifI0NPWBk4dN2qVzIKTlZV8qQrTdlbW7oaPAajk0T4wIqmPKMEzqZUJoZItEoPxqsDj4sC93GY+pSj+od8O2zP94ujAZZpZve6h0OA73gL14ye7yf8Hu1cIS/J72OX7xE4xYWZZdGcjalMJeVs9Xgv0fj0KDztMQ7F2oUf5ftdpsfYW5uUh8Mbi8Zb/P1kXx3s+NU/m+EwLoOM016YeT2JBUA6Da76sp5muXTaSDwxaxLp/O4AZBoVqwapAXCqrz6oLetepw4yVBMBOMR5L4UZr+DiJ1YE6MF+xlAAn5CZSDAUodsGs+fnpW7tgq6jlDSlqBLzTP+19NEdb2v7dTakX9vveLnph6LBKEQvZVzOvB6o9kKxZ+DXIMe2HlpkqKHZyhibg6f9EYO2tLmQ13XBLuqoukYRYV/fvqg+ufTT4FZVEysAjdlNUM5tnxPsvDHfXGjbVg45p7Qi+8ELtSd3qzjMnIFtR9EUicdrrXlmRWoAtS0wSMqFT00LYodwitIOKgcLrPd8NHevWac0kPKsNoqCvWYfqNkVDVVH/nXBxJQT5cf8O9HO7hMmrEywEN446WTyRMlPTI2FoP6Gq+Zeid+v8Rxkutp6LneRvFTcbSPrUID3QTpepGTiEEEwpBBCI1zzD4haTqwlh7hOI+xCtQDsgaJuHjjCwDbLgJS9hRG+DA+7tGir1HinwTxhvqudl+eTkheKONS0l5ToVIK7Pwv+tCJbdaTTDVtTRAdOvfoR6o+wrnijZmbRB4AgSpVRDKgWe3x/ouyr4BZl4ybKG+kySRR/mSzx8J5p5100oJhj6ZSQA+/6VuweZCUYezOs8xqbs8+881QwTUi4ljCroEO6H6zX//um5Nu1HMq6WI1GqgbP5M1ywWPHk68d8VFyVdu0QPdLmxl2C4KmWM0u1ElOq+iVzVLMGYBObKerNjxXvJfbmLieslHdbqLFUz1h+nw6bWuazlVcVES/Ts94DVXq6OGnsouUfvyfZUuITjsHmKyr02xfe3Gq9cslQzrQtHaCf/hH+Fc3q09cltreZoQ5ov0nF+7gNyWxOubdbpKYKzwMW28/wLF7x13lNqjdn0Cp5zQlLJ2WVhjOyEirSAluVjZs7EEndpJypkhmL55hu6BoWEfKulaIPr8Ar6Y27NPMEGNjirXe43I+Me9Kp+OkarXGr2vtZOJ5sAs/2nvNanloPByL9uYV2owlOq2uFLocTfgz3ptWIkZDJ9b4czPtFgZOtnK/fMe3EtEyvKZQIl7AR9Tbz16NQ92RCBpgU59anisOgG34p73KO8uFqI3fA44qoEdNLTii1xXWIaf3XA5dpuAotpGHqXnKZo77NJu5JXq5VrnRBiEdMR9xe6joNwN5IutNNmhkb+/AFX4LC995ED7Q1H3jP+MMedbXlHqsj7fKwTVaUSac8o207LjfWGvX71xtvYr1fzNXsdOB9p48StkM0KoLPNMdsPR9D3xJ883bohR7tF3aTav28gAnsFoYjQiu4bskW4sf1+njx/DuRqs+XACVPK7fFfh/YF1eluaH+RJFi4H9POdPiJ+ZTd6rWFdThgdA2SBCQ+JidFVt12iaOxaAFM/B2DUAJs+V3JvrdeUNIWp2zgGj+GKY2qnbRQhMPfwhfvryvf9CUx3jC2VTTI99Yigz/xsZ/g8CUPTXfGJS1BGdkl6HovrjoQpA9YW3ybNLYTy9ZLjD6+cjn6qVj6ptLwxRxV6iH+tCiP9WeCdD6/E7sYqDmt1+UNR/OIiKZQcrINp4Dpc2dwkAS6daA/JOi+i5s18BqKaNWyCMpxXpY0j9/6sB08lF5fsv9UOnQpjMepWML9bTDc5d+mcPpoNHmscXiho6neEh9rAHDudnGE0N0gdtegGQSqXQe+i4IkJrLntN6Kb+7MTlxMHcu1jfw+Tk5OB/a2nAbUagr2kAAAAASUVORK5CYII= + +[SSH_Hostkeys] +ssh-ed25519@22:192.168.110.161=0x4e3d7b58df136ac2c3d2abb43117263102953ba5959f9fdf8c7aace8fd421d0b,0x57f73a00e16aba771fb816ffebc2c45163a4b4cacb31981090f8ab6382befd6a +ssh-ed25519@22:114.55.66.216=0x26c8205425648231589d409720bf22614767e15fc4a1b1d3b5162d90f2d1cbce,0x335b934b87d8623ae0d8e99a24045e5c46f4d5440773da217676607a32bb0e4e +sha256-ssh-ed25519@22:114.55.66.216=9e:66:16:ba:92:a8:d2:92:52:e8:91:52:4b:fd:1d:35:ec:66:a7:63:07:f6:7c:64:23:a5:c4:ef:50:50:bc:25 +ssh-ed25519@22:192.168.110.92=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +sha256-ssh-ed25519@22:192.168.110.92=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +ssh-ed25519@22:U22.lan=0x408cfe905069023fb775576a0c99df8acc32624116015b504415004f74e80692,0x4ff137c7b5b20c6bc26bdb9b67232327e4c6e26e015092f13a8acf4cb12005d1 +ssh-ed25519@22:ubuntu.lan=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +ssh-ed25519@22:10.211.90.19=0x408cfe905069023fb775576a0c99df8acc32624116015b504415004f74e80692,0x4ff137c7b5b20c6bc26bdb9b67232327e4c6e26e015092f13a8acf4cb12005d1 +sha256-ssh-ed25519@22:10.211.90.19=20:da:00:e0:86:02:5f:93:8e:31:fb:4e:8e:af:0d:1c:71:82:1e:9c:5e:6b:6f:c7:4c:5d:e1:da:30:21:9b:c4 +ssh-ed25519@22:192.168.110.29=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +sha256-ssh-ed25519@22:192.168.110.29=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +ssh-ed25519@22:192.168.110.17=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +ssh-ed25519@22:10.211.90.241=0x58c31df98bd1d56f18db08f35fe608c829740c8812d9311f079f22ad29511cb2,0x2afb8cee07d9cd8d07e08f5d319443cc13500ac9538b1aa515ee00594e02d5b +ssh-ed25519@22:10.211.90.119=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +sha256-ssh-ed25519@22:10.211.90.119=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +ssh-ed25519@22:192.168.110.123=0x58c31df98bd1d56f18db08f35fe608c829740c8812d9311f079f22ad29511cb2,0x2afb8cee07d9cd8d07e08f5d319443cc13500ac9538b1aa515ee00594e02d5b +sha256-ssh-ed25519@22:192.168.110.123=74:0c:c7:09:48:48:ed:fa:22:5c:a3:1e:23:d9:d3:5d:0f:eb:f7:25:a6:6d:cd:12:4c:70:df:2c:47:40:62:10 +sha256-ssh-ed25519@22:10.211.90.241=74:0c:c7:09:48:48:ed:fa:22:5c:a3:1e:23:d9:d3:5d:0f:eb:f7:25:a6:6d:cd:12:4c:70:df:2c:47:40:62:10 +ssh-ed25519@22:192.168.110.126=0x58c31df98bd1d56f18db08f35fe608c829740c8812d9311f079f22ad29511cb2,0x2afb8cee07d9cd8d07e08f5d319443cc13500ac9538b1aa515ee00594e02d5b +ssh-ed25519@22:192.168.110.216=0x4fbdeb0cc708bedaad7244d9ccc03a9b5cb295f23736588e66709ddd9c4b8735,0x5ec1cdf861f8c174c9e669cf4bcd8c288d273792c4b772d85bb963292275a928 +sha256-ssh-ed25519@22:192.168.110.216=1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +ssh-ed25519@22:192.168.110.18=0x58c31df98bd1d56f18db08f35fe608c829740c8812d9311f079f22ad29511cb2,0x2afb8cee07d9cd8d07e08f5d319443cc13500ac9538b1aa515ee00594e02d5b +sha256-ssh-ed25519@22:192.168.110.18=74:0c:c7:09:48:48:ed:fa:22:5c:a3:1e:23:d9:d3:5d:0f:eb:f7:25:a6:6d:cd:12:4c:70:df:2c:47:40:62:10 +sha256-ssh-ed25519@22:192.168.110.126=74:0c:c7:09:48:48:ed:fa:22:5c:a3:1e:23:d9:d3:5d:0f:eb:f7:25:a6:6d:cd:12:4c:70:df:2c:47:40:62:10 +ssh-ed25519@22:10.218.33.190=0x4fbdeb0cc708bedaad7244d9ccc03a9b5cb295f23736588e66709ddd9c4b8735,0x5ec1cdf861f8c174c9e669cf4bcd8c288d273792c4b772d85bb963292275a928 +sha256-ssh-ed25519@22:10.218.33.190=1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +ssh-ed25519@22:192.168.110.100=0x4fbdeb0cc708bedaad7244d9ccc03a9b5cb295f23736588e66709ddd9c4b8735,0x5ec1cdf861f8c174c9e669cf4bcd8c288d273792c4b772d85bb963292275a928 +sha256-ssh-ed25519@22:192.168.110.100=1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +ssh-ed25519@22:192.168.127.10=0x4fbdeb0cc708bedaad7244d9ccc03a9b5cb295f23736588e66709ddd9c4b8735,0x5ec1cdf861f8c174c9e669cf4bcd8c288d273792c4b772d85bb963292275a928 +ssh-ed25519@22:192.168.110.222=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +sha256-ssh-ed25519@22:192.168.110.222=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +ssh-ed25519@22:192.168.110.239=0x4fbdeb0cc708bedaad7244d9ccc03a9b5cb295f23736588e66709ddd9c4b8735,0x5ec1cdf861f8c174c9e669cf4bcd8c288d273792c4b772d85bb963292275a928 +sha256-ssh-ed25519@22:192.168.110.239=1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +sha256-ssh-ed25519@22:192.168.110.161=3f:82:8e:49:a4:23:e7:71:ea:60:9d:12:f0:47:64:9a:ce:41:a6:2c:6a:4b:16:0b:6f:f5:99:3f:22:38:f8:8c +ssh-ed25519@22:10.38.94.230=0x4a2204348c64eb730543972593593d0d4abd75b42dfc32f0d4508e12bdeed7f8,0x691eb210490c331960da49a0f3ebed6a5af3126f1a2866adbd8dfca2b32b39a3 +sha256-ssh-ed25519@22:10.38.94.230=7d:a3:4a:12:57:18:63:7a:da:8e:26:e3:f3:7b:c9:92:e8:a4:1d:db:c4:0d:5e:2e:87:dc:45:b5:ca:a2:58:10 +ssh-ed25519@22:192.168.110.233=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +sha256-ssh-ed25519@22:192.168.110.233=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +ssh-ed25519@22:192.168.110.155=0x58c31df98bd1d56f18db08f35fe608c829740c8812d9311f079f22ad29511cb2,0x2afb8cee07d9cd8d07e08f5d319443cc13500ac9538b1aa515ee00594e02d5b +sha256-ssh-ed25519@22:192.168.110.155=74:0c:c7:09:48:48:ed:fa:22:5c:a3:1e:23:d9:d3:5d:0f:eb:f7:25:a6:6d:cd:12:4c:70:df:2c:47:40:62:10 +ssh-ed25519@22:10.210.165.246=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +sha256-ssh-ed25519@22:10.210.165.246=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +ssh-ed25519@22:192.168.1.10=0x6ddc8450e6c124a5e7e6356e66b39cd3b6833467cee5ddb5587b83193c568562,0x3c74aa1eec8076c6d1b28ff648d9a0205ca5b1d4397bcf0c0f64b4b601d25c3b +sha256-ssh-ed25519@22:192.168.1.10=7a:c1:74:6e:0b:68:64:b0:55:e3:9d:5e:87:30:3a:a7:16:4f:fe:cb:05:1d:d9:28:ce:66:a2:a7:9f:9b:dd:47 +sha256-ssh-ed25519@22:192.168.110.17=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +ssh-ed25519@22:10.222.36.229=0x530d603d651cc83599ab24b0640768c3e55a9164117467ae59ccc3c76acbd112,0x3607b648aaef1653fdba9563c2e72f79c6f78558c55052ab2c97c3876f856a22 +sha256-ssh-ed25519@22:10.222.36.229=84:1d:a7:b1:1c:b5:9d:5c:80:50:7a:2e:3b:f1:b8:c2:4f:34:2a:da:40:5d:a6:e3:62:00:dc:e1:3a:05:b3:53 +ssh-ed25519@22:10.222.36.190=0x25c9f2cf9367637fc12b232491ea337e7eda9fe880a15b2701a4bd40c5963ab8,0x7f3ffb57b3768fbac15ea488d4a5dd2c5a2ab5e57b1eb2d98b7fa2f4826ffbc8 +sha256-ssh-ed25519@22:10.222.36.190=ad:d9:22:86:79:4c:29:2f:eb:7a:6a:58:5d:64:b6:48:b9:62:97:ae:08:bb:46:3d:ed:8c:a1:3e:55:71:89:17 +ssh-ed25519@22:10.92.43.190=0x25c9f2cf9367637fc12b232491ea337e7eda9fe880a15b2701a4bd40c5963ab8,0x7f3ffb57b3768fbac15ea488d4a5dd2c5a2ab5e57b1eb2d98b7fa2f4826ffbc8 +sha256-ssh-ed25519@22:10.92.43.190=ad:d9:22:86:79:4c:29:2f:eb:7a:6a:58:5d:64:b6:48:b9:62:97:ae:08:bb:46:3d:ed:8c:a1:3e:55:71:89:17 +ssh-ed25519@22:10.92.43.229=0x530d603d651cc83599ab24b0640768c3e55a9164117467ae59ccc3c76acbd112,0x3607b648aaef1653fdba9563c2e72f79c6f78558c55052ab2c97c3876f856a22 +sha256-ssh-ed25519@22:10.92.43.229=84:1d:a7:b1:1c:b5:9d:5c:80:50:7a:2e:3b:f1:b8:c2:4f:34:2a:da:40:5d:a6:e3:62:00:dc:e1:3a:05:b3:53 +ssh-ed25519@22:192.168.137.93=0x4e3d7b58df136ac2c3d2abb43117263102953ba5959f9fdf8c7aace8fd421d0b,0x57f73a00e16aba771fb816ffebc2c45163a4b4cacb31981090f8ab6382befd6a +sha256-ssh-ed25519@22:192.168.137.93=3f:82:8e:49:a4:23:e7:71:ea:60:9d:12:f0:47:64:9a:ce:41:a6:2c:6a:4b:16:0b:6f:f5:99:3f:22:38:f8:8c +ssh-ed25519@22:10.92.43.19=0x4e3d7b58df136ac2c3d2abb43117263102953ba5959f9fdf8c7aace8fd421d0b,0x57f73a00e16aba771fb816ffebc2c45163a4b4cacb31981090f8ab6382befd6a +sha256-ssh-ed25519@22:10.92.43.19=3f:82:8e:49:a4:23:e7:71:ea:60:9d:12:f0:47:64:9a:ce:41:a6:2c:6a:4b:16:0b:6f:f5:99:3f:22:38:f8:8c +ssh-ed25519@22:192.168.100.23=0x5097138d4a7a3a99ef80edbbf215439fdff722098f0ffb3a39e09fb2c63490aa,0x3f4928eec8cf0cd2996bc315478a8cbd84d6437f839018c467dd1baf0304bc8d +sha256-ssh-ed25519@22:192.168.100.23=e9:39:da:f5:88:0f:9c:59:0a:34:98:c7:35:93:17:8d:10:a3:42:e0:45:13:30:71:e9:6f:c1:e0:53:d4:9a:0d +ssh-ed25519@22:192.168.100.24=0x5d27fcfe83e413d03ea1dac57f44e21a220df271274ae193c2da4dfbb68523e6,0x4e43402b238acfbb3dbcd9d8c853f787fbbb1441fc6de168e3893b1d9099230f +sha256-ssh-ed25519@22:192.168.100.24=c5:b0:9a:6e:2c:92:e2:3e:7f:79:95:8e:37:97:65:88:94:95:42:85:98:9f:c6:f8:a7:80:c1:98:5d:c4:c3:26 +ssh-ed25519@22:192.168.110.115=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +sha256-ssh-ed25519@22:192.168.110.115=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +ssh-ed25519@22:192.168.0.12=0x315812a72d55b41f72cee2bc4c5ca37f1d9defda7f23701f591a1c94dd216cef,0x26c8ee4a153c46a0b55b650294d526efecfca48641d6cb8de3ddf88938b6e7de +sha256-ssh-ed25519@22:192.168.0.12=a5:8e:5c:91:fe:08:34:8f:e2:0d:9a:63:bb:0a:d2:75:65:8a:f9:c9:5d:e2:2c:fa:b1:89:32:af:8b:ac:c2:cb +sha256-ssh-ed25519@22:192.168.127.10=1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +ssh-ed25519@22:192.168.0.3=0x4fbdeb0cc708bedaad7244d9ccc03a9b5cb295f23736588e66709ddd9c4b8735,0x5ec1cdf861f8c174c9e669cf4bcd8c288d273792c4b772d85bb963292275a928 +sha256-ssh-ed25519@22:192.168.0.3=1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +ssh-ed25519@22:192.168.0.105=0x375d1796bb113c10bdb35b32081ed46dd897e3df77dc0681dde7b6db9a7ffb6d,0x649881426de5a5e61932ab6e824b2fd0eda5c410fe89f72029cd4e68ee9cf62 +sha256-ssh-ed25519@22:192.168.0.105=2b:ca:32:12:87:5d:69:9e:24:78:db:b7:f5:ec:40:a8:c2:4b:0c:47:27:72:0a:10:19:c4:4f:43:cf:7c:05:be +ssh-ed25519@22:10.162.10.242=0x375d1796bb113c10bdb35b32081ed46dd897e3df77dc0681dde7b6db9a7ffb6d,0x649881426de5a5e61932ab6e824b2fd0eda5c410fe89f72029cd4e68ee9cf62 +sha256-ssh-ed25519@22:10.162.10.242=2b:ca:32:12:87:5d:69:9e:24:78:db:b7:f5:ec:40:a8:c2:4b:0c:47:27:72:0a:10:19:c4:4f:43:cf:7c:05:be + +[BrowsersFoldersHistory] +SessionsList=ssh:root@10.162.10.242|ssh:root@192.168.0.105|ssh:root@192.168.127.10|ssh:root@192.168.0.3|ssh:pleaseaskme@192.168.0.12|ssh:pleaseaskme@192.168.110.222|ssh:root@192.168.110.222|ssh:root@ubuntu.lan|ssh:pleaseaskme@192.168.127.10|ssh:root@192.168.110.115|ssh:ros@192.168.100.24|ssh:ros@192.168.100.23|ssh:pleaseaskme@192.168.100.23|ssh:ros@192.168.110.161|ssh:pleaseaskme@10.92.43.19|ssh:pleaseaskme@192.168.137.93|ssh:ros@10.92.43.229|ssh:ros@10.92.43.190|ssh:pleaseaskme@10.222.36.190|ssh:ros@10.222.36.190|ssh:pleaseaskme@10.222.36.229|ssh:pleaseaskme@192.168.1.10|ssh:@192.168.1.10|ssh:root@192.168.1.10| +ssh:ros@192.168.110.161=/home/ros/dev_ws/src/originbot_desktop/originbot_navigation/launch/|/home/ros/dev_ws/src/originbot_desktop/originbot_navigation/config/|/home/ros/dev_ws/src/originbot_desktop/originbot_navigation/param/|/home/ros/dev_ws/src/originbot_desktop/originbot_navigation/maps/|/home/ros/dev_ws/src/originbot_desktop/originbot_navigation/|/home/ros/dev_ws/src/originbot_desktop/|/home/ros/dev_ws/src/|/home/ros/dev_ws/|/home/ros/音乐/|/home/ros/桌面/dev_ws/src/a1_description/|/home/ros/桌面/dev_ws/src/a1_moveit_config/|/home/ros/桌面/|/home/ros/|/home/ros/桌面/dev_ws/src/|/home/ros/桌面/dev_ws/|/home/ros/桌面/dev_ws/src/moveit_controller_server/srv/| +ssh:root@192.168.127.10=/mnt/|/tmp/|/userdata/dev_ws/install/|/|/userdata/|/root/|/userdata/dev_ws/src/yahboomcar_voice_ctrl/yahboomcar_voice_ctrl/|/userdata/dev_ws/src/yahboomcar_voice_ctrl/|/userdata/dev_ws/src/originbot/originbot_linefollower/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/dev_ws/src/originbot/|/userdata/dev_ws/src/originbot/originbot_deeplearning/body_tracking/images/|/userdata/dev_ws/src/originbot/originbot_deeplearning/body_tracking/include/|/userdata/dev_ws/src/originbot/originbot_deeplearning/body_tracking/launch/|/userdata/dev_ws/src/originbot/originbot_deeplearning/body_tracking/src/| +ssh:pleaseaskme@192.168.1.10=/userdata/dev_ws/install/|/userdata/dev_ws/src/originbot/|/userdata/|/|/userdata/dev_ws/src/|/userdata/dev_ws/|/root/|/userdata/dev_ws/src/integrated_line_follower/config/|/userdata/dev_ws/src/integrated_line_follower/integrated_line_follower/__pycache__/|/userdata/dev_ws/src/integrated_line_follower/integrated_line_follower/config/|/userdata/dev_ws/src/integrated_line_follower/launch/|/userdata/dev_ws/src/integrated_line_follower/resource/|/userdata/dev_ws/src/color_detect_pkg/color_detect_pkg/__pycache__/|/userdata/dev_ws/src/color_detect_pkg/resource/|/userdata/dev_ws/src/color_detect_pkg/test/|/userdata/dev_ws/src/buzzer_control/buzzer_control/| +ssh:root@192.168.1.10=/root/|/opt/ros/|/opt/|/|/userdata/dev_ws/install/buzzer_control/lib/|/userdata/dev_ws/install/buzzer_control/|/userdata/dev_ws/install/|/userdata/dev_ws/config/|/userdata/dev_ws/src/buzzer_control/buzzer_control/|/userdata/dev_ws/src/buzzer_control/|/userdata/dev_ws/src/|/userdata/|/userdata/dev_ws/|/userdata/dev_ws/install/buzzer_control/lib/python3.8/site-packages/buzzer_control-0.0.0-py3.8.egg-info/|/userdata/dev_ws/install/buzzer_control/lib/python3.8/site-packages/buzzer_control/__pycache__/|/userdata/dev_ws/install/buzzer_control/lib/python3.8/site-packages/buzzer_control/| +ssh:@192.168.1.10=/userdata/dev_ws/install/color_detect_pkg/share/ament_index/resource_index/packages/|/userdata/dev_ws/install/color_detect_pkg/share/ament_index/resource_index/|/userdata/dev_ws/install/color_detect_pkg/share/ament_index/|/userdata/dev_ws/install/color_detect_pkg/share/colcon-core/packages/|/userdata/dev_ws/install/color_detect_pkg/share/colcon-core/|/userdata/dev_ws/install/color_detect_pkg/share/color_detect_pkg/hook/|/userdata/dev_ws/install/color_detect_pkg/share/color_detect_pkg/|/userdata/dev_ws/install/color_detect_pkg/share/|/userdata/dev_ws/install/color_detect_pkg/lib/color_detect_pkg/|/userdata/dev_ws/install/color_detect_pkg/lib/python3.8/site-packages/|/userdata/dev_ws/install/color_detect_pkg/lib/python3.8/|/userdata/dev_ws/install/color_detect_pkg/lib/|/userdata/dev_ws/install/color_detect_pkg/|/userdata/dev_ws/install/|/userdata/dev_ws/src/color_detect_pkg/color_detect_pkg/|/userdata/dev_ws/src/color_detect_pkg/| +ssh:pleaseaskme@192.168.127.10=/home/sunrise/Pictures/|/home/sunrise/Music/|/home/sunrise/Downloads/|/home/sunrise/Documents/|/home/sunrise/Desktop/|/root/|/|/home/|/home/sunrise/| +ssh:pleaseaskme@10.222.36.229=/home/ros/Desktop/a1x_ros/|/|/home/|/home/ros/Desktop/|/home/ros/| +ssh:pleaseaskme@10.222.36.190=/home/ros/Desktop/a1x_ros/install/|/home/ros/Desktop/A1X/|/home/ros/Desktop/a1x_ros/|/home/ros/Desktop/|/home/|/home/ros/| +ssh:ros@10.222.36.190=/home/ros/Desktop/a1x_ros/|/home/ros/Desktop/|/home/|/home/ros/| +ssh:ros@10.92.43.190=/home/ros/Desktop/a1x_ros/install/|/home/ros/Desktop/a1x_ros/|/home/ros/| +ssh:ros@10.92.43.229=/home/ros/Downloads/|/home/ros/Desktop/a1x_ros/install/|/home/ros/Desktop/a1x_ros/|/home/ros/Desktop/A1X/|/home/ros/Desktop/|/home/ros/| +ssh:pleaseaskme@192.168.137.93=/home/ros/桌面/|/home/ros/| +ssh:pleaseaskme@10.92.43.19=/home/ros/桌面/|/home/ros/音乐/|/home/ros/| +ssh:pleaseaskme@192.168.100.23=/home/ros/roslog/|/home/ros/Desktop/|/home/ros/| +ssh:ros@192.168.100.23=/home/ros/a1x_ros/|/home/ros/Desktop/|/home/ros/roslog/|/home/ros/| +ssh:ros@192.168.100.24=/home/ros/a1x_ros/|/home/ros/| +ssh:root@192.168.110.115=/userdata/dev_ws/src/origintank_base/launch/|/userdata/dev_ws/src/origintank_base/|/userdata/dev_ws/src/origintank_bringup/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/|/|/root/| +ssh:root@ubuntu.lan=/root/| +ssh:root@192.168.110.222=/userdata/dev_ws/src/originbot/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/|/|/root/| +ssh:pleaseaskme@192.168.110.222=/boot/overlays/|/boot/|/vendor/|/|/root/| +ssh:pleaseaskme@192.168.0.12=/root/| +ssh:root@192.168.0.3=/userdata/dev_ws/src/yahboomcar_voice_ctrl/yahboomcar_voice_ctrl/|/userdata/dev_ws/src/yahboomcar_voice_ctrl/|/userdata/dev_ws/src/yahboomcar_nav/|/userdata/dev_ws/src/originbot/|/userdata/dev_ws/src/|/userdata/|/|/root/|/userdata/dev_ws/log/|/userdata/dev_ws/|/userdata/dev_ws/src/originbot/originbot_base/src/|/userdata/dev_ws/src/originbot/originbot_base/include/originbot_base/|/userdata/dev_ws/src/originbot/originbot_base/include/|/userdata/dev_ws/src/originbot/originbot_base/launch/|/userdata/dev_ws/src/originbot/originbot_base/|/userdata/dev_ws/src/originbot/originbot_deeplearning/line_follower_perception/| +ssh:root@192.168.0.105=/root/dev_ws/src/supply_station_nav/supply_station_nav/|/root/dev_ws/src/supply_station_nav/resource/|/root/dev_ws/src/supply_station_nav/launch/|/root/dev_ws/src/supply_station_nav/config/|/root/dev_ws/src/supply_station_nav/|/root/dev_ws/scripts/|/root/dev_ws/src/origintank_base/src/|/root/arm_plane_calib/|/root/dev_ws/src/origintank_bringup/launch/|/root/dev_ws/src/origintank_bringup/|/root/dev_ws/src/origintank_base/launch/|/root/dev_ws/src/origintank_base/|/root/dev_ws/src/|/root/dev_ws/|/root/| +ssh:root@10.162.10.242=/root/dev_ws/src/supply_station_nav/supply_station_nav/|/root/dev_ws/src/supply_station_nav/|/root/dev_ws/src/lerobot_arm_controller/lerobot_arm_controller/|/root/dev_ws/src/lerobot_arm_controller/|/root/dev_ws/src/|/root/dev_ws/src/supply_pickup_manager/supply_pickup_manager/|/root/dev_ws/src/supply_pickup_manager/resource/|/root/dev_ws/src/supply_pickup_manager/launch/|/root/dev_ws/src/supply_pickup_manager/config/|/root/dev_ws/src/supply_pickup_manager/|/root/dev_ws/src/raw_material_detector/resource/|/root/dev_ws/src/raw_material_detector/raw_material_detector/|/root/dev_ws/src/raw_material_detector/launch/|/root/dev_ws/src/raw_material_detector/config/|/root/dev_ws/src/raw_material_detector/|/root/arm_plane_calib/| + +[WindowPos_HUANG_3200_2000_1920_1080] +CompactMode=0 +MonitorCount=2 +Left=-13 +Top=-13 +Width=3226 +Height=1930 +Maximized=1 +SidebarVisible=1 +SidebarWidth=519 + +[Font] +Font2=MobaFont +FontIsBold2=0 +FontHeight2=10 +FontCharset2=0 +FontQuality2=3 +Ligatures=0 +Charset2=UTF-8 +LockRowsCols=0 +LockedCols=80 +LockedRows=24 + +[Colors] +Black=30,30,30 +BoldBlack=128,128,128 +Red=255,96,96 +BoldRed=255,128,128 +Green=14,177,108 +BoldGreen=24,237,147 +Yellow=190,190,18 +BoldYellow=222,220,18 +Blue=18,150,190 +BoldBlue=27,186,233 +Magenta=255,77,255 +BoldMagenta=255,125,255 +Cyan=84,204,239 +BoldCyan=142,221,244 +White=204,204,204 +BoldWhite=204,204,204 +ForegroundColour=236,236,236 +BackgroundColour=30,30,30 +CursorColour=180,180,192 +SyntaxType=1 + +[Cursor] +CursorType=0 +CursorBlinks=0 + +[PopupConsole] +Transparency=16 +Size=36 +Sizeable=0 +Position=3 +TryToOpenInExplorerFolder=1 +BackgroundInsteadOfClose=0 + +[X11Extension] +Composite=1 +DAMAGE=1 +RANDR=1 +XFIXES=1 +XTEST=1 +XINERAMA=1 + +[EditorWindowPos_3200_2000_192] +Left=-13 +Top=-13 +Width=3226 +Height=1930 +Maximized=1 +MonitorCount=1 + +[WindowPos_DESKTOP-63076PO_1920_1080_4206288_-24] +CompactMode=0 +MonitorCount=2 +Left=-8 +Top=-8 +Width=1936 +Height=1056 +Maximized=1 +SidebarVisible=1 +SidebarWidth=240 + +[WindowPos_DESKTOP-63076PO_1920_1080_1920_1080] +CompactMode=0 +MonitorCount=2 +Left=-8 +Top=-8 +Width=1936 +Height=1056 +Maximized=1 +SidebarVisible=1 +SidebarWidth=240 + +[EditorWindowPos_1920_1080_1920_1080_96] +Left=0 +Top=0 +Width=1920 +Height=1040 +Maximized=0 +MonitorCount=2 + +[MobaTextEditor] +FontName3=MobaFanta +FontLigatures3=0 +FontHeight3=-13 +GutterVisible=1 +GutterAutosize=1 +GutterShowLineNumbers=1 +GutterZeroStart=0 +GutterLeadingZeros=0 +GutterFontName=Verdana +GutterFontSize=8 +EdgeColumn=800 +EdgeColor=16777215 +ExtraLineSpacing=0 +TabWidth=2 +BookmarkKeys=1 +BookmarksVisible=1 +Options=39866307 +WantTabs=1 +WordWrap=0 + +[WindowPos_DESKTOP-63076PO_1920_1080] +CompactMode=0 +MonitorCount=1 +Left=-8 +Top=-8 +Width=1936 +Height=1056 +Maximized=1 +SidebarVisible=1 +SidebarWidth=298 + +[LastInstanceSessions] +0= +1=用户会话\COM7 (USB-SERIAL CH340 (COM7)) + +[Bookmarks] +SubRep= +ImgNum=42 + 10.217.155.242 (root)= #109#0% 10.217.155.242%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +10.162.10.242 (root)=#109#0%10.162.10.242%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.0.105 (root)=#109#0%192.168.0.105%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.0.3 (root)=#109#0%192.168.0.3%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.127.10=#128#5%192.168.127.10%5900%-1%0%%%%%-1%0%0%%0%%1080%%%0#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.127.10 (root)=#109#0%192.168.127.10%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +COM7 (USB-SERIAL CH340 (COM7))= #131#8%1%1115200%3%0%0%1%2%COM7 (USB-SERIAL CH340 (COM7))#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +COM8 (USB-SERIAL CH340 (COM8))=#131#8%2%1115200%3%0%0%1%2%COM8 (USB-SERIAL CH340 (COM8))#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 + diff --git a/MobaXterm_25.2_CN/MobaXterm.log b/MobaXterm_25.2_CN/MobaXterm.log new file mode 100644 index 0000000..cfb4569 --- /dev/null +++ b/MobaXterm_25.2_CN/MobaXterm.log @@ -0,0 +1,37878 @@ +[13:41.33.410] 正在启动 MobaXterm +[13:41.33.410] +[13:41.33.410] BEGIN AdaptToGlobalDPI +[13:41.33.410] AdaptToGlobalDPI: DPI=192 +[13:41.33.410] BEGIN LaunchLoadFlatIconsThreads +[13:41.33.410] BEGIN WaitForLoadFlatIconsThreads +[13:41.33.410] END WaitForLoadFlatIconsThreads +[13:41.33.410] BEGIN WaitForGenerateStdListThreads +[13:41.33.410] END WaitForGenerateStdListThreads +[13:41.33.410] 加载平面图标 16 +[13:41.33.410] 加载平面图标 22 +[13:41.33.410] 加载平面图标 64 +[13:41.33.410] 加载扩展图标 +[13:41.33.410] END LaunchLoadFlatIconsThreads +[13:41.33.412] ImChecks <-- ImChecks16 +[13:41.33.416] END AdaptToGlobalDPI +[13:41.33.416] +[13:41.33.418] BEGIN AddMobaConsoleFont +[13:41.33.418] END AddMobaConsoleFont +[13:41.33.418] +[13:41.33.418] +[13:41.33.418] BEGIN MobaProfileDir detection +[13:41.33.418] BEGIN GetProfileDirScore(C:\Users\31554\AppData\Roaming\) +[13:41.33.419] "C:\Users\31554\AppData\Roaming\" 似乎是可写的 +[13:41.33.419] "C:\Users\31554\AppData\Roaming\MobaXterm\MobaXterm.ini" 不存在 +[13:41.33.419] "C:\Users\31554\AppData\Roaming\" 不是一个网络路径 +[13:41.33.419] END GetProfileDirScore(C:\Users\31554\AppData\Roaming\): 28 +[13:41.33.419] BEGIN GetProfileDirScore(C:\Users\31554\DOCUME~1\) +[13:41.33.419] "C:\Users\31554\DOCUME~1\" 似乎是可写的 +[13:41.33.419] "C:\Users\31554\DOCUME~1\MobaXterm\MobaXterm.ini" 不存在 +[13:41.33.419] "C:\Users\31554\DOCUME~1\" 不是一个网络路径 +[13:41.33.419] END GetProfileDirScore(C:\Users\31554\DOCUME~1\): 28 +[13:41.33.419] BEGIN GetProfileDirScore(C:\Users\31554\AppData\Local\) +[13:41.33.420] "C:\Users\31554\AppData\Local\" 似乎是可写的 +[13:41.33.420] "C:\Users\31554\AppData\Local\MobaXterm\MobaXterm.ini" 不存在 +[13:41.33.420] "C:\Users\31554\AppData\Local\" 不是一个网络路径 +[13:41.33.420] END GetProfileDirScore(C:\Users\31554\AppData\Local\): 28 +[13:41.33.420] END MobaProfileDir detection +[13:41.33.420] +[13:41.33.420] --> 已选择的 MobaProfile 目录: "C:\Users\31554\AppData\Roaming\" +[13:41.33.420] +[13:41.33.420] - MobaXterm 版本: 25.2 构建 5296 +[13:41.33.420] - 命令行: "D:\MobaXterm_25.2_CN\MobaXterm_25.2_CN.exe" +[13:41.33.420] - 日期: 2025-10-29 +[13:41.33.420] - Windows 版本号: 10.0.2.26100. +[13:41.33.420] - Windows 版本名称: Windows 10 +[13:41.33.420] - Windows 全名: Windows 10 Enterprise 2009 build 26100 +[13:41.33.420] - Windows 架构: 64 位 +[13:41.33.421] - 用户语言: 简体中文(中国大陆) +[13:41.33.421] - CPU 架构: x86 +[13:41.33.421] - 检测到的 DPI: 192 +[13:41.33.421] - 用户 DPI: 192 +[13:41.33.421] - 当前目录: D:\MobaXterm_25.2_CN\ +[13:41.33.421] - 个人目录: C:\Users\31554\DOCUME~1\ +[13:41.33.421] - AppData 目录: C:\Users\31554\AppData\Roaming\ +[13:41.33.421] - LocalAppData 目录: C:\Users\31554\AppData\Local\ +[13:41.33.421] - 桌面目录: C:\Users\31554\Desktop\ +[13:41.33.421] - 自定义 Profile 目录: 0 +[13:41.33.421] - Moba Profile 目录: C:\Users\31554\AppData\Roaming\ +[13:41.33.421] - Moba Profile 目录的可用空间: 158484MB +[13:41.33.421] - 临时目录: C:\Users\31554\AppData\Local\Temp\ +[13:41.33.421] - 临时目录的可用空间: 158484MB +[13:41.33.421] - 显示器 #0 LxTxWxH: 0x0x3200x2000 +[13:41.33.421] - 用户名: 31554 +[13:41.33.421] - 计算机名称: HUANG +[13:41.33.421] - 当前 Windows 区域设置: 2052 +[13:41.33.421] - Windows beta 版本的 Unicode 支持 未开启 +[13:41.33.421] - 运行时间: 3 天, 21:43:50 +[13:41.33.421] - Windows PATH 环境变量: D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\mingw-w64\bin;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;D:\Nmap +[13:41.33.421] - WSL 路径: C:\WINDOWS\Sysnative\wsl.exe +[13:41.33.421] +[13:41.33.421] BEGIN Form1.FormCreate +[13:41.33.421] 正在检测 安装版/便携版 +[13:41.33.421] --> 便携版 +[13:41.33.421] +[13:41.33.421] 正在检测 IniSettings +[13:41.33.421] MobaXterm 将从该文件获取配置 "D:\MobaXterm_25.2_CN\MobaXterm.ini". +[13:41.33.421] (选定的 ini 文件似乎是可写的) +[13:41.33.421] --> IniSettings= D:\MobaXterm_25.2_CN\MobaXterm.ini +[13:41.33.421] +[13:41.33.433] +[13:41.33.433] 正在检测 ModeIni +[13:41.33.434] --> ModeIni= true +[13:41.33.434] +[13:41.33.434] 正在检测 CygUtils +[13:41.33.434] 检测到 CygUtils32 和 CygUtils64 +[13:41.33.434] --> 使用 CygPackage D:\MobaXterm_25.2_CN\CygUtils.plugin +[13:41.33.434] +[13:41.33.434] 正在启动 CygUtils 软件包线程 +[13:41.33.434] BEGIN GetCygUtilsPackageZip +[13:41.33.434] END GetCygUtilsPackageZip +[13:41.33.434] +[13:41.33.434] 正在检测 MobaXVTDir +[13:41.33.434] IniSlashDir:= +[13:41.33.434] BEGIN IsFolderRW() +[13:41.33.439] END IsFolderRW() --> Ko +[13:41.33.439] BEGIN IsFolderRW(C:\Users\31554\AppData\Local\Temp\Mxt252) +[13:41.33.463] END IsFolderRW(C:\Users\31554\AppData\Local\Temp\Mxt252) --> OK +[13:41.33.463] --> MobaXVTDir= C:\Users\31554\AppData\Local\Temp\Mxt252 +[13:41.33.463] +[13:41.33.463] 正在检测 BinExeDir +[13:41.33.463] --> BinExeDir= C:\Users\31554\AppData\Local\Temp\Mxt252\bin\ +[13:41.33.463] +[13:41.33.463] BEGIN GetMobaseStream +[13:41.33.463] END GetMobaseStream +[13:41.33.463] 正在检测 MobaXVTHomeDir +[13:41.33.464] BEGIN IsFolderRW() +[13:41.33.464] END IsFolderRW() --> Ko +[13:41.33.464] --> MobaXVTHomeDir= C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\home_31554 +[13:41.33.464] +[13:41.33.464] 主题皮肤检测 +[13:41.33.464] 所选主题: +[13:41.33.464] 设置应用程序标题 +[13:41.33.464] 创建 SSH 内存存储 +[13:41.33.464] 清理自定义共享会话 +[13:41.33.464] 检测是否有另一个实例正在运行... +[13:41.33.464] 没有其他实例正在运行. 正在清理之前实例可能遗留的文件... +[13:41.33.508] 清理完成. +[13:41.33.508] 检测已安装的 WSL 和其他基于 bash 的发行版 +[13:41.33.508] +[13:41.33.508] BEGIN ListWslDistrosFromRegistry(HKCU) +[13:41.33.508] END ListWslDistrosFromRegistry(HKCU) +[13:41.33.508] +[13:41.33.508] +[13:41.33.508] BEGIN ListWslDistrosFromRegistry(HKLM) +[13:41.33.508] END ListWslDistrosFromRegistry(HKLM) +[13:41.33.508] +[13:41.33.542] 正在加载皮肤 +[13:41.33.542] +[13:41.33.542] 检测到默认 Windows 主题设置 +[13:41.33.542] 检测到 Windows 处于浅色模式. 激活浅色模式 +[13:41.33.542] +[13:41.33.542] END Form1.Create +[13:41.33.542] +[13:41.33.542] +[13:41.33.542] CREATING Form4 +[13:41.33.746] BEGIN Form4.Create +[13:41.33.746] BEGIN WaitForLoadFlatIconsThreads +[13:41.33.747] END WaitForLoadFlatIconsThreads +[13:41.33.747] BEGIN ReadCustomIcons +[13:41.33.747] 发现自定义图标 #-3 +[13:41.33.761] 自定义图标 #-3 已成功加载! +[13:41.33.763] 找到自定义图标. +[13:41.33.763] END ReadCustomIcons +[13:41.33.763] BEGIN LaunchGenerateStdListThreads +[13:41.33.763] BEGIN WaitForLoadFlatIconsThreads +[13:41.33.763] END WaitForLoadFlatIconsThreads +[13:41.33.763] BEGIN WaitForGenerateStdListThreads +[13:41.33.763] END WaitForGenerateStdListThreads +[13:41.33.763] 生成图标列表 16 (实际大小 32) +[13:41.33.763] 生成图标列表 22 (实际大小 44) +[13:41.33.763] 生成图标列表 64 (实际大小 128) +[13:41.33.763] END LaunchGenerateStdListThreads +[13:41.33.763] BEGIN Form4.AdapterDPI +[13:41.33.763] Form4.AdapterDPI: DPI=192 +[13:41.33.947] Form4.AdapterDPI: 应用字体 +[13:41.33.970] END Form4.AdapterDPI +[13:41.34.008] NbPenguins = 4 +[13:41.34.008] CoeffPenguins = 192 +[13:41.34.010] BEGIN LoadBookmarksFromIni +[13:41.34.010] FindOrCreateTreeFolders() (1) +[13:41.34.023] END LoadBookmarksFromIni +[13:41.34.023] BEGIN LoadMacrosFromIni +[13:41.34.025] END LoadMacrosFromIni +[13:41.34.029] 正在自动检测 WSL 会话 +[13:41.34.029] 自动检测 WSL 发行版 "Ubuntu" +[13:41.34.030] 自动检测 WSL 发行版 "Debian" +[13:41.34.030] 自动检测 WSL 发行版 "OpenSuse" +[13:41.34.031] 自动检测 WSL 发行版 "SLES" +[13:41.34.031] 自动检测 WSL 发行版 "Kali" +[13:41.34.031] 正在自动检测 PuTTY 会话 +[13:41.34.031] 正在自动检测 SCRT 会话 +[13:41.34.031] 正在自动检测 Exceed 会话 +[13:41.34.032] 正在自动检测 MRemoteNG 会话 +[13:41.34.032] 正在自动检测 SuperPuTTY 会话 +[13:41.34.032] 正在加载顶部工具栏上的按钮 +[13:41.34.032] Form4Create1 +[13:41.34.033] Form4Create2 +[13:41.34.054] BEGIN AdaptSidebarArrows +[13:41.34.054] END AdaptSidebarArrows +[13:41.34.068] Form4Create3 +[13:41.34.069] GetMinWidth = 1846 +[13:41.34.070] GetMinHeight = 1076 +[13:41.34.079] Form4Create4 +[13:41.34.079] IsNTFS(C:\) --> NTFS +[13:41.34.079] Slash 根驱动器是 NTFS. +[13:41.34.079] Form4Create5 +[13:41.34.086] 尝试重新检测 DPI,以防窗口移动到另一个显示器 +[13:41.34.086] Form4Create6 +[13:41.34.086] Displaysidebarontheleft1Click: FormClick +[13:41.34.086] BEGIN AdaptSidebarArrows +[13:41.34.086] END AdaptSidebarArrows +[13:41.34.086] Form4Create7 +[13:41.34.086] Form4Create8 +[13:41.34.086] Form4Create9 +[13:41.34.086] ShowButtonsbar1Click: FormClick +[13:41.34.088] Form4Create10 +[13:41.34.088] Form4Create12 +[13:41.34.088] SmallButtons1Click: FormClick +[13:41.34.098] GetMinWidth = 1846 +[13:41.34.098] GetMinHeight = 1047 +[13:41.34.099] Form4Create13 +[13:41.34.099] Form4Create14 +[13:41.34.099] END Form4.Create +[13:41.34.099] +[13:41.34.099] +[13:41.34.099] CREATING FormParams +[13:41.34.406] BEGIN TFormParams.FormCreate +[13:41.34.459] END TFormParams.FormCreate +[13:41.34.459] +[13:41.34.459] +[13:41.34.459] CREATING FormSessionEdit +[13:41.34.759] BEGIN FormSessionEdit.Create +[13:41.34.759] 预加载 IP 地址列表 +[13:41.34.759] 正在生成 shell 列表 +[13:41.34.768] 正在生成 WSL 发行版列表 +[13:41.34.794] 正在生成会话列表组合框 +[13:41.34.794] 正在选择默认会话 #0 +[13:41.34.794] 正在适配窗口 DPI 192 +[13:41.34.806] 正在适配宏组合框 +[13:41.34.816] 正在检测默认 IP 地址 +[13:41.34.816] BEGIN TFormSessionEdit.FindIP +[13:41.34.816] 正在等待 IP 地址线程 +[13:41.34.817] IP 地址列表包含 4 项 +[13:41.34.817] END TFormSessionEdit.FindIP +[13:41.34.817] 正在禁用管理员不允许的会话 +[13:41.34.817] END FormSessionEdit.Create +[13:41.34.817] +[13:41.34.817] +[13:41.34.817] DONE CREATING FORMS +[13:41.34.817] +[13:41.34.817] +[13:41.34.817] +[13:41.34.817] +[13:41.34.823] BEGIN Form1.Show +[13:41.34.823] END Form1.Show +[13:41.34.895] +[13:41.34.895] 正在启动 Form1.Timer1Timer +[13:41.34.895] +[13:41.34.895] BEGIN WaitForGetCygUtilsPackageZip +[13:41.34.895] END WaitForGetCygUtilsPackageZip +[13:41.34.895] +[13:41.34.895] CygUtils 版本: 3.60 (32位) +[13:41.34.895] +[13:41.34.897] +[13:41.34.897] +[13:41.34.897] +[13:41.34.897] +[13:41.34.897] ================================================================================ +[13:41.34.897] ~ INI 文件内容 (D:\MobaXterm_25.2_CN\MobaXterm.ini) ~ +[13:41.34.897] ================================================================================ +[13:41.34.897] +[13:41.34.897] +[Misc] +PasswordsInRegistry=0 +LocalShell=Bash (32位) +NewTabPosition=1 +SingleClickToRunMacros=0 +LastSession=192.168.110.239 (root)|#109#0%192.168.110.239%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +SessionP=330918199908 +StorePasswords=Never +RightClickAction=1 +RightClickAssigned=1 +DefTextEditor= +LogFileFormat= +StoreSSHKeysPassphrases=0 +BackupIni=1 +LogTerminalActivity=0 +LogType=0 +LogFolder= +SkinSat=36 +XAuto=1 +XKeepAlive=1 +BackspaceSendsBS=1 +BSisBS=1 +BoldAsFont=0 +WinPath=1 +ConfirmExit=0 +PromptType=2 +WarnBeforePasteMultipleLines=1 +TransTerm=0 +TransDetachedTabs=0 +X11SharedClipboard2=1 +X11OpenGL=0 +X11DisplayMode=0 +X11AccessControl2=0 +X11DisplayOffset=0 +X11ScreenNumber=1 +X11Keyboard=0 +X11DpiMode=拉伸 +X11Version=MobaX +AdvTermSettings= +HomeDir= +SlashDir= +DefaultHome=<主页 (固定)> +DefaultNewTab=<终端> +ReplaceHomeTab=0 +NoTabClose=0 +AllowMultiInstances=0 + +[Macros_1] +SubRep=originbot +ImgNum=41 + +[Macros_2] +SubRep=origincar +ImgNum=41 + +[Macros_3] +SubRep=originman +ImgNum=41 +动作模仿节点=em:/_@5TIVp5QfuyIpgNPtzlPpVeImCJSXe/2nXjanYTInmY42K3T56GtMZTteDNctq5tO7bGnyKUXtEygnM66MHbEoadj6keHw+TPKMUHVfJhXLa1frsWZ/RtRgnze8gb1RqyR+ofz2fcYWyHOEbRsqajXK3vvrehiT/SGkpcM17ZPvEaTqhhdcMFmN4hFvGHP61W+oSx3H4JWkq9qjDv1tshkA3TAT6h6ZrGgbYRTXRcRcWAu79mewS5Xyc8TVCEWckAZ/aHNUYq5fvUP2Q0YN7M2AQeuN4BWspec= +视觉巡线=em:/_@tv64pFTv7TbUCHwqz6X26YAZedCuYFITsV3MLPT2fXG5bu5KXv8lWe/fPcCPTx6Gnn9ABCxCZOVcCVu4Ux4E9E198sU8Hw/OlJ8ST3RLchxw4Cf8gms2QEeRe3bpGVCbk8yBsBYSxDdBIY2CM= +网页=em:/_@eVPtVTf1MxvhBA711KOfN8Gfrt13vBL7kzsQQqo5DzO6deIrYViQMswPNsgQAoJ6snnm2kCBxsWcbYS+5Ybu03xJhbbW2Op002bIGSOzKxwWMnWIBb71qkWl7HYqhBG5lhNmiUFgEoxcoVW5S8Hb8NMPQ6bVgw +语音交互=em:/_@WP5zmHEzp3nIFvGhtBTNceYxdeYVdrdzOzR2jg+19kvBb1QmXNGMaeN3mo+yISeCIdSUNyqPy6W88WOyMflLZtc9Ob4V2juA+c0M3gUtscUZ0x6qFnIYQmHs08gGCt+svgEo0d4AmuBZ/jejx+41brGRWnqtTsN7i7 +语音交互(运动)=em:/_@PKl435owHAgtJgPMj1ttDrb8d5aw3Me7Zk4olkD6HuP3UTDM8A6wRe3t2Ki+yrTvQUadGimEh92CDEY2sPg2sbXGuCOj/G3OkAffF3MfVsmLjjSD6jIu8cjRcPtn+YmbDtC1hONi2dGbdQQs9zz/9EMMVmLM1LfyKL + +[WindowPos_HUANG_3200_2000] +CompactMode=0 +MonitorCount=1 +Left=-13 +Top=-13 +Width=3226 +Height=1930 +Maximized=1 +SidebarVisible=1 +SidebarWidth=490 + +[SSH] +SFTPShowDotFiles=1 +SFTPAsciiMode=0 +MonitorHost=1 +MonitorCPU=1 +MonitorRAM=1 +MonitorNetUp=1 +MonitorNetDown=1 +MonitorProcesses=0 +MonitoFDs=0 +MonitorUptime=1 +MonitorUsers=1 +MonitorPartitions=1 +MonitorNfsPartitions=0 +MonitorNetstat=0 +StrictHostKeyChecking=0 +BrowserSortType=0 +BrowserSortReverse=1 +RemoteMonitoring=1 +LastDownDir_31554@HUANG=C:\Users\31554\Desktop\ball\jixiebi +UseInternalMobAgent=0 +UseExternalPageant=1 +ValidateEachAgentRequest=0 +MobAgentKeys= +DisplaySSHBanner=1 +UseNewMoTTY=1 +GwUse2factor=0 +AutoStartSSHGUI=1 +SSHKeepAlive2=0 +EnableSFTP=1 +ScpPreservesDates=0 +UseGSSAPI=1 +KrbDomain= +GSSAPICustomLib= +GSSAPILibNumber=0 +DefaultLoginName= + +[Display] +SidebarRight=0 +C10Checked=1 +C11Checked=1 +C12Checked=1 +C13Checked=0 +C14Checked=0 +VisibleTabNum=1 +VisibleTabClose=1 +MenuAndButtons=2 +BtnType2=2 +S3Checked=0 +DisableQuickConnect=0 +CustomDPI_3200_192=0 +IconsTheme=0 +RoundedTabs=1 +GraphicCache=1 + +[Recently started] +16=用户会话\COM4 (USB-SERIAL CH340 (COM4)) +15=用户会话\10.211.90.241 (root) +14=用户会话\114.55.66.216 (root) +13=用户会话\10.211.90.119 (root) +12=用户会话\10.211.90.190 (root) +11=用户会话\192.168.110.123 (root) +10=用户会话\192.168.110.216 (root) +9=用户会话\ubuntu.lan (root) +8=用户会话\COM3 (USB-SERIAL CH340 (COM3)) +7=用户会话\COM5 (USB-SERIAL CH340 (COM5)) +6=用户会话\串口(COM) +5=用户会话\192.168.110.17 (root) +4=用户会话\192.168.110.92 (root) +3=用户会话\192.168.110.161 +2=用户会话\192.168.127.10 (root) +1=用户会话\192.168.110.239 (root) + +[CustomIcons] +-3=iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAKx0lEQVR42s1aCViU1Rp+ZweGnWGTMlDKXCuNrOtFLQmsvHVLQVFIkFRQECwEzQx9DMubJuGCpqRZRkAuCOPgrZTAzADJbiAg1i2UfRcYtpn57/ePo3fYBxzN8zyH/2z/Od97zjvfec/54TAMA72H7GwzpKdvAsMsoNwV8PlBWL++QN/DnDp1Chy9A7h4cTTS0nZTyp0iR1PaCguLYCxc+BUkkvb7F8CZM48gK+sLSj2pZfytUAdr67UICDgIkUh5/wHIzR0NqTSRUlMGaNVGcT7WrZNCKFTdPwCys0dBJttHqVl9zHxvEBJJCObPP3KndNIfgE2bXqW/SRT5Or5RB0vLNVi58hC4XOavA9DaCojFgErFwfbtUZDLI6nUQMe3b9IpPFxGfSjuPYDz551w6dIEeHmlExW6UFFhhqSkCDQ2siB4OoOwsQmlPg7Dyqrj3gHIyHBGZuYJ8vNWMDVdidWrj6nLm5oMERMTQqktQwBRDzOzMISFfX5vAOTlOSM19QClZmhKGojHnli16nsyRIG2NgHi4t5Fc/NbVGeo80rw+T4ICUmjCem8ewAyM0U4e/Y4pWb38DaNRIVgokISUYGlkzkSE4NoRcZo2rlRHDFI782wtfUk73SaNj39A8gkQya3tMB4+/ZQym6lKOzRpAZGRkuwZk2aOieXC6BU8tQADh60QkNDDKXnDjDEaUycOD958tUOT8eIdr0CyLsG59Rf8A75l8+XO1ZesDv5ZSRRJIKqRD2aNpBHeZE8y4VenaSmjiH6ySjl1KOGpUwKM3qUT+bzgom5NelxYq7pR97OG46bCa077hhARgmcv7+CA2AwnbKVJiZYPc+iVDby5OEVNMMbe4EQi9cRgA96dVReboj9+z+hlE+Pmq/g4vLW6cfLzQvqzx3SyJAmG9HIyFccww6ZCCw7hw3g/O9w+rYQqdRkvFZxNc8QSyKndckEW7eEUZ41VqAFwIsAJPcBwAAHDuwlz7VYq/Q7jB37ctoz1SOvNOWeo7yVVl2LAKLFIRP2HRsWgIulcE77FXto5t36kAfXiE4BbziU/eggS2TpFHkbhEh0DEuWLKIfdXce19cLcOTIWnpuoBw76HGMGeOX+SxnQm6NjF2ZJ/ryTqZ8yfK5TuFJFiK7Dp0BnL2ChzNLcIiGeWYAbVNFdArzsr4ufSA5fhnlozV0kpMn8ifpfJTkQnfVWVlpgc8+i0B7+yiizZvSSX8YFzdmf6kxvr9x6q1FD66d5xRx0JBvohgUQPYfcJTlI4WSk3RwBNW0Er7vzFR+w3t/yxqSFJs13ok0BhYhKipF3UomE8DDo4v2C3WW2bKFm75Y8khhw3n2x26myz7BVXHnr5q4P43L4TH9Asj5E6NO5SOOZv55HVTlrVDKNUDgYtvSH0Z+8/UajXdiQYQSgFh1i127NhO4i/D2TqUzgbK+s4yfUhob3tBe9d5QZIeFwG7lK46hCZYi+/ZeAM4QbbJKkEDGTx6C8bf3AKJTiLd9RZp9wicsnd6nGKEFYA+qqwVwc1uB6dO71HK0vczs8NUNaxio3h7CeHVWwhGRC52jDgq4ItVtALmlGC39FV+S8U/dgaiuZOkU6SLPMIiLDUNHRx0BOKiuiY/3UQn5yd/OUjkV1GQIVkyIKxDxjNQHmriikGB6jGNBtCmavehpTpE7wDhylk5B43fLvjt9Vsn56b+MmawAiWS8+zBmvme4JjHAopVjrp1HYaEp3N0bbu8nVQkP59WcZgWbs5nQJuifI0NPWBk4dN2qVzIKTlZV8qQrTdlbW7oaPAajk0T4wIqmPKMEzqZUJoZItEoPxqsDj4sC93GY+pSj+od8O2zP94ujAZZpZve6h0OA73gL14ye7yf8Hu1cIS/J72OX7xE4xYWZZdGcjalMJeVs9Xgv0fj0KDztMQ7F2oUf5ftdpsfYW5uUh8Mbi8Zb/P1kXx3s+NU/m+EwLoOM016YeT2JBUA6Da76sp5muXTaSDwxaxLp/O4AZBoVqwapAXCqrz6oLetepw4yVBMBOMR5L4UZr+DiJ1YE6MF+xlAAn5CZSDAUodsGs+fnpW7tgq6jlDSlqBLzTP+19NEdb2v7dTakX9vveLnph6LBKEQvZVzOvB6o9kKxZ+DXIMe2HlpkqKHZyhibg6f9EYO2tLmQ13XBLuqoukYRYV/fvqg+ufTT4FZVEysAjdlNUM5tnxPsvDHfXGjbVg45p7Qi+8ELtSd3qzjMnIFtR9EUicdrrXlmRWoAtS0wSMqFT00LYodwitIOKgcLrPd8NHevWac0kPKsNoqCvWYfqNkVDVVH/nXBxJQT5cf8O9HO7hMmrEywEN446WTyRMlPTI2FoP6Gq+Zeid+v8Rxkutp6LneRvFTcbSPrUID3QTpepGTiEEEwpBBCI1zzD4haTqwlh7hOI+xCtQDsgaJuHjjCwDbLgJS9hRG+DA+7tGir1HinwTxhvqudl+eTkheKONS0l5ToVIK7Pwv+tCJbdaTTDVtTRAdOvfoR6o+wrnijZmbRB4AgSpVRDKgWe3x/ouyr4BZl4ybKG+kySRR/mSzx8J5p5100oJhj6ZSQA+/6VuweZCUYezOs8xqbs8+881QwTUi4ljCroEO6H6zX//um5Nu1HMq6WI1GqgbP5M1ywWPHk68d8VFyVdu0QPdLmxl2C4KmWM0u1ElOq+iVzVLMGYBObKerNjxXvJfbmLieslHdbqLFUz1h+nw6bWuazlVcVES/Ts94DVXq6OGnsouUfvyfZUuITjsHmKyr02xfe3Gq9cslQzrQtHaCf/hH+Fc3q09cltreZoQ5ov0nF+7gNyWxOubdbpKYKzwMW28/wLF7x13lNqjdn0Cp5zQlLJ2WVhjOyEirSAluVjZs7EEndpJypkhmL55hu6BoWEfKulaIPr8Ar6Y27NPMEGNjirXe43I+Me9Kp+OkarXGr2vtZOJ5sAs/2nvNanloPByL9uYV2owlOq2uFLocTfgz3ptWIkZDJ9b4czPtFgZOtnK/fMe3EtEyvKZQIl7AR9Tbz16NQ92RCBpgU59anisOgG34p73KO8uFqI3fA44qoEdNLTii1xXWIaf3XA5dpuAotpGHqXnKZo77NJu5JXq5VrnRBiEdMR9xe6joNwN5IutNNmhkb+/AFX4LC995ED7Q1H3jP+MMedbXlHqsj7fKwTVaUSac8o207LjfWGvX71xtvYr1fzNXsdOB9p48StkM0KoLPNMdsPR9D3xJ883bohR7tF3aTav28gAnsFoYjQiu4bskW4sf1+njx/DuRqs+XACVPK7fFfh/YF1eluaH+RJFi4H9POdPiJ+ZTd6rWFdThgdA2SBCQ+JidFVt12iaOxaAFM/B2DUAJs+V3JvrdeUNIWp2zgGj+GKY2qnbRQhMPfwhfvryvf9CUx3jC2VTTI99Yigz/xsZ/g8CUPTXfGJS1BGdkl6HovrjoQpA9YW3ybNLYTy9ZLjD6+cjn6qVj6ptLwxRxV6iH+tCiP9WeCdD6/E7sYqDmt1+UNR/OIiKZQcrINp4Dpc2dwkAS6daA/JOi+i5s18BqKaNWyCMpxXpY0j9/6sB08lF5fsv9UOnQpjMepWML9bTDc5d+mcPpoNHmscXiho6neEh9rAHDudnGE0N0gdtegGQSqXQe+i4IkJrLntN6Kb+7MTlxMHcu1jfw+Tk5OB/a2nAbUagr2kAAAAASUVORK5CYII= + +[BrowsersFoldersHistory] +SessionsList=ssh:pleaseaskme@192.168.110.233|ssh:root@192.168.127.10|ssh:ros@192.168.110.161|ssh:pleaseaskme@10.38.94.230|ssh:@192.168.110.161|ssh:root@192.168.110.239|ssh:root@192.168.110.17|ssh:pleaseaskme@192.168.110.222|ssh:pleaseaskme@192.168.110.100|ssh:root@192.168.110.100|ssh:root@10.218.33.190|ssh:pleaseaskme@ubuntu.lan|ssh:pleaseaskme@192.168.110.126|ssh:pleaseaskme@192.168.110.18|ssh:root@192.168.110.123|ssh:root@192.168.110.216|ssh:root@10.211.90.241|ssh:root@192.168.110.92|ssh:pleaseaskme@192.168.110.123|ssh:root@10.211.90.119|ssh:root@192.168.110.29|ssh:pleaseaskme@10.211.90.119|ssh:ros@10.211.90.19|ssh:pleaseaskme@192.168.110.92| +ssh:ros@192.168.110.161=/home/ros/桌面/dev_ws/src/a1_description/|/home/ros/桌面/dev_ws/src/a1_moveit_config/|/home/ros/桌面/|/home/ros/|/home/ros/桌面/dev_ws/src/|/home/ros/桌面/dev_ws/|/home/ros/桌面/dev_ws/src/moveit_controller_server/srv/|/home/ros/桌面/dev_ws/src/moveit_controller_server/src/|/home/ros/桌面/dev_ws/src/moveit_controller_server/scripts/|/home/ros/桌面/dev_ws/src/moveit_controller_server/nouse/|/home/ros/桌面/dev_ws/src/moveit_controller_server/config/|/home/ros/桌面/dev_ws/src/moveit_controller_server/|/home/ros/桌面/dev_ws/src/custom_interface/srv/|/home/ros/桌面/dev_ws/src/custom_interface/|/home/ros/桌面/dev_ws/src/capture_image/src/|/home/ros/桌面/dev_ws/src/capture_image/launch/| +ssh:pleaseaskme@192.168.110.92=/userdata/OriginMan/ActionGroups/|/userdata/OriginMan/|/userdata/hiwonder-tools/lab_tool/|/userdata/hiwonder-tools/originman_action_editor/|/userdata/hiwonder-tools/|/userdata/|/etc/systemd/system/|/etc/systemd/|/etc/|/|/home/ros/|/userdata/dev_ws/src/originman/driver/originman_action_editor/__pycache__/|/userdata/dev_ws/src/originman/driver/originman_action_editor/images/|/userdata/dev_ws/src/originman/driver/originman_action_editor/|/userdata/dev_ws/src/originman/driver/|/root/| +ssh:ros@10.211.90.19=/home/ros/image/|/home/ros/pt-onnx/|/home/ros/dataset_root/images/|/home/ros/dataset_root/labels/|/home/ros/dataset_root/|/home/ros/RDK_ToolChain/deps/wheels/|/home/ros/RDK_ToolChain/deps/|/home/ros/RDK_ToolChain/models/|/home/ros/RDK_ToolChain/|/home/ros/桌面/RDK_ToolChain/|/home/ros/clash-for-linux-install/|/home/ros/公共的/|/home/ros/文档/|/home/ros/|/home/ros/桌面/|/home/ros/音乐/| +ssh:root@192.168.110.29=/root/|/root/yolo_ws/yolo_local_test.py/|/root/yolo_ws/src/yolo_detection_pkg/config/|/root/yolo_ws/src/yolo_detection_pkg/yolo_detection_pkg/|/root/yolo_ws/src/yolo_detection_pkg/|/root/yolo_ws/src/|/root/yolo_ws/|/tmp/|/userdata/dev_ws/src/originman/originman_transport_lab/originman_transport_lab/|/userdata/dev_ws/src/originman/originman_transport_lab/|/userdata/OriginMan/|/userdata/dev_ws/src/originman/originman_apriltag_detect/originman_apriltag_detect/|/userdata/dev_ws/src/originman/originman_apriltag_detect/|/userdata/dev_ws/src/originman/|/userdata/dev_ws/src/|/userdata/dev_ws/| +ssh:root@192.168.110.17=/userdata/dev_ws/install/|/userdata/dev_ws/src/src/|/opt/tros/humble/|/opt/tros/|/opt/|/userdata/dev_ws/src/originbot/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/|/|/root/config/|/root/clean/|/root/|/root/vscode/lib/vscode/extensions/json-language-features/server/dist/node/|/root/vscode/lib/vscode/extensions/json-language-features/server/dist/|/root/vscode/lib/vscode/extensions/json-language-features/server/| +ssh:root@10.211.90.241=/usr/bin/out/|/usr/bin/|/usr/|/root/evdev-right-click-emulation-master/evdev-right-click-emulation-master/out/|/root/evdev-right-click-emulation-master/evdev-right-click-emulation-master/|/root/evdev-right-click-emulation-master/|/|/root/|/root/dev_ws/src/OrbbecSDK_ROS2/orbbec_camera/scripts/|/root/dev_ws/src/OrbbecSDK_ROS2/orbbec_description/|/root/dev_ws/src/OrbbecSDK_ROS2/orbbec_camera/SDK/lib/arm64/|/root/dev_ws/src/OrbbecSDK_ROS2/orbbec_camera/SDK/lib/|/root/dev_ws/src/OrbbecSDK_ROS2/orbbec_camera/SDK/|/root/dev_ws/src/OrbbecSDK_ROS2/orbbec_camera/|/root/dev_ws/src/OrbbecSDK_ROS2/docs/images/|/root/dev_ws/src/OrbbecSDK_ROS2/docs/| +ssh:pleaseaskme@10.211.90.119=/userdata/dev_ws/src/originman/originman_transport_lab/originman_transport_lab/|/userdata/dev_ws/src/originman/originman_transport_lab/|/userdata/OriginMan/|/userdata/dev_ws/src/originman/originman_apriltag_detect/originman_apriltag_detect/|/userdata/dev_ws/src/originman/originman_apriltag_detect/|/userdata/dev_ws/src/originman/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/|/|/root/| +ssh:root@192.168.110.92=/root/colcon_ws/src/originman_vision/launch/|/root/colcon_ws/src/originman_vision/originman_vision/|/root/colcon_ws/src/originman_vision/|/root/colcon_ws/src/|/root/colcon_ws/|/userdata/|/|/root/| +ssh:pleaseaskme@ubuntu.lan=/root/config/|/root/imx415_modes-main/.vscode/|/root/imx415_modes-main/|/etc/profile.d/|/etc/|/root/|/|/usr/src/linux-headers-6.1.83-rt/tools/testing/cxl/test/|/usr/src/linux-headers-6.1.83-rt/tools/testing/cxl/|/usr/src/linux-headers-6.1.83-rt/tools/testing/fault-injection/|/usr/src/linux-headers-6.1.83-rt/tools/testing/ktest/examples/bootconfigs/|/usr/src/linux-headers-6.1.83-rt/tools/testing/ktest/examples/include/|/usr/src/linux-headers-6.1.83-rt/tools/testing/ktest/examples/|/usr/src/linux-headers-6.1.83-rt/tools/testing/ktest/|/usr/src/linux-headers-6.1.83-rt/tools/testing/kunit/configs/|/usr/src/linux-headers-6.1.83-rt/tools/testing/kunit/qemu_configs/| +ssh:root@10.211.90.119=/root/| +ssh:pleaseaskme@192.168.110.123=/userdata/|/|/root/| +ssh:root@192.168.110.123=/var/tmp/|/var/|/etc/systemd/system/|/etc/systemd/|/etc/|/usr/local/bin/|/usr/local/|/usr/|/root/|/|/userdata/|/userdata/dev_ws/|/userdata/dev_ws/src/ybx_chassis/|/userdata/dev_ws/src/rplidar_ros/debian/|/userdata/dev_ws/src/rplidar_ros/scripts/|/userdata/dev_ws/src/rplidar_ros/sdk/include/| +ssh:pleaseaskme@192.168.110.126=/root/|/|/opt/tros/humble/share/audio_tracking/|/opt/tros/humble/share/mipi_cam/launch/|/opt/tros/humble/share/mipi_cam/|/opt/tros/humble/share/|/opt/tros/humble/|/opt/tros/|/opt/ros/humble/|/opt/ros/|/opt/|/app/pydev_demo/03_mipi_camera_sample/|/app/pydev_demo/|/app/|/userdata/dev_ws/src/originbot/originbot_bringup/launch/|/userdata/dev_ws/src/originbot/originbot_bringup/| +ssh:root@192.168.110.216=/root/.vscode-server/|/root/|/| +ssh:pleaseaskme@192.168.110.18=/var/tmp/|/var/|/|/root/| +ssh:root@10.218.33.190=/root/|/userdata/dev_ws/src/originbot/originbot_base/src/|/userdata/dev_ws/src/originbot/|/userdata/dev_ws/build/serial/|/userdata/dev_ws/build/|/userdata/dev_ws/src/originbot/originbot_driver/qpOASES/|/userdata/dev_ws/src/originbot/originbot_driver/serial_ros2/|/userdata/dev_ws/src/originbot/originbot_driver/|/userdata/dev_ws/src/originbot/originbot_base/|/|/userdata/dev_ws/src/originbot/originbot_bringup/config/|/userdata/dev_ws/src/originbot/originbot_bringup/param/|/userdata/dev_ws/src/originbot/originbot_bringup/launch/|/userdata/dev_ws/src/originbot/originbot_bringup/|/userdata/dev_ws/src/|/userdata/dev_ws/install/| +ssh:pleaseaskme@192.168.110.100=/userdata/dev_ws/install/originbot_base/share/originbot_base/launch/|/userdata/dev_ws/install/originbot_base/share/originbot_base/|/userdata/dev_ws/install/originbot_base/share/|/userdata/dev_ws/install/originbot_base/|/userdata/dev_ws/install/|/userdata/dev_ws/src/originbot/originbot_base/launch/|/userdata/dev_ws/src/originbot/originbot_base/include/originbot_base/|/userdata/dev_ws/src/originbot/originbot_base/include/|/userdata/dev_ws/src/originbot/originbot_base/|/userdata/dev_ws/src/originbot/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/|/|/root/| +ssh:root@192.168.110.100=/userdata/dev_ws/src/originbot/originbot_base/include/originbot_base/|/userdata/dev_ws/src/originbot/originbot_base/include/|/userdata/dev_ws/src/originbot/originbot_base/src/|/userdata/dev_ws/src/originbot/originbot_base/launch/|/userdata/dev_ws/src/originbot/originbot_base/|/userdata/dev_ws/src/originbot/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/|/|/root/| +ssh:root@192.168.127.10=/userdata/dev_ws/src/marm_code/|/userdata/dev_ws/src/codbot_base/|/root/Audio/|/userdata/dev_ws/src/marm_code/arm_controller/arm_controller/|/userdata/dev_ws/src/marm_code/arm_controller/|/userdata/dev_ws/src/marm_code/capture_image/|/userdata/dev_ws/src/|/userdata/|/root/|/|/userdata/dev_ws/|/userdata/dev_ws/src/marm_code/moveit_controller_server/src/|/userdata/dev_ws/src/marm_code/moveit_controller_server/scripts/|/userdata/dev_ws/src/marm_code/moveit_controller_server/nouse/|/userdata/dev_ws/src/marm_code/moveit_controller_server/config/|/userdata/dev_ws/src/marm_code/moveit_controller_server/| +ssh:pleaseaskme@192.168.110.222=/userdata/dev_ws/install/|/userdata/dev_ws/src/originbot/originbot_bringup/param/|/userdata/dev_ws/src/originbot/originbot_bringup/launch/|/userdata/dev_ws/src/originbot/originbot_bringup/|/userdata/dev_ws/src/originbot/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/|/|/root/| +ssh:root@192.168.110.239=/userdata/dev_ws/src/car_navigation/param/|/vendor/|/userdata/dev_ws/src/car_navigation/maps/|/userdata/dev_ws/src/car_navigation/launch/|/userdata/dev_ws/src/car_navigation/|/userdata/dev_ws/src/codbot_base/launch/|/userdata/dev_ws/src/codbot_base/|/userdata/dev_ws/src/|/userdata/dev_ws/|/userdata/|/root/.config/|/|/root/| +ssh:@192.168.110.161=/home/ros/桌面/dev_ws/|/home/ros/桌面/dev_ws/src/moveit_controller_server/srv/|/home/ros/桌面/dev_ws/src/moveit_controller_server/src/|/home/ros/桌面/dev_ws/src/moveit_controller_server/scripts/|/home/ros/桌面/dev_ws/src/moveit_controller_server/nouse/|/home/ros/桌面/dev_ws/src/moveit_controller_server/config/|/home/ros/桌面/dev_ws/src/moveit_controller_server/|/home/ros/桌面/dev_ws/src/custom_interface/srv/|/home/ros/桌面/dev_ws/src/custom_interface/|/home/ros/桌面/dev_ws/src/capture_image/src/|/home/ros/桌面/dev_ws/src/capture_image/launch/|/home/ros/桌面/dev_ws/src/capture_image/include/|/home/ros/桌面/dev_ws/src/capture_image/|/home/ros/桌面/dev_ws/src/arm_controller/test/|/home/ros/桌面/dev_ws/src/arm_controller/resource/|/home/ros/桌面/dev_ws/src/arm_controller/arm_controller/| +ssh:pleaseaskme@10.38.94.230=/home/ros/桌面/1/|/home/ros/桌面/|/home/ros/a1x_ros/build/|/home/ros/a1xy_ros/install/share/|/home/ros/a1xy_ros/install/|/home/ros/a1x_ros/src/a1x_teleop/scripts/|/home/ros/a1x_ros/src/a1x_teleop/|/home/ros/a1x_ros/src/|/home/ros/a1x_ros/|/home/ros/a1xy_ros/|/home/ros/| +ssh:pleaseaskme@192.168.110.233=/root/colcon_ws/install/originman_vision/share/originman_vision/launch/|/root/colcon_ws/install/originman_vision/share/originman_vision/|/root/colcon_ws/install/originman_vision/share/|/root/colcon_ws/install/originman_vision/|/root/colcon_ws/install/|/root/colcon_ws/src/originman_vision/launch/|/root/colcon_ws/src/originman_vision/originman_vision/|/root/colcon_ws/src/originman_vision/|/root/colcon_ws/src/|/root/colcon_ws/|/root/| + +[WindowPos_HUANG_3200_2000_1920_1080] +CompactMode=0 +MonitorCount=2 +Left=-13 +Top=-13 +Width=3226 +Height=1930 +Maximized=1 +SidebarVisible=1 +SidebarWidth=377 + +[Font] +Font2=MobaFont +FontIsBold2=0 +FontHeight2=10 +FontCharset2=0 +FontQuality2=3 +Ligatures=0 +Charset2=UTF-8 +LockRowsCols=0 +LockedCols=80 +LockedRows=24 + +[Cursor] +CursorType=0 +CursorBlinks=0 + +[PopupConsole] +Transparency=16 +Size=36 +Sizeable=0 +Position=3 +TryToOpenInExplorerFolder=1 +BackgroundInsteadOfClose=0 + +[X11Extension] +Composite=1 +DAMAGE=1 +RANDR=1 +XFIXES=1 +XTEST=1 +XINERAMA=1 + +[Bookmarks] +SubRep= +ImgNum=42 +10.211.90.190 (root)=#109#0%10.211.90.190%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +10.211.90.241 (root)=#109#0%10.211.90.241%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +114.55.66.216 (root)=#109#0%114.55.66.216%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.110.123 (root)=#109#0%192.168.110.123%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.110.161=#109#0%192.168.110.161%22%ros%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0#小主机 #-1 +192.168.110.17 (root)=#109#0%192.168.110.17%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.110.216 (root)=#109#0%192.168.110.216%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.110.239 (root)=#109#0%192.168.110.239%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.110.92 (root)=#109#0%192.168.110.92%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +192.168.127.10 (root)=#109#0%192.168.127.10%22%root%%-1%-1%%%%%0%0%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +COM3 (USB-SERIAL CH340 (COM3))=#131#8%0%1921600%3%0%0%1%2%COM3 (USB-SERIAL CH340 (COM3))#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +ubuntu.lan (root)=#109#0%ubuntu.lan%22%%%-1%-1%%%%%0%-1%0%%%-1%-1%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0%%#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +WSL-默认=#151#14%默认%%交互式 shell%%%0#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 +串口(COM)=#131#8%-1%1115200%3%0%0%1%2%<在会话启动时选择>#MobaFont%10%0%0%-1%15%236,236,236%30,30,30%180,180,192%0%-1%0%%xterm%-1%0%_Std_Colors_0_%80%24%0%1%-1%<无>%%0%0%-1%0%#0# #-1 + +[LastInstanceSessions] +0= +1=用户会话\192.168.110.239 (root) + +[EditorWindowPos_3200_2000_192] +Left=-13 +Top=-13 +Width=3226 +Height=1930 +Maximized=1 +MonitorCount=1 + +[MobaTextEditor] +FontName3=MobaFanta +FontLigatures3=0 +FontHeight3=-13 +GutterVisible=1 +GutterAutosize=1 +GutterShowLineNumbers=1 +GutterZeroStart=0 +GutterLeadingZeros=0 +GutterFontName=Verdana +GutterFontSize=8 +EdgeColumn=800 +EdgeColor=16777215 +ExtraLineSpacing=0 +TabWidth=2 +BookmarkKeys=1 +BookmarksVisible=1 +Options=39866307 +WantTabs=1 +WordWrap=0 + +[13:41.34.897] +[13:41.34.897] +[13:41.34.897] ================================================================================ +[13:41.34.897] +[13:41.34.897] +[13:41.34.897] +[13:41.34.897] +[13:41.34.897] +[13:41.34.897] 检测是否需要主密码的 INI 文件 +[13:41.34.897] 不需要主密码的 INI 文件 +[13:41.34.897] 未检测到主密码. 正在识别迁移需求... +[13:41.34.897] 正在查找先前存储的密码在 INI 文件 +[13:41.34.897] 未找到存储的密码 在 INI 文件 +[13:41.34.897] NeedMigration:=false +[13:41.34.897] +[13:41.34.897] BEGIN CreerFstab +[13:41.34.897] CreerFstab: RootDirectory = C:/Users/31554/AppData/Local/Temp/Mxt252 +[13:41.34.898] CreerFstab: HomeDirectory = C:/Users/31554/AppData/Local/Temp/Mxt252/tmp/HOME_3~1 +[13:41.34.898] END CreerFstab +[13:41.34.898] BEGIN extraireFichiers1 +[13:41.34.898] BEGIN CreerProfile +[13:41.34.899] END CreerProfile +[13:41.34.899] BEGIN CreerSshConfig +[13:41.34.899] END CreerSshConfig +[13:41.34.899] BEGIN CreerBaseProfile +[13:41.34.899] NEW PLUGIN: mobase +[13:41.34.899] BEGIN ProcessPlugin(mobase) +[13:41.34.899] BEGIN WaitForGetMobaseStream +[13:41.34.899] END WaitForGetMobaseStream +[13:41.34.900] END ProcessPlugin(mobase) +[13:41.34.900] NEW PLUGIN: D:\MobaXterm_25.2_CN\CygUtils.plugin +[13:41.34.900] BEGIN ProcessPlugin(D:\MobaXterm_25.2_CN\CygUtils.plugin) +[13:41.34.904] END ProcessPlugin(D:\MobaXterm_25.2_CN\CygUtils.plugin) +[13:41.34.906] 请求提取文件: /bin/ssh-agent.exe +[13:41.34.932] 文件 ssh-agent.exe 已提取, 来自 CygUtils.plugin. +[13:41.34.933] 请求提取文件: /bin/cyggcc_s-1.dll +[13:41.34.962] 文件 cyggcc_s-1.dll 已提取, 来自 CygUtils.plugin. +[13:41.34.963] 请求提取文件: /bin/cyggcc_s-seh-1.dll +[13:41.34.964] BEGIN WaitForAllThreads +[13:41.34.964] END WaitForAllThreads +[13:41.34.965] END CreerBaseProfile +[13:41.34.965] Creating /etc/group file +[13:41.34.965] BEGIN MkGroupFile +[13:41.34.976] SaveStringListToUnixFile(C:\Users\31554\AppData\Local\Temp\Mxt252\etc\group) +[13:41.34.976] MkGroupFile OK +[13:41.34.976] END MkGroupFile +[13:41.34.976] Creating /etc/passwd file +[13:41.34.977] BEGIN MkPasswdFile +[13:41.34.977] Current Domain: HUANG +[13:41.34.980] MkPasswdFile OK +[13:41.34.980] END MkPasswdFile +[13:41.34.980] Creating /etc/nsswitch.conf file +[13:41.34.980] BEGIN CreerNsswitch +[13:41.34.980] END CreerNsswitch +[13:41.34.981] 请求提取文件: /bin/scrdaemons +[13:41.34.982] 文件 scrdaemons 已提取, 来自 CygUtils.plugin. +[13:41.34.982] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\scrdaemons, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\init.d\tftp); +[13:41.34.982] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\scrdaemons, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\init.d\ftp); +[13:41.34.983] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\scrdaemons, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\init.d\http); +[13:41.34.983] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\scrdaemons, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\init.d\ssh); +[13:41.34.984] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\scrdaemons, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\init.d\telnet); +[13:41.34.984] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\scrdaemons, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\init.d\nfs); +[13:41.34.984] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\scrdaemons, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\init.d\vnc); +[13:41.34.986] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\usr\share\fonts, C:\Users\31554\AppData\Local\Temp\Mxt252\usr\share\X11\fonts); +[13:41.34.989] 请求提取文件: /bin/cygtermd.exe +[13:41.35.016] 文件 cygtermd.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.017] 请求提取文件: /bin/cygz.dll +[13:41.35.048] 文件 cygz.dll 已提取, 来自 CygUtils.plugin. +[13:41.35.050] 请求提取文件: /bin/cyggcc_s-1.dll +[13:41.35.050] 文件 cyggcc_s-1.dll 已提取, 来自 CygUtils.plugin. +[13:41.35.050] 请求提取文件: /bin/cygwin-console-helper.exe +[13:41.35.080] 文件 cygwin-console-helper.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.081] 请求提取文件: /bin/ssh.exe +[13:41.35.083] 文件 ssh.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.084] 请求提取文件: /etc/bash.bash_logout +[13:41.35.085] 请求提取文件: /etc/profile.d +[13:41.35.085] 请求提取文件: /etc/profile.d/* +[13:41.35.085] CreerRaccourciVersMobaXterm(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaListPorts, -listports); +[13:41.35.086] CreerRaccourciVersMobaXterm(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaPictureViewer, -picview); +[13:41.35.086] CreerRaccourciVersMobaXterm(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaTextEditor, -edit); +[13:41.35.086] CreerRaccourciVersMobaXterm(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaGitEditor, -gitedit); +[13:41.35.087] CreerRaccourciVersMobaXterm(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaCompareFiles, -compfiles); +[13:41.35.087] CreerRaccourciVersMobaXterm(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaCompareFolders, -compfolders); +[13:41.35.088] 请求提取文件: /usr/share/terminfo/78/xterm +[13:41.35.091] 文件 xterm 已提取, 来自 CygUtils.plugin. +[13:41.35.092] 请求提取文件: /usr/share/terminfo/63/cygwin +[13:41.35.094] 文件 cygwin 已提取, 来自 CygUtils.plugin. +[13:41.35.095] 请求提取文件: /etc/bash_completion +[13:41.35.098] 文件 bash_completion 已提取, 来自 CygUtils.plugin. +[13:41.35.098] 请求提取文件: /usr/share/zoneinfo/posixrules +[13:41.35.099] 文件 posixrules 已提取, 来自 mobase. +[13:41.35.100] 请求提取文件: /etc/inputrc +[13:41.35.102] 文件 inputrc 已提取, 来自 CygUtils.plugin. +[13:41.35.102] END extraireFichiers1 +[13:41.35.102] CreateSymbolicLink(/proc/registry, C:\Users\31554\AppData\Local\Temp\Mxt252\registry); +[13:41.35.102] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\bash.exe, C:\Users\31554\AppData\Local\Temp\Mxt252\bin\sh); +[13:41.35.103] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\drives, C:\Users\31554\AppData\Local\Temp\Mxt252\cygdrive); +[13:41.35.103] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\drives, C:\Users\31554\AppData\Local\Temp\Mxt252\mnt); +[13:41.35.104] CreateSymbolicLink(C:\Users\31554\AppData\Local\Temp\Mxt252\drives, C:\Users\31554\AppData\Local\Temp\Mxt252\media); +[13:41.35.104] CreateSymbolicLink(/proc/registry, C:\Users\31554\AppData\Local\Temp\Mxt252\registry); +[13:41.35.105] CreateSymbolicLink(C:\WINDOWS\system32\drivers\etc\hosts, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\hosts); +[13:41.35.105] CreateSymbolicLink(C:\WINDOWS\system32\drivers\etc\networks, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\networks); +[13:41.35.106] CreateSymbolicLink(C:\WINDOWS\system32\drivers\etc\protocol, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\protocol); +[13:41.35.107] CreateSymbolicLink(C:\WINDOWS\system32\drivers\etc\services, C:\Users\31554\AppData\Local\Temp\Mxt252\etc\services); +[13:41.35.109] CreateSymbolicLink(C:\Users\31554\Desktop\, C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\home_31554\Desktop); +[13:41.35.110] CreateSymbolicLink(C:\Users\31554\DOCUME~1\, C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\home_31554\MyDocuments); +[13:41.35.110] CreateSymbolicLink(D:\MobaXterm_25.2_CN\, C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\home_31554\LauncherFolder); +[13:41.35.113] BEGIN LoadSharedSessions +[13:41.35.114] END LoadSharedSessions +[13:41.35.114] BEGIN LoadSharedSessions +[13:41.35.114] END LoadSharedSessions +[13:41.35.117] BEGIN RecreateBookmarksMenus +[13:41.35.117] RecreateBookmarksMenus: FreeBookmarksMenuItems(Form1.Xserver3) +[13:41.35.117] RecreateBookmarksMenus: FreeBookmarksMenuItems(Bookmarks1) +[13:41.35.117] 创建会话菜单项 +[13:41.35.117] 创建别名 +[13:41.35.117] TreeSessions.Expand +[13:41.35.117] END RecreateBookmarksMenus +[13:41.35.118] 请求提取文件: /bin/motty.exe +[13:41.35.404] 文件 motty.exe 已提取, 来自 mobase. +[13:41.35.405] 请求提取文件: /bin/cygtermd.exe +[13:41.35.405] 文件 cygtermd.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.405] 请求提取文件: /bin/cygwin1.dll +[13:41.35.547] 文件 cygwin1.dll 已提取, 来自 CygUtils.plugin. +[13:41.35.548] 请求提取文件: /bin/zsh.exe +[13:41.35.623] 请求提取文件: /bin/cygncursesw-10.dll +[13:41.35.664] 文件 cygncursesw-10.dll 已提取, 来自 CygUtils.plugin. +[13:41.35.664] 文件 zsh.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.665] 请求提取文件: /bin/toybox.exe +[13:41.35.710] 文件 toybox.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.711] 请求提取文件: /bin/bash.exe +[13:41.35.771] 文件 bash.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.771] 请求提取文件: /bin/busybox.exe +[13:41.35.819] 文件 busybox.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.819] 请求提取文件: /bin/grep.exe +[13:41.35.854] 请求提取文件: /bin/cygintl-8.dll +[13:41.35.881] 请求提取文件: /bin/cygiconv-2.dll +[13:41.35.958] 文件 cygiconv-2.dll 已提取, 来自 CygUtils.plugin. +[13:41.35.958] 文件 cygintl-8.dll 已提取, 来自 CygUtils.plugin. +[13:41.35.958] 文件 grep.exe 已提取, 来自 CygUtils.plugin. +[13:41.35.958] BEGIN WaitForAllThreads +[13:41.35.958] END WaitForAllThreads +[13:41.35.958] BEGIN WaitForAllThreads +[13:41.35.958] END WaitForAllThreads +[13:41.35.975] BEGIN WaitForGenerateStdListThreads +[13:41.35.975] END WaitForGenerateStdListThreads +[13:41.35.976] +[13:41.35.976] +[13:41.35.976] +-----------------------+ +[13:41.35.976] | 启动程序用时: 2568 ms | +[13:41.35.976] +-----------------------+ +[13:41.35.976] +[13:41.35.976] +[13:41.35.976] +[13:41.35.976] BEGIN Form4.FormActivate +[13:41.35.976] Form4.FormActivate0: 首次窗口激活 +[13:41.35.993] Form4.FormActivate1 +[13:41.35.993] Form4.FormActivate2 +[13:41.36.007] Form4.FormActivate3 +[13:41.36.015] Form4.FormActivate4 +[13:41.36.015] Form4.FormActivate5 +[13:41.36.017] Form4.FormActivate6 +[13:41.36.017] 注册全局显示/隐藏快捷键 +[13:41.36.017] 注册全局显示/隐藏弹窗式终端 +[13:41.36.017] BEGIN LoadParamsFromIni: D:\MobaXterm_25.2_CN\MobaXterm.ini +[13:41.36.017] LoadParamsFromIni: GlobalFontName:=MobaFont +[13:41.36.017] LoadParamsFromIni: GlobalFontCharset:=0 +[13:41.36.017] LoadParamsFromIni1 +[13:41.36.017] LoadParamsFromIni2 +[13:41.36.027] LoadParamsFromIni9 +[13:41.36.027] LoadParamsFromIni10 +[13:41.36.027] LoadParamsFromIni11 +[13:41.36.027] LoadParamsFromIni12 +[13:41.36.027] LoadParamsFromIni13 +[13:41.36.027] LoadParamsFromIni14 +[13:41.36.027] LoadParamsFromIni15 +[13:41.36.027] LoadParamsFromIni16 +[13:41.36.027] END LoadParamsFromIni +[13:41.36.027] Form4.FormActivate: OldMaximized:=Form4.WindowState +[13:41.36.027] Form4.FormActivate: TermImage.Canvas.Font.Assign(MobaFont) +[13:41.36.027] Form4.FormActivate: TermImage.Canvas.Font.Size:=10 +[13:41.36.027] Form4.FormActivate: TermImage.Canvas.Font.Name:=MobaFont +[13:41.36.027] Form4.FormActivate: Starting "GetMinHeight" +[13:41.36.027] GetMinHeight = 1047 +[13:41.36.027] Form4.FormActivate: Form4.Constraints.MinHeight:=1047 +[13:41.36.027] GetMinWidth = 1846 +[13:41.36.027] Form4.FormActivate: Form4.Constraints.MinWidth:=1846 +[13:41.36.027] Form4.FormActivate: Form4.Left:=677 +[13:41.36.027] BEGIN GetNextAvailableX +[13:41.36.028] END GetNextAvailableX = 0 +[13:41.36.028] +[13:41.36.028] CurrentX = 0 +[13:41.36.028] ChDir(Form1.BaseDir): C:\Users\31554\AppData\Local\ +[13:41.36.028] FirstParam: +[13:41.36.028] 正在启动 NewTab +[13:41.36.028] +[13:41.36.028] BEGIN NEWTAB(home, 135, 0) +[13:41.36.033] NEWTAB: Application.ProcessMessages +[13:41.36.034] NEWTAB: Timer1_Disable +[13:41.36.080] +[13:41.36.080] BEGIN Form4.FormActivate +[13:41.36.080] END Form4.FormActivate +[13:41.36.080] +[13:41.36.111] BEGIN TFormXterm.FormResize +[13:41.36.111] TFormXterm.FormResize: CenterBtnReattachTab +[13:41.36.111] TFormXterm.FormResize: SplitModeResize +[13:41.36.111] TFormXterm.FormResize: TabMax<=0. Exiting... +[13:41.36.111] END TFormXterm.FormResize +[13:41.36.111] BEGIN WMSize +[13:41.36.111] BEGIN TFormXterm.FormResize +[13:41.36.111] TFormXterm.FormResize: CenterBtnReattachTab +[13:41.36.111] TFormXterm.FormResize: SplitModeResize +[13:41.36.111] TFormXterm.FormResize: TabMax<=0. Exiting... +[13:41.36.111] END TFormXterm.FormResize +[13:41.36.111] END WMSize +[13:41.36.112] NEWTAB: 检查是否已达到最大标签数... +[13:41.36.112] NEWTAB: 创建 SFTPRecord... +[13:41.36.114] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[13:41.36.114] NEWTAB: 尝试查找旧索引... +[13:41.36.114] NEWTAB: Cts1.BeginUpdate; +[13:41.36.114] NEWTAB: 创建新标签页... +[13:41.36.114] NEWTAB: 标签页索引: 0 +[13:41.36.114] NEWTAB: 终端编号 : 1 +[13:41.36.114] NEWTAB: 标题 : 主页 +[13:41.36.114] NEWTAB: 命令 : home +[13:41.36.114] Cts1ActiveTabChanged: New index = 0 +[13:41.36.114] NEWTAB: Cts1.EndUpdates + + +[13:41.37.835] NEWTAB: 更改标签页索引 A = 0 +[13:41.37.835] BEGIN WaitForAllThreads +[13:41.37.835] END WaitForAllThreads +[13:41.37.835] +[13:41.37.835] LaunchTabContent(home, 主页); +[13:41.37.835] +[13:41.37.835] CreerSessionMoTTY(1, home, 主页) +[13:41.37.835] CreerSessionMoTTY(-1, /bin/_TCPCapture.sh, TCPCapture) +[13:41.37.837] Setting LOCALE=zh_CN.UTF-8 +[13:41.37.880] +[13:41.37.880] FindWindow() +[13:41.37.880] BEGIN MoTTY.SetParent +[13:41.37.884] END MoTTY.SetParent +[13:41.37.884] NEWTAB: Application.OnMessage:=AppMessage +[13:41.37.884] NEWTAB: 更改标签页索引 C = 0 +[13:41.37.884] NEWTAB: 正在启动 DisplayCurrentTab... +[13:41.37.884] BEGIN DisplayCurrentTab +[13:41.37.884] DisplayCurrentTab: FormClick +[13:41.37.884] (SSH-Browser) DisplayCurrentTab(0): ActiverPanel14 +[13:41.37.884] (SSH-Browser) BEGIN ActiverPanel14 +[13:41.37.884] (SSH-Browser) BEGIN DesactiverPanel14 +[13:41.37.884] (SSH-Browser) END DesactiverPanel14 +[13:41.37.884] (SSH-Browser) END ActiverPanel14; +[13:41.37.898] DisplayCurrentTab: Cts1.BeginUpdate; +[13:41.37.898] DisplayCurrentTab: Cts1.EndUpdates +[13:41.37.902] DisplayCurrentTab: 显示所选标签页 +[13:41.37.906] BEGIN ResizeTerminal +[13:41.37.906] END ResizeTerminal +[13:41.37.906] DisplayCurrentTab: 隐藏其他标签页 +[13:41.37.906] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[13:41.37.906] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[13:41.37.906] DisplayCurrentTab: DistribuerLeFocus +[13:41.37.909] BEGIN WMNewTab: 0 +[13:41.37.909] WMNewTab: FormClick +[13:41.37.909] WMNewTab: LooseFocus +[13:41.37.909] END WMNewTab: 0 +[13:41.37.909] BEGIN WMNewTab: 0 +[13:41.37.909] WMNewTab: FormClick +[13:41.37.909] WMNewTab: LooseFocus +[13:41.37.910] END WMNewTab: 0 +[13:41.37.910] BEGIN WMNewTab: 0 +[13:41.37.910] WMNewTab: FormClick +[13:41.37.910] WMNewTab: LooseFocus +[13:41.37.910] END WMNewTab: 0 +[13:41.37.910] BEGIN WMNewTab: 0 +[13:41.37.910] WMNewTab: FormClick +[13:41.37.910] WMNewTab: LooseFocus +[13:41.37.910] END WMNewTab: 0 +[13:41.37.912] END DisplayCurrentTab +[13:41.37.912] NEWTAB: NewTab_ReEnable_Timer1 +[13:41.37.912] NEWTAB: MajVerticalTabs +[13:41.37.912] NEWTAB: Cts1.Resize; +[13:41.37.915] END NEWTAB(home, 135, 0) +[13:41.37.915] +[13:41.37.915] +[13:41.37.915] +[13:41.37.915] +[13:41.37.915] +---------------------------------+ +[13:41.37.915] | 主窗口激活 用时: 1938 ms | +[13:41.37.915] +---------------------------------+ +[13:41.37.915] +[13:41.37.915] +[13:41.37.915] +[13:41.37.915] 正在启动 bookmarks(); +[13:41.37.915] 正在启动 sBitBtn7Click(sBitBtn7); +[13:41.37.915] +[13:41.37.915] BEGIN LaunchX11(); +[13:41.37.915] BEGIN MobaThreadXressources.Execute(nil); +[13:41.37.915] END MobaThreadXressources.Execute(nil); + + +[13:41.39.313] BEGIN ExecuteSessionTree +[13:41.39.313] ExecuteSessionTree: FormClick +[13:41.39.316] BEGIN ExecuteSelectedSession +[13:41.39.316] ExecuteSelectedSession: FormClick +[13:41.39.316] ExecuteSelectedSession0 +[13:41.39.316] ExecuteSelectedSession1 +[13:41.39.316] ExecuteSelectedSession2 +[13:41.39.316] ExecuteSelectedSession3 +[13:41.39.316] BEGIN ChargerLaSession +[13:41.39.316] ChargerLaSession1 +[13:41.39.432] ChargerLaSession2 +[13:41.39.432] ChargerLaSession3 +[13:41.39.432] ChargerLaSession4 +[13:41.39.433] ChargerLaSession5 +[13:41.39.433] ChargerLaSession6 +[13:41.39.437] ChargerLaSession7 +[13:41.39.439] ChargerLaSession8 +[13:41.39.439] ChargerLaSession8_ssh_1 +[13:41.39.439] ChargerLaSession8_ssh_2 +[13:41.39.439] ChargerLaSession8_ssh_3 +[13:41.39.439] ChargerLaSession8_ssh_4 +[13:41.39.439] ChargerLaSession9 +[13:41.39.508] ChargerLaSession10 +[13:41.39.508] END ChargerLaSession +[13:41.39.508] ExecuteSelectedSession4 +[13:41.39.508] LaunchSession0 +[13:41.39.563] LaunchSession1 +[13:41.39.563] LaunchSession4 +[13:41.39.563] LaunchSession5 +[13:41.39.563] +[13:41.39.563] BEGIN NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[13:41.39.563] NEWTAB: Application.ProcessMessages +[13:41.39.567] NEWTAB: Timer1_Disable +[13:41.39.567] NEWTAB: 检查是否已达到最大标签数... +[13:41.39.567] NEWTAB: 创建 SFTPRecord... +[13:41.39.570] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[13:41.39.570] NEWTAB: 尝试查找旧索引... +[13:41.39.570] NEWTAB: Cts1.BeginUpdate; +[13:41.39.570] NEWTAB: 创建新标签页... +[13:41.39.570] NEWTAB: 标签页索引: 1 +[13:41.39.570] NEWTAB: 终端编号 : 2 +[13:41.39.570] NEWTAB: 标题 : 192.168.127.10 (root) +[13:41.39.570] NEWTAB: 命令 : ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[13:41.39.570] Cts1ActiveTabChanged: New index = 1 +[13:41.39.570] NEWTAB: Cts1.EndUpdates +[13:41.39.716] NEWTAB: 更改标签页索引 A = 1 +[13:41.39.732] BEGIN WaitForAllThreads +[13:41.39.732] END WaitForAllThreads +[13:41.39.732] +[13:41.39.732] LaunchTabContent(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)); +[13:41.39.732] +[13:41.39.754] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[13:41.39.937] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[13:41.39.956] MOBANOACL=onlyslash +[13:41.40.010] +[13:41.40.010] ShellExecute: motty.exe +[13:41.40.010] +[13:41.40.010] CreerSessionMoTTY(2, ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)) +[13:41.40.165] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[13:41.40.166] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[13:41.40.166] MOBANOACL=onlyslash +[13:41.40.169] +[13:41.40.169] BEGIN LIVE-CREATING TFormTermConfirmClose +[13:41.40.189] END LIVE-CREATING TFormTermConfirmClose +[13:41.40.189] +[13:41.40.192] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756662") + +[13:41.41.155] ShellExecuteS: ShellExecuteEx 成功. +[13:41.41.227] ShellExecuteS: WaitForInputIdle 成功. +[13:41.41.227] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756662") +[13:41.41.227] +[13:41.41.227] FindWindow(CMoTTY) +[13:41.41.227] 潜在窗口 530304 成功通过第二次验证. +[13:41.41.227] --> 成功 +[13:41.41.228] BEGIN MoTTY.SetParent +[13:41.41.244] END MoTTY.SetParent +[13:41.41.244] NEWTAB: Application.OnMessage:=AppMessage +[13:41.41.250] NEWTAB: 更改标签页索引 C = 1 +[13:41.41.250] NEWTAB: 正在启动 DisplayCurrentTab... +[13:41.41.250] BEGIN DisplayCurrentTab +[13:41.41.250] DisplayCurrentTab: FormClick +[13:41.41.250] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[13:41.41.250] (SSH-Browser) BEGIN ActiverPanel14 +[13:41.41.250] (SSH-Browser) BEGIN DesactiverPanel14 +[13:41.41.250] (SSH-Browser) END DesactiverPanel14 +[13:41.41.250] (SSH-Browser) END ActiverPanel14; +[13:41.41.264] DisplayCurrentTab: Cts1.BeginUpdate; +[13:41.41.264] DisplayCurrentTab: Cts1.EndUpdates +[13:41.41.271] DisplayCurrentTab: 显示所选标签页 +[13:41.41.271] DisplayCurrentTab: 隐藏其他标签页 +[13:41.41.273] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[13:41.41.274] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[13:41.41.274] DisplayCurrentTab: DistribuerLeFocus +[13:41.41.276] END DisplayCurrentTab +[13:41.41.276] NEWTAB: NewTab_ReEnable_Timer1 +[13:41.41.276] NEWTAB: MajVerticalTabs +[13:41.41.276] NEWTAB: Cts1.Resize; +[13:41.41.284] END NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[13:41.41.284] +[13:41.41.284] LaunchSession6 +[13:41.41.284] ExecuteSelectedSession5 +[13:41.41.284] END ExecuteSelectedSession +[13:41.41.284] END ExecuteSessionTree +[13:41.41.289] SetTitle(1, 192.168.127.10 (root)); +[13:41.41.289] BEGIN MobaThreadXressources.WaitFor; +[13:41.41.289] END MobaThreadXressources.WaitFor; +[13:41.41.290] 请求提取文件: /usr/share/x11/xkb/symbols/mokeypad +[13:41.41.290] 文件 mokeypad 已提取, 来自 mobase. +[13:41.41.293] 请求提取文件: /usr/share/x11/xkb/symbols/mopc +[13:41.41.294] 文件 mopc 已提取, 来自 mobase. +[13:41.41.294] 请求提取文件: /usr/share/fonts/misc/7x13-iso8859-1.pcf +[13:41.41.294] 请求提取文件: /usr/share/fonts/misc/6x13-ISO8859-1.pcf +[13:41.41.294] 请求提取文件: /usr/share/fonts/misc/cursor.pcf +[13:41.41.295] 请求提取文件: /usr/share/icons/default/cursors/left_ptr +[13:41.41.295] 请求提取文件: /usr/share/icons/default/index.theme +[13:41.41.295] 请求提取文件: /usr/share/pixmaps/default/cursors/left_ptr +[13:41.41.295] 请求提取文件: /usr/share/pixmaps/default/index.theme +[13:41.41.295] 请求提取文件: /usr/share/fonts/misc/fonts.dir +[13:41.41.295] 请求提取文件: /usr/share/fonts/misc/fonts.alias +[13:41.41.295] 请求提取文件: /usr/share/fonts/75dpi/fonts.dir +[13:41.41.295] 请求提取文件: /usr/share/fonts/75dpi/fonts.alias +[13:41.41.295] 请求提取文件: /usr/share/fonts/100dpi/fonts.dir +[13:41.41.295] 请求提取文件: /usr/share/fonts/100dpi/fonts.alias +[13:41.41.297] 请求提取文件: /usr/share/fonts/Speedo/fonts.dir +[13:41.41.297] 请求提取文件: /usr/share/fonts/Speedo/fonts.alias +[13:41.41.297] 请求提取文件: /usr/share/fonts/OTF/fonts.dir +[13:41.41.297] 请求提取文件: /usr/share/fonts/OTF/fonts.alias +[13:41.41.297] 请求提取文件: /usr/share/fonts/TTF/fonts.dir +[13:41.41.297] 请求提取文件: /usr/share/fonts/TTF/fonts.alias +[13:41.41.297] 请求提取文件: /usr/share/fonts/cyrillic/fonts.dir +[13:41.41.297] 请求提取文件: /usr/share/fonts/cyrillic/fonts.alias +[13:41.41.297] 请求提取文件: /usr/share/fonts/Type1/fonts.dir +[13:41.41.298] 请求提取文件: /usr/share/fonts/Type1/fonts.alias +[13:41.41.298] 请求提取文件: /usr/share/X11/rgb.txt +[13:41.41.298] 请求提取文件: /usr/share/X11/XErrorDB +[13:41.41.298] 请求提取文件: /usr/share/X11/XKeysymDB +[13:41.41.298] BEGIN WaitForAllThreads +[13:41.41.298] END WaitForAllThreads +[13:41.41.298] BEGIN WaitForAllThreads +[13:41.41.298] END WaitForAllThreads +[13:41.41.298] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[13:41.41.298] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\) +[13:41.41.298] MOBANOACL=onlyslash +[13:41.41.298] +[13:41.41.299] XWin Exec: C:\Users\31554\AppData\Local\Temp\Mxt252\bin\XWin_MobaX.exe -silent-dup-error -notrayicon -nolisten inet6 -hostintitle +bs -clipboard -nowgl -multiwindow -noreset :0 +[13:41.41.299] +[13:41.41.299] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\XWin_MobaX.exe, -silent-dup-error -notrayicon -nolisten inet6 -hostintitle +bs -clipboard -nowgl -multiwindow -noreset :0) +[13:41.41.377] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[13:41.41.377] 主机密钥与缓存中的密钥是一致的 +[13:41.41.387] BEGIN GetPassword +[13:41.41.387] BEGIN GetnSaveCredPassword +[13:41.41.387] END GetnSaveCredPassword +[13:41.41.387] END GetPassword +[13:41.41.536] ShellExecuteS: ShellExecuteEx 成功. + +[13:41.42.698] ShellExecuteS: WaitForInputIdle 成功. +[13:41.42.699] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\XWin_MobaX.exe, -silent-dup-error -notrayicon -nolisten inet6 -hostintitle +bs -clipboard -nowgl -multiwindow -noreset :0) +[13:41.42.699] END LaunchX11(); +[13:41.42.699] +[13:41.42.699] +[13:41.42.699] +[13:41.42.699] +--------------------------------+ +[13:41.42.699] | X11 服务器激活 用时: 4784 ms | +[13:41.42.699] +--------------------------------+ +[13:41.42.699] +[13:41.42.699] +[13:41.42.699] END Form4.FormActivate +[13:41.42.699] +[13:41.42.699] Form1.Timer1Timer 已完成. +[13:41.42.699] + + +[13:41.44.286] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[13:41.44.286] BEGIN SauvegarderMotDePasseSSH +[13:41.44.286] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[13:41.44.286] SetTitle(1, root@192.168.127.10); +[13:41.44.286] +[13:41.44.286] (SSH-Browser) BEGIN ConnectSSH(1,192.168.127.10,root,) +[13:41.44.286] (SSH-Browser) ConnectSSH(1): 初始化 TabSFTP +[13:41.44.287] (SSH-Browser) ConnectSSH(1): 未使用代理 +[13:41.44.287] (SSH-Browser) ConnectSSH(1): 未提供密钥 --> 使用其他身份验证类型进行连接 +[13:41.44.294] (SSH-Browser) ConnectSSH(1): 已成功连接到 192.168.127.10. +[13:41.44.294] (SSH-Browser) ConnectSSH(1): SSH.Open +[13:41.44.300] (SSH-Browser) END ConnectSSH(1) +[13:41.44.300] BEGIN DisplayCurrentTab +[13:41.44.300] DisplayCurrentTab: FormClick +[13:41.44.300] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[13:41.44.300] (SSH-Browser) BEGIN ActiverPanel14 +[13:41.44.300] (SSH-Browser) BEGIN DesactiverPanel14 +[13:41.44.300] (SSH-Browser) END DesactiverPanel14 +[13:41.44.300] (SSH-Browser) END ActiverPanel14; +[13:41.44.314] DisplayCurrentTab: Cts1.BeginUpdate; +[13:41.44.314] DisplayCurrentTab: Cts1.EndUpdates +[13:41.44.321] DisplayCurrentTab: 显示所选标签页 +[13:41.44.322] DisplayCurrentTab: 隐藏其他标签页 +[13:41.44.322] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[13:41.44.322] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[13:41.44.322] DisplayCurrentTab: DistribuerLeFocus +[13:41.44.322] END DisplayCurrentTab +[13:41.44.322] BEGIN SavePassword +[13:41.44.322] END SavePassword +[13:41.44.322] END SauvegarderMotDePasseSSH +[13:41.44.322] BEGIN WMNewTab: 80 +[13:41.44.322] 收到消息: 正在启动远程监控 终端 #2 +[13:41.44.347] BEGIN TFormXterm.FormResize +[13:41.44.347] TFormXterm.FormResize: CenterBtnReattachTab +[13:41.44.352] TFormXterm.FormResize: SplitModeResize +[13:41.44.352] TFormXterm.FormResize: BtnSplitNo.Down +[13:41.44.353] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[13:41.44.353] BEGIN ResizeTerminal +[13:41.44.366] END ResizeTerminal +[13:41.44.366] TFormXterm.FormResize: AdaptSidebarArrows; +[13:41.44.366] BEGIN AdaptSidebarArrows +[13:41.44.366] END AdaptSidebarArrows +[13:41.44.366] TFormXterm.FormResize: AdaptTV2; +[13:41.44.366] END TFormXterm.FormResize +[13:41.44.366] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[13:41.44.367] 请求提取文件: /bin/MobaSCP.exe +[13:41.44.499] 文件 MobaSCP.exe 已提取, 来自 mobase. +[13:41.44.502] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[13:41.44.629] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[13:41.44.629] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[13:41.44.629] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[13:41.44.629] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[13:41.44.629] (SSH-Browser) END GetSftpOnValidateStatus +[13:41.44.693] +[13:41.44.693] (SSH-Browser) ElSSH1AuthenticationStart(1, 134) +[13:41.44.693] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[13:41.44.693] (SSH-Browser) 服务器支持以下认证方式: +[13:41.44.693] (SSH-Browser) . PUBLICKEYAGENT +[13:41.44.693] (SSH-Browser) . PUBLICKEY +[13:41.44.693] (SSH-Browser) . PASSWORD +[13:41.44.693] (SSH-Browser) 客户端支持以下认证方式: +[13:41.44.693] (SSH-Browser) . PUBLICKEYAGENT +[13:41.44.693] (SSH-Browser) . PUBLICKEY +[13:41.44.693] (SSH-Browser) . RHOSTS +[13:41.44.693] (SSH-Browser) . HOSTBASED +[13:41.44.693] (SSH-Browser) . PASSWORD +[13:41.44.693] (SSH-Browser) . KEYBOARD +[13:41.44.693] +[13:41.44.693] +[13:41.44.693] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEY) +[13:41.44.693] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEYAGENT) +[13:41.44.693] (SSH-Browser) ElSSH1AuthenticationAttempt(1, PASSWORD) +[13:41.44.920] (SSH-Browser) ElSSH1AuthenticationSuccess(1) +[13:41.44.920] (SSH-Browser) ElSSH1OpenConnection(1) +[13:41.44.920] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[13:41.44.920] +[13:41.44.940] ShellExecuteS: ShellExecuteEx 成功. +[13:41.44.940] ShellExecuteS: WaitForInputIdle 失败. +[13:41.44.941] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[13:41.44.941] END WMNewTab: 80 +[13:41.44.990] [MobaSCP2] Launching remote monitoring in normal mode +[13:41.44.990] [MobaSCP2] Multiplex=1 +[13:41.44.990] [MobaSCP2] HOSTNAME: 192.168.127.10 +[13:41.44.990] [MobaSCP2] USERNAME: root +[13:41.45.024] [MobaSCP2] Using SCP1 +[13:41.45.024] [MobaSCP2] Connected to 192.168.127.10 +[13:41.45.119] (SSH-Browser) BEGIN ElSFTP1OpenConnection(1) +[13:41.45.119] (SSH-Browser) ElSFTP1OpenConnection(1): SFTP 已正确连接 +[13:41.45.119] (SSH-Browser) ElSFTP1OpenConnection(1): ActiverPanel14 +[13:41.45.119] (SSH-Browser) BEGIN ActiverPanel14 +[13:41.45.119] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[13:41.45.124] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[13:41.45.124] (SSH-Browser) ActiverPanel14: 列出远程目录 . +[13:41.45.176] (SSH-Browser) ActiverPanel14: OpenDir(.); +[13:41.45.176] (SSH-Browser) BEGIN OpenDir(1) +[13:41.45.176] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:41.45.176] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:41.45.176] (SSH-Browser) END VerifySFTPConnection(1) +[13:41.45.176] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[13:41.45.176] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(.); +[13:41.45.179] (SSH-Browser) END OpenDir(1) +[13:41.45.190] +[13:41.45.190] BEGIN LIVE-CREATING TFormTransparente +[13:41.45.222] END LIVE-CREATING TFormTransparente +[13:41.45.222] +[13:41.45.251] (SSH-Browser) END ActiverPanel14; +[13:41.45.276] (SSH-Browser) ElSFTP1OpenConnection(1): 已成功打开连接 --> 正在退出 +[13:41.45.276] (SSH-Browser) END ElSFTP1OpenConnection(1) +[13:41.45.300] (SSH-Browser) ElSFTP1AbsolutePath(1) +[13:41.45.300] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[13:41.45.330] (SSH-Browser) ElSFTP1OpenFile(1) +[13:41.45.330] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[13:41.45.391] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[13:41.45.391] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[13:41.45.391] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[13:41.45.391] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:41.45.391] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:41.45.391] (SSH-Browser) END VerifySFTPConnection(1) +[13:41.45.391] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[13:41.45.391] (SSH-Browser) END CloseCurrentHandle(1) +[13:41.45.391] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[13:41.45.391] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=11 +[13:41.45.391] (SSH-Browser) 对项目进行排序 +[13:41.45.391] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[13:41.45.393] (SSH-Browser) END CopySFTPFileListToListView(1) +[13:41.45.423] (SSH-Browser) ElSFTP1Success(1) + +[13:41.45.895] BEGIN WMNewTab: 20 +[13:41.45.895] END WMNewTab: 20 +[13:41.46.172] BEGIN TFormXterm.FormResize +[13:41.46.172] TFormXterm.FormResize: CenterBtnReattachTab +[13:41.46.172] TFormXterm.FormResize: SplitModeResize +[13:41.46.172] TFormXterm.FormResize: BtnSplitNo.Down +[13:41.46.172] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[13:41.46.172] BEGIN ResizeTerminal +[13:41.46.172] END ResizeTerminal +[13:41.46.172] TFormXterm.FormResize: AdaptSidebarArrows; +[13:41.46.172] BEGIN AdaptSidebarArrows +[13:41.46.172] END AdaptSidebarArrows +[13:41.46.172] TFormXterm.FormResize: AdaptTV2; +[13:41.46.172] END TFormXterm.FormResize + +[13:41.47.312] BEGIN WMNewTab: 20 +[13:41.47.312] END WMNewTab: 20 + + +[13:41.48.726] BEGIN WMNewTab: 20 +[13:41.48.726] END WMNewTab: 20 + + +[13:41.50.146] BEGIN WMNewTab: 20 +[13:41.50.146] END WMNewTab: 20 + + +[13:41.51.561] BEGIN WMNewTab: 20 +[13:41.51.561] END WMNewTab: 20 + + +[13:41.52.975] BEGIN WMNewTab: 20 +[13:41.52.975] END WMNewTab: 20 + + +[13:41.54.389] BEGIN WMNewTab: 20 +[13:41.54.389] END WMNewTab: 20 + + +[13:41.55.806] BEGIN WMNewTab: 20 +[13:41.55.806] END WMNewTab: 20 + + +[13:41.57.219] BEGIN WMNewTab: 20 +[13:41.57.219] END WMNewTab: 20 + + +[13:41.58.631] BEGIN WMNewTab: 20 +[13:41.58.631] END WMNewTab: 20 + + +[13:42.00.040] BEGIN WMNewTab: 20 +[13:42.00.040] END WMNewTab: 20 + + +[13:42.01.456] BEGIN WMNewTab: 20 +[13:42.01.456] END WMNewTab: 20 + + +[13:42.02.874] BEGIN WMNewTab: 20 +[13:42.02.874] END WMNewTab: 20 + + +[13:42.04.292] BEGIN WMNewTab: 20 +[13:42.04.292] END WMNewTab: 20 + + +[13:42.05.708] BEGIN WMNewTab: 20 +[13:42.05.708] END WMNewTab: 20 + + +[13:42.07.117] BEGIN WMNewTab: 20 +[13:42.07.117] END WMNewTab: 20 + + +[13:42.08.484] BEGIN WMNewTab: 0 +[13:42.08.484] WMNewTab: FormClick +[13:42.08.484] WMNewTab: LooseFocus +[13:42.08.484] END WMNewTab: 0 +[13:42.08.484] BEGIN WMNewTab: 31 +[13:42.08.484] END WMNewTab: 31 +[13:42.08.537] BEGIN WMNewTab: 20 +[13:42.08.537] END WMNewTab: 20 +[13:42.08.565] BEGIN WMNewTab: 0 +[13:42.08.565] WMNewTab: FormClick +[13:42.08.565] WMNewTab: LooseFocus +[13:42.08.565] END WMNewTab: 0 + +[13:42.09.250] BEGIN CWD +[13:42.09.250] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:42.09.250] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:42.09.250] (SSH-Browser) END VerifySFTPConnection(1) +[13:42.09.250] END CWD +[13:42.09.326] (SSH-Browser) ElCommandSSHTunnel1Open +[13:42.09.356] (SSH-Browser) ExecuteCommandData +[13:42.09.386] (SSH-Browser) ExecuteCommandData +[13:42.09.416] (SSH-Browser) ExecuteCommandData +[13:42.09.447] (SSH-Browser) ExecuteCommandData +[13:42.09.477] (SSH-Browser) ExecuteCommandData +[13:42.09.583] (SSH-Browser) ExecuteCommandClose +[13:42.09.583] BEGIN CWD +[13:42.09.589] (CWD) TenterDeTrouverLeCWD: Minute=0 / Seconde=25 +[13:42.09.651] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:42.09.651] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:42.09.651] (SSH-Browser) END VerifySFTPConnection(1) +[13:42.09.651] END CWD +[13:42.09.674] BEGIN CWD +[13:42.09.734] END CWD + +[13:42.10.203] BEGIN WMNewTab: 20 +[13:42.10.203] END WMNewTab: 20 + + +[13:42.11.617] BEGIN WMNewTab: 20 +[13:42.11.617] END WMNewTab: 20 + + +[13:42.13.040] BEGIN WMNewTab: 20 +[13:42.13.040] END WMNewTab: 20 + + +[13:42.14.454] BEGIN WMNewTab: 20 +[13:42.14.454] END WMNewTab: 20 + +[13:42.15.012] BEGIN CWD +[13:42.15.073] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:42.15.073] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:42.15.073] (SSH-Browser) END VerifySFTPConnection(1) +[13:42.15.073] END CWD +[13:42.15.078] BEGIN CWD +[13:42.15.138] END CWD + +[13:42.16.083] BEGIN WMNewTab: 20 +[13:42.16.083] END WMNewTab: 20 +[13:42.16.373] BEGIN CWD +[13:42.16.434] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:42.16.434] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:42.16.434] (SSH-Browser) END VerifySFTPConnection(1) +[13:42.16.434] END CWD +[13:42.16.449] BEGIN CWD +[13:42.16.509] END CWD + +[13:42.17.454] BEGIN WMNewTab: 20 +[13:42.17.454] END WMNewTab: 20 + +[13:42.18.109] BEGIN CWD +[13:42.18.170] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:42.18.170] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:42.18.170] (SSH-Browser) END VerifySFTPConnection(1) +[13:42.18.170] END CWD +[13:42.18.185] BEGIN CWD +[13:42.18.245] END CWD + +[13:42.18.738] BEGIN WMNewTab: 20 +[13:42.18.738] END WMNewTab: 20 +[13:42.18.873] BEGIN CWD +[13:42.18.934] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:42.18.934] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:42.18.934] (SSH-Browser) END VerifySFTPConnection(1) +[13:42.18.934] END CWD +[13:42.18.943] BEGIN CWD +[13:42.19.004] END CWD + +[13:42.19.951] BEGIN WMNewTab: 20 +[13:42.19.951] END WMNewTab: 20 + + +[13:42.21.366] BEGIN WMNewTab: 20 +[13:42.21.366] END WMNewTab: 20 + + +[13:42.22.783] BEGIN WMNewTab: 20 +[13:42.22.783] END WMNewTab: 20 + + +[13:42.24.194] BEGIN WMNewTab: 20 +[13:42.24.194] END WMNewTab: 20 + + +[13:42.25.610] BEGIN WMNewTab: 20 +[13:42.25.610] END WMNewTab: 20 + + +[13:42.27.022] BEGIN WMNewTab: 20 +[13:42.27.022] END WMNewTab: 20 + + +[13:42.28.437] BEGIN WMNewTab: 20 +[13:42.28.437] END WMNewTab: 20 + + +[13:42.29.853] BEGIN WMNewTab: 20 +[13:42.29.853] END WMNewTab: 20 + +[13:42.30.718] BEGIN WMNewTab: 0 +[13:42.30.718] WMNewTab: FormClick +[13:42.30.718] WMNewTab: LooseFocus +[13:42.30.718] END WMNewTab: 0 +[13:42.30.845] BEGIN WMNewTab: 0 +[13:42.30.845] WMNewTab: FormClick +[13:42.30.845] WMNewTab: LooseFocus +[13:42.30.846] END WMNewTab: 0 + +[13:42.31.268] BEGIN WMNewTab: 20 +[13:42.31.268] END WMNewTab: 20 + + +[13:42.32.685] BEGIN WMNewTab: 20 +[13:42.32.686] END WMNewTab: 20 + + +[13:42.34.106] BEGIN WMNewTab: 20 +[13:42.34.106] END WMNewTab: 20 + + +[13:42.35.523] BEGIN WMNewTab: 20 +[13:42.35.523] END WMNewTab: 20 + + +[13:42.36.817] BEGIN WMNewTab: 20 +[13:42.36.817] END WMNewTab: 20 +[13:42.36.838] BEGIN WMNewTab: 48 +[13:42.36.838] 收到消息: SSH 会话部分关闭 (2) +[13:42.36.908] BEGIN TFormXterm.FormResize +[13:42.36.908] TFormXterm.FormResize: CenterBtnReattachTab +[13:42.36.909] TFormXterm.FormResize: SplitModeResize +[13:42.36.909] TFormXterm.FormResize: BtnSplitNo.Down +[13:42.36.910] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[13:42.36.910] BEGIN ResizeTerminal +[13:42.36.935] END ResizeTerminal +[13:42.36.935] TFormXterm.FormResize: AdaptSidebarArrows; +[13:42.36.935] BEGIN AdaptSidebarArrows +[13:42.36.935] END AdaptSidebarArrows +[13:42.36.935] TFormXterm.FormResize: AdaptTV2; +[13:42.36.935] END TFormXterm.FormResize +[13:42.36.935] BEGIN DisconnectSSH(1) +[13:42.36.935] (SSH-Browser) DisconnectSSH(1): (Socket.Active) and (SocketState<>SOCKET_STATE_CONNECTING) +[13:42.36.945] SetTitle(1, ); +[13:42.36.962] (SSH-Browser) ElSFTP1CloseConnection(1) +[13:42.36.962] (SSH-Browser) ElSFTP1Error(1): #103 - 连接被低层协议关闭 +[13:42.36.962] SFTPErr #103 附带说明 "连接被低层协议关闭" +[13:42.36.962] (SSH-Browser) ElSFTP1CloseConnection(1) +[13:42.36.962] BEGIN ElSSH1CloseConnection(1) +[13:42.36.962] END ElSSH1CloseConnection(1) +[13:42.36.962] (SSH-Browser) DisconnectSSH(1): Socket.Close; +[13:42.36.962] (SSH-Browser) BEGIN DesactiverPanel14 +[13:42.36.974] (SSH-Browser) END DesactiverPanel14 +[13:42.36.974] END DisconnectSSH(1) +[13:42.36.981] END WMNewTab: 48 + + + +[13:43.00.330] BEGIN WMNewTab: 62 +[13:43.00.338] END WMNewTab: 62 + +[13:43.00.754] SetTitle(1, 192.168.127.10 (root)); + + + +[13:43.21.396] BEGIN WMNewTab: 48 +[13:43.21.396] 收到消息: SSH 会话部分关闭 (2) +[13:43.21.409] BEGIN DisconnectSSH(1) +[13:43.21.409] (SSH-Browser) BEGIN DesactiverPanel14 +[13:43.21.409] (SSH-Browser) END DesactiverPanel14 +[13:43.21.409] END DisconnectSSH(1) +[13:43.21.414] END WMNewTab: 48 +[13:43.21.414] SetTitle(1, ); + + +[13:43.22.977] BEGIN WMNewTab: 62 +[13:43.22.984] END WMNewTab: 62 +[13:43.23.105] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[13:43.23.105] 主机密钥与缓存中的密钥是一致的 +[13:43.23.116] BEGIN GetPassword +[13:43.23.116] BEGIN GetnSaveCredPassword +[13:43.23.116] END GetnSaveCredPassword +[13:43.23.116] END GetPassword +[13:43.23.136] SetTitle(1, 192.168.127.10 (root)); + + +[13:43.25.344] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[13:43.25.344] BEGIN SauvegarderMotDePasseSSH +[13:43.25.344] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[13:43.25.344] SetTitle(1, root@192.168.127.10); +[13:43.25.344] +[13:43.25.344] (SSH-Browser) BEGIN ConnectSSH(1,192.168.127.10,root,) +[13:43.25.344] (SSH-Browser) ConnectSSH(1): 初始化 TabSFTP +[13:43.25.346] (SSH-Browser) ConnectSSH(1): 未使用代理 +[13:43.25.346] (SSH-Browser) ConnectSSH(1): 未提供密钥 --> 使用其他身份验证类型进行连接 +[13:43.25.347] (SSH-Browser) ConnectSSH(1): 已成功连接到 192.168.127.10. +[13:43.25.347] (SSH-Browser) ConnectSSH(1): SSH.Open +[13:43.25.347] (SSH-Browser) END ConnectSSH(1) +[13:43.25.347] BEGIN DisplayCurrentTab +[13:43.25.347] DisplayCurrentTab: FormClick +[13:43.25.347] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[13:43.25.347] (SSH-Browser) BEGIN ActiverPanel14 +[13:43.25.347] (SSH-Browser) BEGIN DesactiverPanel14 +[13:43.25.347] (SSH-Browser) END DesactiverPanel14 +[13:43.25.347] (SSH-Browser) END ActiverPanel14; +[13:43.25.361] DisplayCurrentTab: Cts1.BeginUpdate; +[13:43.25.361] DisplayCurrentTab: Cts1.EndUpdates +[13:43.25.368] DisplayCurrentTab: 显示所选标签页 +[13:43.25.368] DisplayCurrentTab: 隐藏其他标签页 +[13:43.25.368] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[13:43.25.369] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[13:43.25.369] DisplayCurrentTab: DistribuerLeFocus +[13:43.25.369] END DisplayCurrentTab +[13:43.25.369] BEGIN SavePassword +[13:43.25.369] END SavePassword +[13:43.25.369] END SauvegarderMotDePasseSSH +[13:43.25.369] BEGIN WMNewTab: 80 +[13:43.25.369] 收到消息: 正在启动远程监控 终端 #2 +[13:43.25.391] BEGIN TFormXterm.FormResize +[13:43.25.391] TFormXterm.FormResize: CenterBtnReattachTab +[13:43.25.392] TFormXterm.FormResize: SplitModeResize +[13:43.25.392] TFormXterm.FormResize: BtnSplitNo.Down +[13:43.25.392] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[13:43.25.392] BEGIN ResizeTerminal +[13:43.25.403] END ResizeTerminal +[13:43.25.403] TFormXterm.FormResize: AdaptSidebarArrows; +[13:43.25.403] BEGIN AdaptSidebarArrows +[13:43.25.403] END AdaptSidebarArrows +[13:43.25.403] TFormXterm.FormResize: AdaptTV2; +[13:43.25.403] END TFormXterm.FormResize +[13:43.25.403] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[13:43.25.403] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[13:43.25.420] ShellExecuteS: ShellExecuteEx 成功. +[13:43.25.420] ShellExecuteS: WaitForInputIdle 失败. +[13:43.25.420] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[13:43.25.420] END WMNewTab: 80 +[13:43.25.473] [MobaSCP2] Launching remote monitoring in normal mode +[13:43.25.474] [MobaSCP2] Multiplex=1 +[13:43.25.474] [MobaSCP2] HOSTNAME: 192.168.127.10 +[13:43.25.474] [MobaSCP2] USERNAME: root +[13:43.25.519] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[13:43.25.519] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[13:43.25.519] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[13:43.25.519] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[13:43.25.519] (SSH-Browser) END GetSftpOnValidateStatus +[13:43.25.599] +[13:43.25.599] (SSH-Browser) ElSSH1AuthenticationStart(1, 134) +[13:43.25.599] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[13:43.25.599] (SSH-Browser) 服务器支持以下认证方式: +[13:43.25.599] (SSH-Browser) . PUBLICKEYAGENT +[13:43.25.599] (SSH-Browser) . PUBLICKEY +[13:43.25.599] (SSH-Browser) . PASSWORD +[13:43.25.599] (SSH-Browser) 客户端支持以下认证方式: +[13:43.25.599] (SSH-Browser) . PUBLICKEYAGENT +[13:43.25.599] (SSH-Browser) . PUBLICKEY +[13:43.25.599] (SSH-Browser) . RHOSTS +[13:43.25.599] (SSH-Browser) . HOSTBASED +[13:43.25.599] (SSH-Browser) . PASSWORD +[13:43.25.599] (SSH-Browser) . KEYBOARD +[13:43.25.599] +[13:43.25.599] +[13:43.25.599] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEY) +[13:43.25.599] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEYAGENT) +[13:43.25.599] (SSH-Browser) ElSSH1AuthenticationAttempt(1, PASSWORD) + +[13:43.26.103] (SSH-Browser) ElSSH1AuthenticationSuccess(1) +[13:43.26.103] (SSH-Browser) ElSSH1OpenConnection(1) +[13:43.26.103] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[13:43.26.103] +[13:43.26.115] [MobaSCP2] Using SCP1 +[13:43.26.115] [MobaSCP2] Connected to 192.168.127.10 +[13:43.26.255] (SSH-Browser) BEGIN ElSFTP1OpenConnection(1) +[13:43.26.255] (SSH-Browser) ElSFTP1OpenConnection(1): SFTP 已正确连接 +[13:43.26.255] (SSH-Browser) ElSFTP1OpenConnection(1): ActiverPanel14 +[13:43.26.255] (SSH-Browser) BEGIN ActiverPanel14 +[13:43.26.255] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[13:43.26.259] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[13:43.26.259] (SSH-Browser) ActiverPanel14: 列出远程目录 +[13:43.26.259] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[13:43.26.260] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[13:43.26.283] (SSH-Browser) END ActiverPanel14; +[13:43.26.314] (SSH-Browser) ElSFTP1OpenConnection(1): 已成功打开连接 --> 正在退出 +[13:43.26.314] (SSH-Browser) END ElSFTP1OpenConnection(1) + +[13:43.26.783] BEGIN WMNewTab: 20 +[13:43.26.783] END WMNewTab: 20 + +[13:43.27.208] BEGIN TFormXterm.FormResize +[13:43.27.208] TFormXterm.FormResize: CenterBtnReattachTab +[13:43.27.208] TFormXterm.FormResize: SplitModeResize +[13:43.27.208] TFormXterm.FormResize: BtnSplitNo.Down +[13:43.27.208] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[13:43.27.208] BEGIN ResizeTerminal +[13:43.27.208] END ResizeTerminal +[13:43.27.208] TFormXterm.FormResize: AdaptSidebarArrows; +[13:43.27.208] BEGIN AdaptSidebarArrows +[13:43.27.208] END AdaptSidebarArrows +[13:43.27.208] TFormXterm.FormResize: AdaptTV2; +[13:43.27.208] END TFormXterm.FormResize + +[13:43.28.204] BEGIN WMNewTab: 20 +[13:43.28.204] END WMNewTab: 20 + + +[13:43.29.624] BEGIN WMNewTab: 20 +[13:43.29.624] END WMNewTab: 20 + + +[13:43.31.046] BEGIN WMNewTab: 20 +[13:43.31.046] END WMNewTab: 20 + + +[13:43.32.465] BEGIN WMNewTab: 20 +[13:43.32.465] END WMNewTab: 20 + + +[13:43.33.881] BEGIN WMNewTab: 20 +[13:43.33.881] END WMNewTab: 20 + + +[13:43.35.305] BEGIN WMNewTab: 20 +[13:43.35.305] END WMNewTab: 20 + + +[13:43.36.715] BEGIN WMNewTab: 20 +[13:43.36.715] END WMNewTab: 20 + + +[13:43.38.137] BEGIN WMNewTab: 20 +[13:43.38.137] END WMNewTab: 20 + + +[13:43.39.553] BEGIN WMNewTab: 20 +[13:43.39.553] END WMNewTab: 20 + + +[13:43.40.970] BEGIN WMNewTab: 20 +[13:43.40.970] END WMNewTab: 20 + +[13:43.41.784] BEGIN BtnNewSessionClick +[13:43.41.784] BtnNewSessionClick: FormClick +[13:43.41.795] BEGIN ChargerLaSession +[13:43.41.814] ChargerLaSession1 +[13:43.41.857] ChargerLaSession2 + +[13:43.42.384] BEGIN WMNewTab: 20 +[13:43.42.384] END WMNewTab: 20 + +[13:43.43.480] BEGIN FormSessions.Btn0Click: 5 +[13:43.43.480] BEGIN LockControl(FormSessionEdit, Btn0Click) +[13:43.43.480] END LockControl(FormSessionEdit, Btn0Click) +[13:43.43.480] 加载新会话类型的默认值 #5 +[13:43.43.480] BEGIN ChargerLePreset EMPTY_PRESETS +[13:43.43.481] ChargerLaSession1 +[13:43.43.487] END ChargerLePreset +[13:43.43.512] BEGIN UnlockControl(FormSessionEdit, Btn0Click) +[13:43.43.512] END UnlockControl(FormSessionEdit, Btn0Click) +[13:43.43.512] END FormSessions.Btn0Click +[13:43.43.800] BEGIN WMNewTab: 20 +[13:43.43.800] END WMNewTab: 20 + + +[13:43.45.214] BEGIN WMNewTab: 20 +[13:43.45.214] END WMNewTab: 20 + + +[13:43.46.636] BEGIN WMNewTab: 20 +[13:43.46.636] END WMNewTab: 20 + + +[13:43.48.052] BEGIN WMNewTab: 20 +[13:43.48.052] END WMNewTab: 20 + + +[13:43.49.465] BEGIN WMNewTab: 20 +[13:43.49.465] END WMNewTab: 20 + + +[13:43.50.845] BEGIN SessionClickOK +[13:43.50.873] LaunchSession0 +[13:43.50.875] LaunchSession1 +[13:43.50.875] LaunchSession4 +[13:43.50.875] LaunchSession5 +[13:43.50.875] +[13:43.50.875] BEGIN NEWTAB(vnc "192.168.127.10" 5900 -autoscale, 128, 0) +[13:43.50.875] NEWTAB: Application.ProcessMessages +[13:43.50.880] NEWTAB: Timer1_Disable +[13:43.50.880] NEWTAB: 检查是否已达到最大标签数... +[13:43.50.880] NEWTAB: 创建 SFTPRecord... +[13:43.50.883] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[13:43.50.883] NEWTAB: 尝试查找旧索引... +[13:43.50.883] NEWTAB: Cts1.BeginUpdate; +[13:43.50.883] NEWTAB: 创建新标签页... +[13:43.50.883] NEWTAB: 标签页索引: 2 +[13:43.50.883] NEWTAB: 终端编号 : 3 +[13:43.50.883] NEWTAB: 标题 : 192.168.127.10 +[13:43.50.883] NEWTAB: 命令 : vnc "192.168.127.10" 5900 -autoscale +[13:43.50.883] Cts1ActiveTabChanged: New index = 2 +[13:43.50.883] NEWTAB: Cts1.EndUpdates +[13:43.50.886] NEWTAB: 更改标签页索引 A = 2 +[13:43.50.886] BEGIN WaitForAllThreads +[13:43.50.886] END WaitForAllThreads +[13:43.50.886] +[13:43.50.886] LaunchTabContent(vnc "192.168.127.10" 5900 -autoscale, 192.168.127.10); +[13:43.50.886] +[13:43.50.886] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[13:43.50.887] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[13:43.50.887] MOBANOACL=onlyslash +[13:43.50.887] +[13:43.50.887] ShellExecute: motty.exe +[13:43.50.887] +[13:43.50.888] CreerSessionMoTTY(3, vnc "192.168.127.10" 5900 -autoscale, 192.168.127.10) +[13:43.50.889] Setting LOCALE=zh_CN.UTF-8 +[13:43.50.892] BEGIN WMNewTab: 20 +[13:43.50.892] END WMNewTab: 20 +[13:43.50.893] BEGIN WaitForAllThreads +[13:43.50.893] END WaitForAllThreads +[13:43.50.894] 请求提取文件: /bin/vnp.exe +[13:43.50.929] 文件 vnp.exe 已提取, 来自 CygUtils.plugin. +[13:43.50.929] 请求提取文件: /bin/TurboVNC.exe +[13:43.51.020] 文件 TurboVNC.exe 已提取, 来自 CygUtils.plugin. +[13:43.51.020] BEGIN GetPassword +[13:43.51.020] BEGIN GetnSaveCredPassword +[13:43.51.020] END GetnSaveCredPassword +[13:43.51.020] +[13:43.51.020] +[13:43.51.021] BEGIN TForm1.MobaInputDialog +[13:43.51.021] +[13:43.51.021] BEGIN LIVE-CREATING TFormInputDialog +[13:43.51.040] END LIVE-CREATING TFormInputDialog +[13:43.51.040] +[13:43.51.060] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[13:43.51.060] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=Form4.Handle; +[13:43.51.061] TForm1.MobaInputDialog: FormInputDialog.ShowModal + + +[13:43.52.297] BEGIN WMNewTab: 20 +[13:43.52.297] END WMNewTab: 20 + + +[13:43.53.720] BEGIN WMNewTab: 20 +[13:43.53.720] END WMNewTab: 20 + + +[13:43.55.135] BEGIN WMNewTab: 20 +[13:43.55.135] END WMNewTab: 20 + + +[13:43.56.551] BEGIN WMNewTab: 20 +[13:43.56.551] END WMNewTab: 20 + + +[13:43.57.961] BEGIN WMNewTab: 20 +[13:43.57.961] END WMNewTab: 20 + +[13:43.58.543] BEGIN TFormXterm.FormResize +[13:43.58.543] TFormXterm.FormResize: CenterBtnReattachTab +[13:43.58.547] TFormXterm.FormResize: SplitModeResize +[13:43.58.547] TFormXterm.FormResize: BtnSplitNo.Down +[13:43.58.548] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[13:43.58.548] BEGIN ResizeTerminal +[13:43.58.548] END ResizeTerminal +[13:43.58.548] TFormXterm.FormResize: AdaptSidebarArrows; +[13:43.58.548] BEGIN AdaptSidebarArrows +[13:43.58.548] END AdaptSidebarArrows +[13:43.58.548] TFormXterm.FormResize: AdaptTV2; +[13:43.58.548] END TFormXterm.FormResize + +[13:43.59.385] BEGIN WMNewTab: 20 +[13:43.59.385] END WMNewTab: 20 + + +[13:44.00.801] BEGIN WMNewTab: 20 +[13:44.00.801] END WMNewTab: 20 + + +[13:44.02.217] BEGIN WMNewTab: 20 +[13:44.02.217] END WMNewTab: 20 + + +[13:44.03.633] BEGIN WMNewTab: 20 +[13:44.03.633] END WMNewTab: 20 + + +[13:44.05.049] BEGIN WMNewTab: 20 +[13:44.05.049] END WMNewTab: 20 + +[13:44.05.415] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[13:44.05.415] END TForm1.MobaInputDialog +[13:44.05.415] +[13:44.05.415] +[13:44.05.415] END GetPassword +[13:44.05.764] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\TurboVNC.exe, /loglevel 3 /config "C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\mo.vnc") +[13:44.06.012] ShellExecuteS: ShellExecuteEx 成功. + +[13:44.06.456] BEGIN WMNewTab: 20 +[13:44.06.457] END WMNewTab: 20 + + +[13:44.07.871] BEGIN WMNewTab: 20 +[13:44.07.871] END WMNewTab: 20 +[13:44.08.122] ShellExecuteS: WaitForInputIdle 成功. +[13:44.08.122] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\TurboVNC.exe, /loglevel 3 /config "C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\mo.vnc") + +[13:44.09.298] BEGIN WMNewTab: 20 +[13:44.09.298] END WMNewTab: 20 +[13:44.09.358] BEGIN GetPassword +[13:44.09.358] +[13:44.09.358] +[13:44.09.358] BEGIN TForm1.MobaInputDialog +[13:44.09.358] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[13:44.09.358] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=0; +[13:44.09.359] TForm1.MobaInputDialog: FormInputDialog.ShowModal + + +[13:44.10.708] BEGIN WMNewTab: 20 +[13:44.10.708] END WMNewTab: 20 + + +[13:44.12.125] BEGIN WMNewTab: 20 +[13:44.12.125] END WMNewTab: 20 + + +[13:44.13.542] BEGIN WMNewTab: 20 +[13:44.13.542] END WMNewTab: 20 + + +[13:44.14.963] BEGIN WMNewTab: 20 +[13:44.14.963] END WMNewTab: 20 + + +[13:44.16.381] BEGIN WMNewTab: 20 +[13:44.16.381] END WMNewTab: 20 + + +[13:44.17.796] BEGIN WMNewTab: 20 +[13:44.17.796] END WMNewTab: 20 + +[13:44.18.517] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[13:44.18.517] END TForm1.MobaInputDialog +[13:44.18.517] +[13:44.18.517] +[13:44.18.517] END GetPassword +[13:44.18.654] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\TurboVNC.exe, /loglevel 3 /config "C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\mo.vnc") +[13:44.18.672] ShellExecuteS: ShellExecuteEx 成功. + +[13:44.19.215] BEGIN WMNewTab: 20 +[13:44.19.215] END WMNewTab: 20 + + +[13:44.20.631] BEGIN WMNewTab: 20 +[13:44.20.631] END WMNewTab: 20 +[13:44.20.760] ShellExecuteS: WaitForInputIdle 成功. +[13:44.20.760] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\TurboVNC.exe, /loglevel 3 /config "C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\mo.vnc") + + +[13:44.22.099] BEGIN WMNewTab: 20 +[13:44.22.099] END WMNewTab: 20 +[13:44.22.225] NEWTAB: LaunchTabContent 失败. 删除新创建的标签页... +[13:44.22.225] NEWTAB: BEGIN Cts1.Tabs.DeleteTab(2); +[13:44.22.229] Cts1ActiveTabChanged: New index = 1 +[13:44.22.238] NEWTAB: END Cts1.Tabs.DeleteTab +[13:44.22.238] NEWTAB: 更改标签页索引 B = 1 +[13:44.22.238] BEGIN DisplayCurrentTab +[13:44.22.238] DisplayCurrentTab: FormClick +[13:44.22.238] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[13:44.22.238] (SSH-Browser) BEGIN ActiverPanel14 +[13:44.22.238] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[13:44.22.251] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[13:44.22.251] (SSH-Browser) ActiverPanel14: 远程目录已列出 +[13:44.22.251] (SSH-Browser) END ActiverPanel14; +[13:44.22.270] BEGIN TFormXterm.FormResize +[13:44.22.270] TFormXterm.FormResize: CenterBtnReattachTab +[13:44.22.271] TFormXterm.FormResize: SplitModeResize +[13:44.22.271] TFormXterm.FormResize: BtnSplitNo.Down +[13:44.22.271] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[13:44.22.271] BEGIN ResizeTerminal +[13:44.22.274] END ResizeTerminal +[13:44.22.274] TFormXterm.FormResize: AdaptSidebarArrows; +[13:44.22.274] BEGIN AdaptSidebarArrows +[13:44.22.274] END AdaptSidebarArrows +[13:44.22.274] TFormXterm.FormResize: AdaptTV2; +[13:44.22.274] END TFormXterm.FormResize +[13:44.22.274] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[13:44.22.274] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[13:44.22.285] ShellExecuteS: ShellExecuteEx 成功. +[13:44.22.285] ShellExecuteS: WaitForInputIdle 失败. +[13:44.22.285] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[13:44.22.285] DisplayCurrentTab: Cts1.BeginUpdate; +[13:44.22.285] DisplayCurrentTab: Cts1.EndUpdates +[13:44.22.295] DisplayCurrentTab: 显示所选标签页 +[13:44.22.295] DisplayCurrentTab: 隐藏其他标签页 +[13:44.22.295] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[13:44.22.295] +[13:44.22.295] BEGIN Form4.FormActivate +[13:44.22.295] END Form4.FormActivate +[13:44.22.295] +[13:44.22.295] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[13:44.22.295] DisplayCurrentTab: DistribuerLeFocus +[13:44.22.295] END DisplayCurrentTab +[13:44.22.295] NEWTAB: NewTab_ReEnable_Timer1 +[13:44.22.296] NEWTAB: MajVerticalTabs +[13:44.22.296] NEWTAB: Cts1.Resize; +[13:44.22.308] END NEWTAB(vnc "192.168.127.10" 5900 -autoscale, 128, 0) +[13:44.22.308] +[13:44.22.308] LaunchSession6 +[13:44.22.312] END SessionClickOK +[13:44.22.312] BEGIN TFormSessionEdit.FormClose +[13:44.22.312] END TFormSessionEdit.FormClose +[13:44.22.315] END BtnNewSessionClick +[13:44.22.346] [MobaSCP2] Launching remote monitoring in normal mode +[13:44.22.346] [MobaSCP2] Multiplex=1 +[13:44.22.346] [MobaSCP2] HOSTNAME: 192.168.127.10 +[13:44.22.346] [MobaSCP2] USERNAME: root +[13:44.22.390] [MobaSCP2] Using SCP1 +[13:44.22.390] [MobaSCP2] Connected to 192.168.127.10 + +[13:44.23.505] BEGIN TFormXterm.FormResize +[13:44.23.505] TFormXterm.FormResize: CenterBtnReattachTab +[13:44.23.505] TFormXterm.FormResize: SplitModeResize +[13:44.23.505] TFormXterm.FormResize: BtnSplitNo.Down +[13:44.23.505] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[13:44.23.505] BEGIN ResizeTerminal +[13:44.23.506] END ResizeTerminal +[13:44.23.506] TFormXterm.FormResize: AdaptSidebarArrows; +[13:44.23.506] BEGIN AdaptSidebarArrows +[13:44.23.506] END AdaptSidebarArrows +[13:44.23.506] TFormXterm.FormResize: AdaptTV2; +[13:44.23.506] END TFormXterm.FormResize +[13:44.23.512] BEGIN WMNewTab: 20 +[13:44.23.512] END WMNewTab: 20 + + +[13:44.24.935] BEGIN WMNewTab: 20 +[13:44.24.935] END WMNewTab: 20 + + +[13:44.26.347] BEGIN WMNewTab: 20 +[13:44.26.347] END WMNewTab: 20 + + +[13:44.27.765] BEGIN WMNewTab: 20 +[13:44.27.765] END WMNewTab: 20 + + +[13:44.29.180] BEGIN WMNewTab: 20 +[13:44.29.180] END WMNewTab: 20 + + +[13:44.30.616] BEGIN WMNewTab: 20 +[13:44.30.616] END WMNewTab: 20 + + +[13:44.32.029] BEGIN WMNewTab: 20 +[13:44.32.029] END WMNewTab: 20 + + +[13:44.33.439] BEGIN WMNewTab: 20 +[13:44.33.439] END WMNewTab: 20 + + +[13:44.34.849] BEGIN WMNewTab: 20 +[13:44.34.849] END WMNewTab: 20 + + +[13:44.36.265] BEGIN WMNewTab: 20 +[13:44.36.265] END WMNewTab: 20 + + +[13:44.37.680] BEGIN WMNewTab: 20 +[13:44.37.680] END WMNewTab: 20 +[13:44.37.881] BEGIN WMNewTab: 0 +[13:44.37.881] WMNewTab: FormClick +[13:44.37.881] WMNewTab: LooseFocus +[13:44.37.881] END WMNewTab: 0 +[13:44.37.881] BEGIN WMNewTab: 31 +[13:44.37.881] END WMNewTab: 31 +[13:44.37.973] BEGIN WMNewTab: 0 +[13:44.37.973] WMNewTab: FormClick +[13:44.37.973] WMNewTab: LooseFocus +[13:44.37.974] END WMNewTab: 0 + +[13:44.38.703] BEGIN CWD +[13:44.38.703] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:44.38.703] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:44.38.703] (SSH-Browser) END VerifySFTPConnection(1) +[13:44.38.703] END CWD +[13:44.38.794] (SSH-Browser) ElCommandSSHTunnel1Open +[13:44.38.824] (SSH-Browser) ExecuteCommandData +[13:44.38.855] (SSH-Browser) ExecuteCommandData +[13:44.38.886] (SSH-Browser) ExecuteCommandData +[13:44.38.886] BEGIN WMNewTab: 20 +[13:44.38.886] END WMNewTab: 20 +[13:44.38.916] (SSH-Browser) ExecuteCommandData +[13:44.38.946] (SSH-Browser) ExecuteCommandData +[13:44.39.038] (SSH-Browser) ExecuteCommandClose +[13:44.39.038] BEGIN CWD +[13:44.39.040] (CWD) TenterDeTrouverLeCWD: Minute=1 / Seconde=14 +[13:44.39.101] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:44.39.101] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:44.39.101] (SSH-Browser) END VerifySFTPConnection(1) +[13:44.39.101] END CWD +[13:44.39.133] BEGIN CWD +[13:44.39.194] END CWD + +[13:44.40.136] BEGIN WMNewTab: 20 +[13:44.40.136] END WMNewTab: 20 + + +[13:44.41.548] BEGIN WMNewTab: 20 +[13:44.41.548] END WMNewTab: 20 + + +[13:44.42.956] BEGIN WMNewTab: 20 +[13:44.42.956] END WMNewTab: 20 + +[13:44.43.719] BEGIN CWD +[13:44.43.779] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:44.43.779] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:44.43.779] (SSH-Browser) END VerifySFTPConnection(1) +[13:44.43.779] END CWD +[13:44.43.794] BEGIN CWD +[13:44.43.867] END CWD + +[13:44.44.328] BEGIN WMNewTab: 20 +[13:44.44.328] END WMNewTab: 20 + + +[13:44.45.747] BEGIN WMNewTab: 20 +[13:44.45.747] END WMNewTab: 20 + + +[13:44.47.162] BEGIN WMNewTab: 20 +[13:44.47.162] END WMNewTab: 20 + + +[13:44.48.580] BEGIN WMNewTab: 20 +[13:44.48.580] END WMNewTab: 20 +[13:44.48.852] BEGIN CWD +[13:44.48.912] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:44.48.912] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:44.48.912] (SSH-Browser) END VerifySFTPConnection(1) +[13:44.48.912] END CWD +[13:44.48.928] BEGIN CWD +[13:44.49.004] END CWD + +[13:44.49.946] BEGIN WMNewTab: 20 +[13:44.49.946] END WMNewTab: 20 + + +[13:44.51.365] BEGIN WMNewTab: 20 +[13:44.51.365] END WMNewTab: 20 + + +[13:44.52.785] BEGIN WMNewTab: 20 +[13:44.52.785] END WMNewTab: 20 + + +[13:44.54.205] BEGIN WMNewTab: 20 +[13:44.54.205] END WMNewTab: 20 + + +[13:44.55.620] BEGIN WMNewTab: 20 +[13:44.55.620] END WMNewTab: 20 + + +[13:44.57.032] BEGIN WMNewTab: 20 +[13:44.57.032] END WMNewTab: 20 + + +[13:44.58.450] BEGIN WMNewTab: 20 +[13:44.58.450] END WMNewTab: 20 + + +[13:44.59.870] BEGIN WMNewTab: 20 +[13:44.59.870] END WMNewTab: 20 + + +[13:45.01.289] BEGIN WMNewTab: 20 +[13:45.01.289] END WMNewTab: 20 + + +[13:45.02.702] BEGIN WMNewTab: 20 +[13:45.02.702] END WMNewTab: 20 + + +[13:45.04.121] BEGIN WMNewTab: 20 +[13:45.04.121] END WMNewTab: 20 + + +[13:45.05.535] BEGIN WMNewTab: 20 +[13:45.05.535] END WMNewTab: 20 + + +[13:45.06.955] BEGIN WMNewTab: 20 +[13:45.06.955] END WMNewTab: 20 + + +[13:45.08.371] BEGIN WMNewTab: 20 +[13:45.08.371] END WMNewTab: 20 + + +[13:45.09.791] BEGIN WMNewTab: 20 +[13:45.09.791] END WMNewTab: 20 + + +[13:45.11.211] BEGIN WMNewTab: 20 +[13:45.11.211] END WMNewTab: 20 + + +[13:45.12.631] BEGIN WMNewTab: 20 +[13:45.12.631] END WMNewTab: 20 + + +[13:45.14.050] BEGIN WMNewTab: 20 +[13:45.14.050] END WMNewTab: 20 + + +[13:45.15.471] BEGIN WMNewTab: 20 +[13:45.15.471] END WMNewTab: 20 + + +[13:45.16.891] BEGIN WMNewTab: 20 +[13:45.16.891] END WMNewTab: 20 + + +[13:45.18.308] BEGIN WMNewTab: 20 +[13:45.18.308] END WMNewTab: 20 + + +[13:45.19.727] BEGIN WMNewTab: 20 +[13:45.19.727] END WMNewTab: 20 + + +[13:45.21.139] BEGIN WMNewTab: 20 +[13:45.21.139] END WMNewTab: 20 + + +[13:45.22.550] BEGIN WMNewTab: 20 +[13:45.22.550] END WMNewTab: 20 + + +[13:45.23.968] BEGIN WMNewTab: 20 +[13:45.23.968] END WMNewTab: 20 + + +[13:45.25.386] BEGIN WMNewTab: 20 +[13:45.25.386] END WMNewTab: 20 + + +[13:45.26.806] BEGIN WMNewTab: 20 +[13:45.26.806] END WMNewTab: 20 + + +[13:45.28.221] BEGIN WMNewTab: 20 +[13:45.28.221] END WMNewTab: 20 + + +[13:45.29.635] BEGIN WMNewTab: 20 +[13:45.29.635] END WMNewTab: 20 + + +[13:45.31.054] BEGIN WMNewTab: 20 +[13:45.31.054] END WMNewTab: 20 + + +[13:45.32.473] BEGIN WMNewTab: 20 +[13:45.32.473] END WMNewTab: 20 + + +[13:45.33.891] BEGIN WMNewTab: 20 +[13:45.33.891] END WMNewTab: 20 + + +[13:45.35.316] BEGIN WMNewTab: 20 +[13:45.35.316] END WMNewTab: 20 + + +[13:45.36.739] BEGIN WMNewTab: 20 +[13:45.36.739] END WMNewTab: 20 + + +[13:45.38.154] BEGIN WMNewTab: 20 +[13:45.38.154] END WMNewTab: 20 + + +[13:45.39.574] BEGIN WMNewTab: 20 +[13:45.39.574] END WMNewTab: 20 + + +[13:45.40.995] BEGIN WMNewTab: 20 +[13:45.40.995] END WMNewTab: 20 + + +[13:45.42.412] BEGIN WMNewTab: 20 +[13:45.42.412] END WMNewTab: 20 + + +[13:45.43.836] BEGIN WMNewTab: 20 +[13:45.43.836] END WMNewTab: 20 + + +[13:45.45.256] BEGIN WMNewTab: 20 +[13:45.45.256] END WMNewTab: 20 + + +[13:45.46.667] BEGIN WMNewTab: 20 +[13:45.46.667] END WMNewTab: 20 + + +[13:45.48.086] BEGIN WMNewTab: 20 +[13:45.48.086] END WMNewTab: 20 + + +[13:45.49.509] BEGIN WMNewTab: 20 +[13:45.49.509] END WMNewTab: 20 + + +[13:45.50.919] BEGIN WMNewTab: 20 +[13:45.50.919] END WMNewTab: 20 + + +[13:45.52.340] BEGIN WMNewTab: 20 +[13:45.52.340] END WMNewTab: 20 + + +[13:45.53.758] BEGIN WMNewTab: 20 +[13:45.53.758] END WMNewTab: 20 + + +[13:45.55.173] BEGIN WMNewTab: 20 +[13:45.55.173] END WMNewTab: 20 + + +[13:45.56.592] BEGIN WMNewTab: 20 +[13:45.56.592] END WMNewTab: 20 + + +[13:45.58.007] BEGIN WMNewTab: 20 +[13:45.58.007] END WMNewTab: 20 + + +[13:45.59.428] BEGIN WMNewTab: 20 +[13:45.59.428] END WMNewTab: 20 + + +[13:46.00.841] BEGIN WMNewTab: 20 +[13:46.00.841] END WMNewTab: 20 + + +[13:46.02.263] BEGIN WMNewTab: 20 +[13:46.02.263] END WMNewTab: 20 + + +[13:46.03.679] BEGIN WMNewTab: 20 +[13:46.03.679] END WMNewTab: 20 + + +[13:46.05.100] BEGIN WMNewTab: 20 +[13:46.05.100] END WMNewTab: 20 + + +[13:46.06.539] BEGIN WMNewTab: 20 +[13:46.06.539] END WMNewTab: 20 + + +[13:46.07.960] BEGIN WMNewTab: 20 +[13:46.07.960] END WMNewTab: 20 + + +[13:46.09.381] BEGIN WMNewTab: 20 +[13:46.09.381] END WMNewTab: 20 + + +[13:46.10.798] BEGIN WMNewTab: 20 +[13:46.10.798] END WMNewTab: 20 + + +[13:46.12.220] BEGIN WMNewTab: 20 +[13:46.12.220] END WMNewTab: 20 + + +[13:46.13.637] BEGIN WMNewTab: 20 +[13:46.13.637] END WMNewTab: 20 + + +[13:46.15.062] BEGIN WMNewTab: 20 +[13:46.15.062] END WMNewTab: 20 + + +[13:46.16.478] BEGIN WMNewTab: 20 +[13:46.16.478] END WMNewTab: 20 + + +[13:46.17.892] BEGIN WMNewTab: 20 +[13:46.17.892] END WMNewTab: 20 + + +[13:46.19.315] BEGIN WMNewTab: 20 +[13:46.19.315] END WMNewTab: 20 + +[13:46.20.199] BEGIN WMNewTab: 0 +[13:46.20.199] WMNewTab: FormClick +[13:46.20.199] WMNewTab: LooseFocus +[13:46.20.200] END WMNewTab: 0 +[13:46.20.343] BEGIN WMNewTab: 0 +[13:46.20.343] WMNewTab: FormClick +[13:46.20.343] WMNewTab: LooseFocus +[13:46.20.344] END WMNewTab: 0 + +[13:46.20.729] BEGIN WMNewTab: 20 +[13:46.20.729] END WMNewTab: 20 + + +[13:46.22.147] BEGIN WMNewTab: 20 +[13:46.22.147] END WMNewTab: 20 + + +[13:46.23.569] BEGIN WMNewTab: 20 +[13:46.23.569] END WMNewTab: 20 + + +[13:46.24.983] BEGIN WMNewTab: 20 +[13:46.24.983] END WMNewTab: 20 + + +[13:46.26.402] BEGIN WMNewTab: 20 +[13:46.26.402] END WMNewTab: 20 + + +[13:46.27.826] BEGIN WMNewTab: 20 +[13:46.27.826] END WMNewTab: 20 + + +[13:46.29.243] BEGIN WMNewTab: 20 +[13:46.29.243] END WMNewTab: 20 + + +[13:46.30.661] BEGIN WMNewTab: 20 +[13:46.30.661] END WMNewTab: 20 + + +[13:46.32.081] BEGIN WMNewTab: 20 +[13:46.32.081] END WMNewTab: 20 + + +[13:46.33.495] BEGIN WMNewTab: 20 +[13:46.33.495] END WMNewTab: 20 + + +[13:46.34.915] BEGIN WMNewTab: 20 +[13:46.34.915] END WMNewTab: 20 + + +[13:46.36.334] BEGIN WMNewTab: 20 +[13:46.36.334] END WMNewTab: 20 + + +[13:46.37.757] BEGIN WMNewTab: 20 +[13:46.37.757] END WMNewTab: 20 + + +[13:46.39.173] BEGIN WMNewTab: 20 +[13:46.39.173] END WMNewTab: 20 + + +[13:46.40.596] BEGIN WMNewTab: 20 +[13:46.40.596] END WMNewTab: 20 + + +[13:46.42.014] BEGIN WMNewTab: 20 +[13:46.42.014] END WMNewTab: 20 + + +[13:46.43.433] BEGIN WMNewTab: 20 +[13:46.43.433] END WMNewTab: 20 + + +[13:46.44.856] BEGIN WMNewTab: 20 +[13:46.44.856] END WMNewTab: 20 + + +[13:46.46.274] BEGIN WMNewTab: 20 +[13:46.46.274] END WMNewTab: 20 + + +[13:46.47.695] BEGIN WMNewTab: 20 +[13:46.47.695] END WMNewTab: 20 + + +[13:46.49.114] BEGIN WMNewTab: 20 +[13:46.49.114] END WMNewTab: 20 + + +[13:46.50.533] BEGIN WMNewTab: 20 +[13:46.50.533] END WMNewTab: 20 + + +[13:46.51.952] BEGIN WMNewTab: 20 +[13:46.51.952] END WMNewTab: 20 + + +[13:46.53.388] BEGIN WMNewTab: 20 +[13:46.53.388] END WMNewTab: 20 + +[13:46.53.941] BEGIN CWD +[13:46.54.001] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[13:46.54.001] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[13:46.54.001] (SSH-Browser) END VerifySFTPConnection(1) +[13:46.54.001] END CWD +[13:46.54.005] BEGIN CWD +[13:46.54.065] END CWD + +[13:46.55.011] BEGIN WMNewTab: 20 +[13:46.55.011] END WMNewTab: 20 + + +[13:46.56.437] BEGIN WMNewTab: 20 +[13:46.56.437] END WMNewTab: 20 + + +[13:46.57.848] BEGIN WMNewTab: 20 +[13:46.57.848] END WMNewTab: 20 + + +[13:46.59.261] BEGIN WMNewTab: 20 +[13:46.59.261] END WMNewTab: 20 + + +[13:47.00.675] BEGIN WMNewTab: 20 +[13:47.00.675] END WMNewTab: 20 + + +[13:47.02.083] BEGIN WMNewTab: 20 +[13:47.02.083] END WMNewTab: 20 + + +[13:47.03.491] BEGIN WMNewTab: 20 +[13:47.03.491] END WMNewTab: 20 + + +[13:47.04.907] BEGIN WMNewTab: 20 +[13:47.04.907] END WMNewTab: 20 + +[13:47.05.417] BEGIN WMNewTab: 0 +[13:47.05.417] WMNewTab: FormClick +[13:47.05.417] WMNewTab: LooseFocus +[13:47.05.418] END WMNewTab: 0 +[13:47.05.545] BEGIN WMNewTab: 0 +[13:47.05.545] WMNewTab: FormClick +[13:47.05.545] WMNewTab: LooseFocus +[13:47.05.546] END WMNewTab: 0 + +[13:47.06.320] BEGIN WMNewTab: 20 +[13:47.06.320] END WMNewTab: 20 + + +[13:47.07.733] BEGIN WMNewTab: 20 +[13:47.07.733] END WMNewTab: 20 + + +[13:47.09.148] BEGIN WMNewTab: 20 +[13:47.09.148] END WMNewTab: 20 + + +[13:47.10.557] BEGIN WMNewTab: 20 +[13:47.10.557] END WMNewTab: 20 + + +[13:47.11.977] BEGIN WMNewTab: 20 +[13:47.11.977] END WMNewTab: 20 + + +[13:47.13.394] BEGIN WMNewTab: 20 +[13:47.13.394] END WMNewTab: 20 + + +[13:47.14.829] BEGIN WMNewTab: 20 +[13:47.14.829] END WMNewTab: 20 + + +[13:47.16.244] BEGIN WMNewTab: 20 +[13:47.16.244] END WMNewTab: 20 + + +[13:47.17.659] BEGIN WMNewTab: 20 +[13:47.17.659] END WMNewTab: 20 + + +[13:47.19.075] BEGIN WMNewTab: 20 +[13:47.19.075] END WMNewTab: 20 + + +[13:47.20.487] BEGIN WMNewTab: 20 +[13:47.20.487] END WMNewTab: 20 + + +[13:47.21.903] BEGIN WMNewTab: 20 +[13:47.21.903] END WMNewTab: 20 + + +[13:47.23.314] BEGIN WMNewTab: 20 +[13:47.23.314] END WMNewTab: 20 + + +[13:47.24.726] BEGIN WMNewTab: 20 +[13:47.24.726] END WMNewTab: 20 + + +[13:47.26.135] BEGIN WMNewTab: 20 +[13:47.26.135] END WMNewTab: 20 + + +[13:47.27.549] BEGIN WMNewTab: 20 +[13:47.27.549] END WMNewTab: 20 + + +[13:47.28.966] BEGIN WMNewTab: 20 +[13:47.28.966] END WMNewTab: 20 + + +[13:47.30.384] BEGIN WMNewTab: 20 +[13:47.30.384] END WMNewTab: 20 + + +[13:47.31.801] BEGIN WMNewTab: 20 +[13:47.31.801] END WMNewTab: 20 + + +[13:47.33.231] BEGIN WMNewTab: 20 +[13:47.33.231] END WMNewTab: 20 + + +[13:47.34.641] BEGIN WMNewTab: 20 +[13:47.34.641] END WMNewTab: 20 + + +[13:47.36.061] BEGIN WMNewTab: 20 +[13:47.36.061] END WMNewTab: 20 + + +[13:47.37.476] BEGIN WMNewTab: 20 +[13:47.37.476] END WMNewTab: 20 + + +[13:47.38.896] BEGIN WMNewTab: 20 +[13:47.38.896] END WMNewTab: 20 + + +[13:47.40.307] BEGIN WMNewTab: 20 +[13:47.40.307] END WMNewTab: 20 + + +[13:47.41.722] BEGIN WMNewTab: 20 +[13:47.41.722] END WMNewTab: 20 + + +[13:47.43.135] BEGIN WMNewTab: 20 +[13:47.43.135] END WMNewTab: 20 + + +[13:47.44.550] BEGIN WMNewTab: 20 +[13:47.44.550] END WMNewTab: 20 +[13:47.44.628] BEGIN WMNCLButtonDown +[13:47.44.718] BEGIN WMSysCommand (minimize/restore) +[13:47.44.744] BEGIN WMSize +[13:47.44.744] END WMSize +[13:47.44.776] END WMSysCommand +[13:47.44.776] END WMNCLButtonDown + +[13:47.45.965] BEGIN WMNewTab: 20 +[13:47.45.965] END WMNewTab: 20 + + +[13:47.47.384] BEGIN WMNewTab: 20 +[13:47.47.384] END WMNewTab: 20 + + +[13:47.48.803] BEGIN WMNewTab: 20 +[13:47.48.803] END WMNewTab: 20 + + +[13:47.50.218] BEGIN WMNewTab: 20 +[13:47.50.218] END WMNewTab: 20 + + +[13:47.51.641] BEGIN WMNewTab: 20 +[13:47.51.641] END WMNewTab: 20 + + +[13:47.53.050] BEGIN WMNewTab: 20 +[13:47.53.050] END WMNewTab: 20 + + +[13:47.54.465] BEGIN WMNewTab: 20 +[13:47.54.465] END WMNewTab: 20 + + +[13:47.55.879] BEGIN WMNewTab: 20 +[13:47.55.879] END WMNewTab: 20 + + +[13:47.57.288] BEGIN WMNewTab: 20 +[13:47.57.288] END WMNewTab: 20 + + +[13:47.58.693] BEGIN WMNewTab: 20 +[13:47.58.693] END WMNewTab: 20 + + +[13:48.00.103] BEGIN WMNewTab: 20 +[13:48.00.103] END WMNewTab: 20 + + +[13:48.01.518] BEGIN WMNewTab: 20 +[13:48.01.518] END WMNewTab: 20 + + +[13:48.02.928] BEGIN WMNewTab: 20 +[13:48.02.928] END WMNewTab: 20 + + +[13:48.04.336] BEGIN WMNewTab: 20 +[13:48.04.336] END WMNewTab: 20 + + +[13:48.05.742] BEGIN WMNewTab: 20 +[13:48.05.742] END WMNewTab: 20 + + +[13:48.07.159] BEGIN WMNewTab: 20 +[13:48.07.159] END WMNewTab: 20 + + +[13:48.08.569] BEGIN WMNewTab: 20 +[13:48.08.569] END WMNewTab: 20 + + +[13:48.09.980] BEGIN WMNewTab: 20 +[13:48.09.980] END WMNewTab: 20 + + +[13:48.11.389] BEGIN WMNewTab: 20 +[13:48.11.389] END WMNewTab: 20 + + +[13:48.12.796] BEGIN WMNewTab: 20 +[13:48.12.796] END WMNewTab: 20 + + +[13:48.14.202] BEGIN WMNewTab: 20 +[13:48.14.202] END WMNewTab: 20 + + +[13:48.15.615] BEGIN WMNewTab: 20 +[13:48.15.615] END WMNewTab: 20 + + +[13:48.17.022] BEGIN WMNewTab: 20 +[13:48.17.022] END WMNewTab: 20 + + +[13:48.18.432] BEGIN WMNewTab: 20 +[13:48.18.432] END WMNewTab: 20 + + +[13:48.19.845] BEGIN WMNewTab: 20 +[13:48.19.845] END WMNewTab: 20 + + +[13:48.21.257] BEGIN WMNewTab: 20 +[13:48.21.257] END WMNewTab: 20 + + +[13:48.22.666] BEGIN WMNewTab: 20 +[13:48.22.666] END WMNewTab: 20 + + +[13:48.24.076] BEGIN WMNewTab: 20 +[13:48.24.076] END WMNewTab: 20 + + +[13:48.25.485] BEGIN WMNewTab: 20 +[13:48.25.485] END WMNewTab: 20 + + +[13:48.26.894] BEGIN WMNewTab: 20 +[13:48.26.894] END WMNewTab: 20 + + +[13:48.28.302] BEGIN WMNewTab: 20 +[13:48.28.302] END WMNewTab: 20 + + +[13:48.29.711] BEGIN WMNewTab: 20 +[13:48.29.711] END WMNewTab: 20 + + +[13:48.31.120] BEGIN WMNewTab: 20 +[13:48.31.120] END WMNewTab: 20 + + +[13:48.32.529] BEGIN WMNewTab: 20 +[13:48.32.529] END WMNewTab: 20 + + +[13:48.33.936] BEGIN WMNewTab: 20 +[13:48.33.936] END WMNewTab: 20 + + +[13:48.35.350] BEGIN WMNewTab: 20 +[13:48.35.350] END WMNewTab: 20 + + +[13:48.36.761] BEGIN WMNewTab: 20 +[13:48.36.761] END WMNewTab: 20 + + +[13:48.38.170] BEGIN WMNewTab: 20 +[13:48.38.170] END WMNewTab: 20 + + +[13:48.39.580] BEGIN WMNewTab: 20 +[13:48.39.580] END WMNewTab: 20 + + +[13:48.40.990] BEGIN WMNewTab: 20 +[13:48.40.990] END WMNewTab: 20 + + +[13:48.42.402] BEGIN WMNewTab: 20 +[13:48.42.402] END WMNewTab: 20 + + +[13:48.43.809] BEGIN WMNewTab: 20 +[13:48.43.809] END WMNewTab: 20 + + +[13:48.45.221] BEGIN WMNewTab: 20 +[13:48.45.221] END WMNewTab: 20 + + +[13:48.46.630] BEGIN WMNewTab: 20 +[13:48.46.630] END WMNewTab: 20 + + +[13:48.48.046] BEGIN WMNewTab: 20 +[13:48.48.046] END WMNewTab: 20 + + +[13:48.49.456] BEGIN WMNewTab: 20 +[13:48.49.456] END WMNewTab: 20 + + +[13:48.50.863] BEGIN WMNewTab: 20 +[13:48.50.863] END WMNewTab: 20 + + +[13:48.52.282] BEGIN WMNewTab: 20 +[13:48.52.282] END WMNewTab: 20 + + +[13:48.53.693] BEGIN WMNewTab: 20 +[13:48.53.693] END WMNewTab: 20 + + +[13:48.55.107] BEGIN WMNewTab: 20 +[13:48.55.107] END WMNewTab: 20 + + +[13:48.56.516] BEGIN WMNewTab: 20 +[13:48.56.516] END WMNewTab: 20 + + +[13:48.57.938] BEGIN WMNewTab: 20 +[13:48.57.938] END WMNewTab: 20 + + +[13:48.59.350] BEGIN WMNewTab: 20 +[13:48.59.350] END WMNewTab: 20 + + +[13:49.00.766] BEGIN WMNewTab: 20 +[13:49.00.766] END WMNewTab: 20 + + +[13:49.02.182] BEGIN WMNewTab: 20 +[13:49.02.182] END WMNewTab: 20 + + +[13:49.03.599] BEGIN WMNewTab: 20 +[13:49.03.599] END WMNewTab: 20 + + +[13:49.05.013] BEGIN WMNewTab: 20 +[13:49.05.013] END WMNewTab: 20 + + +[13:49.06.435] BEGIN WMNewTab: 20 +[13:49.06.435] END WMNewTab: 20 + + +[13:49.07.860] BEGIN WMNewTab: 20 +[13:49.07.860] END WMNewTab: 20 + + +[13:49.09.276] BEGIN WMNewTab: 20 +[13:49.09.276] END WMNewTab: 20 + + +[13:49.10.695] BEGIN WMNewTab: 20 +[13:49.10.695] END WMNewTab: 20 + + +[13:49.12.114] BEGIN WMNewTab: 20 +[13:49.12.114] END WMNewTab: 20 + + +[13:49.13.533] BEGIN WMNewTab: 20 +[13:49.13.533] END WMNewTab: 20 + + +[13:49.14.954] BEGIN WMNewTab: 20 +[13:49.14.954] END WMNewTab: 20 + + +[13:49.16.379] BEGIN WMNewTab: 20 +[13:49.16.379] END WMNewTab: 20 + + +[13:49.17.804] BEGIN WMNewTab: 20 +[13:49.17.804] END WMNewTab: 20 + + +[13:49.19.223] BEGIN WMNewTab: 20 +[13:49.19.223] END WMNewTab: 20 + + +[13:49.20.644] BEGIN WMNewTab: 20 +[13:49.20.644] END WMNewTab: 20 + + +[13:49.22.058] BEGIN WMNewTab: 20 +[13:49.22.058] END WMNewTab: 20 + + +[13:49.23.501] BEGIN WMNewTab: 20 +[13:49.23.501] END WMNewTab: 20 + + +[13:49.24.916] BEGIN WMNewTab: 20 +[13:49.24.916] END WMNewTab: 20 + + +[13:49.26.338] BEGIN WMNewTab: 20 +[13:49.26.338] END WMNewTab: 20 + + +[13:49.27.758] BEGIN WMNewTab: 20 +[13:49.27.758] END WMNewTab: 20 + + +[13:49.29.177] BEGIN WMNewTab: 20 +[13:49.29.177] END WMNewTab: 20 + + +[13:49.30.591] BEGIN WMNewTab: 20 +[13:49.30.591] END WMNewTab: 20 + + +[13:49.32.008] BEGIN WMNewTab: 20 +[13:49.32.009] END WMNewTab: 20 + + +[13:49.33.423] BEGIN WMNewTab: 20 +[13:49.33.423] END WMNewTab: 20 + + +[13:49.34.844] BEGIN WMNewTab: 20 +[13:49.34.844] END WMNewTab: 20 + +[13:49.35.991] BEGIN WMNewTab: 48 +[13:49.35.991] 收到消息: SSH 会话部分关闭 (2) +[13:49.36.080] BEGIN DisconnectSSH(1) +[13:49.36.080] (SSH-Browser) DisconnectSSH(1): (Socket.Active) and (SocketState<>SOCKET_STATE_CONNECTING) +[13:49.36.080] SetTitle(1, ); +[13:49.36.080] BEGIN WMNewTab: 20 +[13:49.36.080] END WMNewTab: 20 +[13:49.36.139] (SSH-Browser) ElSFTP1CloseConnection(1) +[13:49.36.139] (SSH-Browser) ElSFTP1Error(1): #103 - 连接被低层协议关闭 +[13:49.36.139] SFTPErr #103 附带说明 "连接被低层协议关闭" +[13:49.36.139] (SSH-Browser) ElSFTP1CloseConnection(1) +[13:49.36.139] BEGIN ElSSH1CloseConnection(1) +[13:49.36.139] END ElSSH1CloseConnection(1) +[13:49.36.139] (SSH-Browser) DisconnectSSH(1): Socket.Close; +[13:49.36.139] (SSH-Browser) BEGIN DesactiverPanel14 +[13:49.36.147] (SSH-Browser) END DesactiverPanel14 +[13:49.36.147] END DisconnectSSH(1) +[13:49.36.147] END WMNewTab: 48 + + + + + + + +[14:06:50] BEGIN WMSysCommand (minimize/restore) +[14:06:50] BEGIN WMNewTab: 0 +[14:06:50] WMNewTab: FormClick +[14:06:50] WMNewTab: LooseFocus +[14:06:50] END WMNewTab: 0 +[14:06:50] BEGIN WMSize +[14:06:50] BEGIN TFormXterm.FormResize +[14:06:50] TFormXterm.FormResize: CenterBtnReattachTab +[14:06:50] TFormXterm.FormResize: SplitModeResize +[14:06:50] TFormXterm.FormResize: BtnSplitNo.Down +[14:06:50] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:06:50] BEGIN ResizeTerminal +[14:06:50] END ResizeTerminal +[14:06:50] TFormXterm.FormResize: AdaptSidebarArrows; +[14:06:50] BEGIN AdaptSidebarArrows +[14:06:50] END AdaptSidebarArrows +[14:06:50] TFormXterm.FormResize: AdaptTV2; +[14:06:50] END TFormXterm.FormResize +[14:06:50] END WMSize +[14:06:50] END WMSysCommand + + + +[14:07:08] BEGIN WMNewTab: 0 +[14:07:08] WMNewTab: FormClick +[14:07:08] WMNewTab: LooseFocus +[14:07:08] END WMNewTab: 0 +[14:07:08] BEGIN WMNewTab: 0 +[14:07:08] WMNewTab: FormClick +[14:07:08] WMNewTab: LooseFocus +[14:07:08] END WMNewTab: 0 + +[14:07:09] BEGIN BtnNewSessionClick +[14:07:09] BtnNewSessionClick: FormClick +[14:07:09] BEGIN ChargerLaSession +[14:07:09] ChargerLaSession1 +[14:07:09] ChargerLaSession2 + +[14:07:10] BEGIN FormSessions.Btn0Click: 8 +[14:07:10] BEGIN LockControl(FormSessionEdit, Btn0Click) +[14:07:10] END LockControl(FormSessionEdit, Btn0Click) +[14:07:10] 加载新会话类型的默认值 #8 +[14:07:10] BEGIN ChargerLePreset EMPTY_PRESETS +[14:07:10] ChargerLaSession1 +[14:07:10] END ChargerLePreset +[14:07:10] BEGIN SetupEnumAvailableComPorts +[14:07:10] SetupEnumAvailableComPorts: SetupDiClassGuidsFromName +[14:07:10] SetupEnumAvailableComPorts: SetupDiGetClassDevs +[14:07:10] SetupEnumAvailableComPorts: SetupDiEnumDeviceInfo +[14:07:10] SetupEnumAvailableComPorts: SetupDiGetDeviceRegistryProperty +[14:07:10] SetupEnumAvailableComPorts: SetupDiGetDeviceRegistryProperty +[14:07:10] SetupEnumAvailableComPorts: SetupDiEnumDeviceInfo +[14:07:10] SetupEnumAvailableComPorts: SetupDiGetDeviceRegistryProperty +[14:07:10] SetupEnumAvailableComPorts: SetupDiGetDeviceRegistryProperty +[14:07:10] SetupEnumAvailableComPorts: SetupDiEnumDeviceInfo +[14:07:10] SetupEnumAvailableComPorts: SetupDiGetDeviceRegistryProperty +[14:07:10] SetupEnumAvailableComPorts: SetupDiGetDeviceRegistryProperty +[14:07:10] SetupEnumAvailableComPorts: SetupDiEnumDeviceInfo +[14:07:10] SetupEnumAvailableComPorts: SetupDiDestroyDeviceInfoList +[14:07:10] END SetupEnumAvailableComPorts +[14:07:10] BEGIN UnlockControl(FormSessionEdit, Btn0Click) +[14:07:10] END UnlockControl(FormSessionEdit, Btn0Click) +[14:07:10] END FormSessions.Btn0Click + + +[14:07:17] BEGIN SessionClickOK +[14:07:17] LaunchSession0 +[14:07:17] LaunchSession1 +[14:07:17] LaunchSession4 +[14:07:17] LaunchSession5 +[14:07:17] +[14:07:17] BEGIN NEWTAB(PuCom COM3, 131, 0) +[14:07:17] NEWTAB: Application.ProcessMessages +[14:07:17] NEWTAB: Timer1_Disable +[14:07:17] NEWTAB: 检查是否已达到最大标签数... +[14:07:17] NEWTAB: 创建 SFTPRecord... +[14:07:17] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[14:07:17] NEWTAB: 尝试查找旧索引... +[14:07:17] NEWTAB: Cts1.BeginUpdate; +[14:07:17] NEWTAB: 创建新标签页... +[14:07:17] NEWTAB: 标签页索引: 2 +[14:07:17] NEWTAB: 终端编号 : 4 +[14:07:17] NEWTAB: 标题 : COM3 (USB-SERIAL CH340 (COM3)) +[14:07:17] NEWTAB: 命令 : PuCom COM3 +[14:07:17] Cts1ActiveTabChanged: New index = 2 +[14:07:17] NEWTAB: Cts1.EndUpdates +[14:07:17] NEWTAB: 更改标签页索引 A = 2 +[14:07:17] BEGIN WaitForAllThreads +[14:07:17] END WaitForAllThreads +[14:07:17] +[14:07:17] LaunchTabContent(PuCom COM3, COM3 (USB-SERIAL CH340 (COM3))); +[14:07:17] +[14:07:17] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[14:07:17] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[14:07:17] MOBANOACL=onlyslash +[14:07:17] +[14:07:17] ShellExecute: motty.exe +[14:07:17] +[14:07:17] CreerSessionMoTTY(4, PuCom COM3, COM3 (USB-SERIAL CH340 (COM3))) +[14:07:17] Setting LOCALE=zh_CN.UTF-8 +[14:07:17] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[14:07:17] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[14:07:17] MOBANOACL=onlyslash +[14:07:17] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756664") +[14:07:18] ShellExecuteS: ShellExecuteEx 成功. +[14:07:18] ShellExecuteS: WaitForInputIdle 成功. +[14:07:18] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756664") +[14:07:18] +[14:07:18] FindWindow(CMoTTY) +[14:07:18] BEGIN WMNewTab: 60 +[14:07:18] END WMNewTab: 60 +[14:07:18] SetTitle(2, COM3 (USB-SERIAL CH340 (COM3))); +[14:07:18] 潜在窗口 530298 成功通过第二次验证. +[14:07:18] --> 成功 +[14:07:18] BEGIN MoTTY.SetParent +[14:07:18] END MoTTY.SetParent +[14:07:18] NEWTAB: Application.OnMessage:=AppMessage +[14:07:18] +[14:07:18] BEGIN Form4.FormActivate +[14:07:18] END Form4.FormActivate +[14:07:18] +[14:07:18] NEWTAB: 更改标签页索引 C = 2 +[14:07:18] NEWTAB: 正在启动 DisplayCurrentTab... +[14:07:18] BEGIN DisplayCurrentTab +[14:07:18] DisplayCurrentTab: FormClick +[14:07:18] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[14:07:18] (SSH-Browser) BEGIN ActiverPanel14 +[14:07:18] (SSH-Browser) BEGIN DesactiverPanel14 +[14:07:18] (SSH-Browser) END DesactiverPanel14 +[14:07:18] (SSH-Browser) END ActiverPanel14; +[14:07:18] DisplayCurrentTab: Cts1.BeginUpdate; +[14:07:18] DisplayCurrentTab: Cts1.EndUpdates +[14:07:18] DisplayCurrentTab: 显示所选标签页 +[14:07:18] DisplayCurrentTab: 隐藏其他标签页 +[14:07:18] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:07:18] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:07:18] DisplayCurrentTab: DistribuerLeFocus +[14:07:18] END DisplayCurrentTab +[14:07:18] NEWTAB: NewTab_ReEnable_Timer1 +[14:07:18] NEWTAB: MajVerticalTabs +[14:07:18] NEWTAB: Cts1.Resize; +[14:07:18] END NEWTAB(PuCom COM3, 131, 0) +[14:07:18] +[14:07:18] LaunchSession6 +[14:07:18] END SessionClickOK +[14:07:18] BEGIN TFormSessionEdit.FormClose +[14:07:18] END TFormSessionEdit.FormClose +[14:07:18] END BtnNewSessionClick +[14:07:18] BEGIN WMNewTab: 62 +[14:07:18] END WMNewTab: 62 + + + +[14:07:59] Cts1MouseDown: FormClick +[14:07:59] Cts1ActiveTabChanged: New index = 1 +[14:07:59] BEGIN DisplayCurrentTab +[14:07:59] DisplayCurrentTab: FormClick +[14:07:59] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[14:07:59] (SSH-Browser) BEGIN ActiverPanel14 +[14:07:59] (SSH-Browser) BEGIN DesactiverPanel14 +[14:07:59] (SSH-Browser) END DesactiverPanel14 +[14:07:59] (SSH-Browser) END ActiverPanel14; +[14:07:59] DisplayCurrentTab: Cts1.BeginUpdate; +[14:07:59] DisplayCurrentTab: Cts1.EndUpdates +[14:07:59] DisplayCurrentTab: 显示所选标签页 +[14:07:59] DisplayCurrentTab: 隐藏其他标签页 +[14:07:59] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:07:59] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:07:59] DisplayCurrentTab: DistribuerLeFocus +[14:07:59] END DisplayCurrentTab + +[14:07:59] BEGIN WMNewTab: 0 +[14:07:59] WMNewTab: FormClick +[14:07:59] WMNewTab: LooseFocus +[14:07:59] END WMNewTab: 0 +[14:07:59] BEGIN WMNewTab: 0 +[14:07:59] WMNewTab: FormClick +[14:07:59] WMNewTab: LooseFocus +[14:07:59] END WMNewTab: 0 + +[14:08:00] BEGIN WMNewTab: 62 +[14:08:00] END WMNewTab: 62 +[14:08:00] SetTitle(1, 192.168.127.10 (root)); +[14:08:00] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[14:08:00] 主机密钥与缓存中的密钥是不一致的 +[14:08:00] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[14:08:00] 主机密钥与缓存中的密钥是不一致的 + + +[14:08:04] 收到主机密钥存储请求: ssh-ed25519@22:192.168.127.10|0x375d1796bb113c10bdb35b32081ed46dd897e3df77dc0681dde7b6db9a7ffb6d,0x649881426de5a5e61932ab6e824b2fd0eda5c410fe89f72029cd4e68ee9cf62 +[14:08:04] BEGIN GetPassword +[14:08:04] BEGIN GetnSaveCredPassword +[14:08:04] END GetnSaveCredPassword +[14:08:04] END GetPassword + + +[14:08:06] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[14:08:06] BEGIN SauvegarderMotDePasseSSH +[14:08:06] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[14:08:06] SetTitle(1, root@192.168.127.10); +[14:08:06] +[14:08:06] (SSH-Browser) BEGIN ConnectSSH(1,192.168.127.10,root,) +[14:08:06] (SSH-Browser) ConnectSSH(1): 初始化 TabSFTP +[14:08:06] (SSH-Browser) ConnectSSH(1): 未使用代理 +[14:08:06] (SSH-Browser) ConnectSSH(1): 未提供密钥 --> 使用其他身份验证类型进行连接 +[14:08:06] (SSH-Browser) ConnectSSH(1): 已成功连接到 192.168.127.10. +[14:08:06] (SSH-Browser) ConnectSSH(1): SSH.Open +[14:08:06] (SSH-Browser) END ConnectSSH(1) +[14:08:06] BEGIN DisplayCurrentTab +[14:08:06] DisplayCurrentTab: FormClick +[14:08:06] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[14:08:06] (SSH-Browser) BEGIN ActiverPanel14 +[14:08:06] (SSH-Browser) BEGIN DesactiverPanel14 +[14:08:06] (SSH-Browser) END DesactiverPanel14 +[14:08:06] (SSH-Browser) END ActiverPanel14; +[14:08:06] DisplayCurrentTab: Cts1.BeginUpdate; +[14:08:06] DisplayCurrentTab: Cts1.EndUpdates +[14:08:06] DisplayCurrentTab: 显示所选标签页 +[14:08:06] DisplayCurrentTab: 隐藏其他标签页 +[14:08:06] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:08:06] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:08:06] DisplayCurrentTab: DistribuerLeFocus +[14:08:06] END DisplayCurrentTab +[14:08:06] BEGIN SavePassword +[14:08:06] END SavePassword +[14:08:06] END SauvegarderMotDePasseSSH +[14:08:06] BEGIN WMNewTab: 80 +[14:08:06] 收到消息: 正在启动远程监控 终端 #2 +[14:08:06] BEGIN TFormXterm.FormResize +[14:08:06] TFormXterm.FormResize: CenterBtnReattachTab +[14:08:06] TFormXterm.FormResize: SplitModeResize +[14:08:06] TFormXterm.FormResize: BtnSplitNo.Down +[14:08:06] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:08:06] BEGIN ResizeTerminal +[14:08:06] END ResizeTerminal +[14:08:06] TFormXterm.FormResize: AdaptSidebarArrows; +[14:08:06] BEGIN AdaptSidebarArrows +[14:08:06] END AdaptSidebarArrows +[14:08:06] TFormXterm.FormResize: AdaptTV2; +[14:08:06] END TFormXterm.FormResize +[14:08:06] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[14:08:06] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:08:06] ShellExecuteS: ShellExecuteEx 成功. +[14:08:06] ShellExecuteS: WaitForInputIdle 失败. +[14:08:06] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:08:06] END WMNewTab: 80 +[14:08:06] [MobaSCP2] Launching remote monitoring in normal mode +[14:08:06] [MobaSCP2] Multiplex=1 +[14:08:06] [MobaSCP2] HOSTNAME: 192.168.127.10 +[14:08:06] [MobaSCP2] USERNAME: root +[14:08:06] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[14:08:06] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[14:08:06] (SSH-Browser) 主机密钥指纹信息 (Sha256): 2b:ca:32:12:87:5d:69:9e:24:78:db:b7:f5:ec:40:a8:c2:4b:0c:47:27:72:0a:10:19:c4:4f:43:cf:7c:05:be +[14:08:06] (SSH-Browser) 主机密钥数据已存在于 INI 文件中 +[14:08:06] (SSH-Browser) END GetSftpOnValidateStatus +[14:08:06] [MobaSCP2] Using SCP1 +[14:08:06] [MobaSCP2] Connected to 192.168.127.10 +[14:08:06] +[14:08:06] (SSH-Browser) ElSSH1AuthenticationStart(1, 134) +[14:08:06] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[14:08:06] (SSH-Browser) 服务器支持以下认证方式: +[14:08:06] (SSH-Browser) . PUBLICKEYAGENT +[14:08:06] (SSH-Browser) . PUBLICKEY +[14:08:06] (SSH-Browser) . PASSWORD +[14:08:06] (SSH-Browser) 客户端支持以下认证方式: +[14:08:06] (SSH-Browser) . PUBLICKEYAGENT +[14:08:06] (SSH-Browser) . PUBLICKEY +[14:08:06] (SSH-Browser) . RHOSTS +[14:08:06] (SSH-Browser) . HOSTBASED +[14:08:06] (SSH-Browser) . PASSWORD +[14:08:06] (SSH-Browser) . KEYBOARD +[14:08:06] +[14:08:06] +[14:08:06] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEY) +[14:08:06] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEYAGENT) +[14:08:06] (SSH-Browser) ElSSH1AuthenticationAttempt(1, PASSWORD) + +[14:08:06] (SSH-Browser) ElSSH1AuthenticationSuccess(1) +[14:08:06] (SSH-Browser) ElSSH1OpenConnection(1) +[14:08:06] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[14:08:06] +[14:08:07] (SSH-Browser) BEGIN ElSFTP1OpenConnection(1) +[14:08:07] (SSH-Browser) ElSFTP1OpenConnection(1): SFTP 已正确连接 +[14:08:07] (SSH-Browser) ElSFTP1OpenConnection(1): ActiverPanel14 +[14:08:07] (SSH-Browser) BEGIN ActiverPanel14 +[14:08:07] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[14:08:07] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[14:08:07] (SSH-Browser) ActiverPanel14: 列出远程目录 +[14:08:07] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[14:08:07] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[14:08:07] (SSH-Browser) END ActiverPanel14; +[14:08:07] (SSH-Browser) ElSFTP1OpenConnection(1): 已成功打开连接 --> 正在退出 +[14:08:07] (SSH-Browser) END ElSFTP1OpenConnection(1) +[14:08:07] BEGIN TFormXterm.FormResize +[14:08:07] TFormXterm.FormResize: CenterBtnReattachTab +[14:08:07] TFormXterm.FormResize: SplitModeResize +[14:08:07] TFormXterm.FormResize: BtnSplitNo.Down +[14:08:07] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:08:07] BEGIN ResizeTerminal +[14:08:07] END ResizeTerminal +[14:08:07] TFormXterm.FormResize: AdaptSidebarArrows; +[14:08:07] BEGIN AdaptSidebarArrows +[14:08:07] END AdaptSidebarArrows +[14:08:07] TFormXterm.FormResize: AdaptTV2; +[14:08:07] END TFormXterm.FormResize +[14:08:07] BEGIN WMNewTab: 20 +[14:08:07] END WMNewTab: 20 +[14:08:08] BEGIN CWD +[14:08:08] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:08:08] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:08:08] (SSH-Browser) END VerifySFTPConnection(1) +[14:08:08] END CWD +[14:08:08] (SSH-Browser) ElCommandSSHTunnel1Open +[14:08:08] (SSH-Browser) ExecuteCommandData +[14:08:08] (SSH-Browser) ExecuteCommandData +[14:08:08] (SSH-Browser) ExecuteCommandData +[14:08:08] (SSH-Browser) ExecuteCommandData +[14:08:08] (SSH-Browser) ExecuteCommandData +[14:08:08] (SSH-Browser) ExecuteCommandData +[14:08:08] (SSH-Browser) ExecuteCommandClose +[14:08:08] BEGIN CWD +[14:08:08] (CWD) TenterDeTrouverLeCWD: Minute=0 / Seconde=1 +[14:08:08] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:08:08] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:08:08] (SSH-Browser) END VerifySFTPConnection(1) +[14:08:08] END CWD +[14:08:08] BEGIN CWD +[14:08:08] END CWD + +[14:08:09] BEGIN WMNewTab: 20 +[14:08:09] END WMNewTab: 20 + + +[14:08:10] BEGIN WMNewTab: 20 +[14:08:10] END WMNewTab: 20 + + +[14:08:11] BEGIN WMNewTab: 20 +[14:08:11] END WMNewTab: 20 + + +[14:08:13] BEGIN WMNewTab: 20 +[14:08:13] END WMNewTab: 20 + + +[14:08:14] BEGIN WMNewTab: 20 +[14:08:14] END WMNewTab: 20 + + +[14:08:16] BEGIN WMNewTab: 20 +[14:08:16] END WMNewTab: 20 + +[14:08:17] BEGIN CWD +[14:08:17] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:08:17] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:08:17] (SSH-Browser) END VerifySFTPConnection(1) +[14:08:17] END CWD +[14:08:17] BEGIN WMNewTab: 20 +[14:08:17] END WMNewTab: 20 +[14:08:17] BEGIN CWD +[14:08:17] END CWD + + +[14:08:18] BEGIN WMNewTab: 20 +[14:08:18] END WMNewTab: 20 + + +[14:08:20] BEGIN WMNewTab: 20 +[14:08:20] END WMNewTab: 20 + + +[14:08:21] BEGIN WMNewTab: 20 +[14:08:21] END WMNewTab: 20 +[14:08:21] BEGIN CWD +[14:08:21] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:08:21] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:08:21] (SSH-Browser) END VerifySFTPConnection(1) +[14:08:21] END CWD +[14:08:21] BEGIN CWD +[14:08:21] END CWD + + +[14:08:23] BEGIN WMNewTab: 20 +[14:08:23] END WMNewTab: 20 + +[14:08:24] BEGIN CWD +[14:08:24] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:08:24] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:08:24] (SSH-Browser) END VerifySFTPConnection(1) +[14:08:24] END CWD +[14:08:24] BEGIN CWD +[14:08:24] END CWD + +[14:08:24] BEGIN WMNewTab: 20 +[14:08:24] END WMNewTab: 20 + +[14:08:25] BEGIN CWD +[14:08:25] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:08:25] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:08:25] (SSH-Browser) END VerifySFTPConnection(1) +[14:08:25] END CWD +[14:08:25] BEGIN CWD +[14:08:25] END CWD + +[14:08:26] BEGIN WMNewTab: 20 +[14:08:26] END WMNewTab: 20 +[14:08:26] BEGIN CWD +[14:08:26] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:08:26] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:08:26] (SSH-Browser) END VerifySFTPConnection(1) +[14:08:26] END CWD +[14:08:26] BEGIN CWD +[14:08:26] END CWD + +[14:08:27] BEGIN CWD +[14:08:27] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:08:27] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:08:27] (SSH-Browser) END VerifySFTPConnection(1) +[14:08:27] END CWD +[14:08:27] BEGIN CWD +[14:08:27] END CWD + +[14:08:28] BEGIN WMNewTab: 20 +[14:08:28] END WMNewTab: 20 + + +[14:08:29] BEGIN WMNewTab: 20 +[14:08:29] END WMNewTab: 20 + + +[14:08:30] BEGIN WMNewTab: 20 +[14:08:30] END WMNewTab: 20 + +[14:08:31] Cts1MouseDown: FormClick +[14:08:31] Cts1ActiveTabChanged: New index = 2 +[14:08:31] BEGIN DisplayCurrentTab +[14:08:31] DisplayCurrentTab: FormClick +[14:08:31] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[14:08:31] (SSH-Browser) BEGIN ActiverPanel14 +[14:08:31] (SSH-Browser) BEGIN DesactiverPanel14 +[14:08:31] (SSH-Browser) END DesactiverPanel14 +[14:08:31] (SSH-Browser) END ActiverPanel14; +[14:08:31] BEGIN TFormXterm.FormResize +[14:08:31] TFormXterm.FormResize: CenterBtnReattachTab +[14:08:31] TFormXterm.FormResize: SplitModeResize +[14:08:31] TFormXterm.FormResize: BtnSplitNo.Down +[14:08:31] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:08:31] BEGIN ResizeTerminal +[14:08:31] END ResizeTerminal +[14:08:31] TFormXterm.FormResize: AdaptSidebarArrows; +[14:08:31] BEGIN AdaptSidebarArrows +[14:08:31] END AdaptSidebarArrows +[14:08:31] TFormXterm.FormResize: AdaptTV2; +[14:08:31] END TFormXterm.FormResize +[14:08:31] DisplayCurrentTab: Cts1.BeginUpdate; +[14:08:31] DisplayCurrentTab: Cts1.EndUpdates +[14:08:31] DisplayCurrentTab: 显示所选标签页 +[14:08:31] DisplayCurrentTab: 隐藏其他标签页 +[14:08:31] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:08:31] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:08:31] DisplayCurrentTab: DistribuerLeFocus +[14:08:31] END DisplayCurrentTab + +[14:08:32] BEGIN WMNewTab: 0 +[14:08:32] WMNewTab: FormClick +[14:08:32] WMNewTab: LooseFocus +[14:08:32] END WMNewTab: 0 +[14:08:32] BEGIN WMNewTab: 20 +[14:08:32] END WMNewTab: 20 +[14:08:32] BEGIN WMNewTab: 0 +[14:08:32] WMNewTab: FormClick +[14:08:32] WMNewTab: LooseFocus +[14:08:32] END WMNewTab: 0 + + +[14:08:33] BEGIN WMNewTab: 20 +[14:08:33] END WMNewTab: 20 + + +[14:08:35] BEGIN WMNewTab: 20 +[14:08:35] END WMNewTab: 20 + + +[14:08:36] BEGIN WMNewTab: 20 +[14:08:36] END WMNewTab: 20 + +[14:08:37] BEGIN WMNewTab: 48 +[14:08:37] 收到消息: SSH 会话部分关闭 (2) +[14:08:37] BEGIN DisconnectSSH(1) +[14:08:37] (SSH-Browser) DisconnectSSH(1): (Socket.Active) and (SocketState<>SOCKET_STATE_CONNECTING) +[14:08:37] SetTitle(1, ); +[14:08:37] (SSH-Browser) ElSFTP1CloseConnection(1) +[14:08:37] (SSH-Browser) ElSFTP1Error(1): #103 - 连接被低层协议关闭 +[14:08:37] SFTPErr #103 附带说明 "连接被低层协议关闭" +[14:08:37] (SSH-Browser) ElSFTP1CloseConnection(1) +[14:08:37] BEGIN ElSSH1CloseConnection(1) +[14:08:37] END ElSSH1CloseConnection(1) +[14:08:37] (SSH-Browser) DisconnectSSH(1): Socket.Close; +[14:08:37] END DisconnectSSH(1) +[14:08:37] END WMNewTab: 48 + + + +[14:09:31] BEGIN BtnNewSessionClick +[14:09:31] BtnNewSessionClick: FormClick +[14:09:31] BEGIN ChargerLaSession +[14:09:32] ChargerLaSession1 +[14:09:32] ChargerLaSession2 + + +[14:09:33] BEGIN FormSessions.Btn0Click: 5 +[14:09:33] BEGIN LockControl(FormSessionEdit, Btn0Click) +[14:09:33] END LockControl(FormSessionEdit, Btn0Click) +[14:09:33] 加载新会话类型的默认值 #5 +[14:09:33] BEGIN ChargerLePreset EMPTY_PRESETS +[14:09:33] ChargerLaSession1 +[14:09:33] END ChargerLePreset +[14:09:33] BEGIN UnlockControl(FormSessionEdit, Btn0Click) +[14:09:33] END UnlockControl(FormSessionEdit, Btn0Click) +[14:09:33] END FormSessions.Btn0Click + + +[14:09:40] BEGIN SessionClickOK +[14:09:40] LaunchSession0 +[14:09:40] LaunchSession1 +[14:09:40] LaunchSession4 +[14:09:40] LaunchSession5 +[14:09:40] +[14:09:40] BEGIN NEWTAB(vnc "192.168.127.10" 5900 -autoscale, 128, 0) +[14:09:40] NEWTAB: Application.ProcessMessages +[14:09:40] NEWTAB: Timer1_Disable +[14:09:40] NEWTAB: 检查是否已达到最大标签数... +[14:09:40] NEWTAB: 创建 SFTPRecord... +[14:09:40] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[14:09:40] NEWTAB: 尝试查找旧索引... +[14:09:40] NEWTAB: Cts1.BeginUpdate; +[14:09:40] NEWTAB: 创建新标签页... +[14:09:40] NEWTAB: 标签页索引: 3 +[14:09:40] NEWTAB: 终端编号 : 5 +[14:09:40] NEWTAB: 标题 : 192.168.127.10 +[14:09:40] NEWTAB: 命令 : vnc "192.168.127.10" 5900 -autoscale +[14:09:40] Cts1ActiveTabChanged: New index = 3 +[14:09:40] NEWTAB: Cts1.EndUpdates +[14:09:40] NEWTAB: 更改标签页索引 A = 3 +[14:09:40] BEGIN WaitForAllThreads +[14:09:40] END WaitForAllThreads +[14:09:40] +[14:09:40] LaunchTabContent(vnc "192.168.127.10" 5900 -autoscale, 192.168.127.10); +[14:09:40] +[14:09:40] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[14:09:40] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[14:09:40] MOBANOACL=onlyslash +[14:09:40] +[14:09:40] ShellExecute: motty.exe +[14:09:40] +[14:09:40] CreerSessionMoTTY(5, vnc "192.168.127.10" 5900 -autoscale, 192.168.127.10) +[14:09:40] Setting LOCALE=zh_CN.UTF-8 +[14:09:40] BEGIN WaitForAllThreads +[14:09:40] END WaitForAllThreads +[14:09:40] BEGIN GetPassword +[14:09:40] BEGIN GetnSaveCredPassword +[14:09:40] END GetnSaveCredPassword +[14:09:40] +[14:09:40] +[14:09:40] BEGIN TForm1.MobaInputDialog +[14:09:40] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[14:09:40] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=Form4.Handle; +[14:09:40] TForm1.MobaInputDialog: FormInputDialog.ShowModal + + +[14:09:43] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[14:09:43] END TForm1.MobaInputDialog +[14:09:43] +[14:09:43] +[14:09:43] END GetPassword +[14:09:43] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\TurboVNC.exe, /loglevel 5 /config "C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\mo.vnc") +[14:09:43] ShellExecuteS: ShellExecuteEx 成功. + + +[14:09:46] ShellExecuteS: WaitForInputIdle 成功. +[14:09:46] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\TurboVNC.exe, /loglevel 5 /config "C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\mo.vnc") + + +[14:09:47] BEGIN GetPassword +[14:09:47] +[14:09:47] +[14:09:47] BEGIN TForm1.MobaInputDialog +[14:09:47] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[14:09:47] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=0; +[14:09:47] TForm1.MobaInputDialog: FormInputDialog.ShowModal + + + +[14:10:24] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[14:10:24] END TForm1.MobaInputDialog +[14:10:24] +[14:10:24] +[14:10:24] END GetPassword +[14:10:24] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\TurboVNC.exe, /loglevel 5 /config "C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\mo.vnc") +[14:10:24] ShellExecuteS: ShellExecuteEx 成功. + + +[14:10:26] ShellExecuteS: WaitForInputIdle 成功. +[14:10:26] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\TurboVNC.exe, /loglevel 5 /config "C:\Users\31554\AppData\Local\Temp\Mxt252\tmp\mo.vnc") + + +[14:10:28] NEWTAB: LaunchTabContent 失败. 删除新创建的标签页... +[14:10:28] NEWTAB: BEGIN Cts1.Tabs.DeleteTab(3); +[14:10:28] Cts1ActiveTabChanged: New index = 2 +[14:10:28] NEWTAB: END Cts1.Tabs.DeleteTab +[14:10:28] NEWTAB: 更改标签页索引 B = 2 +[14:10:28] BEGIN DisplayCurrentTab +[14:10:28] DisplayCurrentTab: FormClick +[14:10:28] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[14:10:28] (SSH-Browser) BEGIN ActiverPanel14 +[14:10:28] (SSH-Browser) BEGIN DesactiverPanel14 +[14:10:28] (SSH-Browser) END DesactiverPanel14 +[14:10:28] (SSH-Browser) END ActiverPanel14; +[14:10:28] DisplayCurrentTab: Cts1.BeginUpdate; +[14:10:28] DisplayCurrentTab: Cts1.EndUpdates +[14:10:28] DisplayCurrentTab: 显示所选标签页 +[14:10:28] DisplayCurrentTab: 隐藏其他标签页 +[14:10:28] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:10:28] +[14:10:28] BEGIN Form4.FormActivate +[14:10:28] END Form4.FormActivate +[14:10:28] +[14:10:28] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:10:28] DisplayCurrentTab: DistribuerLeFocus +[14:10:28] END DisplayCurrentTab +[14:10:28] NEWTAB: NewTab_ReEnable_Timer1 +[14:10:28] NEWTAB: MajVerticalTabs +[14:10:28] NEWTAB: Cts1.Resize; +[14:10:28] END NEWTAB(vnc "192.168.127.10" 5900 -autoscale, 128, 0) +[14:10:28] +[14:10:28] LaunchSession6 +[14:10:28] END SessionClickOK +[14:10:28] BEGIN TFormSessionEdit.FormClose +[14:10:28] END TFormSessionEdit.FormClose +[14:10:28] END BtnNewSessionClick + + + +[14:10:41] +[14:10:41] BEGIN Form4.FormActivate +[14:10:41] END Form4.FormActivate +[14:10:41] + + +[14:10:42] BEGIN BtnNewSessionClick +[14:10:42] BtnNewSessionClick: FormClick +[14:10:42] BEGIN ChargerLaSession +[14:10:42] ChargerLaSession1 +[14:10:42] ChargerLaSession2 + + +[14:10:44] BEGIN FormSessions.Btn0Click: 5 +[14:10:44] BEGIN LockControl(FormSessionEdit, Btn0Click) +[14:10:44] END LockControl(FormSessionEdit, Btn0Click) +[14:10:44] 加载新会话类型的默认值 #5 +[14:10:44] BEGIN ChargerLePreset EMPTY_PRESETS +[14:10:44] ChargerLaSession1 +[14:10:44] END ChargerLePreset +[14:10:44] BEGIN UnlockControl(FormSessionEdit, Btn0Click) +[14:10:44] END UnlockControl(FormSessionEdit, Btn0Click) +[14:10:44] END FormSessions.Btn0Click + + + + +[14:13:25] BEGIN TFormSessionEdit.FormClose +[14:13:25] END TFormSessionEdit.FormClose +[14:13:25] END BtnNewSessionClick + +[14:13:26] BEGIN WMNCLButtonDown +[14:13:26] BEGIN WMSysCommand (minimize/restore) +[14:13:26] BEGIN WMSize +[14:13:26] END WMSize +[14:13:26] END WMSysCommand +[14:13:26] END WMNCLButtonDown + + + + +[14:15:47] BEGIN WMSysCommand (minimize/restore) +[14:15:47] BEGIN WMNewTab: 0 +[14:15:47] WMNewTab: FormClick +[14:15:47] WMNewTab: LooseFocus +[14:15:47] END WMNewTab: 0 +[14:15:47] BEGIN WMSize +[14:15:47] BEGIN TFormXterm.FormResize +[14:15:47] TFormXterm.FormResize: CenterBtnReattachTab +[14:15:47] TFormXterm.FormResize: SplitModeResize +[14:15:47] TFormXterm.FormResize: BtnSplitNo.Down +[14:15:47] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:15:47] BEGIN ResizeTerminal +[14:15:47] END ResizeTerminal +[14:15:47] TFormXterm.FormResize: AdaptSidebarArrows; +[14:15:47] BEGIN AdaptSidebarArrows +[14:15:47] END AdaptSidebarArrows +[14:15:47] TFormXterm.FormResize: AdaptTV2; +[14:15:47] END TFormXterm.FormResize +[14:15:47] END WMSize +[14:15:47] END WMSysCommand + + + +[14:17:24] BEGIN WMNewTab: 48 +[14:17:24] 收到消息: SSH 会话部分关闭 (4) +[14:17:24] BEGIN DisconnectSSH(2) +[14:17:24] (SSH-Browser) BEGIN DesactiverPanel14 +[14:17:24] (SSH-Browser) END DesactiverPanel14 +[14:17:24] END DisconnectSSH(2) +[14:17:24] END WMNewTab: 48 +[14:17:24] SetTitle(2, ); +[14:17:24] BEGIN WMNewTab: 48 +[14:17:24] 收到消息: SSH 会话部分关闭 (4) +[14:17:24] BEGIN DisconnectSSH(2) +[14:17:24] (SSH-Browser) BEGIN DesactiverPanel14 +[14:17:24] (SSH-Browser) END DesactiverPanel14 +[14:17:24] END DisconnectSSH(2) +[14:17:24] END WMNewTab: 48 +[14:17:24] SetTitle(2, ); + + + + + + + +[14:32:32] BEGIN WMNewTab: 0 +[14:32:32] WMNewTab: FormClick +[14:32:32] WMNewTab: LooseFocus +[14:32:32] END WMNewTab: 0 +[14:32:32] BEGIN WMNewTab: 0 +[14:32:32] WMNewTab: FormClick +[14:32:32] WMNewTab: LooseFocus +[14:32:32] END WMNewTab: 0 + + + + +[14:34:56] BEGIN WMNewTab: 0 +[14:34:56] WMNewTab: FormClick +[14:34:56] WMNewTab: LooseFocus +[14:34:56] END WMNewTab: 0 +[14:34:56] BEGIN WMNewTab: 0 +[14:34:56] WMNewTab: FormClick +[14:34:56] WMNewTab: LooseFocus +[14:34:56] END WMNewTab: 0 + + + +[14:35:19] BEGIN WMNewTab: 0 +[14:35:19] WMNewTab: FormClick +[14:35:19] WMNewTab: LooseFocus +[14:35:19] END WMNewTab: 0 +[14:35:19] BEGIN WMNewTab: 0 +[14:35:19] WMNewTab: FormClick +[14:35:19] WMNewTab: LooseFocus +[14:35:19] END WMNewTab: 0 +[14:35:19] BEGIN WMNewTab: 62 +[14:35:19] END WMNewTab: 62 +[14:35:19] SetTitle(2, COM3 (USB-SERIAL CH340 (COM3))); + + + + +[14:38:27] BEGIN WMNewTab: 0 +[14:38:27] WMNewTab: FormClick +[14:38:27] WMNewTab: LooseFocus +[14:38:27] END WMNewTab: 0 +[14:38:28] BEGIN WMNewTab: 0 +[14:38:28] WMNewTab: FormClick +[14:38:28] WMNewTab: LooseFocus +[14:38:28] END WMNewTab: 0 + + +[14:38:32] BEGIN WMNewTab: 0 +[14:38:32] WMNewTab: FormClick +[14:38:32] WMNewTab: LooseFocus +[14:38:32] END WMNewTab: 0 +[14:38:32] BEGIN WMNewTab: 0 +[14:38:32] WMNewTab: FormClick +[14:38:32] WMNewTab: LooseFocus +[14:38:32] END WMNewTab: 0 + + +[14:38:34] BEGIN WMNewTab: 0 +[14:38:34] WMNewTab: FormClick +[14:38:34] WMNewTab: LooseFocus +[14:38:34] END WMNewTab: 0 +[14:38:34] BEGIN WMNewTab: 0 +[14:38:34] WMNewTab: FormClick +[14:38:34] WMNewTab: LooseFocus +[14:38:34] END WMNewTab: 0 +[14:38:34] BEGIN WMNewTab: 0 +[14:38:34] WMNewTab: FormClick +[14:38:34] WMNewTab: LooseFocus +[14:38:34] END WMNewTab: 0 +[14:38:34] BEGIN WMNewTab: 0 +[14:38:34] WMNewTab: FormClick +[14:38:34] WMNewTab: LooseFocus +[14:38:34] END WMNewTab: 0 +[14:38:34] BEGIN WMNewTab: 0 +[14:38:34] WMNewTab: FormClick +[14:38:34] WMNewTab: LooseFocus +[14:38:34] END WMNewTab: 0 +[14:38:34] BEGIN WMNewTab: 0 +[14:38:34] WMNewTab: FormClick +[14:38:34] WMNewTab: LooseFocus +[14:38:34] END WMNewTab: 0 + +[14:38:35] Cts1MouseDown: FormClick + +[14:38:36] Cts1MouseDown: FormClick +[14:38:36] Cts1ActiveTabChanged: New index = 1 +[14:38:36] BEGIN DisplayCurrentTab +[14:38:36] DisplayCurrentTab: FormClick +[14:38:36] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[14:38:36] (SSH-Browser) BEGIN ActiverPanel14 +[14:38:36] (SSH-Browser) BEGIN DesactiverPanel14 +[14:38:36] (SSH-Browser) END DesactiverPanel14 +[14:38:36] (SSH-Browser) END ActiverPanel14; +[14:38:36] DisplayCurrentTab: Cts1.BeginUpdate; +[14:38:36] DisplayCurrentTab: Cts1.EndUpdates +[14:38:36] DisplayCurrentTab: 显示所选标签页 +[14:38:36] DisplayCurrentTab: 隐藏其他标签页 +[14:38:36] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:38:36] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:38:36] DisplayCurrentTab: DistribuerLeFocus +[14:38:36] END DisplayCurrentTab + +[14:38:36] BEGIN WMNewTab: 0 +[14:38:36] WMNewTab: FormClick +[14:38:36] WMNewTab: LooseFocus +[14:38:36] END WMNewTab: 0 +[14:38:36] BEGIN WMNewTab: 0 +[14:38:36] WMNewTab: FormClick +[14:38:36] WMNewTab: LooseFocus +[14:38:36] END WMNewTab: 0 + +[14:38:38] BEGIN WMNewTab: 62 +[14:38:38] END WMNewTab: 62 +[14:38:38] SetTitle(1, 192.168.127.10 (root)); + + +[14:38:42] BEGIN WMNewTab: 60 +[14:38:42] END WMNewTab: 60 + +[14:38:43] BEGIN WMNewTab: 60 +[14:38:43] END WMNewTab: 60 + +[14:38:44] BEGIN WMNewTab: 60 +[14:38:44] END WMNewTab: 60 + +[14:38:45] BEGIN WMNewTab: 60 +[14:38:45] END WMNewTab: 60 +[14:38:45] Cts1MouseDown: FormClick +[14:38:45] Cts1ActiveTabChanged: New index = 2 +[14:38:45] BEGIN DisplayCurrentTab +[14:38:45] DisplayCurrentTab: FormClick +[14:38:45] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[14:38:45] (SSH-Browser) BEGIN ActiverPanel14 +[14:38:45] (SSH-Browser) BEGIN DesactiverPanel14 +[14:38:45] (SSH-Browser) END DesactiverPanel14 +[14:38:45] (SSH-Browser) END ActiverPanel14; +[14:38:45] DisplayCurrentTab: Cts1.BeginUpdate; +[14:38:45] DisplayCurrentTab: Cts1.EndUpdates +[14:38:45] DisplayCurrentTab: 显示所选标签页 +[14:38:45] DisplayCurrentTab: 隐藏其他标签页 +[14:38:45] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:38:45] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:38:45] DisplayCurrentTab: DistribuerLeFocus +[14:38:45] END DisplayCurrentTab +[14:38:45] BEGIN WMNewTab: 62 +[14:38:45] END WMNewTab: 62 + + + +[14:38:59] BEGIN WMNewTab: 48 +[14:38:59] 收到消息: SSH 会话部分关闭 (2) +[14:38:59] BEGIN DisconnectSSH(1) +[14:38:59] END DisconnectSSH(1) +[14:38:59] END WMNewTab: 48 +[14:38:59] SetTitle(1, ); + + + +[14:39:27] BEGIN WMNewTab: 0 +[14:39:27] WMNewTab: FormClick +[14:39:27] WMNewTab: LooseFocus +[14:39:27] END WMNewTab: 0 +[14:39:27] BEGIN WMNewTab: 0 +[14:39:27] WMNewTab: FormClick +[14:39:27] WMNewTab: LooseFocus +[14:39:27] END WMNewTab: 0 + +[14:39:28] BEGIN WMNewTab: 0 +[14:39:28] WMNewTab: FormClick +[14:39:28] WMNewTab: LooseFocus +[14:39:28] END WMNewTab: 0 +[14:39:28] BEGIN WMNewTab: 0 +[14:39:28] WMNewTab: FormClick +[14:39:28] WMNewTab: LooseFocus +[14:39:28] END WMNewTab: 0 + + + +[14:40:27] BEGIN WMNewTab: 0 +[14:40:27] WMNewTab: FormClick +[14:40:27] WMNewTab: LooseFocus +[14:40:27] END WMNewTab: 0 +[14:40:28] BEGIN WMNewTab: 0 +[14:40:28] WMNewTab: FormClick +[14:40:28] WMNewTab: LooseFocus +[14:40:28] END WMNewTab: 0 + + +[14:40:36] BEGIN WMNewTab: 0 +[14:40:36] WMNewTab: FormClick +[14:40:36] WMNewTab: LooseFocus +[14:40:36] END WMNewTab: 0 + + +[14:40:38] BEGIN WMNewTab: 0 +[14:40:38] WMNewTab: FormClick +[14:40:38] WMNewTab: LooseFocus +[14:40:38] END WMNewTab: 0 + + + +[14:41:05] BEGIN WMNewTab: 0 +[14:41:05] WMNewTab: FormClick +[14:41:05] WMNewTab: LooseFocus +[14:41:05] END WMNewTab: 0 +[14:41:05] BEGIN WMNewTab: 0 +[14:41:05] WMNewTab: FormClick +[14:41:05] WMNewTab: LooseFocus +[14:41:05] END WMNewTab: 0 + + +[14:41:08] BEGIN WMNewTab: 0 +[14:41:08] WMNewTab: FormClick +[14:41:08] WMNewTab: LooseFocus +[14:41:08] END WMNewTab: 0 + + +[14:41:11] BEGIN WMNewTab: 0 +[14:41:11] WMNewTab: FormClick +[14:41:11] WMNewTab: LooseFocus +[14:41:11] END WMNewTab: 0 + + + +[14:42:26] BEGIN WMNewTab: 0 +[14:42:26] WMNewTab: FormClick +[14:42:26] WMNewTab: LooseFocus +[14:42:26] END WMNewTab: 0 +[14:42:26] BEGIN WMNewTab: 31 +[14:42:26] END WMNewTab: 31 + + +[14:42:33] BEGIN WMNewTab: 0 +[14:42:33] WMNewTab: FormClick +[14:42:33] WMNewTab: LooseFocus +[14:42:33] END WMNewTab: 0 + + +[14:42:35] BEGIN WMNewTab: 0 +[14:42:35] WMNewTab: FormClick +[14:42:35] WMNewTab: LooseFocus +[14:42:35] END WMNewTab: 0 + + + +[14:42:58] BEGIN WMNewTab: 0 +[14:42:58] WMNewTab: FormClick +[14:42:58] WMNewTab: LooseFocus +[14:42:58] END WMNewTab: 0 +[14:42:58] BEGIN WMNewTab: 31 +[14:42:58] END WMNewTab: 31 + + +[14:43:05] BEGIN WMNewTab: 0 +[14:43:05] WMNewTab: FormClick +[14:43:05] WMNewTab: LooseFocus +[14:43:05] END WMNewTab: 0 + +[14:43:06] BEGIN WMNewTab: 0 +[14:43:06] WMNewTab: FormClick +[14:43:06] WMNewTab: LooseFocus +[14:43:06] END WMNewTab: 0 + + + +[14:43:25] BEGIN WMNewTab: 0 +[14:43:25] WMNewTab: FormClick +[14:43:25] WMNewTab: LooseFocus +[14:43:25] END WMNewTab: 0 +[14:43:25] BEGIN WMNewTab: 31 +[14:43:25] END WMNewTab: 31 + + + +[14:43:53] BEGIN WMNewTab: 0 +[14:43:53] WMNewTab: FormClick +[14:43:53] WMNewTab: LooseFocus +[14:43:53] END WMNewTab: 0 +[14:43:53] BEGIN WMNewTab: 31 +[14:43:53] END WMNewTab: 31 + + + +[14:44:58] BEGIN WMNewTab: 0 +[14:44:58] WMNewTab: FormClick +[14:44:58] WMNewTab: LooseFocus +[14:44:58] END WMNewTab: 0 +[14:44:58] BEGIN WMNewTab: 0 +[14:44:58] WMNewTab: FormClick +[14:44:58] WMNewTab: LooseFocus +[14:44:58] END WMNewTab: 0 + + +[14:45:02] BEGIN WMSysCommand (minimize/restore) +[14:45:02] BEGIN WMSize +[14:45:02] END WMSize +[14:45:02] END WMSysCommand + + +[14:45:08] BEGIN WMSysCommand (minimize/restore) +[14:45:08] BEGIN WMNewTab: 0 +[14:45:08] WMNewTab: FormClick +[14:45:08] WMNewTab: LooseFocus +[14:45:08] END WMNewTab: 0 +[14:45:08] BEGIN WMSize +[14:45:08] BEGIN TFormXterm.FormResize +[14:45:08] TFormXterm.FormResize: CenterBtnReattachTab +[14:45:08] TFormXterm.FormResize: SplitModeResize +[14:45:08] TFormXterm.FormResize: BtnSplitNo.Down +[14:45:08] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:45:08] BEGIN ResizeTerminal +[14:45:08] END ResizeTerminal +[14:45:08] TFormXterm.FormResize: AdaptSidebarArrows; +[14:45:08] BEGIN AdaptSidebarArrows +[14:45:08] END AdaptSidebarArrows +[14:45:08] TFormXterm.FormResize: AdaptTV2; +[14:45:08] END TFormXterm.FormResize +[14:45:08] END WMSize +[14:45:08] END WMSysCommand +[14:45:08] BEGIN WMNewTab: 31 +[14:45:08] END WMNewTab: 31 +[14:45:08] BEGIN WMNewTab: 0 +[14:45:08] WMNewTab: FormClick +[14:45:08] WMNewTab: LooseFocus +[14:45:08] END WMNewTab: 0 +[14:45:08] BEGIN WMNewTab: 0 +[14:45:08] WMNewTab: FormClick +[14:45:08] WMNewTab: LooseFocus +[14:45:08] END WMNewTab: 0 + + + +[14:47:06] BEGIN WMNewTab: 0 +[14:47:06] WMNewTab: FormClick +[14:47:06] WMNewTab: LooseFocus +[14:47:06] END WMNewTab: 0 +[14:47:06] BEGIN WMNewTab: 0 +[14:47:06] WMNewTab: FormClick +[14:47:06] WMNewTab: LooseFocus +[14:47:06] END WMNewTab: 0 + + +[14:47:10] BEGIN WMSysCommand (minimize/restore) +[14:47:10] BEGIN WMSize +[14:47:10] END WMSize +[14:47:10] END WMSysCommand + +[14:47:10] BEGIN WMSysCommand (minimize/restore) +[14:47:10] BEGIN WMNewTab: 0 +[14:47:10] WMNewTab: FormClick +[14:47:10] WMNewTab: LooseFocus +[14:47:10] END WMNewTab: 0 +[14:47:10] BEGIN WMSize +[14:47:10] BEGIN TFormXterm.FormResize +[14:47:10] TFormXterm.FormResize: CenterBtnReattachTab +[14:47:10] TFormXterm.FormResize: SplitModeResize +[14:47:10] TFormXterm.FormResize: BtnSplitNo.Down +[14:47:10] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:47:10] BEGIN ResizeTerminal +[14:47:10] END ResizeTerminal +[14:47:10] TFormXterm.FormResize: AdaptSidebarArrows; +[14:47:10] BEGIN AdaptSidebarArrows +[14:47:10] END AdaptSidebarArrows +[14:47:10] TFormXterm.FormResize: AdaptTV2; +[14:47:10] END TFormXterm.FormResize +[14:47:10] END WMSize +[14:47:10] END WMSysCommand + + + +[14:47:30] BEGIN WMNewTab: 31 +[14:47:30] END WMNewTab: 31 +[14:47:30] BEGIN WMNewTab: 0 +[14:47:30] WMNewTab: FormClick +[14:47:30] WMNewTab: LooseFocus +[14:47:30] END WMNewTab: 0 +[14:47:30] BEGIN WMNewTab: 0 +[14:47:30] WMNewTab: FormClick +[14:47:30] WMNewTab: LooseFocus +[14:47:30] END WMNewTab: 0 + + + + + + +[14:55:12] BEGIN WMNewTab: 0 +[14:55:12] WMNewTab: FormClick +[14:55:12] WMNewTab: LooseFocus +[14:55:12] END WMNewTab: 0 +[14:55:12] BEGIN WMNewTab: 0 +[14:55:12] WMNewTab: FormClick +[14:55:12] WMNewTab: LooseFocus +[14:55:12] END WMNewTab: 0 + + + +[14:56:40] BEGIN WMNewTab: 0 +[14:56:40] WMNewTab: FormClick +[14:56:40] WMNewTab: LooseFocus +[14:56:40] END WMNewTab: 0 +[14:56:40] BEGIN WMNewTab: 0 +[14:56:40] WMNewTab: FormClick +[14:56:40] WMNewTab: LooseFocus +[14:56:40] END WMNewTab: 0 + + + +[14:57:06] Cts1MouseDown: FormClick +[14:57:06] Cts1ActiveTabChanged: New index = 1 +[14:57:06] BEGIN DisplayCurrentTab +[14:57:06] DisplayCurrentTab: FormClick +[14:57:06] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[14:57:06] (SSH-Browser) BEGIN ActiverPanel14 +[14:57:06] (SSH-Browser) BEGIN DesactiverPanel14 +[14:57:06] (SSH-Browser) END DesactiverPanel14 +[14:57:06] (SSH-Browser) END ActiverPanel14; +[14:57:06] DisplayCurrentTab: Cts1.BeginUpdate; +[14:57:06] DisplayCurrentTab: Cts1.EndUpdates +[14:57:06] DisplayCurrentTab: 显示所选标签页 +[14:57:06] DisplayCurrentTab: 隐藏其他标签页 +[14:57:06] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:57:06] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:57:06] DisplayCurrentTab: DistribuerLeFocus +[14:57:06] END DisplayCurrentTab + +[14:57:06] BEGIN WMNewTab: 0 +[14:57:06] WMNewTab: FormClick +[14:57:06] WMNewTab: LooseFocus +[14:57:06] END WMNewTab: 0 +[14:57:06] BEGIN WMNewTab: 0 +[14:57:06] WMNewTab: FormClick +[14:57:06] WMNewTab: LooseFocus +[14:57:06] END WMNewTab: 0 + +[14:57:07] BEGIN WMNewTab: 62 +[14:57:07] END WMNewTab: 62 +[14:57:07] SetTitle(1, 192.168.127.10 (root)); +[14:57:07] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[14:57:07] 主机密钥与缓存中的密钥是一致的 +[14:57:07] BEGIN GetPassword +[14:57:07] BEGIN GetnSaveCredPassword +[14:57:07] END GetnSaveCredPassword +[14:57:07] END GetPassword + + +[14:57:09] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[14:57:09] BEGIN SauvegarderMotDePasseSSH +[14:57:09] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[14:57:09] SetTitle(1, root@192.168.127.10); +[14:57:09] +[14:57:09] (SSH-Browser) BEGIN ConnectSSH(1,192.168.127.10,root,) +[14:57:09] (SSH-Browser) ConnectSSH(1): 初始化 TabSFTP +[14:57:09] (SSH-Browser) ConnectSSH(1): 未使用代理 +[14:57:09] (SSH-Browser) ConnectSSH(1): 未提供密钥 --> 使用其他身份验证类型进行连接 +[14:57:09] (SSH-Browser) ConnectSSH(1): 已成功连接到 192.168.127.10. +[14:57:09] (SSH-Browser) ConnectSSH(1): SSH.Open +[14:57:09] (SSH-Browser) END ConnectSSH(1) +[14:57:09] BEGIN DisplayCurrentTab +[14:57:09] DisplayCurrentTab: FormClick +[14:57:09] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[14:57:09] (SSH-Browser) BEGIN ActiverPanel14 +[14:57:09] (SSH-Browser) BEGIN DesactiverPanel14 +[14:57:09] (SSH-Browser) END DesactiverPanel14 +[14:57:09] (SSH-Browser) END ActiverPanel14; +[14:57:09] DisplayCurrentTab: Cts1.BeginUpdate; +[14:57:09] DisplayCurrentTab: Cts1.EndUpdates +[14:57:09] DisplayCurrentTab: 显示所选标签页 +[14:57:09] DisplayCurrentTab: 隐藏其他标签页 +[14:57:09] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:57:09] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:57:09] DisplayCurrentTab: DistribuerLeFocus +[14:57:09] END DisplayCurrentTab +[14:57:09] BEGIN SavePassword +[14:57:09] END SavePassword +[14:57:09] END SauvegarderMotDePasseSSH +[14:57:09] BEGIN WMNewTab: 80 +[14:57:09] 收到消息: 正在启动远程监控 终端 #2 +[14:57:09] BEGIN TFormXterm.FormResize +[14:57:09] TFormXterm.FormResize: CenterBtnReattachTab +[14:57:09] TFormXterm.FormResize: SplitModeResize +[14:57:09] TFormXterm.FormResize: BtnSplitNo.Down +[14:57:09] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:57:09] BEGIN ResizeTerminal +[14:57:09] END ResizeTerminal +[14:57:09] TFormXterm.FormResize: AdaptSidebarArrows; +[14:57:09] BEGIN AdaptSidebarArrows +[14:57:09] END AdaptSidebarArrows +[14:57:09] TFormXterm.FormResize: AdaptTV2; +[14:57:09] END TFormXterm.FormResize +[14:57:09] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[14:57:09] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:57:09] ShellExecuteS: ShellExecuteEx 成功. +[14:57:09] ShellExecuteS: WaitForInputIdle 失败. +[14:57:09] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:57:09] END WMNewTab: 80 +[14:57:09] [MobaSCP2] Launching remote monitoring in normal mode +[14:57:09] [MobaSCP2] Multiplex=1 +[14:57:09] [MobaSCP2] HOSTNAME: 192.168.127.10 +[14:57:09] [MobaSCP2] USERNAME: root +[14:57:09] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[14:57:09] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[14:57:09] (SSH-Browser) 主机密钥指纹信息 (Sha256): 2b:ca:32:12:87:5d:69:9e:24:78:db:b7:f5:ec:40:a8:c2:4b:0c:47:27:72:0a:10:19:c4:4f:43:cf:7c:05:be +[14:57:09] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[14:57:09] (SSH-Browser) END GetSftpOnValidateStatus +[14:57:09] +[14:57:09] (SSH-Browser) ElSSH1AuthenticationStart(1, 134) +[14:57:09] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[14:57:09] (SSH-Browser) 服务器支持以下认证方式: +[14:57:09] (SSH-Browser) . PUBLICKEYAGENT +[14:57:09] (SSH-Browser) . PUBLICKEY +[14:57:09] (SSH-Browser) . PASSWORD +[14:57:09] (SSH-Browser) 客户端支持以下认证方式: +[14:57:09] (SSH-Browser) . PUBLICKEYAGENT +[14:57:09] (SSH-Browser) . PUBLICKEY +[14:57:09] (SSH-Browser) . RHOSTS +[14:57:09] (SSH-Browser) . HOSTBASED +[14:57:09] (SSH-Browser) . PASSWORD +[14:57:09] (SSH-Browser) . KEYBOARD +[14:57:09] +[14:57:09] +[14:57:09] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEY) +[14:57:09] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEYAGENT) +[14:57:09] (SSH-Browser) ElSSH1AuthenticationAttempt(1, PASSWORD) +[14:57:09] [MobaSCP2] Using SCP1 +[14:57:09] [MobaSCP2] Connected to 192.168.127.10 +[14:57:10] (SSH-Browser) ElSSH1AuthenticationSuccess(1) +[14:57:10] (SSH-Browser) ElSSH1OpenConnection(1) +[14:57:10] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[14:57:10] +[14:57:10] (SSH-Browser) BEGIN ElSFTP1OpenConnection(1) +[14:57:10] (SSH-Browser) ElSFTP1OpenConnection(1): SFTP 已正确连接 +[14:57:10] (SSH-Browser) ElSFTP1OpenConnection(1): ActiverPanel14 +[14:57:10] (SSH-Browser) BEGIN ActiverPanel14 +[14:57:10] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[14:57:10] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[14:57:10] (SSH-Browser) ActiverPanel14: 列出远程目录 +[14:57:10] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[14:57:10] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[14:57:10] (SSH-Browser) END ActiverPanel14; +[14:57:10] (SSH-Browser) ElSFTP1OpenConnection(1): 已成功打开连接 --> 正在退出 +[14:57:10] (SSH-Browser) END ElSFTP1OpenConnection(1) + +[14:57:11] BEGIN TFormXterm.FormResize +[14:57:11] TFormXterm.FormResize: CenterBtnReattachTab +[14:57:11] TFormXterm.FormResize: SplitModeResize +[14:57:11] TFormXterm.FormResize: BtnSplitNo.Down +[14:57:11] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:57:11] BEGIN ResizeTerminal +[14:57:11] END ResizeTerminal +[14:57:11] TFormXterm.FormResize: AdaptSidebarArrows; +[14:57:11] BEGIN AdaptSidebarArrows +[14:57:11] END AdaptSidebarArrows +[14:57:11] TFormXterm.FormResize: AdaptTV2; +[14:57:11] END TFormXterm.FormResize +[14:57:11] BEGIN WMNewTab: 20 +[14:57:11] END WMNewTab: 20 + +[14:57:12] BEGIN WMNewTab: 0 +[14:57:12] WMNewTab: FormClick +[14:57:12] WMNewTab: LooseFocus +[14:57:12] END WMNewTab: 0 + +[14:57:12] BEGIN WMNewTab: 20 +[14:57:12] END WMNewTab: 20 + +[14:57:13] BEGIN WMNewTab: 0 +[14:57:13] WMNewTab: FormClick +[14:57:13] WMNewTab: LooseFocus +[14:57:13] END WMNewTab: 0 +[14:57:13] BEGIN WMNewTab: 0 +[14:57:13] WMNewTab: FormClick +[14:57:13] WMNewTab: LooseFocus +[14:57:13] END WMNewTab: 0 +[14:57:13] BEGIN WMNewTab: 0 +[14:57:13] WMNewTab: FormClick +[14:57:13] WMNewTab: LooseFocus +[14:57:13] END WMNewTab: 0 + +[14:57:14] BEGIN WMNewTab: 20 +[14:57:14] END WMNewTab: 20 + +[14:57:15] sListView1Click: FormClick +[14:57:15] (SSH-Browser) BEGIN OpenDir(1) +[14:57:15] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:57:15] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:57:15] (SSH-Browser) END VerifySFTPConnection(1) +[14:57:15] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[14:57:15] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/Audio/); +[14:57:15] (SSH-Browser) END OpenDir(1) +[14:57:15] (SSH-Browser) ElSFTP1Error(1): #2 - No such file +[14:57:15] SFTPErr #2 附带说明 "No such file" + + +[14:57:16] BEGIN WMNewTab: 20 +[14:57:16] END WMNewTab: 20 + + +[14:57:18] BEGIN WMNewTab: 20 +[14:57:18] END WMNewTab: 20 + + +[14:57:19] BEGIN WMNewTab: 20 +[14:57:19] END WMNewTab: 20 +[14:57:19] (SSH-Browser) BEGIN OpenDir(1) +[14:57:19] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:57:19] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:57:19] (SSH-Browser) END VerifySFTPConnection(1) +[14:57:19] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[14:57:19] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/); +[14:57:19] (SSH-Browser) END OpenDir(1) +[14:57:19] (SSH-Browser) ElSFTP1AbsolutePath(1) +[14:57:19] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[14:57:19] (SSH-Browser) ElSFTP1OpenFile(1) +[14:57:19] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[14:57:19] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[14:57:19] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[14:57:19] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[14:57:19] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:57:19] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:57:19] (SSH-Browser) END VerifySFTPConnection(1) +[14:57:19] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[14:57:19] (SSH-Browser) END CloseCurrentHandle(1) +[14:57:19] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[14:57:19] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=14 +[14:57:19] (SSH-Browser) 对项目进行排序 +[14:57:19] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[14:57.19.824] (SSH-Browser) END CopySFTPFileListToListView(1) +[14:57.19.856] (SSH-Browser) ElSFTP1Success(1) + + +[14:57.21.265] BEGIN WMNewTab: 20 +[14:57.21.265] END WMNewTab: 20 + + +[14:57.22.679] BEGIN WMNewTab: 20 +[14:57.22.679] END WMNewTab: 20 + + +[14:57.24.097] BEGIN WMNewTab: 20 +[14:57.24.097] END WMNewTab: 20 + + +[14:57.25.512] BEGIN WMNewTab: 20 +[14:57.25.512] END WMNewTab: 20 + + +[14:57.26.926] BEGIN WMNewTab: 20 +[14:57.26.926] END WMNewTab: 20 + + +[14:57.28.343] BEGIN WMNewTab: 20 +[14:57.28.343] END WMNewTab: 20 + + +[14:57.29.759] BEGIN WMNewTab: 20 +[14:57.29.759] END WMNewTab: 20 + + +[14:57.31.178] BEGIN WMNewTab: 20 +[14:57.31.178] END WMNewTab: 20 + +[14:57.31.719] BEGIN WMNewTab: 0 +[14:57.31.719] WMNewTab: FormClick +[14:57.31.719] WMNewTab: LooseFocus +[14:57.31.723] END WMNewTab: 0 +[14:57.31.854] BEGIN WMNewTab: 0 +[14:57.31.854] WMNewTab: FormClick +[14:57.31.854] WMNewTab: LooseFocus +[14:57.31.855] END WMNewTab: 0 + +[14:57.32.335] BEGIN WMNewTab: 0 +[14:57.32.335] WMNewTab: FormClick +[14:57.32.335] WMNewTab: LooseFocus +[14:57.32.335] END WMNewTab: 0 +[14:57.32.573] BEGIN WMNewTab: 0 +[14:57.32.573] WMNewTab: FormClick +[14:57.32.573] WMNewTab: LooseFocus +[14:57.32.578] END WMNewTab: 0 +[14:57.32.592] BEGIN WMNewTab: 20 +[14:57.32.592] END WMNewTab: 20 +[14:57.32.950] BEGIN WMNewTab: 0 +[14:57.32.950] WMNewTab: FormClick +[14:57.32.950] WMNewTab: LooseFocus +[14:57.32.950] END WMNewTab: 0 +[14:57.33.078] BEGIN WMNewTab: 0 +[14:57.33.078] WMNewTab: FormClick +[14:57.33.078] WMNewTab: LooseFocus +[14:57.33.078] END WMNewTab: 0 +[14:57.33.288] BEGIN WMNewTab: 0 +[14:57.33.288] WMNewTab: FormClick +[14:57.33.288] WMNewTab: LooseFocus +[14:57.33.288] END WMNewTab: 0 + +[14:57.33.670] BEGIN WMNewTab: 0 +[14:57.33.670] WMNewTab: FormClick +[14:57.33.670] WMNewTab: LooseFocus +[14:57.33.673] END WMNewTab: 0 +[14:57.34.006] BEGIN WMNewTab: 20 +[14:57.34.006] END WMNewTab: 20 +[14:57.34.167] BEGIN WMNewTab: 0 +[14:57.34.167] WMNewTab: FormClick +[14:57.34.167] WMNewTab: LooseFocus +[14:57.34.167] END WMNewTab: 0 +[14:57.34.278] BEGIN WMNewTab: 0 +[14:57.34.278] WMNewTab: FormClick +[14:57.34.278] WMNewTab: LooseFocus +[14:57.34.281] END WMNewTab: 0 + +[14:57.34.923] BEGIN WMNewTab: 0 +[14:57.34.923] WMNewTab: FormClick +[14:57.34.923] WMNewTab: LooseFocus +[14:57.34.923] END WMNewTab: 0 + +[14:57.35.428] BEGIN WMNewTab: 20 +[14:57.35.428] END WMNewTab: 20 + +[14:57.35.877] BEGIN WMNewTab: 0 +[14:57.35.877] WMNewTab: FormClick +[14:57.35.877] WMNewTab: LooseFocus +[14:57.35.877] END WMNewTab: 0 + +[14:57.36.312] BEGIN WMNewTab: 0 +[14:57.36.312] WMNewTab: FormClick +[14:57.36.312] WMNewTab: LooseFocus +[14:57.36.312] END WMNewTab: 0 +[14:57.36.431] BEGIN WMNewTab: 0 +[14:57.36.431] WMNewTab: FormClick +[14:57.36.431] WMNewTab: LooseFocus +[14:57.36.435] END WMNewTab: 0 + +[14:57.36.848] BEGIN WMNewTab: 20 +[14:57.36.848] END WMNewTab: 20 + +[14:57.37.550] Cts1MouseDown: FormClick +[14:57.37.556] Cts1ActiveTabChanged: New index = 2 +[14:57.37.556] BEGIN DisplayCurrentTab +[14:57.37.556] DisplayCurrentTab: FormClick +[14:57.37.556] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[14:57.37.556] (SSH-Browser) BEGIN ActiverPanel14 +[14:57.37.556] (SSH-Browser) BEGIN DesactiverPanel14 +[14:57.37.569] (SSH-Browser) END DesactiverPanel14 +[14:57.37.569] (SSH-Browser) END ActiverPanel14; +[14:57.37.679] BEGIN TFormXterm.FormResize +[14:57.37.679] TFormXterm.FormResize: CenterBtnReattachTab +[14:57.37.679] TFormXterm.FormResize: SplitModeResize +[14:57.37.679] TFormXterm.FormResize: BtnSplitNo.Down +[14:57.37.680] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:57.37.680] BEGIN ResizeTerminal +[14:57.37.680] END ResizeTerminal +[14:57.37.680] TFormXterm.FormResize: AdaptSidebarArrows; +[14:57.37.680] BEGIN AdaptSidebarArrows +[14:57.37.680] END AdaptSidebarArrows +[14:57.37.680] TFormXterm.FormResize: AdaptTV2; +[14:57.37.680] END TFormXterm.FormResize +[14:57.37.680] DisplayCurrentTab: Cts1.BeginUpdate; +[14:57.37.680] DisplayCurrentTab: Cts1.EndUpdates +[14:57.37.695] DisplayCurrentTab: 显示所选标签页 +[14:57.37.697] DisplayCurrentTab: 隐藏其他标签页 +[14:57.37.711] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:57.37.714] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:57.37.714] DisplayCurrentTab: DistribuerLeFocus +[14:57.37.714] END DisplayCurrentTab + +[14:57.38.266] BEGIN WMNewTab: 20 +[14:57.38.266] END WMNewTab: 20 +[14:57.38.479] Cts1MouseDown: FormClick +[14:57.38.484] Cts1ActiveTabChanged: New index = 1 +[14:57.38.484] BEGIN DisplayCurrentTab +[14:57.38.484] DisplayCurrentTab: FormClick +[14:57.38.484] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[14:57.38.484] (SSH-Browser) BEGIN ActiverPanel14 +[14:57.38.484] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[14:57.38.488] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[14:57.38.488] (SSH-Browser) ActiverPanel14: 列出远程目录 +[14:57.38.488] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[14:57.38.489] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[14:57.38.513] (SSH-Browser) END ActiverPanel14; +[14:57.38.533] BEGIN TFormXterm.FormResize +[14:57.38.533] TFormXterm.FormResize: CenterBtnReattachTab +[14:57.38.533] TFormXterm.FormResize: SplitModeResize +[14:57.38.533] TFormXterm.FormResize: BtnSplitNo.Down +[14:57.38.533] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:57.38.533] BEGIN ResizeTerminal +[14:57.38.540] END ResizeTerminal +[14:57.38.540] TFormXterm.FormResize: AdaptSidebarArrows; +[14:57.38.540] BEGIN AdaptSidebarArrows +[14:57.38.540] END AdaptSidebarArrows +[14:57.38.540] TFormXterm.FormResize: AdaptTV2; +[14:57.38.540] END TFormXterm.FormResize +[14:57.38.540] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[14:57.38.540] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:57.38.553] ShellExecuteS: ShellExecuteEx 成功. +[14:57.38.553] ShellExecuteS: WaitForInputIdle 失败. +[14:57.38.553] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:57.38.553] DisplayCurrentTab: Cts1.BeginUpdate; +[14:57.38.553] DisplayCurrentTab: Cts1.EndUpdates +[14:57.38.568] DisplayCurrentTab: 显示所选标签页 +[14:57.38.569] DisplayCurrentTab: 隐藏其他标签页 +[14:57.38.600] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:57.38.603] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:57.38.603] DisplayCurrentTab: DistribuerLeFocus +[14:57.38.603] END DisplayCurrentTab +[14:57.38.617] [MobaSCP2] Launching remote monitoring in normal mode +[14:57.38.617] [MobaSCP2] Multiplex=1 +[14:57.38.621] [MobaSCP2] HOSTNAME: 192.168.127.10 +[14:57.38.622] [MobaSCP2] USERNAME: root +[14:57.38.662] [MobaSCP2] Using SCP1 +[14:57.38.662] [MobaSCP2] Connected to 192.168.127.10 + +[14:57.39.676] BEGIN WMNewTab: 20 +[14:57.39.676] END WMNewTab: 20 +[14:57.39.790] BEGIN TFormXterm.FormResize +[14:57.39.790] TFormXterm.FormResize: CenterBtnReattachTab +[14:57.39.790] TFormXterm.FormResize: SplitModeResize +[14:57.39.790] TFormXterm.FormResize: BtnSplitNo.Down +[14:57.39.790] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:57.39.790] BEGIN ResizeTerminal +[14:57.39.790] END ResizeTerminal +[14:57.39.790] TFormXterm.FormResize: AdaptSidebarArrows; +[14:57.39.790] BEGIN AdaptSidebarArrows +[14:57.39.790] END AdaptSidebarArrows +[14:57.39.790] TFormXterm.FormResize: AdaptTV2; +[14:57.39.790] END TFormXterm.FormResize + + +[14:57.41.096] BEGIN WMNewTab: 20 +[14:57.41.096] END WMNewTab: 20 + + +[14:57.42.510] BEGIN WMNewTab: 20 +[14:57.42.510] END WMNewTab: 20 + +[14:57.43.238] BEGIN WMNewTab: 0 +[14:57.43.238] WMNewTab: FormClick +[14:57.43.238] WMNewTab: LooseFocus +[14:57.43.239] END WMNewTab: 0 +[14:57.43.342] BEGIN WMNewTab: 0 +[14:57.43.342] WMNewTab: FormClick +[14:57.43.342] WMNewTab: LooseFocus +[14:57.43.343] END WMNewTab: 0 + +[14:57.43.924] BEGIN WMNewTab: 20 +[14:57.43.924] END WMNewTab: 20 + + +[14:57.45.346] BEGIN WMNewTab: 20 +[14:57.45.346] END WMNewTab: 20 + +[14:57.46.501] BEGIN CWD +[14:57.46.501] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:57.46.501] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:57.46.501] (SSH-Browser) END VerifySFTPConnection(1) +[14:57.46.501] END CWD +[14:57.46.549] BEGIN WMNewTab: 20 +[14:57.46.549] END WMNewTab: 20 +[14:57.46.580] (SSH-Browser) ElCommandSSHTunnel1Open +[14:57.46.611] (SSH-Browser) ExecuteCommandData +[14:57.46.641] (SSH-Browser) ExecuteCommandData +[14:57.46.672] (SSH-Browser) ExecuteCommandData +[14:57.46.701] (SSH-Browser) ExecuteCommandData +[14:57.46.732] (SSH-Browser) ExecuteCommandData +[14:57.46.824] (SSH-Browser) ExecuteCommandClose +[14:57.46.824] BEGIN CWD +[14:57.46.825] (CWD) TenterDeTrouverLeCWD: Minute=0 / Seconde=37 +[14:57.46.887] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:57.46.887] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:57.46.887] (SSH-Browser) END VerifySFTPConnection(1) +[14:57.46.887] END CWD +[14:57.46.917] BEGIN CWD +[14:57.46.978] END CWD + +[14:57.47.919] BEGIN WMNewTab: 20 +[14:57.47.919] END WMNewTab: 20 + +[14:57.48.858] Cts1MouseDown: FormClick +[14:57.48.862] Cts1ActiveTabChanged: New index = 2 +[14:57.48.862] BEGIN DisplayCurrentTab +[14:57.48.862] DisplayCurrentTab: FormClick +[14:57.48.862] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[14:57.48.862] (SSH-Browser) BEGIN ActiverPanel14 +[14:57.48.862] (SSH-Browser) BEGIN DesactiverPanel14 +[14:57.48.873] (SSH-Browser) END DesactiverPanel14 +[14:57.48.873] (SSH-Browser) END ActiverPanel14; +[14:57.48.976] BEGIN TFormXterm.FormResize +[14:57.48.976] TFormXterm.FormResize: CenterBtnReattachTab +[14:57.48.977] TFormXterm.FormResize: SplitModeResize +[14:57.48.977] TFormXterm.FormResize: BtnSplitNo.Down +[14:57.48.977] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:57.48.977] BEGIN ResizeTerminal +[14:57.48.983] END ResizeTerminal +[14:57.48.983] TFormXterm.FormResize: AdaptSidebarArrows; +[14:57.48.983] BEGIN AdaptSidebarArrows +[14:57.48.983] END AdaptSidebarArrows +[14:57.48.983] TFormXterm.FormResize: AdaptTV2; +[14:57.48.983] END TFormXterm.FormResize +[14:57.48.983] DisplayCurrentTab: Cts1.BeginUpdate; +[14:57.48.983] DisplayCurrentTab: Cts1.EndUpdates +[14:57.48.997] DisplayCurrentTab: 显示所选标签页 +[14:57.49.000] DisplayCurrentTab: 隐藏其他标签页 +[14:57.49.012] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:57.49.015] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:57.49.015] DisplayCurrentTab: DistribuerLeFocus +[14:57.49.015] END DisplayCurrentTab +[14:57.49.332] BEGIN WMNewTab: 20 +[14:57.49.332] END WMNewTab: 20 + + +[14:57.50.747] BEGIN WMNewTab: 20 +[14:57.50.747] END WMNewTab: 20 + + +[14:57.52.159] BEGIN WMNewTab: 20 +[14:57.52.159] END WMNewTab: 20 + + +[14:57.53.575] BEGIN WMNewTab: 20 +[14:57.53.575] END WMNewTab: 20 + + +[14:57.54.993] BEGIN WMNewTab: 20 +[14:57.54.993] END WMNewTab: 20 + + +[14:57.56.413] BEGIN WMNewTab: 20 +[14:57.56.413] END WMNewTab: 20 + + +[14:57.57.833] BEGIN WMNewTab: 20 +[14:57.57.833] END WMNewTab: 20 + + +[14:57.59.246] BEGIN WMNewTab: 20 +[14:57.59.246] END WMNewTab: 20 + + +[14:58.00.659] BEGIN WMNewTab: 20 +[14:58.00.659] END WMNewTab: 20 + + +[14:58.02.072] BEGIN WMNewTab: 20 +[14:58.02.072] END WMNewTab: 20 + + +[14:58.03.486] BEGIN WMNewTab: 20 +[14:58.03.486] END WMNewTab: 20 + + +[14:58.04.902] BEGIN WMNewTab: 20 +[14:58.04.902] END WMNewTab: 20 + + +[14:58.06.318] BEGIN WMNewTab: 20 +[14:58.06.318] END WMNewTab: 20 + + +[14:58.07.739] BEGIN WMNewTab: 20 +[14:58.07.739] END WMNewTab: 20 + + +[14:58.09.071] Cts1MouseDown: FormClick +[14:58.09.076] Cts1ActiveTabChanged: New index = 1 +[14:58.09.076] BEGIN DisplayCurrentTab +[14:58.09.076] DisplayCurrentTab: FormClick +[14:58.09.076] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[14:58.09.076] (SSH-Browser) BEGIN ActiverPanel14 +[14:58.09.076] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[14:58.09.080] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[14:58.09.080] (SSH-Browser) ActiverPanel14: 列出远程目录 +[14:58.09.080] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[14:58.09.080] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[14:58.09.100] (SSH-Browser) END ActiverPanel14; +[14:58.09.119] BEGIN TFormXterm.FormResize +[14:58.09.119] TFormXterm.FormResize: CenterBtnReattachTab +[14:58.09.120] TFormXterm.FormResize: SplitModeResize +[14:58.09.120] TFormXterm.FormResize: BtnSplitNo.Down +[14:58.09.120] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:58.09.120] BEGIN ResizeTerminal +[14:58.09.128] END ResizeTerminal +[14:58.09.128] TFormXterm.FormResize: AdaptSidebarArrows; +[14:58.09.128] BEGIN AdaptSidebarArrows +[14:58.09.128] END AdaptSidebarArrows +[14:58.09.128] TFormXterm.FormResize: AdaptTV2; +[14:58.09.128] END TFormXterm.FormResize +[14:58.09.129] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[14:58.09.129] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:58.09.140] ShellExecuteS: ShellExecuteEx 成功. +[14:58.09.140] ShellExecuteS: WaitForInputIdle 失败. +[14:58.09.140] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:58.09.140] DisplayCurrentTab: Cts1.BeginUpdate; +[14:58.09.140] DisplayCurrentTab: Cts1.EndUpdates +[14:58.09.155] DisplayCurrentTab: 显示所选标签页 +[14:58.09.155] BEGIN WMNewTab: 20 +[14:58.09.155] END WMNewTab: 20 +[14:58.09.156] DisplayCurrentTab: 隐藏其他标签页 +[14:58.09.186] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:58.09.190] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:58.09.190] DisplayCurrentTab: DistribuerLeFocus +[14:58.09.190] END DisplayCurrentTab +[14:58.09.202] [MobaSCP2] Launching remote monitoring in normal mode +[14:58.09.202] [MobaSCP2] Multiplex=1 +[14:58.09.202] [MobaSCP2] HOSTNAME: 192.168.127.10 +[14:58.09.204] [MobaSCP2] USERNAME: root +[14:58.09.243] [MobaSCP2] Using SCP1 +[14:58.09.243] [MobaSCP2] Connected to 192.168.127.10 + +[14:58.09.824] BEGIN WMNewTab: 0 +[14:58.09.824] WMNewTab: FormClick +[14:58.09.824] WMNewTab: LooseFocus +[14:58.09.824] END WMNewTab: 0 +[14:58.09.942] BEGIN WMNewTab: 0 +[14:58.09.942] WMNewTab: FormClick +[14:58.09.942] WMNewTab: LooseFocus +[14:58.09.943] END WMNewTab: 0 + +[14:58.10.372] BEGIN TFormXterm.FormResize +[14:58.10.373] TFormXterm.FormResize: CenterBtnReattachTab +[14:58.10.373] TFormXterm.FormResize: SplitModeResize +[14:58.10.373] TFormXterm.FormResize: BtnSplitNo.Down +[14:58.10.373] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:58.10.373] BEGIN ResizeTerminal +[14:58.10.373] END ResizeTerminal +[14:58.10.373] TFormXterm.FormResize: AdaptSidebarArrows; +[14:58.10.373] BEGIN AdaptSidebarArrows +[14:58.10.373] END AdaptSidebarArrows +[14:58.10.373] TFormXterm.FormResize: AdaptTV2; +[14:58.10.373] END TFormXterm.FormResize +[14:58.10.575] BEGIN WMNewTab: 20 +[14:58.10.575] END WMNewTab: 20 + + +[14:58.11.997] BEGIN WMNewTab: 20 +[14:58.11.997] END WMNewTab: 20 + +[14:58.12.742] BEGIN CWD +[14:58.12.803] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[14:58.12.803] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[14:58.12.803] (SSH-Browser) END VerifySFTPConnection(1) +[14:58.12.803] END CWD +[14:58.12.816] BEGIN CWD +[14:58.12.876] END CWD + +[14:58.13.346] BEGIN WMNewTab: 20 +[14:58.13.346] END WMNewTab: 20 + + +[14:58.14.760] BEGIN WMNewTab: 20 +[14:58.14.760] END WMNewTab: 20 + +[14:58.15.199] Cts1MouseDown: FormClick +[14:58.15.205] Cts1ActiveTabChanged: New index = 2 +[14:58.15.205] BEGIN DisplayCurrentTab +[14:58.15.205] DisplayCurrentTab: FormClick +[14:58.15.205] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[14:58.15.205] (SSH-Browser) BEGIN ActiverPanel14 +[14:58.15.205] (SSH-Browser) BEGIN DesactiverPanel14 +[14:58.15.219] (SSH-Browser) END DesactiverPanel14 +[14:58.15.219] (SSH-Browser) END ActiverPanel14; +[14:58.15.329] BEGIN TFormXterm.FormResize +[14:58.15.329] TFormXterm.FormResize: CenterBtnReattachTab +[14:58.15.330] TFormXterm.FormResize: SplitModeResize +[14:58.15.330] TFormXterm.FormResize: BtnSplitNo.Down +[14:58.15.330] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:58.15.330] BEGIN ResizeTerminal +[14:58.15.337] END ResizeTerminal +[14:58.15.337] TFormXterm.FormResize: AdaptSidebarArrows; +[14:58.15.337] BEGIN AdaptSidebarArrows +[14:58.15.337] END AdaptSidebarArrows +[14:58.15.337] TFormXterm.FormResize: AdaptTV2; +[14:58.15.337] END TFormXterm.FormResize +[14:58.15.337] DisplayCurrentTab: Cts1.BeginUpdate; +[14:58.15.337] DisplayCurrentTab: Cts1.EndUpdates +[14:58.15.351] DisplayCurrentTab: 显示所选标签页 +[14:58.15.354] DisplayCurrentTab: 隐藏其他标签页 +[14:58.15.368] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:58.15.371] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:58.15.371] DisplayCurrentTab: DistribuerLeFocus +[14:58.15.372] END DisplayCurrentTab + +[14:58.16.176] BEGIN WMNewTab: 20 +[14:58.16.176] END WMNewTab: 20 + + +[14:58.17.597] BEGIN WMNewTab: 20 +[14:58.17.597] END WMNewTab: 20 + + +[14:58.19.010] BEGIN WMNewTab: 20 +[14:58.19.010] END WMNewTab: 20 + + +[14:58.20.430] BEGIN WMNewTab: 20 +[14:58.20.430] END WMNewTab: 20 + + +[14:58.21.848] BEGIN WMNewTab: 20 +[14:58.21.848] END WMNewTab: 20 + + +[14:58.23.272] BEGIN WMNewTab: 20 +[14:58.23.272] END WMNewTab: 20 + + +[14:58.24.686] BEGIN WMNewTab: 20 +[14:58.24.686] END WMNewTab: 20 + +[14:58.25.561] BEGIN WMNewTab: 0 +[14:58.25.561] WMNewTab: FormClick +[14:58.25.561] WMNewTab: LooseFocus +[14:58.25.561] END WMNewTab: 0 + +[14:58.26.109] BEGIN WMNewTab: 20 +[14:58.26.110] END WMNewTab: 20 + +[14:58.27.096] BEGIN WMNewTab: 0 +[14:58.27.096] WMNewTab: FormClick +[14:58.27.096] WMNewTab: LooseFocus +[14:58.27.096] END WMNewTab: 0 + +[14:58.27.528] BEGIN WMNewTab: 20 +[14:58.27.528] END WMNewTab: 20 + + +[14:58.28.946] BEGIN WMNewTab: 20 +[14:58.28.946] END WMNewTab: 20 +[14:58.29.065] Cts1MouseDown: FormClick +[14:58.29.070] Cts1ActiveTabChanged: New index = 1 +[14:58.29.070] BEGIN DisplayCurrentTab +[14:58.29.070] DisplayCurrentTab: FormClick +[14:58.29.070] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[14:58.29.070] (SSH-Browser) BEGIN ActiverPanel14 +[14:58.29.070] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[14:58.29.074] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[14:58.29.074] (SSH-Browser) ActiverPanel14: 列出远程目录 +[14:58.29.074] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[14:58.29.074] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[14:58.29.103] (SSH-Browser) END ActiverPanel14; +[14:58.29.122] BEGIN TFormXterm.FormResize +[14:58.29.122] TFormXterm.FormResize: CenterBtnReattachTab +[14:58.29.124] TFormXterm.FormResize: SplitModeResize +[14:58.29.124] TFormXterm.FormResize: BtnSplitNo.Down +[14:58.29.124] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:58.29.124] BEGIN ResizeTerminal +[14:58.29.129] END ResizeTerminal +[14:58.29.129] TFormXterm.FormResize: AdaptSidebarArrows; +[14:58.29.129] BEGIN AdaptSidebarArrows +[14:58.29.129] END AdaptSidebarArrows +[14:58.29.129] TFormXterm.FormResize: AdaptTV2; +[14:58.29.129] END TFormXterm.FormResize +[14:58.29.129] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[14:58.29.129] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:58.29.144] ShellExecuteS: ShellExecuteEx 成功. +[14:58.29.144] ShellExecuteS: WaitForInputIdle 失败. +[14:58.29.144] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[14:58.29.144] DisplayCurrentTab: Cts1.BeginUpdate; +[14:58.29.144] DisplayCurrentTab: Cts1.EndUpdates +[14:58.29.161] DisplayCurrentTab: 显示所选标签页 +[14:58.29.165] DisplayCurrentTab: 隐藏其他标签页 +[14:58.29.194] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:58.29.197] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:58.29.197] DisplayCurrentTab: DistribuerLeFocus +[14:58.29.198] END DisplayCurrentTab +[14:58.29.212] [MobaSCP2] Launching remote monitoring in normal mode +[14:58.29.225] TFormDetachedTab MyDPI=192 +[14:58.29.274] [MobaSCP2] Multiplex=1 +[14:58.29.275] [MobaSCP2] HOSTNAME: 192.168.127.10 +[14:58.29.275] [MobaSCP2] USERNAME: root +[14:58.29.343] [MobaSCP2] Using SCP1 +[14:58.29.347] [MobaSCP2] Connected to 192.168.127.10 + +[14:58.30.447] BEGIN TFormXterm.FormResize +[14:58.30.447] TFormXterm.FormResize: CenterBtnReattachTab +[14:58.30.447] TFormXterm.FormResize: SplitModeResize +[14:58.30.447] TFormXterm.FormResize: BtnSplitNo.Down +[14:58.30.447] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:58.30.447] BEGIN ResizeTerminal +[14:58.30.447] BEGIN WMNewTab: 20 +[14:58.30.447] END WMNewTab: 20 +[14:58.30.447] END ResizeTerminal +[14:58.30.447] TFormXterm.FormResize: AdaptSidebarArrows; +[14:58.30.447] BEGIN AdaptSidebarArrows +[14:58.30.447] END AdaptSidebarArrows +[14:58.30.447] TFormXterm.FormResize: AdaptTV2; +[14:58.30.447] END TFormXterm.FormResize +[14:58.30.788] +[14:58.30.788] BEGIN Form4.FormActivate +[14:58.30.788] END Form4.FormActivate +[14:58.30.788] + +[14:58.31.156] +[14:58.31.156] BEGIN Form4.FormActivate +[14:58.31.156] END Form4.FormActivate +[14:58.31.156] + +[14:58.31.860] BEGIN WMNewTab: 20 +[14:58.31.860] END WMNewTab: 20 +[14:58.32.112] BEGIN Detachtab1Click +[14:58.32.112] +[14:58.32.112] BEGIN LIVE-CREATING TFormDetachedTab +[14:58.32.119] TFormDetachedTab MyDPI=192 +[14:58.32.120] END LIVE-CREATING TFormDetachedTab +[14:58.32.120] +[14:58.32.127] TFormDetachedTab MyDPI=192 +[14:58.32.128] BEGIN TFormDetachedTab.FormResize +[14:58.32.144] END TFormDetachedTab.FormResize +[14:58.32.147] BEGIN TFormDetachedTab.FormResize +[14:58.32.158] END TFormDetachedTab.FormResize +[14:58.32.169] BEGIN TFormDetachedTab.FormResize +[14:58.32.190] END TFormDetachedTab.FormResize +[14:58.32.207] BEGIN TFormDetachedTab.FormResize +[14:58.32.208] END TFormDetachedTab.FormResize +[14:58.32.234] END Detachtab1Click + +[14:58.33.191] +[14:58.33.191] BEGIN Form4.FormActivate +[14:58.33.191] END Form4.FormActivate +[14:58.33.191] +[14:58.33.275] BEGIN WMNewTab: 20 +[14:58.33.275] END WMNewTab: 20 + +[14:58.33.656] Cts1MouseDown: FormClick +[14:58.33.661] Cts1ActiveTabChanged: New index = 2 +[14:58.33.661] BEGIN DisplayCurrentTab +[14:58.33.661] DisplayCurrentTab: FormClick +[14:58.33.661] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[14:58.33.661] (SSH-Browser) BEGIN ActiverPanel14 +[14:58.33.661] (SSH-Browser) BEGIN DesactiverPanel14 +[14:58.33.675] (SSH-Browser) END DesactiverPanel14 +[14:58.33.675] (SSH-Browser) END ActiverPanel14; +[14:58.33.785] BEGIN TFormXterm.FormResize +[14:58.33.785] TFormXterm.FormResize: CenterBtnReattachTab +[14:58.33.785] TFormXterm.FormResize: SplitModeResize +[14:58.33.785] TFormXterm.FormResize: BtnSplitNo.Down +[14:58.33.786] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[14:58.33.786] BEGIN ResizeTerminal +[14:58.33.792] END ResizeTerminal +[14:58.33.792] TFormXterm.FormResize: AdaptSidebarArrows; +[14:58.33.792] BEGIN AdaptSidebarArrows +[14:58.33.792] END AdaptSidebarArrows +[14:58.33.792] TFormXterm.FormResize: AdaptTV2; +[14:58.33.792] END TFormXterm.FormResize +[14:58.33.792] DisplayCurrentTab: Cts1.BeginUpdate; +[14:58.33.792] DisplayCurrentTab: Cts1.EndUpdates +[14:58.33.810] DisplayCurrentTab: 显示所选标签页 +[14:58.33.813] DisplayCurrentTab: 隐藏其他标签页 +[14:58.33.813] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[14:58.33.815] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[14:58.33.816] DisplayCurrentTab: DistribuerLeFocus +[14:58.33.816] END DisplayCurrentTab + +[14:58.34.689] BEGIN WMNewTab: 20 +[14:58.34.689] END WMNewTab: 20 + + +[14:58.36.108] BEGIN WMNewTab: 20 +[14:58.36.108] END WMNewTab: 20 + + +[14:58.37.523] BEGIN WMNewTab: 20 +[14:58.37.523] END WMNewTab: 20 + + +[14:58.38.937] BEGIN WMNewTab: 20 +[14:58.38.937] END WMNewTab: 20 + + +[14:58.40.349] BEGIN WMNewTab: 20 +[14:58.40.349] END WMNewTab: 20 + + +[14:58.41.767] BEGIN WMNewTab: 20 +[14:58.41.767] END WMNewTab: 20 + +[14:58.42.906] BEGIN TFormDetachedTab.FormResize +[14:58.42.920] END TFormDetachedTab.FormResize +[14:58.42.934] BEGIN TFormDetachedTab.FormResize +[14:58.42.940] END TFormDetachedTab.FormResize +[14:58.42.946] BEGIN TFormDetachedTab.FormResize +[14:58.42.949] END TFormDetachedTab.FormResize +[14:58.42.960] BEGIN TFormDetachedTab.FormResize +[14:58.42.962] END TFormDetachedTab.FormResize +[14:58.42.971] BEGIN TFormDetachedTab.FormResize +[14:58.42.974] END TFormDetachedTab.FormResize +[14:58.42.988] BEGIN TFormDetachedTab.FormResize +[14:58.42.991] END TFormDetachedTab.FormResize +[14:58.43.002] BEGIN TFormDetachedTab.FormResize +[14:58.43.005] END TFormDetachedTab.FormResize +[14:58.43.022] BEGIN TFormDetachedTab.FormResize +[14:58.43.026] END TFormDetachedTab.FormResize +[14:58.43.034] BEGIN TFormDetachedTab.FormResize +[14:58.43.037] END TFormDetachedTab.FormResize +[14:58.43.049] BEGIN TFormDetachedTab.FormResize +[14:58.43.051] END TFormDetachedTab.FormResize +[14:58.43.067] BEGIN TFormDetachedTab.FormResize +[14:58.43.070] END TFormDetachedTab.FormResize +[14:58.43.083] BEGIN TFormDetachedTab.FormResize +[14:58.43.085] END TFormDetachedTab.FormResize +[14:58.43.184] BEGIN WMNewTab: 20 +[14:58.43.184] END WMNewTab: 20 + +[14:58.44.059] BEGIN WMNewTab: 0 +[14:58.44.059] WMNewTab: FormClick +[14:58.44.059] END WMNewTab: 0 +[14:58.44.059] BEGIN WMNewTab: 31 +[14:58.44.059] END WMNewTab: 31 +[14:58.44.152] BEGIN WMNewTab: 0 +[14:58.44.152] WMNewTab: FormClick +[14:58.44.152] END WMNewTab: 0 + +[14:58.44.600] BEGIN WMNewTab: 20 +[14:58.44.600] END WMNewTab: 20 + + +[14:58.46.019] BEGIN WMNewTab: 20 +[14:58.46.019] END WMNewTab: 20 + + +[14:58.47.439] BEGIN WMNewTab: 20 +[14:58.47.439] END WMNewTab: 20 + + +[14:58.48.858] BEGIN WMNewTab: 20 +[14:58.48.858] END WMNewTab: 20 + + +[14:58.50.279] BEGIN WMNewTab: 20 +[14:58.50.279] END WMNewTab: 20 + + +[14:58.51.696] BEGIN WMNewTab: 20 +[14:58.51.696] END WMNewTab: 20 + + +[14:58.53.119] BEGIN WMNewTab: 20 +[14:58.53.119] END WMNewTab: 20 + + +[14:58.54.535] BEGIN WMNewTab: 20 +[14:58.54.535] END WMNewTab: 20 + + +[14:58.55.954] BEGIN WMNewTab: 20 +[14:58.55.954] END WMNewTab: 20 + + +[14:58.57.373] BEGIN WMNewTab: 20 +[14:58.57.373] END WMNewTab: 20 + + +[14:58.58.791] BEGIN WMNewTab: 20 +[14:58.58.791] END WMNewTab: 20 + + +[14:59.00.209] BEGIN WMNewTab: 20 +[14:59.00.209] END WMNewTab: 20 + + +[14:59.01.625] BEGIN WMNewTab: 20 +[14:59.01.625] END WMNewTab: 20 + + +[14:59.03.038] BEGIN WMNewTab: 20 +[14:59.03.038] END WMNewTab: 20 + + +[14:59.04.445] BEGIN WMNewTab: 20 +[14:59.04.445] END WMNewTab: 20 + + +[14:59.05.865] BEGIN WMNewTab: 20 +[14:59.05.865] END WMNewTab: 20 + + +[14:59.07.281] BEGIN WMNewTab: 20 +[14:59.07.281] END WMNewTab: 20 + + +[14:59.08.699] BEGIN WMNewTab: 20 +[14:59.08.699] END WMNewTab: 20 + + +[14:59.10.115] BEGIN WMNewTab: 20 +[14:59.10.115] END WMNewTab: 20 + + +[14:59.11.533] BEGIN WMNewTab: 20 +[14:59.11.533] END WMNewTab: 20 + + +[14:59.12.949] BEGIN WMNewTab: 20 +[14:59.12.949] END WMNewTab: 20 + + +[14:59.14.372] BEGIN WMNewTab: 20 +[14:59.14.372] END WMNewTab: 20 + + +[14:59.15.791] BEGIN WMNewTab: 20 +[14:59.15.791] END WMNewTab: 20 + + +[14:59.17.212] BEGIN WMNewTab: 20 +[14:59.17.212] END WMNewTab: 20 + + +[14:59.18.629] BEGIN WMNewTab: 20 +[14:59.18.629] END WMNewTab: 20 + + +[14:59.20.049] BEGIN WMNewTab: 20 +[14:59.20.049] END WMNewTab: 20 + + +[14:59.21.472] BEGIN WMNewTab: 20 +[14:59.21.472] END WMNewTab: 20 + + +[14:59.22.894] BEGIN WMNewTab: 20 +[14:59.22.894] END WMNewTab: 20 + + +[14:59.24.314] BEGIN WMNewTab: 20 +[14:59.24.314] END WMNewTab: 20 + + +[14:59.25.732] BEGIN WMNewTab: 20 +[14:59.25.732] END WMNewTab: 20 + + +[14:59.27.156] BEGIN WMNewTab: 20 +[14:59.27.156] END WMNewTab: 20 + + +[14:59.28.578] BEGIN WMNewTab: 20 +[14:59.28.578] END WMNewTab: 20 + + +[14:59.29.993] BEGIN WMNewTab: 20 +[14:59.29.993] END WMNewTab: 20 + + +[14:59.31.409] BEGIN WMNewTab: 20 +[14:59.31.409] END WMNewTab: 20 + + +[14:59.32.824] BEGIN WMNewTab: 20 +[14:59.32.824] END WMNewTab: 20 + + +[14:59.34.243] BEGIN WMNewTab: 20 +[14:59.34.243] END WMNewTab: 20 + + +[14:59.35.663] BEGIN WMNewTab: 20 +[14:59.35.663] END WMNewTab: 20 + + +[14:59.37.080] BEGIN WMNewTab: 20 +[14:59.37.080] END WMNewTab: 20 + + +[14:59.38.496] BEGIN WMNewTab: 20 +[14:59.38.496] END WMNewTab: 20 + + +[14:59.39.919] BEGIN WMNewTab: 20 +[14:59.39.919] END WMNewTab: 20 + + +[14:59.41.334] BEGIN WMNewTab: 20 +[14:59.41.334] END WMNewTab: 20 + + +[14:59.42.751] BEGIN WMNewTab: 20 +[14:59.42.751] END WMNewTab: 20 + + +[14:59.44.170] BEGIN WMNewTab: 20 +[14:59.44.170] END WMNewTab: 20 + + +[14:59.45.591] BEGIN WMNewTab: 20 +[14:59.45.591] END WMNewTab: 20 + + +[14:59.47.007] BEGIN WMNewTab: 20 +[14:59.47.007] END WMNewTab: 20 + + +[14:59.48.428] BEGIN WMNewTab: 20 +[14:59.48.428] END WMNewTab: 20 + + +[14:59.49.850] BEGIN WMNewTab: 20 +[14:59.49.850] END WMNewTab: 20 + + +[14:59.51.271] BEGIN WMNewTab: 20 +[14:59.51.271] END WMNewTab: 20 + + +[14:59.52.692] BEGIN WMNewTab: 20 +[14:59.52.692] END WMNewTab: 20 + + +[14:59.54.110] BEGIN WMNewTab: 20 +[14:59.54.110] END WMNewTab: 20 + + +[14:59.55.529] BEGIN WMNewTab: 20 +[14:59.55.529] END WMNewTab: 20 + + +[14:59.56.953] BEGIN WMNewTab: 20 +[14:59.56.953] END WMNewTab: 20 + + +[14:59.58.377] BEGIN WMNewTab: 20 +[14:59.58.377] END WMNewTab: 20 + + +[14:59.59.799] BEGIN WMNewTab: 20 +[14:59.59.799] END WMNewTab: 20 + + +[15:00.01.218] BEGIN WMNewTab: 20 +[15:00.01.218] END WMNewTab: 20 + + +[15:00.02.642] BEGIN WMNewTab: 20 +[15:00.02.642] END WMNewTab: 20 + + +[15:00.04.059] BEGIN WMNewTab: 20 +[15:00.04.059] END WMNewTab: 20 + + +[15:00.05.479] BEGIN WMNewTab: 20 +[15:00.05.479] END WMNewTab: 20 + + +[15:00.06.901] BEGIN WMNewTab: 20 +[15:00.06.901] END WMNewTab: 20 + + +[15:00.08.318] BEGIN WMNewTab: 20 +[15:00.08.318] END WMNewTab: 20 + + +[15:00.09.734] BEGIN WMNewTab: 20 +[15:00.09.734] END WMNewTab: 20 + + +[15:00.11.157] BEGIN WMNewTab: 20 +[15:00.11.157] END WMNewTab: 20 + + +[15:00.12.572] BEGIN WMNewTab: 20 +[15:00.12.572] END WMNewTab: 20 + + +[15:00.13.998] BEGIN WMNewTab: 20 +[15:00.13.998] END WMNewTab: 20 + + +[15:00.15.420] BEGIN WMNewTab: 20 +[15:00.15.420] END WMNewTab: 20 + + +[15:00.16.838] BEGIN WMNewTab: 20 +[15:00.16.838] END WMNewTab: 20 + + +[15:00.18.260] BEGIN WMNewTab: 20 +[15:00.18.260] END WMNewTab: 20 + + +[15:00.19.687] BEGIN WMNewTab: 20 +[15:00.19.687] END WMNewTab: 20 + + +[15:00.21.099] BEGIN WMNewTab: 20 +[15:00.21.099] END WMNewTab: 20 + + +[15:00.22.519] BEGIN WMNewTab: 20 +[15:00.22.519] END WMNewTab: 20 + + +[15:00.23.940] BEGIN WMNewTab: 20 +[15:00.23.940] END WMNewTab: 20 + + +[15:00.25.355] BEGIN WMNewTab: 20 +[15:00.25.355] END WMNewTab: 20 + + +[15:00.26.776] BEGIN WMNewTab: 20 +[15:00.26.776] END WMNewTab: 20 + +[15:00.27.225] +[15:00.27.225] BEGIN Form4.FormActivate +[15:00.27.225] END Form4.FormActivate +[15:00.27.225] +[15:00.27.226] BEGIN WMNewTab: 0 +[15:00.27.226] WMNewTab: FormClick +[15:00.27.226] WMNewTab: LooseFocus +[15:00.27.226] END WMNewTab: 0 + +[15:00.27.775] BEGIN WMNewTab: 0 +[15:00.27.775] WMNewTab: FormClick +[15:00.27.775] WMNewTab: LooseFocus +[15:00.27.777] END WMNewTab: 0 + +[15:00.28.194] BEGIN WMNewTab: 20 +[15:00.28.194] END WMNewTab: 20 +[15:00.28.339] BEGIN WMNewTab: 0 +[15:00.28.339] WMNewTab: FormClick +[15:00.28.339] WMNewTab: LooseFocus +[15:00.28.340] END WMNewTab: 0 +[15:00.28.471] BEGIN WMNewTab: 0 +[15:00.28.471] WMNewTab: FormClick +[15:00.28.471] WMNewTab: LooseFocus +[15:00.28.472] END WMNewTab: 0 + +[15:00.29.603] BEGIN WMNewTab: 20 +[15:00.29.603] END WMNewTab: 20 + +[15:00.30.703] BEGIN WMNewTab: 0 +[15:00.30.703] WMNewTab: FormClick +[15:00.30.703] WMNewTab: LooseFocus +[15:00.30.703] END WMNewTab: 0 +[15:00.31.020] BEGIN WMNewTab: 20 +[15:00.31.020] END WMNewTab: 20 + + +[15:00.32.438] BEGIN WMNewTab: 20 +[15:00.32.438] END WMNewTab: 20 +[15:00.32.510] BEGIN WMNewTab: 0 +[15:00.32.510] WMNewTab: FormClick +[15:00.32.510] WMNewTab: LooseFocus +[15:00.32.512] END WMNewTab: 0 + + +[15:00.33.853] BEGIN WMNewTab: 20 +[15:00.33.853] END WMNewTab: 20 + +[15:00.34.607] BEGIN WMNewTab: 0 +[15:00.34.607] WMNewTab: FormClick +[15:00.34.607] END WMNewTab: 0 +[15:00.34.607] BEGIN WMNewTab: 31 +[15:00.34.607] END WMNewTab: 31 +[15:00.34.695] BEGIN WMNewTab: 0 +[15:00.34.695] WMNewTab: FormClick +[15:00.34.695] END WMNewTab: 0 + +[15:00.35.273] BEGIN WMNewTab: 20 +[15:00.35.273] END WMNewTab: 20 + + +[15:00.36.688] BEGIN WMNewTab: 20 +[15:00.36.688] END WMNewTab: 20 + + +[15:00.38.111] BEGIN WMNewTab: 20 +[15:00.38.111] END WMNewTab: 20 + + +[15:00.39.535] BEGIN WMNewTab: 20 +[15:00.39.535] END WMNewTab: 20 +[15:00.39.696] +[15:00.39.696] BEGIN Form4.FormActivate +[15:00.39.696] END Form4.FormActivate +[15:00.39.696] +[15:00.39.697] BEGIN WMNewTab: 0 +[15:00.39.697] WMNewTab: FormClick +[15:00.39.697] WMNewTab: LooseFocus +[15:00.39.698] END WMNewTab: 0 + +[15:00.40.303] BEGIN WMNewTab: 0 +[15:00.40.303] WMNewTab: FormClick +[15:00.40.303] WMNewTab: LooseFocus +[15:00.40.303] END WMNewTab: 0 + +[15:00.40.957] BEGIN WMNewTab: 20 +[15:00.40.957] END WMNewTab: 20 +[15:00.40.984] BEGIN WMNewTab: 0 +[15:00.40.984] WMNewTab: FormClick +[15:00.40.984] WMNewTab: LooseFocus +[15:00.40.984] END WMNewTab: 0 + + +[15:00.42.372] BEGIN WMNewTab: 20 +[15:00.42.372] END WMNewTab: 20 + +[15:00.43.279] BEGIN WMNewTab: 0 +[15:00.43.279] WMNewTab: FormClick +[15:00.43.279] WMNewTab: LooseFocus +[15:00.43.282] END WMNewTab: 0 +[15:00.43.424] BEGIN WMNewTab: 0 +[15:00.43.424] WMNewTab: FormClick +[15:00.43.424] WMNewTab: LooseFocus +[15:00.43.425] END WMNewTab: 0 +[15:00.43.425] BEGIN WMNewTab: 31 +[15:00.43.425] END WMNewTab: 31 +[15:00.43.560] BEGIN WMNewTab: 0 +[15:00.43.560] WMNewTab: FormClick +[15:00.43.560] WMNewTab: LooseFocus +[15:00.43.561] END WMNewTab: 0 +[15:00.43.790] BEGIN WMNewTab: 20 +[15:00.43.790] END WMNewTab: 20 + + +[15:00.45.205] BEGIN WMNewTab: 20 +[15:00.45.205] END WMNewTab: 20 + + +[15:00.46.620] BEGIN WMNewTab: 20 +[15:00.46.620] END WMNewTab: 20 + + +[15:00.47.928] BEGIN WMNewTab: 0 +[15:00.47.928] WMNewTab: FormClick +[15:00.47.928] END WMNewTab: 0 +[15:00.47.928] BEGIN WMNewTab: 31 +[15:00.47.928] END WMNewTab: 31 +[15:00.48.039] BEGIN WMNewTab: 20 +[15:00.48.039] END WMNewTab: 20 +[15:00.48.040] BEGIN WMNewTab: 0 +[15:00.48.040] WMNewTab: FormClick +[15:00.48.040] END WMNewTab: 0 + + +[15:00.49.455] BEGIN WMNewTab: 20 +[15:00.49.455] END WMNewTab: 20 + + +[15:00.50.869] BEGIN WMNewTab: 20 +[15:00.50.869] END WMNewTab: 20 + +[15:00.51.454] +[15:00.51.454] BEGIN Form4.FormActivate +[15:00.51.454] END Form4.FormActivate +[15:00.51.454] + +[15:00.52.282] BEGIN WMNewTab: 20 +[15:00.52.283] END WMNewTab: 20 + + +[15:00.53.696] BEGIN WMNewTab: 20 +[15:00.53.696] END WMNewTab: 20 + + +[15:00.55.113] BEGIN WMNewTab: 20 +[15:00.55.113] END WMNewTab: 20 + + +[15:00.56.536] BEGIN WMNewTab: 20 +[15:00.56.536] END WMNewTab: 20 + +[15:00.57.307] +[15:00.57.307] BEGIN Form4.FormActivate +[15:00.57.307] END Form4.FormActivate +[15:00.57.307] +[15:00.57.308] Cts1MouseDown: FormClick +[15:00.57.313] Cts1ActiveTabChanged: New index = 1 +[15:00.57.313] BEGIN DisplayCurrentTab +[15:00.57.313] DisplayCurrentTab: FormClick +[15:00.57.313] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:00.57.313] (SSH-Browser) BEGIN ActiverPanel14 +[15:00.57.313] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:00.57.317] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:00.57.317] (SSH-Browser) ActiverPanel14: 列出远程目录 +[15:00.57.317] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[15:00.57.318] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[15:00.57.348] (SSH-Browser) END ActiverPanel14; +[15:00.57.370] BEGIN TFormXterm.FormResize +[15:00.57.370] TFormXterm.FormResize: CenterBtnReattachTab +[15:00.57.371] TFormXterm.FormResize: SplitModeResize +[15:00.57.371] TFormXterm.FormResize: BtnSplitNo.Down +[15:00.57.371] TFormXterm.FormResize: AdaptSidebarArrows; +[15:00.57.371] BEGIN AdaptSidebarArrows +[15:00.57.371] END AdaptSidebarArrows +[15:00.57.371] TFormXterm.FormResize: AdaptTV2; +[15:00.57.371] END TFormXterm.FormResize +[15:00.57.372] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[15:00.57.372] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:00.57.387] ShellExecuteS: ShellExecuteEx 成功. +[15:00.57.387] ShellExecuteS: WaitForInputIdle 失败. +[15:00.57.387] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:00.57.387] DisplayCurrentTab: Cts1.BeginUpdate; +[15:00.57.387] DisplayCurrentTab: Cts1.EndUpdates +[15:00.57.402] DisplayCurrentTab: 显示所选标签页 +[15:00.57.402] DisplayCurrentTab: 隐藏其他标签页 +[15:00.57.412] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:00.57.412] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:00.57.413] DisplayCurrentTab: DistribuerLeFocus +[15:00.57.413] END DisplayCurrentTab +[15:00.57.450] [MobaSCP2] Launching remote monitoring in normal mode +[15:00.57.450] [MobaSCP2] Multiplex=1 +[15:00.57.451] [MobaSCP2] HOSTNAME: 192.168.127.10 +[15:00.57.451] [MobaSCP2] USERNAME: root +[15:00.57.493] [MobaSCP2] Using SCP1 +[15:00.57.494] [MobaSCP2] Connected to 192.168.127.10 + +[15:00.57.953] BEGIN WMNewTab: 20 +[15:00.57.953] END WMNewTab: 20 + +[15:00.58.619] BEGIN TFormXterm.FormResize +[15:00.58.619] TFormXterm.FormResize: CenterBtnReattachTab +[15:00.58.619] TFormXterm.FormResize: SplitModeResize +[15:00.58.619] TFormXterm.FormResize: BtnSplitNo.Down +[15:00.58.619] TFormXterm.FormResize: AdaptSidebarArrows; +[15:00.58.619] BEGIN AdaptSidebarArrows +[15:00.58.619] END AdaptSidebarArrows +[15:00.58.619] TFormXterm.FormResize: AdaptTV2; +[15:00.58.619] END TFormXterm.FormResize +[15:00.58.977] BtnDetachTabClick: FormClick +[15:00.58.977] BEGIN Reattachtab1Click +[15:00.59.012] BEGIN TFormDetachedTab.FormCloseQuery +[15:00.59.012] END TFormDetachedTab.FormCloseQuery +[15:00.59.017] 更改标签页索引 R = 1 +[15:00.59.017] BEGIN DisplayCurrentTab +[15:00.59.017] DisplayCurrentTab: FormClick +[15:00.59.017] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:00.59.017] (SSH-Browser) BEGIN ActiverPanel14 +[15:00.59.017] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:00.59.032] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:00.59.032] (SSH-Browser) ActiverPanel14: 远程目录已列出 +[15:00.59.032] (SSH-Browser) END ActiverPanel14; +[15:00.59.032] DisplayCurrentTab: Cts1.BeginUpdate; +[15:00.59.032] DisplayCurrentTab: Cts1.EndUpdates +[15:00.59.045] DisplayCurrentTab: 显示所选标签页 +[15:00.59.045] DisplayCurrentTab: 隐藏其他标签页 +[15:00.59.046] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:00.59.048] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:00.59.049] DisplayCurrentTab: DistribuerLeFocus +[15:00.59.049] END DisplayCurrentTab +[15:00.59.049] END Reattachtab1Click +[15:00.59.369] BEGIN WMNewTab: 20 +[15:00.59.369] END WMNewTab: 20 + + +[15:01.00.783] BEGIN WMNewTab: 20 +[15:01.00.783] END WMNewTab: 20 + + +[15:01.02.195] BEGIN WMNewTab: 20 +[15:01.02.195] END WMNewTab: 20 + + +[15:01.03.614] BEGIN WMNewTab: 20 +[15:01.03.614] END WMNewTab: 20 + + +[15:01.05.033] BEGIN WMNewTab: 20 +[15:01.05.033] END WMNewTab: 20 + + +[15:01.06.450] BEGIN WMNewTab: 20 +[15:01.06.450] END WMNewTab: 20 + + +[15:01.07.863] BEGIN WMNewTab: 20 +[15:01.07.863] END WMNewTab: 20 + + +[15:01.09.279] BEGIN WMNewTab: 20 +[15:01.09.279] END WMNewTab: 20 + + +[15:01.10.694] BEGIN WMNewTab: 20 +[15:01.10.694] END WMNewTab: 20 + + +[15:01.12.110] BEGIN WMNewTab: 20 +[15:01.12.110] END WMNewTab: 20 + + +[15:01.13.528] BEGIN WMNewTab: 20 +[15:01.13.528] END WMNewTab: 20 + + +[15:01.14.948] BEGIN WMNewTab: 20 +[15:01.14.948] END WMNewTab: 20 + + +[15:01.16.364] BEGIN WMNewTab: 20 +[15:01.16.364] END WMNewTab: 20 + + +[15:01.17.782] BEGIN WMNewTab: 20 +[15:01.17.782] END WMNewTab: 20 + + +[15:01.19.196] BEGIN WMNewTab: 20 +[15:01.19.196] END WMNewTab: 20 + + +[15:01.20.614] BEGIN WMNewTab: 20 +[15:01.20.614] END WMNewTab: 20 + + +[15:01.22.029] BEGIN WMNewTab: 20 +[15:01.22.029] END WMNewTab: 20 + + +[15:01.23.444] BEGIN WMNewTab: 20 +[15:01.23.444] END WMNewTab: 20 + + +[15:01.24.861] BEGIN WMNewTab: 20 +[15:01.24.861] END WMNewTab: 20 + + +[15:01.26.277] BEGIN WMNewTab: 20 +[15:01.26.277] END WMNewTab: 20 + + +[15:01.27.694] BEGIN WMNewTab: 20 +[15:01.27.694] END WMNewTab: 20 + + +[15:01.29.108] BEGIN WMNewTab: 20 +[15:01.29.108] END WMNewTab: 20 + +[15:01.29.626] BEGIN WMSysCommand (minimize/restore) +[15:01.29.653] BEGIN WMSize +[15:01.29.653] END WMSize +[15:01.29.674] END WMSysCommand + +[15:01.30.524] BEGIN WMNewTab: 20 +[15:01.30.524] END WMNewTab: 20 + + +[15:01.31.948] BEGIN WMNewTab: 20 +[15:01.31.948] END WMNewTab: 20 + + +[15:01.33.366] BEGIN WMNewTab: 20 +[15:01.33.366] END WMNewTab: 20 +[15:01.33.633] BEGIN WMSysCommand (minimize/restore) +[15:01.33.633] BEGIN WMNewTab: 0 +[15:01.33.633] WMNewTab: FormClick +[15:01.33.633] WMNewTab: LooseFocus +[15:01.33.634] END WMNewTab: 0 +[15:01.33.719] BEGIN WMSize +[15:01.33.719] BEGIN TFormXterm.FormResize +[15:01.33.719] TFormXterm.FormResize: CenterBtnReattachTab +[15:01.33.719] TFormXterm.FormResize: SplitModeResize +[15:01.33.719] TFormXterm.FormResize: BtnSplitNo.Down +[15:01.33.719] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:01.33.719] BEGIN ResizeTerminal +[15:01.33.720] END ResizeTerminal +[15:01.33.720] TFormXterm.FormResize: AdaptSidebarArrows; +[15:01.33.720] BEGIN AdaptSidebarArrows +[15:01.33.720] END AdaptSidebarArrows +[15:01.33.720] TFormXterm.FormResize: AdaptTV2; +[15:01.33.720] END TFormXterm.FormResize +[15:01.33.720] END WMSize +[15:01.33.724] END WMSysCommand + +[15:01.34.281] BEGIN WMNewTab: 0 +[15:01.34.281] WMNewTab: FormClick +[15:01.34.281] WMNewTab: LooseFocus +[15:01.34.281] END WMNewTab: 0 +[15:01.34.408] BEGIN WMNewTab: 0 +[15:01.34.408] WMNewTab: FormClick +[15:01.34.408] WMNewTab: LooseFocus +[15:01.34.410] END WMNewTab: 0 + +[15:01.34.788] BEGIN WMNewTab: 20 +[15:01.34.788] END WMNewTab: 20 + + +[15:01.36.207] BEGIN WMNewTab: 20 +[15:01.36.207] END WMNewTab: 20 + + +[15:01.37.621] BEGIN WMNewTab: 20 +[15:01.37.621] END WMNewTab: 20 + + +[15:01.39.032] BEGIN WMNewTab: 20 +[15:01.39.032] END WMNewTab: 20 + + +[15:01.40.444] BEGIN WMNewTab: 20 +[15:01.40.444] END WMNewTab: 20 + + +[15:01.41.857] BEGIN WMNewTab: 20 +[15:01.41.857] END WMNewTab: 20 + + +[15:01.43.278] BEGIN WMNewTab: 20 +[15:01.43.278] END WMNewTab: 20 + + +[15:01.44.698] BEGIN WMNewTab: 20 +[15:01.44.698] END WMNewTab: 20 +[15:01.44.993] BEGIN WMNewTab: 0 +[15:01.44.993] WMNewTab: FormClick +[15:01.44.993] WMNewTab: LooseFocus +[15:01.44.993] END WMNewTab: 0 +[15:01.44.993] BEGIN WMNewTab: 31 +[15:01.44.993] END WMNewTab: 31 + +[15:01.46.111] BEGIN WMNewTab: 20 +[15:01.46.111] END WMNewTab: 20 + + +[15:01.47.529] BEGIN WMNewTab: 20 +[15:01.47.529] END WMNewTab: 20 + +[15:01.48.365] BEGIN CWD +[15:01.48.426] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:01.48.426] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:01.48.426] (SSH-Browser) END VerifySFTPConnection(1) +[15:01.48.426] END CWD +[15:01.48.516] BEGIN CWD +[15:01.48.576] END CWD + +[15:01.49.046] BEGIN WMNewTab: 20 +[15:01.49.046] END WMNewTab: 20 + + +[15:01.50.469] BEGIN WMNewTab: 20 +[15:01.50.469] END WMNewTab: 20 + + +[15:01.51.890] BEGIN WMNewTab: 20 +[15:01.51.890] END WMNewTab: 20 + + +[15:01.53.305] BEGIN WMNewTab: 20 +[15:01.53.305] END WMNewTab: 20 +[15:01.53.534] BEGIN CWD +[15:01.53.612] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:01.53.612] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:01.53.612] (SSH-Browser) END VerifySFTPConnection(1) +[15:01.53.612] END CWD +[15:01.53.625] BEGIN CWD +[15:01.53.687] END CWD + +[15:01.54.630] BEGIN WMNewTab: 20 +[15:01.54.630] END WMNewTab: 20 + + +[15:01.56.043] BEGIN WMNewTab: 20 +[15:01.56.043] END WMNewTab: 20 + + +[15:01.57.453] BEGIN WMNewTab: 20 +[15:01.57.453] END WMNewTab: 20 +[15:01.57.803] BEGIN WMNewTab: 0 +[15:01.57.803] WMNewTab: FormClick +[15:01.57.803] WMNewTab: LooseFocus +[15:01.57.804] END WMNewTab: 0 + +[15:01.58.871] BEGIN WMNewTab: 20 +[15:01.58.871] END WMNewTab: 20 + +[15:01.59.505] BEGIN WMNewTab: 0 +[15:01.59.505] WMNewTab: FormClick +[15:01.59.505] WMNewTab: LooseFocus +[15:01.59.509] END WMNewTab: 0 + +[15:02.00.289] BEGIN WMNewTab: 20 +[15:02.00.289] END WMNewTab: 20 + + +[15:02.01.698] BEGIN WMNewTab: 20 +[15:02.01.698] END WMNewTab: 20 + + +[15:02.03.109] BEGIN WMNewTab: 20 +[15:02.03.109] END WMNewTab: 20 + + +[15:02.04.528] BEGIN WMNewTab: 20 +[15:02.04.528] END WMNewTab: 20 + + +[15:02.05.947] BEGIN WMNewTab: 20 +[15:02.05.947] END WMNewTab: 20 + + +[15:02.07.367] BEGIN WMNewTab: 20 +[15:02.07.367] END WMNewTab: 20 + +[15:02.08.050] BEGIN WMNewTab: 0 +[15:02.08.050] WMNewTab: FormClick +[15:02.08.050] WMNewTab: LooseFocus +[15:02.08.050] END WMNewTab: 0 +[15:02.08.169] BEGIN WMNewTab: 0 +[15:02.08.169] WMNewTab: FormClick +[15:02.08.169] WMNewTab: LooseFocus +[15:02.08.170] END WMNewTab: 0 + +[15:02.08.778] BEGIN WMNewTab: 20 +[15:02.08.778] END WMNewTab: 20 + + +[15:02.10.193] BEGIN WMNewTab: 20 +[15:02.10.193] END WMNewTab: 20 + + +[15:02.11.609] BEGIN WMNewTab: 20 +[15:02.11.609] END WMNewTab: 20 +[15:02.11.777] BEGIN CWD +[15:02.11.837] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.11.837] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.11.837] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.11.837] END CWD +[15:02.11.853] BEGIN CWD +[15:02.11.914] END CWD +[15:02.12.125] BEGIN CWD +[15:02.12.186] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.12.186] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.12.186] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.12.186] END CWD +[15:02.12.202] BEGIN CWD +[15:02.12.263] END CWD + +[15:02.13.179] BEGIN WMNewTab: 0 +[15:02.13.179] WMNewTab: FormClick +[15:02.13.179] WMNewTab: LooseFocus +[15:02.13.179] END WMNewTab: 0 +[15:02.13.210] BEGIN WMNewTab: 20 +[15:02.13.210] END WMNewTab: 20 +[15:02.13.338] BEGIN WMNewTab: 0 +[15:02.13.338] WMNewTab: FormClick +[15:02.13.338] WMNewTab: LooseFocus +[15:02.13.339] END WMNewTab: 0 + + +[15:02.14.628] BEGIN WMNewTab: 20 +[15:02.14.628] END WMNewTab: 20 + +[15:02.15.034] BEGIN WMNewTab: 0 +[15:02.15.034] WMNewTab: FormClick +[15:02.15.034] WMNewTab: LooseFocus +[15:02.15.035] END WMNewTab: 0 +[15:02.15.162] BEGIN WMNewTab: 0 +[15:02.15.162] WMNewTab: FormClick +[15:02.15.162] WMNewTab: LooseFocus +[15:02.15.163] END WMNewTab: 0 + +[15:02.16.049] BEGIN WMNewTab: 20 +[15:02.16.049] END WMNewTab: 20 + +[15:02.17.024] BEGIN CWD +[15:02.17.084] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.17.084] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.17.084] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.17.084] END CWD +[15:02.17.100] BEGIN CWD +[15:02.17.161] END CWD +[15:02.17.190] BEGIN CWD +[15:02.17.251] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.17.251] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.17.251] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.17.251] END CWD +[15:02.17.252] BEGIN WMNewTab: 20 +[15:02.17.252] END WMNewTab: 20 +[15:02.17.267] BEGIN CWD +[15:02.17.327] END CWD +[15:02.17.343] BEGIN CWD +[15:02.17.404] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.17.404] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.17.404] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.17.404] END CWD +[15:02.17.419] BEGIN CWD +[15:02.17.479] END CWD + +[15:02.18.427] BEGIN WMNewTab: 0 +[15:02.18.427] WMNewTab: FormClick +[15:02.18.427] WMNewTab: LooseFocus +[15:02.18.428] END WMNewTab: 0 +[15:02.18.585] BEGIN WMNewTab: 0 +[15:02.18.585] WMNewTab: FormClick +[15:02.18.585] WMNewTab: LooseFocus +[15:02.18.586] END WMNewTab: 0 +[15:02.18.682] BEGIN WMNewTab: 0 +[15:02.18.682] WMNewTab: FormClick +[15:02.18.682] WMNewTab: LooseFocus +[15:02.18.682] END WMNewTab: 0 +[15:02.18.682] BEGIN WMNewTab: 31 +[15:02.18.682] END WMNewTab: 31 +[15:02.18.897] BEGIN WMNewTab: 20 +[15:02.18.897] END WMNewTab: 20 + + +[15:02.20.311] BEGIN WMNewTab: 20 +[15:02.20.311] END WMNewTab: 20 + + +[15:02.21.727] BEGIN WMNewTab: 20 +[15:02.21.727] END WMNewTab: 20 + + +[15:02.23.143] BEGIN WMNewTab: 20 +[15:02.23.143] END WMNewTab: 20 + + +[15:02.24.559] BEGIN WMNewTab: 20 +[15:02.24.559] END WMNewTab: 20 + + +[15:02.25.977] BEGIN WMNewTab: 20 +[15:02.25.977] END WMNewTab: 20 + + +[15:02.27.387] BEGIN WMNewTab: 20 +[15:02.27.387] END WMNewTab: 20 + + +[15:02.28.803] BEGIN WMNewTab: 20 +[15:02.28.803] END WMNewTab: 20 + + +[15:02.30.219] BEGIN WMNewTab: 20 +[15:02.30.219] END WMNewTab: 20 + + +[15:02.31.633] BEGIN WMNewTab: 20 +[15:02.31.633] END WMNewTab: 20 + + +[15:02.33.047] BEGIN WMNewTab: 20 +[15:02.33.047] END WMNewTab: 20 + + +[15:02.34.465] BEGIN WMNewTab: 20 +[15:02.34.465] END WMNewTab: 20 + + +[15:02.35.848] BEGIN CWD +[15:02.35.877] BEGIN WMNewTab: 20 +[15:02.35.877] END WMNewTab: 20 +[15:02.35.909] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.35.909] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.35.909] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.35.909] END CWD +[15:02.35.923] BEGIN CWD +[15:02.35.984] END CWD + + +[15:02.37.393] BEGIN WMNewTab: 20 +[15:02.37.393] END WMNewTab: 20 + + +[15:02.38.804] BEGIN WMNewTab: 20 +[15:02.38.804] END WMNewTab: 20 + + +[15:02.40.221] BEGIN WMNewTab: 20 +[15:02.40.221] END WMNewTab: 20 + + +[15:02.41.638] BEGIN WMNewTab: 20 +[15:02.41.638] END WMNewTab: 20 + + +[15:02.43.054] BEGIN WMNewTab: 20 +[15:02.43.054] END WMNewTab: 20 + + +[15:02.44.466] BEGIN WMNewTab: 20 +[15:02.44.466] END WMNewTab: 20 + + +[15:02.45.878] BEGIN WMNewTab: 20 +[15:02.45.878] END WMNewTab: 20 + + +[15:02.47.295] BEGIN WMNewTab: 20 +[15:02.47.295] END WMNewTab: 20 + + +[15:02.48.728] BEGIN WMNewTab: 20 +[15:02.48.728] END WMNewTab: 20 + +[15:02.49.536] BEGIN WMNewTab: 0 +[15:02.49.536] WMNewTab: FormClick +[15:02.49.536] WMNewTab: LooseFocus +[15:02.49.536] END WMNewTab: 0 +[15:02.49.683] BEGIN WMNewTab: 0 +[15:02.49.683] WMNewTab: FormClick +[15:02.49.683] WMNewTab: LooseFocus +[15:02.49.683] END WMNewTab: 0 +[15:02.49.794] Received Ctrl+Clic message (launch something from the terminal): +[15:02.49.834] BEGIN WMNewTab: 0 +[15:02.49.834] WMNewTab: FormClick +[15:02.49.834] WMNewTab: LooseFocus +[15:02.49.834] END WMNewTab: 0 +[15:02.49.910] BEGIN WMNewTab: 0 +[15:02.49.910] WMNewTab: FormClick +[15:02.49.910] WMNewTab: LooseFocus +[15:02.49.913] END WMNewTab: 0 +[15:02.50.052] BEGIN WMNewTab: 0 +[15:02.50.052] WMNewTab: FormClick +[15:02.50.052] WMNewTab: LooseFocus +[15:02.50.052] END WMNewTab: 0 +[15:02.50.138] BEGIN WMNewTab: 0 +[15:02.50.138] WMNewTab: FormClick +[15:02.50.138] WMNewTab: LooseFocus +[15:02.50.141] END WMNewTab: 0 +[15:02.50.143] BEGIN WMNewTab: 20 +[15:02.50.143] END WMNewTab: 20 + +[15:02.50.693] Cts1MouseDown: FormClick +[15:02.50.698] Cts1ActiveTabChanged: New index = 2 +[15:02.50.698] BEGIN DisplayCurrentTab +[15:02.50.698] DisplayCurrentTab: FormClick +[15:02.50.698] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[15:02.50.698] (SSH-Browser) BEGIN ActiverPanel14 +[15:02.50.698] (SSH-Browser) BEGIN DesactiverPanel14 +[15:02.50.713] (SSH-Browser) END DesactiverPanel14 +[15:02.50.713] (SSH-Browser) END ActiverPanel14; +[15:02.50.823] BEGIN TFormXterm.FormResize +[15:02.50.823] TFormXterm.FormResize: CenterBtnReattachTab +[15:02.50.823] TFormXterm.FormResize: SplitModeResize +[15:02.50.823] TFormXterm.FormResize: BtnSplitNo.Down +[15:02.50.824] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:02.50.824] BEGIN ResizeTerminal +[15:02.50.830] END ResizeTerminal +[15:02.50.830] TFormXterm.FormResize: AdaptSidebarArrows; +[15:02.50.830] BEGIN AdaptSidebarArrows +[15:02.50.830] END AdaptSidebarArrows +[15:02.50.831] TFormXterm.FormResize: AdaptTV2; +[15:02.50.831] END TFormXterm.FormResize +[15:02.50.831] DisplayCurrentTab: Cts1.BeginUpdate; +[15:02.50.831] DisplayCurrentTab: Cts1.EndUpdates +[15:02.50.844] DisplayCurrentTab: 显示所选标签页 +[15:02.50.851] DisplayCurrentTab: 隐藏其他标签页 +[15:02.50.858] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:02.50.860] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:02.50.860] DisplayCurrentTab: DistribuerLeFocus +[15:02.50.860] END DisplayCurrentTab + +[15:02.51.563] BEGIN WMNewTab: 20 +[15:02.51.563] END WMNewTab: 20 +[15:02.51.887] Cts1MouseDown: FormClick +[15:02.51.892] Cts1ActiveTabChanged: New index = 1 +[15:02.51.892] BEGIN DisplayCurrentTab +[15:02.51.892] DisplayCurrentTab: FormClick +[15:02.51.892] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:02.51.892] (SSH-Browser) BEGIN ActiverPanel14 +[15:02.51.892] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:02.51.896] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:02.51.896] (SSH-Browser) ActiverPanel14: 列出远程目录 +[15:02.51.896] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[15:02.51.896] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[15:02.51.922] (SSH-Browser) END ActiverPanel14; +[15:02.51.944] BEGIN TFormXterm.FormResize +[15:02.51.944] TFormXterm.FormResize: CenterBtnReattachTab +[15:02.51.944] TFormXterm.FormResize: SplitModeResize +[15:02.51.944] TFormXterm.FormResize: BtnSplitNo.Down +[15:02.51.945] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:02.51.945] BEGIN ResizeTerminal +[15:02.51.951] END ResizeTerminal +[15:02.51.951] TFormXterm.FormResize: AdaptSidebarArrows; +[15:02.51.951] BEGIN AdaptSidebarArrows +[15:02.51.951] END AdaptSidebarArrows +[15:02.51.951] TFormXterm.FormResize: AdaptTV2; +[15:02.51.951] END TFormXterm.FormResize +[15:02.51.952] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[15:02.51.952] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:02.51.970] ShellExecuteS: ShellExecuteEx 成功. +[15:02.51.970] ShellExecuteS: WaitForInputIdle 失败. +[15:02.51.970] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:02.51.970] DisplayCurrentTab: Cts1.BeginUpdate; +[15:02.51.970] DisplayCurrentTab: Cts1.EndUpdates +[15:02.51.986] DisplayCurrentTab: 显示所选标签页 +[15:02.51.988] DisplayCurrentTab: 隐藏其他标签页 +[15:02.52.000] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:02.52.004] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:02.52.004] DisplayCurrentTab: DistribuerLeFocus +[15:02.52.004] END DisplayCurrentTab +[15:02.52.031] [MobaSCP2] Launching remote monitoring in normal mode +[15:02.52.032] [MobaSCP2] Multiplex=1 +[15:02.52.032] [MobaSCP2] HOSTNAME: 192.168.127.10 +[15:02.52.034] [MobaSCP2] USERNAME: root +[15:02.52.076] [MobaSCP2] Using SCP1 +[15:02.52.076] [MobaSCP2] Connected to 192.168.127.10 +[15:02.52.364] BEGIN WMNewTab: 0 +[15:02.52.364] WMNewTab: FormClick +[15:02.52.364] WMNewTab: LooseFocus +[15:02.52.364] END WMNewTab: 0 +[15:02.52.486] BEGIN WMNewTab: 0 +[15:02.52.486] WMNewTab: FormClick +[15:02.52.486] WMNewTab: LooseFocus +[15:02.52.486] END WMNewTab: 0 +[15:02.52.599] Received Ctrl+Clic message (launch something from the terminal): +[15:02.52.642] BEGIN WMNewTab: 0 +[15:02.52.642] WMNewTab: FormClick +[15:02.52.642] WMNewTab: LooseFocus +[15:02.52.642] END WMNewTab: 0 +[15:02.52.746] BEGIN WMNewTab: 0 +[15:02.52.746] WMNewTab: FormClick +[15:02.52.746] WMNewTab: LooseFocus +[15:02.52.751] END WMNewTab: 0 +[15:02.52.835] BEGIN WMNewTab: 0 +[15:02.52.835] WMNewTab: FormClick +[15:02.52.835] WMNewTab: LooseFocus +[15:02.52.835] END WMNewTab: 0 +[15:02.52.950] BEGIN WMNewTab: 0 +[15:02.52.950] WMNewTab: FormClick +[15:02.52.950] WMNewTab: LooseFocus +[15:02.52.954] END WMNewTab: 0 +[15:02.52.981] BEGIN WMNewTab: 20 +[15:02.52.981] END WMNewTab: 20 +[15:02.53.207] BEGIN TFormXterm.FormResize +[15:02.53.207] TFormXterm.FormResize: CenterBtnReattachTab +[15:02.53.207] TFormXterm.FormResize: SplitModeResize +[15:02.53.207] TFormXterm.FormResize: BtnSplitNo.Down +[15:02.53.207] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:02.53.207] BEGIN ResizeTerminal +[15:02.53.207] END ResizeTerminal +[15:02.53.207] TFormXterm.FormResize: AdaptSidebarArrows; +[15:02.53.207] BEGIN AdaptSidebarArrows +[15:02.53.207] END AdaptSidebarArrows +[15:02.53.207] TFormXterm.FormResize: AdaptTV2; +[15:02.53.207] END TFormXterm.FormResize +[15:02.53.236] BEGIN WMNewTab: 0 +[15:02.53.236] WMNewTab: FormClick +[15:02.53.236] WMNewTab: LooseFocus +[15:02.53.236] END WMNewTab: 0 +[15:02.53.351] BEGIN WMNewTab: 0 +[15:02.53.351] WMNewTab: FormClick +[15:02.53.351] WMNewTab: LooseFocus +[15:02.53.351] END WMNewTab: 0 +[15:02.53.463] Received Ctrl+Clic message (launch something from the terminal): + +[15:02.54.394] BEGIN WMNewTab: 20 +[15:02.54.394] END WMNewTab: 20 + +[15:02.55.579] BEGIN WMNewTab: 0 +[15:02.55.579] WMNewTab: FormClick +[15:02.55.579] WMNewTab: LooseFocus +[15:02.55.580] END WMNewTab: 0 +[15:02.55.675] BEGIN WMNewTab: 0 +[15:02.55.675] WMNewTab: FormClick +[15:02.55.675] WMNewTab: LooseFocus +[15:02.55.675] END WMNewTab: 0 +[15:02.55.811] BEGIN WMNewTab: 20 +[15:02.55.811] END WMNewTab: 20 +[15:02.55.901] BEGIN WMNewTab: 0 +[15:02.55.901] WMNewTab: FormClick +[15:02.55.901] WMNewTab: LooseFocus +[15:02.55.901] END WMNewTab: 0 +[15:02.55.901] BEGIN WMNewTab: 31 +[15:02.55.901] END WMNewTab: 31 + + +[15:02.57.244] BEGIN WMNewTab: 20 +[15:02.57.244] END WMNewTab: 20 +[15:02.57.535] BEGIN WMNewTab: 0 +[15:02.57.535] WMNewTab: FormClick +[15:02.57.535] WMNewTab: LooseFocus +[15:02.57.536] END WMNewTab: 0 +[15:02.57.651] BEGIN WMNewTab: 0 +[15:02.57.651] WMNewTab: FormClick +[15:02.57.651] WMNewTab: LooseFocus +[15:02.57.651] END WMNewTab: 0 + +[15:02.58.665] BEGIN WMNewTab: 20 +[15:02.58.665] END WMNewTab: 20 + +[15:02.59.287] BEGIN CWD +[15:02.59.347] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.59.347] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.59.347] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.59.347] END CWD +[15:02.59.362] BEGIN CWD +[15:02.59.422] END CWD +[15:02.59.438] BEGIN CWD +[15:02.59.499] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.59.499] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.59.499] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.59.499] END CWD +[15:02.59.514] BEGIN CWD +[15:02.59.574] END CWD +[15:02.59.606] BEGIN CWD +[15:02.59.667] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.59.667] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.59.667] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.59.667] END CWD +[15:02.59.681] BEGIN CWD +[15:02.59.742] END CWD +[15:02.59.789] BEGIN CWD +[15:02.59.849] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:02.59.849] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:02.59.849] (SSH-Browser) END VerifySFTPConnection(1) +[15:02.59.849] END CWD +[15:02.59.864] BEGIN CWD +[15:02.59.924] END CWD +[15:02.59.924] BEGIN WMNewTab: 20 +[15:02.59.924] END WMNewTab: 20 +[15:02.59.955] BEGIN CWD +[15:03.00.015] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:03.00.015] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:03.00.015] (SSH-Browser) END VerifySFTPConnection(1) +[15:03.00.015] END CWD +[15:03.00.030] BEGIN CWD +[15:03.00.090] END CWD + + +[15:03.01.500] BEGIN WMNewTab: 20 +[15:03.01.500] END WMNewTab: 20 + + +[15:03.02.912] BEGIN WMNewTab: 20 +[15:03.02.912] END WMNewTab: 20 + + +[15:03.04.320] BEGIN WMNewTab: 20 +[15:03.04.320] END WMNewTab: 20 + + +[15:03.05.732] BEGIN WMNewTab: 20 +[15:03.05.732] END WMNewTab: 20 + + +[15:03.07.147] BEGIN WMNewTab: 20 +[15:03.07.147] END WMNewTab: 20 + + +[15:03.08.571] BEGIN WMNewTab: 20 +[15:03.08.571] END WMNewTab: 20 + + +[15:03.09.985] BEGIN WMNewTab: 20 +[15:03.09.985] END WMNewTab: 20 + + +[15:03.11.399] BEGIN WMNewTab: 20 +[15:03.11.399] END WMNewTab: 20 + + +[15:03.12.815] BEGIN WMNewTab: 20 +[15:03.12.815] END WMNewTab: 20 + + +[15:03.14.227] BEGIN WMNewTab: 20 +[15:03.14.227] END WMNewTab: 20 + + +[15:03.15.646] BEGIN WMNewTab: 20 +[15:03.15.646] END WMNewTab: 20 + + +[15:03.17.057] BEGIN WMNewTab: 20 +[15:03.17.057] END WMNewTab: 20 + + +[15:03.18.468] BEGIN WMNewTab: 20 +[15:03.18.468] END WMNewTab: 20 + + +[15:03.19.886] BEGIN WMNewTab: 20 +[15:03.19.886] END WMNewTab: 20 + + +[15:03.21.305] BEGIN WMNewTab: 20 +[15:03.21.305] END WMNewTab: 20 + + +[15:03.22.743] BEGIN WMNewTab: 20 +[15:03.22.743] END WMNewTab: 20 + + +[15:03.24.145] BEGIN WMNewTab: 20 +[15:03.24.145] END WMNewTab: 20 + + +[15:03.25.563] BEGIN WMNewTab: 20 +[15:03.25.563] END WMNewTab: 20 + + +[15:03.26.973] BEGIN WMNewTab: 20 +[15:03.26.973] END WMNewTab: 20 + + +[15:03.28.200] BEGIN WMNewTab: 0 +[15:03.28.200] WMNewTab: FormClick +[15:03.28.200] WMNewTab: LooseFocus +[15:03.28.201] END WMNewTab: 0 +[15:03.28.312] BEGIN WMNewTab: 0 +[15:03.28.312] WMNewTab: FormClick +[15:03.28.312] WMNewTab: LooseFocus +[15:03.28.314] END WMNewTab: 0 +[15:03.28.386] BEGIN WMNewTab: 20 +[15:03.28.386] END WMNewTab: 20 +[15:03.28.676] BEGIN WMNewTab: 0 +[15:03.28.676] WMNewTab: FormClick +[15:03.28.676] WMNewTab: LooseFocus +[15:03.28.676] END WMNewTab: 0 +[15:03.28.783] BEGIN WMNewTab: 0 +[15:03.28.783] WMNewTab: FormClick +[15:03.28.783] WMNewTab: LooseFocus +[15:03.28.784] END WMNewTab: 0 + +[15:03.29.803] BEGIN WMNewTab: 20 +[15:03.29.803] END WMNewTab: 20 + + +[15:03.31.219] BEGIN WMNewTab: 20 +[15:03.31.219] END WMNewTab: 20 + + +[15:03.32.633] BEGIN WMNewTab: 20 +[15:03.32.633] END WMNewTab: 20 + + +[15:03.34.051] BEGIN WMNewTab: 20 +[15:03.34.051] END WMNewTab: 20 + + +[15:03.35.463] BEGIN WMNewTab: 20 +[15:03.35.463] END WMNewTab: 20 + + +[15:03.36.879] BEGIN WMNewTab: 20 +[15:03.36.879] END WMNewTab: 20 + + +[15:03.38.299] BEGIN WMNewTab: 20 +[15:03.38.299] END WMNewTab: 20 + + +[15:03.39.717] BEGIN WMNewTab: 20 +[15:03.39.717] END WMNewTab: 20 + + +[15:03.41.138] BEGIN WMNewTab: 20 +[15:03.41.138] END WMNewTab: 20 + + +[15:03.42.554] BEGIN WMNewTab: 20 +[15:03.42.554] END WMNewTab: 20 + + +[15:03.43.972] BEGIN WMNewTab: 20 +[15:03.43.972] END WMNewTab: 20 + + +[15:03.45.391] BEGIN WMNewTab: 20 +[15:03.45.391] END WMNewTab: 20 + + +[15:03.46.813] BEGIN WMNewTab: 20 +[15:03.46.813] END WMNewTab: 20 + + +[15:03.48.248] BEGIN WMNewTab: 20 +[15:03.48.248] END WMNewTab: 20 + + +[15:03.49.659] BEGIN WMNewTab: 20 +[15:03.49.659] END WMNewTab: 20 + + +[15:03.51.071] BEGIN WMNewTab: 20 +[15:03.51.071] END WMNewTab: 20 + + +[15:03.52.486] BEGIN WMNewTab: 20 +[15:03.52.486] END WMNewTab: 20 + + +[15:03.53.902] BEGIN WMNewTab: 20 +[15:03.53.902] END WMNewTab: 20 + + +[15:03.55.321] BEGIN WMNewTab: 20 +[15:03.55.321] END WMNewTab: 20 + + +[15:03.56.742] BEGIN WMNewTab: 20 +[15:03.56.742] END WMNewTab: 20 + + +[15:03.58.164] BEGIN WMNewTab: 20 +[15:03.58.164] END WMNewTab: 20 + + +[15:03.59.582] BEGIN WMNewTab: 20 +[15:03.59.582] END WMNewTab: 20 + + +[15:04.00.998] BEGIN WMNewTab: 20 +[15:04.00.998] END WMNewTab: 20 + + +[15:04.02.418] BEGIN WMNewTab: 20 +[15:04.02.418] END WMNewTab: 20 + + +[15:04.03.831] BEGIN WMNewTab: 20 +[15:04.03.831] END WMNewTab: 20 + + +[15:04.05.253] BEGIN WMNewTab: 20 +[15:04.05.253] END WMNewTab: 20 + + +[15:04.06.667] BEGIN WMNewTab: 20 +[15:04.06.668] END WMNewTab: 20 + + +[15:04.08.083] BEGIN WMNewTab: 20 +[15:04.08.083] END WMNewTab: 20 + + +[15:04.09.506] BEGIN WMNewTab: 20 +[15:04.09.506] END WMNewTab: 20 + + +[15:04.10.920] BEGIN WMNewTab: 20 +[15:04.10.920] END WMNewTab: 20 + + +[15:04.12.337] BEGIN WMNewTab: 20 +[15:04.12.337] END WMNewTab: 20 + + +[15:04.13.752] BEGIN WMNewTab: 20 +[15:04.13.752] END WMNewTab: 20 + + +[15:04.15.163] BEGIN WMNewTab: 20 +[15:04.15.163] END WMNewTab: 20 + + +[15:04.16.584] BEGIN WMNewTab: 20 +[15:04.16.584] END WMNewTab: 20 + + +[15:04.17.997] BEGIN WMNewTab: 20 +[15:04.17.997] END WMNewTab: 20 + + +[15:04.19.413] BEGIN WMNewTab: 20 +[15:04.19.413] END WMNewTab: 20 + + +[15:04.20.836] BEGIN WMNewTab: 20 +[15:04.20.836] END WMNewTab: 20 + + +[15:04.22.257] BEGIN WMNewTab: 20 +[15:04.22.257] END WMNewTab: 20 + + +[15:04.23.669] BEGIN WMNewTab: 20 +[15:04.23.669] END WMNewTab: 20 + + +[15:04.25.089] BEGIN WMNewTab: 20 +[15:04.25.089] END WMNewTab: 20 + + +[15:04.26.507] BEGIN WMNewTab: 20 +[15:04.26.507] END WMNewTab: 20 + + +[15:04.27.926] BEGIN WMNewTab: 20 +[15:04.27.926] END WMNewTab: 20 + + +[15:04.29.343] BEGIN WMNewTab: 20 +[15:04.29.343] END WMNewTab: 20 + + +[15:04.30.758] BEGIN WMNewTab: 20 +[15:04.30.758] END WMNewTab: 20 + + +[15:04.32.173] BEGIN WMNewTab: 20 +[15:04.32.173] END WMNewTab: 20 + + +[15:04.33.592] BEGIN WMNewTab: 20 +[15:04.33.592] END WMNewTab: 20 + + +[15:04.35.009] BEGIN WMNewTab: 20 +[15:04.35.009] END WMNewTab: 20 + + +[15:04.36.426] BEGIN WMNewTab: 20 +[15:04.36.426] END WMNewTab: 20 + + +[15:04.37.847] BEGIN WMNewTab: 20 +[15:04.37.847] END WMNewTab: 20 + + +[15:04.39.266] BEGIN WMNewTab: 20 +[15:04.39.266] END WMNewTab: 20 + + +[15:04.40.689] BEGIN WMNewTab: 20 +[15:04.40.689] END WMNewTab: 20 + + +[15:04.42.109] BEGIN WMNewTab: 20 +[15:04.42.109] END WMNewTab: 20 + + +[15:04.43.529] BEGIN WMNewTab: 20 +[15:04.43.529] END WMNewTab: 20 + + +[15:04.44.944] BEGIN WMNewTab: 20 +[15:04.44.944] END WMNewTab: 20 + + +[15:04.46.361] BEGIN WMNewTab: 20 +[15:04.46.361] END WMNewTab: 20 + + +[15:04.47.779] BEGIN WMNewTab: 20 +[15:04.47.779] END WMNewTab: 20 + + +[15:04.49.197] BEGIN WMNewTab: 20 +[15:04.49.197] END WMNewTab: 20 + + +[15:04.50.614] BEGIN WMNewTab: 20 +[15:04.50.614] END WMNewTab: 20 + + +[15:04.52.033] BEGIN WMNewTab: 20 +[15:04.52.033] END WMNewTab: 20 + + +[15:04.53.451] BEGIN WMNewTab: 20 +[15:04.53.451] END WMNewTab: 20 + + +[15:04.54.874] BEGIN WMNewTab: 20 +[15:04.54.874] END WMNewTab: 20 + + +[15:04.56.289] BEGIN WMNewTab: 20 +[15:04.56.289] END WMNewTab: 20 + + +[15:04.57.706] BEGIN WMNewTab: 20 +[15:04.57.706] END WMNewTab: 20 + + +[15:04.59.121] BEGIN WMNewTab: 20 +[15:04.59.121] END WMNewTab: 20 + + +[15:05.00.541] BEGIN WMNewTab: 20 +[15:05.00.541] END WMNewTab: 20 + + +[15:05.01.961] BEGIN WMNewTab: 20 +[15:05.01.961] END WMNewTab: 20 + + +[15:05.03.376] BEGIN WMNewTab: 20 +[15:05.03.376] END WMNewTab: 20 + + +[15:05.04.788] BEGIN WMNewTab: 20 +[15:05.04.788] END WMNewTab: 20 + + +[15:05.06.212] BEGIN WMNewTab: 20 +[15:05.06.212] END WMNewTab: 20 + + +[15:05.07.630] BEGIN WMNewTab: 20 +[15:05.07.630] END WMNewTab: 20 + + +[15:05.09.048] BEGIN WMNewTab: 20 +[15:05.09.048] END WMNewTab: 20 + + +[15:05.10.467] BEGIN WMNewTab: 20 +[15:05.10.467] END WMNewTab: 20 + + +[15:05.11.889] BEGIN WMNewTab: 20 +[15:05.11.889] END WMNewTab: 20 + + +[15:05.13.307] BEGIN WMNewTab: 20 +[15:05.13.307] END WMNewTab: 20 + + +[15:05.14.723] BEGIN WMNewTab: 20 +[15:05.14.723] END WMNewTab: 20 + + +[15:05.16.137] BEGIN WMNewTab: 20 +[15:05.16.137] END WMNewTab: 20 + + +[15:05.17.553] BEGIN WMNewTab: 20 +[15:05.17.553] END WMNewTab: 20 + + +[15:05.18.968] BEGIN WMNewTab: 20 +[15:05.18.968] END WMNewTab: 20 + + +[15:05.20.387] BEGIN WMNewTab: 20 +[15:05.20.387] END WMNewTab: 20 + + +[15:05.21.806] BEGIN WMNewTab: 20 +[15:05.21.806] END WMNewTab: 20 + + +[15:05.23.229] BEGIN WMNewTab: 20 +[15:05.23.229] END WMNewTab: 20 + + +[15:05.24.645] BEGIN WMNewTab: 20 +[15:05.24.645] END WMNewTab: 20 + + +[15:05.26.057] BEGIN WMNewTab: 20 +[15:05.26.057] END WMNewTab: 20 + + +[15:05.27.478] BEGIN WMNewTab: 20 +[15:05.27.478] END WMNewTab: 20 + + +[15:05.28.896] BEGIN WMNewTab: 20 +[15:05.28.896] END WMNewTab: 20 + + +[15:05.30.312] BEGIN WMNewTab: 20 +[15:05.30.312] END WMNewTab: 20 + + +[15:05.31.729] BEGIN WMNewTab: 20 +[15:05.31.729] END WMNewTab: 20 + + +[15:05.33.152] BEGIN WMNewTab: 20 +[15:05.33.152] END WMNewTab: 20 + + +[15:05.34.566] BEGIN WMNewTab: 20 +[15:05.34.566] END WMNewTab: 20 + + +[15:05.35.982] BEGIN WMNewTab: 20 +[15:05.35.982] END WMNewTab: 20 + + +[15:05.37.398] BEGIN WMNewTab: 20 +[15:05.37.398] END WMNewTab: 20 + + +[15:05.38.813] BEGIN WMNewTab: 20 +[15:05.38.813] END WMNewTab: 20 + + +[15:05.40.230] BEGIN WMNewTab: 20 +[15:05.40.230] END WMNewTab: 20 + + +[15:05.41.647] BEGIN WMNewTab: 20 +[15:05.41.647] END WMNewTab: 20 + + +[15:05.43.064] BEGIN WMNewTab: 20 +[15:05.43.064] END WMNewTab: 20 + + +[15:05.44.485] BEGIN WMNewTab: 20 +[15:05.44.485] END WMNewTab: 20 + + +[15:05.45.898] BEGIN WMNewTab: 20 +[15:05.45.898] END WMNewTab: 20 + + +[15:05.47.316] BEGIN WMNewTab: 20 +[15:05.47.316] END WMNewTab: 20 + + +[15:05.48.736] BEGIN WMNewTab: 20 +[15:05.48.736] END WMNewTab: 20 + + +[15:05.50.154] BEGIN WMNewTab: 20 +[15:05.50.154] END WMNewTab: 20 + + +[15:05.51.569] BEGIN WMNewTab: 20 +[15:05.51.569] END WMNewTab: 20 + + +[15:05.52.983] BEGIN WMNewTab: 20 +[15:05.52.983] END WMNewTab: 20 + + +[15:05.54.395] BEGIN WMNewTab: 20 +[15:05.54.395] END WMNewTab: 20 + + +[15:05.55.814] BEGIN WMNewTab: 20 +[15:05.55.814] END WMNewTab: 20 + + +[15:05.57.228] BEGIN WMNewTab: 20 +[15:05.57.228] END WMNewTab: 20 + + +[15:05.58.643] BEGIN WMNewTab: 20 +[15:05.58.643] END WMNewTab: 20 + + +[15:06.00.061] BEGIN WMNewTab: 20 +[15:06.00.061] END WMNewTab: 20 + + +[15:06.01.477] BEGIN WMNewTab: 20 +[15:06.01.477] END WMNewTab: 20 + + +[15:06.02.896] BEGIN WMNewTab: 20 +[15:06.02.896] END WMNewTab: 20 + + +[15:06.04.316] BEGIN WMNewTab: 20 +[15:06.04.316] END WMNewTab: 20 + + +[15:06.05.734] BEGIN WMNewTab: 20 +[15:06.05.734] END WMNewTab: 20 + + +[15:06.07.152] BEGIN WMNewTab: 20 +[15:06.07.152] END WMNewTab: 20 + + +[15:06.08.569] BEGIN WMNewTab: 20 +[15:06.08.569] END WMNewTab: 20 + + +[15:06.09.983] BEGIN WMNewTab: 20 +[15:06.09.983] END WMNewTab: 20 + + +[15:06.11.397] BEGIN WMNewTab: 20 +[15:06.11.397] END WMNewTab: 20 + + +[15:06.12.813] BEGIN WMNewTab: 20 +[15:06.12.813] END WMNewTab: 20 + + +[15:06.14.231] BEGIN WMNewTab: 20 +[15:06.14.231] END WMNewTab: 20 + + +[15:06.15.649] BEGIN WMNewTab: 20 +[15:06.15.649] END WMNewTab: 20 + + +[15:06.17.065] BEGIN WMNewTab: 20 +[15:06.17.065] END WMNewTab: 20 + + +[15:06.18.483] BEGIN WMNewTab: 20 +[15:06.18.483] END WMNewTab: 20 + + +[15:06.19.902] BEGIN WMNewTab: 20 +[15:06.19.902] END WMNewTab: 20 + + +[15:06.21.316] BEGIN WMNewTab: 20 +[15:06.21.316] END WMNewTab: 20 + + +[15:06.22.740] BEGIN WMNewTab: 20 +[15:06.22.740] END WMNewTab: 20 + + +[15:06.24.158] BEGIN WMNewTab: 20 +[15:06.24.158] END WMNewTab: 20 + + +[15:06.25.572] BEGIN WMNewTab: 20 +[15:06.25.572] END WMNewTab: 20 + + +[15:06.26.993] BEGIN WMNewTab: 20 +[15:06.26.993] END WMNewTab: 20 + + +[15:06.28.407] BEGIN WMNewTab: 20 +[15:06.28.407] END WMNewTab: 20 + + +[15:06.29.821] BEGIN WMNewTab: 20 +[15:06.29.821] END WMNewTab: 20 + + +[15:06.31.236] BEGIN WMNewTab: 20 +[15:06.31.236] END WMNewTab: 20 + + +[15:06.32.652] BEGIN WMNewTab: 20 +[15:06.32.652] END WMNewTab: 20 + + +[15:06.34.069] BEGIN WMNewTab: 20 +[15:06.34.069] END WMNewTab: 20 + + +[15:06.35.486] BEGIN WMNewTab: 20 +[15:06.35.486] END WMNewTab: 20 + + +[15:06.36.908] BEGIN WMNewTab: 20 +[15:06.36.908] END WMNewTab: 20 + + +[15:06.38.324] BEGIN WMNewTab: 20 +[15:06.38.324] END WMNewTab: 20 + + +[15:06.39.740] BEGIN WMNewTab: 20 +[15:06.39.740] END WMNewTab: 20 + + +[15:06.41.159] BEGIN WMNewTab: 20 +[15:06.41.159] END WMNewTab: 20 + + +[15:06.42.573] BEGIN WMNewTab: 20 +[15:06.42.573] END WMNewTab: 20 + + +[15:06.43.993] BEGIN WMNewTab: 20 +[15:06.43.993] END WMNewTab: 20 + + +[15:06.45.411] BEGIN WMNewTab: 20 +[15:06.45.411] END WMNewTab: 20 + + +[15:06.46.831] BEGIN WMNewTab: 20 +[15:06.46.831] END WMNewTab: 20 + + +[15:06.48.249] BEGIN WMNewTab: 20 +[15:06.48.249] END WMNewTab: 20 + + +[15:06.49.669] BEGIN WMNewTab: 20 +[15:06.49.669] END WMNewTab: 20 + + +[15:06.51.088] BEGIN WMNewTab: 20 +[15:06.51.088] END WMNewTab: 20 + + +[15:06.52.506] BEGIN WMNewTab: 20 +[15:06.52.506] END WMNewTab: 20 + + +[15:06.53.917] BEGIN WMNewTab: 20 +[15:06.53.917] END WMNewTab: 20 + + +[15:06.55.334] BEGIN WMNewTab: 20 +[15:06.55.334] END WMNewTab: 20 + + +[15:06.56.754] BEGIN WMNewTab: 20 +[15:06.56.754] END WMNewTab: 20 + + +[15:06.58.172] BEGIN WMNewTab: 20 +[15:06.58.172] END WMNewTab: 20 + + +[15:06.59.585] BEGIN WMNewTab: 20 +[15:06.59.585] END WMNewTab: 20 + + +[15:07.00.998] BEGIN WMNewTab: 20 +[15:07.00.998] END WMNewTab: 20 + + +[15:07.02.414] BEGIN WMNewTab: 20 +[15:07.02.414] END WMNewTab: 20 + + +[15:07.03.833] BEGIN WMNewTab: 20 +[15:07.03.833] END WMNewTab: 20 + + +[15:07.05.250] BEGIN WMNewTab: 20 +[15:07.05.250] END WMNewTab: 20 + + +[15:07.06.672] BEGIN WMNewTab: 20 +[15:07.06.672] END WMNewTab: 20 + + +[15:07.08.091] BEGIN WMNewTab: 20 +[15:07.08.091] END WMNewTab: 20 + + +[15:07.09.507] BEGIN WMNewTab: 20 +[15:07.09.507] END WMNewTab: 20 + + +[15:07.10.932] BEGIN WMNewTab: 20 +[15:07.10.932] END WMNewTab: 20 + + +[15:07.12.343] BEGIN WMNewTab: 20 +[15:07.12.343] END WMNewTab: 20 + + +[15:07.13.760] BEGIN WMNewTab: 20 +[15:07.13.760] END WMNewTab: 20 + + +[15:07.15.176] BEGIN WMNewTab: 20 +[15:07.15.176] END WMNewTab: 20 + + +[15:07.16.588] BEGIN WMNewTab: 20 +[15:07.16.588] END WMNewTab: 20 + + +[15:07.18.005] BEGIN WMNewTab: 20 +[15:07.18.005] END WMNewTab: 20 + + +[15:07.19.416] BEGIN WMNewTab: 20 +[15:07.19.416] END WMNewTab: 20 + + +[15:07.20.840] BEGIN WMNewTab: 20 +[15:07.20.840] END WMNewTab: 20 + + +[15:07.22.256] BEGIN WMNewTab: 20 +[15:07.22.256] END WMNewTab: 20 + + +[15:07.23.675] BEGIN WMNewTab: 20 +[15:07.23.675] END WMNewTab: 20 + + +[15:07.25.092] BEGIN WMNewTab: 20 +[15:07.25.092] END WMNewTab: 20 + + +[15:07.26.514] BEGIN WMNewTab: 20 +[15:07.26.514] END WMNewTab: 20 + + +[15:07.27.931] BEGIN WMNewTab: 20 +[15:07.27.931] END WMNewTab: 20 + + +[15:07.29.352] BEGIN WMNewTab: 20 +[15:07.29.352] END WMNewTab: 20 + + +[15:07.30.774] BEGIN WMNewTab: 20 +[15:07.30.774] END WMNewTab: 20 + + +[15:07.32.193] BEGIN WMNewTab: 20 +[15:07.32.193] END WMNewTab: 20 + + +[15:07.33.611] BEGIN WMNewTab: 20 +[15:07.33.611] END WMNewTab: 20 + + +[15:07.35.034] BEGIN WMNewTab: 20 +[15:07.35.034] END WMNewTab: 20 + + +[15:07.36.450] BEGIN WMNewTab: 20 +[15:07.36.450] END WMNewTab: 20 + + +[15:07.37.867] BEGIN WMNewTab: 20 +[15:07.37.867] END WMNewTab: 20 + + +[15:07.39.283] BEGIN WMNewTab: 20 +[15:07.39.283] END WMNewTab: 20 + + +[15:07.40.701] BEGIN WMNewTab: 20 +[15:07.40.701] END WMNewTab: 20 + + +[15:07.42.114] BEGIN WMNewTab: 20 +[15:07.42.114] END WMNewTab: 20 + + +[15:07.43.530] BEGIN WMNewTab: 20 +[15:07.43.530] END WMNewTab: 20 + + +[15:07.44.952] BEGIN WMNewTab: 20 +[15:07.44.952] END WMNewTab: 20 + + +[15:07.46.372] BEGIN WMNewTab: 20 +[15:07.46.372] END WMNewTab: 20 + + +[15:07.47.789] BEGIN WMNewTab: 20 +[15:07.47.789] END WMNewTab: 20 + + +[15:07.49.220] BEGIN WMNewTab: 20 +[15:07.49.220] END WMNewTab: 20 + + +[15:07.50.631] BEGIN WMNewTab: 20 +[15:07.50.631] END WMNewTab: 20 + + +[15:07.52.050] BEGIN WMNewTab: 20 +[15:07.52.050] END WMNewTab: 20 + + +[15:07.53.462] BEGIN WMNewTab: 20 +[15:07.53.462] END WMNewTab: 20 + + +[15:07.54.877] BEGIN WMNewTab: 20 +[15:07.54.877] END WMNewTab: 20 + + +[15:07.56.298] BEGIN WMNewTab: 20 +[15:07.56.298] END WMNewTab: 20 + + +[15:07.57.714] BEGIN WMNewTab: 20 +[15:07.57.714] END WMNewTab: 20 + + +[15:07.59.126] BEGIN WMNewTab: 20 +[15:07.59.126] END WMNewTab: 20 + + +[15:08.00.532] BEGIN WMNewTab: 20 +[15:08.00.532] END WMNewTab: 20 + + +[15:08.01.937] BEGIN WMNewTab: 20 +[15:08.01.937] END WMNewTab: 20 + + +[15:08.03.349] BEGIN WMNewTab: 20 +[15:08.03.349] END WMNewTab: 20 + + +[15:08.04.760] BEGIN WMNewTab: 20 +[15:08.04.760] END WMNewTab: 20 + + +[15:08.06.168] BEGIN WMNewTab: 20 +[15:08.06.168] END WMNewTab: 20 + + +[15:08.07.575] BEGIN WMNewTab: 20 +[15:08.07.575] END WMNewTab: 20 + + +[15:08.08.988] BEGIN WMNewTab: 20 +[15:08.08.988] END WMNewTab: 20 + + +[15:08.10.403] BEGIN WMNewTab: 20 +[15:08.10.403] END WMNewTab: 20 + + +[15:08.11.824] BEGIN WMNewTab: 20 +[15:08.11.824] END WMNewTab: 20 + + +[15:08.13.247] BEGIN WMNewTab: 20 +[15:08.13.247] END WMNewTab: 20 + + +[15:08.14.665] BEGIN WMNewTab: 20 +[15:08.14.665] END WMNewTab: 20 + + +[15:08.16.086] BEGIN WMNewTab: 20 +[15:08.16.086] END WMNewTab: 20 + + +[15:08.17.500] BEGIN WMNewTab: 20 +[15:08.17.500] END WMNewTab: 20 + + +[15:08.18.921] BEGIN WMNewTab: 20 +[15:08.18.921] END WMNewTab: 20 + + +[15:08.20.337] BEGIN WMNewTab: 20 +[15:08.20.337] END WMNewTab: 20 + + +[15:08.21.756] BEGIN WMNewTab: 20 +[15:08.21.756] END WMNewTab: 20 + + +[15:08.23.175] BEGIN WMNewTab: 20 +[15:08.23.175] END WMNewTab: 20 + + +[15:08.24.594] BEGIN WMNewTab: 20 +[15:08.24.595] END WMNewTab: 20 + + +[15:08.26.015] BEGIN WMNewTab: 20 +[15:08.26.015] END WMNewTab: 20 + + +[15:08.27.431] BEGIN WMNewTab: 20 +[15:08.27.431] END WMNewTab: 20 + + +[15:08.28.854] BEGIN WMNewTab: 20 +[15:08.28.854] END WMNewTab: 20 + + +[15:08.30.273] BEGIN WMNewTab: 20 +[15:08.30.273] END WMNewTab: 20 + + +[15:08.31.684] BEGIN WMNewTab: 20 +[15:08.31.684] END WMNewTab: 20 + + +[15:08.33.123] BEGIN WMNewTab: 20 +[15:08.33.123] END WMNewTab: 20 + + +[15:08.34.533] BEGIN WMNewTab: 20 +[15:08.34.533] END WMNewTab: 20 + + +[15:08.35.955] BEGIN WMNewTab: 20 +[15:08.35.955] END WMNewTab: 20 + + +[15:08.37.378] BEGIN WMNewTab: 20 +[15:08.37.378] END WMNewTab: 20 + + +[15:08.38.797] BEGIN WMNewTab: 20 +[15:08.38.797] END WMNewTab: 20 + + +[15:08.40.214] BEGIN WMNewTab: 20 +[15:08.40.214] END WMNewTab: 20 + + +[15:08.41.630] BEGIN WMNewTab: 20 +[15:08.41.630] END WMNewTab: 20 + + +[15:08.43.050] BEGIN WMNewTab: 20 +[15:08.43.050] END WMNewTab: 20 + + +[15:08.44.464] BEGIN WMNewTab: 20 +[15:08.44.464] END WMNewTab: 20 + + +[15:08.45.883] BEGIN WMNewTab: 20 +[15:08.45.883] END WMNewTab: 20 + + +[15:08.47.304] BEGIN WMNewTab: 20 +[15:08.47.304] END WMNewTab: 20 + + +[15:08.48.717] BEGIN WMNewTab: 20 +[15:08.48.717] END WMNewTab: 20 + + +[15:08.50.138] BEGIN WMNewTab: 20 +[15:08.50.138] END WMNewTab: 20 + + +[15:08.51.555] BEGIN WMNewTab: 20 +[15:08.51.555] END WMNewTab: 20 + + +[15:08.52.971] BEGIN WMNewTab: 20 +[15:08.52.971] END WMNewTab: 20 + + +[15:08.54.386] BEGIN WMNewTab: 20 +[15:08.54.386] END WMNewTab: 20 + + +[15:08.55.804] BEGIN WMNewTab: 20 +[15:08.55.804] END WMNewTab: 20 + + +[15:08.57.226] BEGIN WMNewTab: 20 +[15:08.57.226] END WMNewTab: 20 + + +[15:08.58.652] BEGIN WMNewTab: 20 +[15:08.58.652] END WMNewTab: 20 + + +[15:09.00.068] BEGIN WMNewTab: 20 +[15:09.00.068] END WMNewTab: 20 + + +[15:09.01.479] BEGIN WMNewTab: 20 +[15:09.01.479] END WMNewTab: 20 + + +[15:09.02.894] BEGIN WMNewTab: 20 +[15:09.02.894] END WMNewTab: 20 + + +[15:09.04.312] BEGIN WMNewTab: 20 +[15:09.04.312] END WMNewTab: 20 + + +[15:09.05.726] BEGIN WMNewTab: 20 +[15:09.05.726] END WMNewTab: 20 + + +[15:09.07.140] BEGIN WMNewTab: 20 +[15:09.07.140] END WMNewTab: 20 + + +[15:09.08.554] BEGIN WMNewTab: 20 +[15:09.08.554] END WMNewTab: 20 + + +[15:09.09.974] BEGIN WMNewTab: 20 +[15:09.09.974] END WMNewTab: 20 + + +[15:09.11.396] BEGIN WMNewTab: 20 +[15:09.11.396] END WMNewTab: 20 + + +[15:09.12.815] BEGIN WMNewTab: 20 +[15:09.12.815] END WMNewTab: 20 + + +[15:09.14.231] BEGIN WMNewTab: 20 +[15:09.14.231] END WMNewTab: 20 + + +[15:09.15.649] BEGIN WMNewTab: 20 +[15:09.15.649] END WMNewTab: 20 + + +[15:09.17.069] BEGIN WMNewTab: 20 +[15:09.17.069] END WMNewTab: 20 + + +[15:09.18.482] BEGIN WMNewTab: 20 +[15:09.18.482] END WMNewTab: 20 + + +[15:09.19.900] BEGIN WMNewTab: 20 +[15:09.19.900] END WMNewTab: 20 + + +[15:09.21.317] BEGIN WMNewTab: 20 +[15:09.21.317] END WMNewTab: 20 + + +[15:09.22.736] BEGIN WMNewTab: 20 +[15:09.22.736] END WMNewTab: 20 + + +[15:09.24.157] BEGIN WMNewTab: 20 +[15:09.24.157] END WMNewTab: 20 + + +[15:09.25.579] BEGIN WMNewTab: 20 +[15:09.25.579] END WMNewTab: 20 + + +[15:09.26.996] BEGIN WMNewTab: 20 +[15:09.26.996] END WMNewTab: 20 + + +[15:09.28.417] BEGIN WMNewTab: 20 +[15:09.28.417] END WMNewTab: 20 + + +[15:09.29.835] BEGIN WMNewTab: 20 +[15:09.29.835] END WMNewTab: 20 + + +[15:09.31.253] BEGIN WMNewTab: 20 +[15:09.31.253] END WMNewTab: 20 + + +[15:09.32.675] BEGIN WMNewTab: 20 +[15:09.32.675] END WMNewTab: 20 + + +[15:09.34.095] BEGIN WMNewTab: 20 +[15:09.34.095] END WMNewTab: 20 + + +[15:09.35.512] BEGIN WMNewTab: 20 +[15:09.35.512] END WMNewTab: 20 + + +[15:09.36.930] BEGIN WMNewTab: 20 +[15:09.36.930] END WMNewTab: 20 + + +[15:09.38.348] BEGIN WMNewTab: 20 +[15:09.38.348] END WMNewTab: 20 + + +[15:09.39.766] BEGIN WMNewTab: 20 +[15:09.39.766] END WMNewTab: 20 + + +[15:09.41.185] BEGIN WMNewTab: 20 +[15:09.41.185] END WMNewTab: 20 + + +[15:09.42.606] BEGIN WMNewTab: 20 +[15:09.42.606] END WMNewTab: 20 + + +[15:09.44.024] BEGIN WMNewTab: 20 +[15:09.44.024] END WMNewTab: 20 + + +[15:09.45.436] BEGIN WMNewTab: 20 +[15:09.45.436] END WMNewTab: 20 + + +[15:09.46.855] BEGIN WMNewTab: 20 +[15:09.46.855] END WMNewTab: 20 + + +[15:09.48.273] BEGIN WMNewTab: 20 +[15:09.48.273] END WMNewTab: 20 + + +[15:09.49.697] BEGIN WMNewTab: 20 +[15:09.49.697] END WMNewTab: 20 + + +[15:09.51.117] BEGIN WMNewTab: 20 +[15:09.51.117] END WMNewTab: 20 + + +[15:09.52.532] BEGIN WMNewTab: 20 +[15:09.52.532] END WMNewTab: 20 + + +[15:09.53.946] BEGIN WMNewTab: 20 +[15:09.53.946] END WMNewTab: 20 + + +[15:09.55.354] BEGIN WMNewTab: 20 +[15:09.55.354] END WMNewTab: 20 + + +[15:09.56.773] BEGIN WMNewTab: 20 +[15:09.56.773] END WMNewTab: 20 + + +[15:09.58.191] BEGIN WMNewTab: 20 +[15:09.58.191] END WMNewTab: 20 + + +[15:09.59.612] BEGIN WMNewTab: 20 +[15:09.59.612] END WMNewTab: 20 + + +[15:10.01.030] BEGIN WMNewTab: 20 +[15:10.01.030] END WMNewTab: 20 + + +[15:10.02.445] BEGIN WMNewTab: 20 +[15:10.02.445] END WMNewTab: 20 + + +[15:10.03.869] BEGIN WMNewTab: 20 +[15:10.03.869] END WMNewTab: 20 + + +[15:10.05.285] BEGIN WMNewTab: 20 +[15:10.05.285] END WMNewTab: 20 + + +[15:10.06.704] BEGIN WMNewTab: 20 +[15:10.06.704] END WMNewTab: 20 + + +[15:10.08.120] BEGIN WMNewTab: 20 +[15:10.08.120] END WMNewTab: 20 + + +[15:10.09.543] BEGIN WMNewTab: 20 +[15:10.09.543] END WMNewTab: 20 + + +[15:10.10.964] BEGIN WMNewTab: 20 +[15:10.10.964] END WMNewTab: 20 + + +[15:10.12.385] BEGIN WMNewTab: 20 +[15:10.12.385] END WMNewTab: 20 + + +[15:10.13.798] BEGIN WMNewTab: 20 +[15:10.13.798] END WMNewTab: 20 + + +[15:10.15.213] BEGIN WMNewTab: 20 +[15:10.15.213] END WMNewTab: 20 + + +[15:10.16.627] BEGIN WMNewTab: 20 +[15:10.16.627] END WMNewTab: 20 + + +[15:10.18.046] BEGIN WMNewTab: 20 +[15:10.18.046] END WMNewTab: 20 + + +[15:10.19.467] BEGIN WMNewTab: 20 +[15:10.19.467] END WMNewTab: 20 + + +[15:10.20.887] BEGIN WMNewTab: 20 +[15:10.20.887] END WMNewTab: 20 + + +[15:10.22.326] BEGIN WMNewTab: 20 +[15:10.22.326] END WMNewTab: 20 + + +[15:10.23.748] BEGIN WMNewTab: 20 +[15:10.23.748] END WMNewTab: 20 + + +[15:10.25.162] BEGIN WMNewTab: 20 +[15:10.25.162] END WMNewTab: 20 + + +[15:10.26.575] BEGIN WMNewTab: 20 +[15:10.26.575] END WMNewTab: 20 + + +[15:10.27.992] BEGIN WMNewTab: 20 +[15:10.27.992] END WMNewTab: 20 + + +[15:10.29.411] BEGIN WMNewTab: 20 +[15:10.29.411] END WMNewTab: 20 + + +[15:10.30.828] BEGIN WMNewTab: 20 +[15:10.30.828] END WMNewTab: 20 + + +[15:10.32.250] BEGIN WMNewTab: 20 +[15:10.32.250] END WMNewTab: 20 + + +[15:10.33.670] BEGIN WMNewTab: 20 +[15:10.33.670] END WMNewTab: 20 + + +[15:10.35.079] BEGIN WMNewTab: 20 +[15:10.35.079] END WMNewTab: 20 + + +[15:10.36.501] BEGIN WMNewTab: 20 +[15:10.36.501] END WMNewTab: 20 + + +[15:10.37.921] BEGIN WMNewTab: 20 +[15:10.37.921] END WMNewTab: 20 + + +[15:10.39.336] BEGIN WMNewTab: 20 +[15:10.39.336] END WMNewTab: 20 + + +[15:10.40.757] BEGIN WMNewTab: 20 +[15:10.40.757] END WMNewTab: 20 + + +[15:10.42.176] BEGIN WMNewTab: 20 +[15:10.42.176] END WMNewTab: 20 + + +[15:10.43.593] BEGIN WMNewTab: 20 +[15:10.43.593] END WMNewTab: 20 + + +[15:10.45.009] BEGIN WMNewTab: 20 +[15:10.45.009] END WMNewTab: 20 + + +[15:10.46.424] BEGIN WMNewTab: 20 +[15:10.46.424] END WMNewTab: 20 + + +[15:10.47.854] BEGIN WMNewTab: 20 +[15:10.47.854] END WMNewTab: 20 + + +[15:10.49.269] BEGIN WMNewTab: 20 +[15:10.49.269] END WMNewTab: 20 + + +[15:10.50.685] BEGIN WMNewTab: 20 +[15:10.50.685] END WMNewTab: 20 + + +[15:10.52.102] BEGIN WMNewTab: 20 +[15:10.52.102] END WMNewTab: 20 + + +[15:10.53.516] BEGIN WMNewTab: 20 +[15:10.53.516] END WMNewTab: 20 + + +[15:10.54.934] BEGIN WMNewTab: 20 +[15:10.54.934] END WMNewTab: 20 + + +[15:10.56.350] BEGIN WMNewTab: 20 +[15:10.56.350] END WMNewTab: 20 + + +[15:10.57.766] BEGIN WMNewTab: 20 +[15:10.57.766] END WMNewTab: 20 + + +[15:10.59.186] BEGIN WMNewTab: 20 +[15:10.59.186] END WMNewTab: 20 + + +[15:11.00.598] BEGIN WMNewTab: 20 +[15:11.00.598] END WMNewTab: 20 + + +[15:11.02.020] BEGIN WMNewTab: 20 +[15:11.02.020] END WMNewTab: 20 + + +[15:11.03.440] BEGIN WMNewTab: 20 +[15:11.03.440] END WMNewTab: 20 + + +[15:11.04.860] BEGIN WMNewTab: 20 +[15:11.04.860] END WMNewTab: 20 + + +[15:11.06.279] BEGIN WMNewTab: 20 +[15:11.06.279] END WMNewTab: 20 + + +[15:11.07.699] BEGIN WMNewTab: 20 +[15:11.07.699] END WMNewTab: 20 + + +[15:11.09.111] BEGIN WMNewTab: 20 +[15:11.09.111] END WMNewTab: 20 + + +[15:11.10.531] BEGIN WMNewTab: 20 +[15:11.10.531] END WMNewTab: 20 + + +[15:11.11.952] BEGIN WMNewTab: 20 +[15:11.11.952] END WMNewTab: 20 + + +[15:11.13.368] BEGIN WMNewTab: 20 +[15:11.13.368] END WMNewTab: 20 + + +[15:11.14.784] BEGIN WMNewTab: 20 +[15:11.14.784] END WMNewTab: 20 + + +[15:11.16.201] BEGIN WMNewTab: 20 +[15:11.16.201] END WMNewTab: 20 + + +[15:11.17.615] BEGIN WMNewTab: 20 +[15:11.17.616] END WMNewTab: 20 + + +[15:11.19.034] BEGIN WMNewTab: 20 +[15:11.19.034] END WMNewTab: 20 + + +[15:11.20.455] BEGIN WMNewTab: 20 +[15:11.20.455] END WMNewTab: 20 + + +[15:11.21.875] BEGIN WMNewTab: 20 +[15:11.21.875] END WMNewTab: 20 + + +[15:11.23.292] BEGIN WMNewTab: 20 +[15:11.23.292] END WMNewTab: 20 + + +[15:11.24.706] BEGIN WMNewTab: 20 +[15:11.24.706] END WMNewTab: 20 + + +[15:11.26.125] BEGIN WMNewTab: 20 +[15:11.26.125] END WMNewTab: 20 + + +[15:11.27.545] BEGIN WMNewTab: 20 +[15:11.27.545] END WMNewTab: 20 + + +[15:11.28.963] BEGIN WMNewTab: 20 +[15:11.28.963] END WMNewTab: 20 + + +[15:11.30.378] BEGIN WMNewTab: 20 +[15:11.30.378] END WMNewTab: 20 + + +[15:11.31.800] BEGIN WMNewTab: 20 +[15:11.31.800] END WMNewTab: 20 + + +[15:11.33.213] BEGIN WMNewTab: 20 +[15:11.33.213] END WMNewTab: 20 + + +[15:11.34.633] BEGIN WMNewTab: 20 +[15:11.34.633] END WMNewTab: 20 + + +[15:11.36.046] BEGIN WMNewTab: 20 +[15:11.36.046] END WMNewTab: 20 + + +[15:11.37.464] BEGIN WMNewTab: 20 +[15:11.37.464] END WMNewTab: 20 + + +[15:11.38.882] BEGIN WMNewTab: 20 +[15:11.38.882] END WMNewTab: 20 + + +[15:11.40.305] BEGIN WMNewTab: 20 +[15:11.40.305] END WMNewTab: 20 + + +[15:11.41.722] BEGIN WMNewTab: 20 +[15:11.41.722] END WMNewTab: 20 + + +[15:11.43.136] BEGIN WMNewTab: 20 +[15:11.43.136] END WMNewTab: 20 + + +[15:11.44.555] BEGIN WMNewTab: 20 +[15:11.44.555] END WMNewTab: 20 + + +[15:11.45.971] BEGIN WMNewTab: 20 +[15:11.45.971] END WMNewTab: 20 + + +[15:11.47.384] BEGIN WMNewTab: 20 +[15:11.47.384] END WMNewTab: 20 + + +[15:11.48.800] BEGIN WMNewTab: 20 +[15:11.48.800] END WMNewTab: 20 + + +[15:11.50.215] BEGIN WMNewTab: 20 +[15:11.50.215] END WMNewTab: 20 + + +[15:11.51.632] BEGIN WMNewTab: 20 +[15:11.51.632] END WMNewTab: 20 + + +[15:11.53.048] BEGIN WMNewTab: 20 +[15:11.53.048] END WMNewTab: 20 + + +[15:11.54.470] BEGIN WMNewTab: 20 +[15:11.54.470] END WMNewTab: 20 + + +[15:11.55.889] BEGIN WMNewTab: 20 +[15:11.55.889] END WMNewTab: 20 + + +[15:11.57.303] BEGIN WMNewTab: 20 +[15:11.57.303] END WMNewTab: 20 + + +[15:11.58.714] BEGIN WMNewTab: 20 +[15:11.58.714] END WMNewTab: 20 + + +[15:12.00.129] BEGIN WMNewTab: 20 +[15:12.00.129] END WMNewTab: 20 + + +[15:12.01.550] BEGIN WMNewTab: 20 +[15:12.01.550] END WMNewTab: 20 + + +[15:12.02.971] BEGIN WMNewTab: 20 +[15:12.02.971] END WMNewTab: 20 + + +[15:12.04.399] BEGIN WMNewTab: 20 +[15:12.04.399] END WMNewTab: 20 + + +[15:12.05.797] BEGIN WMNewTab: 20 +[15:12.05.797] END WMNewTab: 20 + + +[15:12.07.202] BEGIN WMNewTab: 20 +[15:12.07.202] END WMNewTab: 20 + + +[15:12.08.616] BEGIN WMNewTab: 20 +[15:12.08.616] END WMNewTab: 20 + + +[15:12.10.029] BEGIN WMNewTab: 20 +[15:12.10.029] END WMNewTab: 20 + + +[15:12.11.450] BEGIN WMNewTab: 20 +[15:12.11.450] END WMNewTab: 20 + + +[15:12.12.867] BEGIN WMNewTab: 20 +[15:12.12.867] END WMNewTab: 20 + + +[15:12.14.283] BEGIN WMNewTab: 20 +[15:12.14.283] END WMNewTab: 20 + + +[15:12.15.700] BEGIN WMNewTab: 20 +[15:12.15.700] END WMNewTab: 20 + + +[15:12.17.128] BEGIN WMNewTab: 20 +[15:12.17.128] END WMNewTab: 20 + + +[15:12.18.543] BEGIN WMNewTab: 20 +[15:12.18.543] END WMNewTab: 20 + + +[15:12.19.968] BEGIN WMNewTab: 20 +[15:12.19.968] END WMNewTab: 20 + + +[15:12.21.384] BEGIN WMNewTab: 20 +[15:12.21.384] END WMNewTab: 20 + + +[15:12.22.796] BEGIN WMNewTab: 20 +[15:12.22.796] END WMNewTab: 20 + + +[15:12.24.214] BEGIN WMNewTab: 20 +[15:12.24.214] END WMNewTab: 20 + + +[15:12.25.634] BEGIN WMNewTab: 20 +[15:12.25.634] END WMNewTab: 20 + + +[15:12.27.052] BEGIN WMNewTab: 20 +[15:12.27.052] END WMNewTab: 20 + + +[15:12.28.475] BEGIN WMNewTab: 20 +[15:12.28.475] END WMNewTab: 20 + + +[15:12.29.894] BEGIN WMNewTab: 20 +[15:12.29.894] END WMNewTab: 20 + + +[15:12.31.312] BEGIN WMNewTab: 20 +[15:12.31.312] END WMNewTab: 20 + + +[15:12.32.727] BEGIN WMNewTab: 20 +[15:12.32.727] END WMNewTab: 20 + + +[15:12.34.141] BEGIN WMNewTab: 20 +[15:12.34.141] END WMNewTab: 20 + + +[15:12.35.558] BEGIN WMNewTab: 20 +[15:12.35.558] END WMNewTab: 20 + + +[15:12.36.973] BEGIN WMNewTab: 20 +[15:12.36.973] END WMNewTab: 20 + + +[15:12.38.393] BEGIN WMNewTab: 20 +[15:12.38.393] END WMNewTab: 20 + + +[15:12.39.806] BEGIN WMNewTab: 20 +[15:12.39.806] END WMNewTab: 20 + + +[15:12.41.217] BEGIN WMNewTab: 20 +[15:12.41.217] END WMNewTab: 20 + + +[15:12.42.637] BEGIN WMNewTab: 20 +[15:12.42.637] END WMNewTab: 20 + + +[15:12.44.051] BEGIN WMNewTab: 20 +[15:12.44.051] END WMNewTab: 20 + + +[15:12.45.462] BEGIN WMNewTab: 20 +[15:12.45.462] END WMNewTab: 20 + + +[15:12.46.885] BEGIN WMNewTab: 20 +[15:12.46.885] END WMNewTab: 20 + + +[15:12.48.310] BEGIN WMNewTab: 20 +[15:12.48.310] END WMNewTab: 20 + + +[15:12.49.719] BEGIN WMNewTab: 20 +[15:12.49.719] END WMNewTab: 20 + + +[15:12.51.142] BEGIN WMNewTab: 20 +[15:12.51.142] END WMNewTab: 20 + + +[15:12.52.561] BEGIN WMNewTab: 20 +[15:12.52.561] END WMNewTab: 20 + + +[15:12.53.983] BEGIN WMNewTab: 20 +[15:12.53.983] END WMNewTab: 20 + + +[15:12.55.404] BEGIN WMNewTab: 20 +[15:12.55.404] END WMNewTab: 20 + + +[15:12.56.828] BEGIN WMNewTab: 20 +[15:12.56.828] END WMNewTab: 20 + + +[15:12.58.249] BEGIN WMNewTab: 20 +[15:12.58.249] END WMNewTab: 20 + + +[15:12.59.668] BEGIN WMNewTab: 20 +[15:12.59.668] END WMNewTab: 20 + + +[15:13.01.076] BEGIN WMNewTab: 20 +[15:13.01.076] END WMNewTab: 20 + + +[15:13.02.490] BEGIN WMNewTab: 20 +[15:13.02.490] END WMNewTab: 20 + + +[15:13.03.898] BEGIN WMNewTab: 20 +[15:13.03.898] END WMNewTab: 20 + + +[15:13.05.304] BEGIN WMNewTab: 20 +[15:13.05.304] END WMNewTab: 20 + + +[15:13.06.719] BEGIN WMNewTab: 20 +[15:13.06.719] END WMNewTab: 20 + + +[15:13.08.129] BEGIN WMNewTab: 20 +[15:13.08.129] END WMNewTab: 20 + + +[15:13.09.540] BEGIN WMNewTab: 20 +[15:13.09.540] END WMNewTab: 20 + + +[15:13.10.951] BEGIN WMNewTab: 20 +[15:13.10.951] END WMNewTab: 20 + + +[15:13.12.372] BEGIN WMNewTab: 20 +[15:13.12.372] END WMNewTab: 20 + + +[15:13.13.793] BEGIN WMNewTab: 20 +[15:13.13.793] END WMNewTab: 20 + + +[15:13.15.211] BEGIN WMNewTab: 20 +[15:13.15.211] END WMNewTab: 20 + + +[15:13.16.633] BEGIN WMNewTab: 20 +[15:13.16.633] END WMNewTab: 20 + + +[15:13.18.055] BEGIN WMNewTab: 20 +[15:13.18.055] END WMNewTab: 20 + + +[15:13.19.473] BEGIN WMNewTab: 20 +[15:13.19.473] END WMNewTab: 20 + + +[15:13.20.892] BEGIN WMNewTab: 20 +[15:13.20.892] END WMNewTab: 20 + + +[15:13.22.314] BEGIN WMNewTab: 20 +[15:13.22.314] END WMNewTab: 20 + + +[15:13.23.728] BEGIN WMNewTab: 20 +[15:13.23.728] END WMNewTab: 20 + + +[15:13.25.141] BEGIN WMNewTab: 20 +[15:13.25.141] END WMNewTab: 20 + + +[15:13.26.558] BEGIN WMNewTab: 20 +[15:13.26.558] END WMNewTab: 20 + + +[15:13.27.970] BEGIN WMNewTab: 20 +[15:13.27.970] END WMNewTab: 20 + + +[15:13.29.381] BEGIN WMNewTab: 20 +[15:13.29.381] END WMNewTab: 20 + + +[15:13.30.803] BEGIN WMNewTab: 20 +[15:13.30.803] END WMNewTab: 20 + + +[15:13.32.215] BEGIN WMNewTab: 20 +[15:13.32.215] END WMNewTab: 20 + + +[15:13.33.633] BEGIN WMNewTab: 20 +[15:13.33.633] END WMNewTab: 20 + + +[15:13.35.054] BEGIN WMNewTab: 20 +[15:13.35.054] END WMNewTab: 20 + + +[15:13.36.470] BEGIN WMNewTab: 20 +[15:13.36.470] END WMNewTab: 20 + + +[15:13.37.889] BEGIN WMNewTab: 20 +[15:13.37.889] END WMNewTab: 20 + + +[15:13.39.310] BEGIN WMNewTab: 20 +[15:13.39.310] END WMNewTab: 20 + + +[15:13.40.726] BEGIN WMNewTab: 20 +[15:13.40.726] END WMNewTab: 20 + + +[15:13.42.142] BEGIN WMNewTab: 20 +[15:13.42.142] END WMNewTab: 20 + + +[15:13.43.559] BEGIN WMNewTab: 20 +[15:13.43.559] END WMNewTab: 20 + + +[15:13.44.979] BEGIN WMNewTab: 20 +[15:13.44.979] END WMNewTab: 20 + + +[15:13.46.400] BEGIN WMNewTab: 20 +[15:13.46.400] END WMNewTab: 20 + + +[15:13.47.814] BEGIN WMNewTab: 20 +[15:13.47.814] END WMNewTab: 20 + + +[15:13.49.226] BEGIN WMNewTab: 20 +[15:13.49.226] END WMNewTab: 20 + + +[15:13.50.640] BEGIN WMNewTab: 20 +[15:13.50.640] END WMNewTab: 20 + + +[15:13.52.054] BEGIN WMNewTab: 20 +[15:13.52.054] END WMNewTab: 20 + + +[15:13.53.475] BEGIN WMNewTab: 20 +[15:13.53.475] END WMNewTab: 20 + + +[15:13.54.890] BEGIN WMNewTab: 20 +[15:13.54.890] END WMNewTab: 20 + + +[15:13.56.312] BEGIN WMNewTab: 20 +[15:13.56.312] END WMNewTab: 20 + + +[15:13.57.730] BEGIN WMNewTab: 20 +[15:13.57.730] END WMNewTab: 20 + + +[15:13.59.153] BEGIN WMNewTab: 20 +[15:13.59.153] END WMNewTab: 20 + + +[15:14.00.570] BEGIN WMNewTab: 20 +[15:14.00.570] END WMNewTab: 20 + + +[15:14.01.986] BEGIN WMNewTab: 20 +[15:14.01.986] END WMNewTab: 20 + + +[15:14.03.406] BEGIN WMNewTab: 20 +[15:14.03.406] END WMNewTab: 20 + + +[15:14.04.825] BEGIN WMNewTab: 20 +[15:14.04.825] END WMNewTab: 20 + + +[15:14.06.238] BEGIN WMNewTab: 20 +[15:14.06.238] END WMNewTab: 20 + + +[15:14.07.655] BEGIN WMNewTab: 20 +[15:14.07.655] END WMNewTab: 20 + + +[15:14.09.070] BEGIN WMNewTab: 20 +[15:14.09.070] END WMNewTab: 20 + + +[15:14.10.489] BEGIN WMNewTab: 20 +[15:14.10.489] END WMNewTab: 20 + + +[15:14.11.908] BEGIN WMNewTab: 20 +[15:14.11.908] END WMNewTab: 20 + + +[15:14.13.329] BEGIN WMNewTab: 20 +[15:14.13.329] END WMNewTab: 20 + + +[15:14.14.740] BEGIN WMNewTab: 20 +[15:14.14.740] END WMNewTab: 20 + + +[15:14.16.159] BEGIN WMNewTab: 20 +[15:14.16.159] END WMNewTab: 20 + + +[15:14.17.583] BEGIN WMNewTab: 20 +[15:14.17.583] END WMNewTab: 20 + + +[15:14.18.997] BEGIN WMNewTab: 20 +[15:14.18.997] END WMNewTab: 20 + + +[15:14.20.422] BEGIN WMNewTab: 20 +[15:14.20.422] END WMNewTab: 20 + + +[15:14.21.840] BEGIN WMNewTab: 20 +[15:14.21.840] END WMNewTab: 20 + + +[15:14.23.252] BEGIN WMNewTab: 20 +[15:14.23.252] END WMNewTab: 20 + + +[15:14.24.672] BEGIN WMNewTab: 20 +[15:14.24.672] END WMNewTab: 20 + + +[15:14.26.087] BEGIN WMNewTab: 20 +[15:14.26.087] END WMNewTab: 20 + + +[15:14.27.506] BEGIN WMNewTab: 20 +[15:14.27.506] END WMNewTab: 20 + + +[15:14.28.927] BEGIN WMNewTab: 20 +[15:14.28.927] END WMNewTab: 20 + + +[15:14.30.370] BEGIN WMNewTab: 20 +[15:14.30.370] END WMNewTab: 20 + + +[15:14.31.777] BEGIN WMNewTab: 20 +[15:14.31.777] END WMNewTab: 20 + + +[15:14.33.195] BEGIN WMNewTab: 20 +[15:14.33.195] END WMNewTab: 20 + + +[15:14.34.615] BEGIN WMNewTab: 20 +[15:14.34.615] END WMNewTab: 20 + + +[15:14.36.030] BEGIN WMNewTab: 20 +[15:14.36.030] END WMNewTab: 20 + + +[15:14.37.448] BEGIN WMNewTab: 20 +[15:14.37.448] END WMNewTab: 20 + + +[15:14.38.866] BEGIN WMNewTab: 20 +[15:14.38.866] END WMNewTab: 20 + + +[15:14.40.276] BEGIN WMNewTab: 20 +[15:14.40.276] END WMNewTab: 20 + + +[15:14.41.695] BEGIN WMNewTab: 20 +[15:14.41.695] END WMNewTab: 20 + + +[15:14.43.110] BEGIN WMNewTab: 20 +[15:14.43.110] END WMNewTab: 20 + + +[15:14.44.528] BEGIN WMNewTab: 20 +[15:14.44.528] END WMNewTab: 20 + + +[15:14.45.949] BEGIN WMNewTab: 20 +[15:14.45.949] END WMNewTab: 20 + + +[15:14.47.363] BEGIN WMNewTab: 20 +[15:14.47.363] END WMNewTab: 20 + + +[15:14.48.775] BEGIN WMNewTab: 20 +[15:14.48.775] END WMNewTab: 20 + + +[15:14.50.189] BEGIN WMNewTab: 20 +[15:14.50.189] END WMNewTab: 20 + + +[15:14.51.605] BEGIN WMNewTab: 20 +[15:14.51.605] END WMNewTab: 20 + + +[15:14.53.021] BEGIN WMNewTab: 20 +[15:14.53.021] END WMNewTab: 20 + + +[15:14.54.443] BEGIN WMNewTab: 20 +[15:14.54.443] END WMNewTab: 20 + + +[15:14.55.889] BEGIN WMNewTab: 20 +[15:14.55.889] END WMNewTab: 20 + + +[15:14.57.296] BEGIN WMNewTab: 20 +[15:14.57.297] END WMNewTab: 20 + + +[15:14.58.715] BEGIN WMNewTab: 20 +[15:14.58.715] END WMNewTab: 20 + + +[15:15.00.131] BEGIN WMNewTab: 20 +[15:15.00.131] END WMNewTab: 20 + + +[15:15.01.550] BEGIN WMNewTab: 20 +[15:15.01.550] END WMNewTab: 20 + + +[15:15.02.969] BEGIN WMNewTab: 20 +[15:15.02.969] END WMNewTab: 20 + + +[15:15.04.382] BEGIN WMNewTab: 20 +[15:15.04.382] END WMNewTab: 20 + + +[15:15.05.796] BEGIN WMNewTab: 20 +[15:15.05.796] END WMNewTab: 20 + + +[15:15.07.217] BEGIN WMNewTab: 20 +[15:15.07.217] END WMNewTab: 20 + + +[15:15.08.631] BEGIN WMNewTab: 20 +[15:15.08.631] END WMNewTab: 20 + + +[15:15.10.053] BEGIN WMNewTab: 20 +[15:15.10.053] END WMNewTab: 20 + + +[15:15.11.471] BEGIN WMNewTab: 20 +[15:15.11.471] END WMNewTab: 20 + + +[15:15.12.885] BEGIN WMNewTab: 20 +[15:15.12.885] END WMNewTab: 20 + + +[15:15.14.307] BEGIN WMNewTab: 20 +[15:15.14.307] END WMNewTab: 20 + + +[15:15.15.722] BEGIN WMNewTab: 20 +[15:15.15.722] END WMNewTab: 20 + + +[15:15.17.137] BEGIN WMNewTab: 20 +[15:15.17.137] END WMNewTab: 20 + + +[15:15.18.555] BEGIN WMNewTab: 20 +[15:15.18.555] END WMNewTab: 20 + + +[15:15.19.972] BEGIN WMNewTab: 20 +[15:15.19.972] END WMNewTab: 20 + + +[15:15.21.414] BEGIN WMNewTab: 20 +[15:15.21.414] END WMNewTab: 20 + + +[15:15.22.819] BEGIN WMNewTab: 20 +[15:15.22.819] END WMNewTab: 20 + + +[15:15.24.242] BEGIN WMNewTab: 20 +[15:15.24.242] END WMNewTab: 20 + + +[15:15.25.659] BEGIN WMNewTab: 20 +[15:15.25.659] END WMNewTab: 20 + + +[15:15.27.078] BEGIN WMNewTab: 20 +[15:15.27.078] END WMNewTab: 20 + + +[15:15.28.499] BEGIN WMNewTab: 20 +[15:15.28.499] END WMNewTab: 20 + + +[15:15.29.913] BEGIN WMNewTab: 20 +[15:15.29.913] END WMNewTab: 20 + + +[15:15.31.333] BEGIN WMNewTab: 20 +[15:15.31.333] END WMNewTab: 20 + + +[15:15.32.749] BEGIN WMNewTab: 20 +[15:15.32.749] END WMNewTab: 20 + + +[15:15.34.163] BEGIN WMNewTab: 20 +[15:15.34.163] END WMNewTab: 20 + + +[15:15.35.580] BEGIN WMNewTab: 20 +[15:15.35.580] END WMNewTab: 20 + + +[15:15.36.999] BEGIN WMNewTab: 20 +[15:15.36.999] END WMNewTab: 20 + + +[15:15.38.420] BEGIN WMNewTab: 20 +[15:15.38.420] END WMNewTab: 20 + + +[15:15.39.839] BEGIN WMNewTab: 20 +[15:15.39.839] END WMNewTab: 20 + + +[15:15.41.253] BEGIN WMNewTab: 20 +[15:15.41.253] END WMNewTab: 20 + + +[15:15.42.670] BEGIN WMNewTab: 20 +[15:15.42.670] END WMNewTab: 20 + + +[15:15.44.085] BEGIN WMNewTab: 20 +[15:15.44.085] END WMNewTab: 20 + + +[15:15.45.507] BEGIN WMNewTab: 20 +[15:15.45.507] END WMNewTab: 20 + + +[15:15.46.940] BEGIN WMNewTab: 20 +[15:15.46.940] END WMNewTab: 20 + + +[15:15.48.354] BEGIN WMNewTab: 20 +[15:15.48.354] END WMNewTab: 20 + + +[15:15.49.769] BEGIN WMNewTab: 20 +[15:15.49.769] END WMNewTab: 20 + + +[15:15.51.187] BEGIN WMNewTab: 20 +[15:15.51.187] END WMNewTab: 20 + + +[15:15.52.607] BEGIN WMNewTab: 20 +[15:15.52.607] END WMNewTab: 20 + + +[15:15.54.027] BEGIN WMNewTab: 20 +[15:15.54.027] END WMNewTab: 20 + + +[15:15.55.441] BEGIN WMNewTab: 20 +[15:15.55.441] END WMNewTab: 20 + + +[15:15.56.861] BEGIN WMNewTab: 20 +[15:15.56.861] END WMNewTab: 20 + + +[15:15.58.276] BEGIN WMNewTab: 20 +[15:15.58.276] END WMNewTab: 20 + + +[15:15.59.690] BEGIN WMNewTab: 20 +[15:15.59.690] END WMNewTab: 20 + + +[15:16.01.112] BEGIN WMNewTab: 20 +[15:16.01.112] END WMNewTab: 20 + + +[15:16.02.532] BEGIN WMNewTab: 20 +[15:16.02.532] END WMNewTab: 20 + + +[15:16.03.947] BEGIN WMNewTab: 20 +[15:16.03.947] END WMNewTab: 20 + + +[15:16.05.370] BEGIN WMNewTab: 20 +[15:16.05.370] END WMNewTab: 20 + + +[15:16.06.790] BEGIN WMNewTab: 20 +[15:16.06.790] END WMNewTab: 20 + + +[15:16.08.215] BEGIN WMNewTab: 20 +[15:16.08.215] END WMNewTab: 20 + + +[15:16.09.639] BEGIN WMNewTab: 20 +[15:16.09.639] END WMNewTab: 20 + + +[15:16.11.057] BEGIN WMNewTab: 20 +[15:16.11.057] END WMNewTab: 20 + + +[15:16.12.470] BEGIN WMNewTab: 20 +[15:16.12.470] END WMNewTab: 20 + + +[15:16.13.878] BEGIN WMNewTab: 20 +[15:16.13.878] END WMNewTab: 20 + + +[15:16.15.291] BEGIN WMNewTab: 20 +[15:16.15.291] END WMNewTab: 20 + + +[15:16.16.710] BEGIN WMNewTab: 20 +[15:16.16.710] END WMNewTab: 20 + + +[15:16.18.131] BEGIN WMNewTab: 20 +[15:16.18.131] END WMNewTab: 20 + + +[15:16.19.550] BEGIN WMNewTab: 20 +[15:16.19.550] END WMNewTab: 20 + + +[15:16.20.973] BEGIN WMNewTab: 20 +[15:16.20.973] END WMNewTab: 20 + + +[15:16.22.392] BEGIN WMNewTab: 20 +[15:16.22.392] END WMNewTab: 20 + + +[15:16.23.813] BEGIN WMNewTab: 20 +[15:16.23.813] END WMNewTab: 20 + + +[15:16.25.231] BEGIN WMNewTab: 20 +[15:16.25.231] END WMNewTab: 20 + + +[15:16.26.652] BEGIN WMNewTab: 20 +[15:16.26.652] END WMNewTab: 20 + + +[15:16.28.077] BEGIN WMNewTab: 20 +[15:16.28.077] END WMNewTab: 20 + + +[15:16.29.492] BEGIN WMNewTab: 20 +[15:16.29.492] END WMNewTab: 20 + + +[15:16.30.914] BEGIN WMNewTab: 20 +[15:16.30.914] END WMNewTab: 20 + + +[15:16.32.329] BEGIN WMNewTab: 20 +[15:16.32.329] END WMNewTab: 20 + + +[15:16.33.743] BEGIN WMNewTab: 20 +[15:16.33.743] END WMNewTab: 20 + + +[15:16.35.159] BEGIN WMNewTab: 20 +[15:16.35.159] END WMNewTab: 20 + + +[15:16.36.575] BEGIN WMNewTab: 20 +[15:16.36.575] END WMNewTab: 20 + + +[15:16.37.992] BEGIN WMNewTab: 20 +[15:16.37.992] END WMNewTab: 20 + + +[15:16.39.409] BEGIN WMNewTab: 20 +[15:16.39.409] END WMNewTab: 20 + + +[15:16.40.828] BEGIN WMNewTab: 20 +[15:16.40.828] END WMNewTab: 20 + + +[15:16.42.251] BEGIN WMNewTab: 20 +[15:16.42.251] END WMNewTab: 20 + + +[15:16.43.667] BEGIN WMNewTab: 20 +[15:16.43.667] END WMNewTab: 20 + + +[15:16.45.090] BEGIN WMNewTab: 20 +[15:16.45.090] END WMNewTab: 20 + + +[15:16.46.505] BEGIN WMNewTab: 20 +[15:16.46.505] END WMNewTab: 20 + + +[15:16.47.924] BEGIN WMNewTab: 20 +[15:16.47.924] END WMNewTab: 20 + + +[15:16.49.343] BEGIN WMNewTab: 20 +[15:16.49.343] END WMNewTab: 20 + + +[15:16.50.763] BEGIN WMNewTab: 20 +[15:16.50.763] END WMNewTab: 20 + + +[15:16.52.175] BEGIN WMNewTab: 20 +[15:16.52.175] END WMNewTab: 20 + + +[15:16.53.588] BEGIN WMNewTab: 20 +[15:16.53.588] END WMNewTab: 20 + + +[15:16.55.002] BEGIN WMNewTab: 20 +[15:16.55.002] END WMNewTab: 20 + + +[15:16.56.421] BEGIN WMNewTab: 20 +[15:16.56.421] END WMNewTab: 20 + + +[15:16.57.843] BEGIN WMNewTab: 20 +[15:16.57.843] END WMNewTab: 20 + + +[15:16.59.263] BEGIN WMNewTab: 20 +[15:16.59.263] END WMNewTab: 20 + + +[15:17.00.681] BEGIN WMNewTab: 20 +[15:17.00.681] END WMNewTab: 20 + + +[15:17.02.097] BEGIN WMNewTab: 20 +[15:17.02.097] END WMNewTab: 20 + + +[15:17.03.510] BEGIN WMNewTab: 20 +[15:17.03.510] END WMNewTab: 20 + + +[15:17.04.932] BEGIN WMNewTab: 20 +[15:17.04.932] END WMNewTab: 20 + + +[15:17.06.351] BEGIN WMNewTab: 20 +[15:17.06.351] END WMNewTab: 20 + + +[15:17.07.764] BEGIN WMNewTab: 20 +[15:17.07.764] END WMNewTab: 20 + + +[15:17.09.182] BEGIN WMNewTab: 20 +[15:17.09.182] END WMNewTab: 20 + + +[15:17.10.603] BEGIN WMNewTab: 20 +[15:17.10.603] END WMNewTab: 20 + + +[15:17.12.016] BEGIN WMNewTab: 20 +[15:17.12.016] END WMNewTab: 20 + + +[15:17.13.434] BEGIN WMNewTab: 20 +[15:17.13.434] END WMNewTab: 20 + + +[15:17.14.854] BEGIN WMNewTab: 20 +[15:17.14.854] END WMNewTab: 20 + + +[15:17.16.272] BEGIN WMNewTab: 20 +[15:17.16.272] END WMNewTab: 20 + + +[15:17.17.719] BEGIN WMNewTab: 20 +[15:17.17.719] END WMNewTab: 20 + + +[15:17.19.127] BEGIN WMNewTab: 20 +[15:17.19.127] END WMNewTab: 20 + + +[15:17.20.544] BEGIN WMNewTab: 20 +[15:17.20.544] END WMNewTab: 20 + + +[15:17.21.968] BEGIN WMNewTab: 20 +[15:17.21.968] END WMNewTab: 20 + + +[15:17.23.387] BEGIN WMNewTab: 20 +[15:17.23.387] END WMNewTab: 20 + + +[15:17.24.809] BEGIN WMNewTab: 20 +[15:17.24.809] END WMNewTab: 20 + + +[15:17.26.228] BEGIN WMNewTab: 20 +[15:17.26.228] END WMNewTab: 20 + + +[15:17.27.640] BEGIN WMNewTab: 20 +[15:17.27.640] END WMNewTab: 20 + + +[15:17.29.055] BEGIN WMNewTab: 20 +[15:17.29.055] END WMNewTab: 20 + + +[15:17.30.469] BEGIN WMNewTab: 20 +[15:17.30.469] END WMNewTab: 20 + + +[15:17.31.891] BEGIN WMNewTab: 20 +[15:17.31.891] END WMNewTab: 20 + + +[15:17.33.306] BEGIN WMNewTab: 20 +[15:17.33.306] END WMNewTab: 20 + + +[15:17.34.724] BEGIN WMNewTab: 20 +[15:17.34.724] END WMNewTab: 20 + + +[15:17.36.140] BEGIN WMNewTab: 20 +[15:17.36.140] END WMNewTab: 20 + + +[15:17.37.549] BEGIN WMNewTab: 20 +[15:17.37.549] END WMNewTab: 20 + + +[15:17.38.969] BEGIN WMNewTab: 20 +[15:17.38.969] END WMNewTab: 20 + + +[15:17.40.386] BEGIN WMNewTab: 20 +[15:17.40.386] END WMNewTab: 20 + + +[15:17.41.804] BEGIN WMNewTab: 20 +[15:17.41.804] END WMNewTab: 20 + + +[15:17.43.231] BEGIN WMNewTab: 20 +[15:17.43.231] END WMNewTab: 20 + + +[15:17.44.650] BEGIN WMNewTab: 20 +[15:17.44.650] END WMNewTab: 20 + + +[15:17.46.060] BEGIN WMNewTab: 20 +[15:17.46.060] END WMNewTab: 20 + + +[15:17.47.480] BEGIN WMNewTab: 20 +[15:17.47.480] END WMNewTab: 20 + + +[15:17.48.894] BEGIN WMNewTab: 20 +[15:17.48.894] END WMNewTab: 20 + + +[15:17.50.311] BEGIN WMNewTab: 20 +[15:17.50.311] END WMNewTab: 20 + + +[15:17.51.732] BEGIN WMNewTab: 20 +[15:17.51.732] END WMNewTab: 20 + + +[15:17.53.150] BEGIN WMNewTab: 20 +[15:17.53.150] END WMNewTab: 20 + + +[15:17.54.568] BEGIN WMNewTab: 20 +[15:17.54.568] END WMNewTab: 20 + + +[15:17.55.985] BEGIN WMNewTab: 20 +[15:17.55.985] END WMNewTab: 20 + + +[15:17.57.399] BEGIN WMNewTab: 20 +[15:17.57.399] END WMNewTab: 20 + + +[15:17.58.813] BEGIN WMNewTab: 20 +[15:17.58.813] END WMNewTab: 20 + + +[15:18.00.230] BEGIN WMNewTab: 20 +[15:18.00.230] END WMNewTab: 20 + + +[15:18.01.644] BEGIN WMNewTab: 20 +[15:18.01.644] END WMNewTab: 20 + +[15:18.02.464] BEGIN WMNewTab: 0 +[15:18.02.464] WMNewTab: FormClick +[15:18.02.464] WMNewTab: LooseFocus +[15:18.02.464] END WMNewTab: 0 +[15:18.02.630] BEGIN WMNewTab: 0 +[15:18.02.630] WMNewTab: FormClick +[15:18.02.630] WMNewTab: LooseFocus +[15:18.02.630] END WMNewTab: 0 + +[15:18.03.059] BEGIN WMNewTab: 20 +[15:18.03.059] END WMNewTab: 20 + + +[15:18.04.465] BEGIN WMNewTab: 20 +[15:18.04.465] END WMNewTab: 20 + + +[15:18.05.875] BEGIN WMNewTab: 20 +[15:18.05.875] END WMNewTab: 20 +[15:18.05.999] BEGIN WMNewTab: 0 +[15:18.05.999] WMNewTab: FormClick +[15:18.05.999] WMNewTab: LooseFocus +[15:18.05.999] END WMNewTab: 0 + +[15:18.06.582] BEGIN WMNewTab: 0 +[15:18.06.582] WMNewTab: FormClick +[15:18.06.582] WMNewTab: LooseFocus +[15:18.06.585] END WMNewTab: 0 + +[15:18.07.288] BEGIN WMNewTab: 20 +[15:18.07.288] END WMNewTab: 20 + + +[15:18.08.703] BEGIN WMNewTab: 20 +[15:18.08.703] END WMNewTab: 20 + + +[15:18.10.124] BEGIN WMNewTab: 20 +[15:18.10.124] END WMNewTab: 20 +[15:18.10.271] BEGIN WMNewTab: 0 +[15:18.10.271] WMNewTab: FormClick +[15:18.10.271] WMNewTab: LooseFocus +[15:18.10.272] END WMNewTab: 0 +[15:18.10.407] BEGIN WMNewTab: 0 +[15:18.10.407] WMNewTab: FormClick +[15:18.10.407] WMNewTab: LooseFocus +[15:18.10.407] END WMNewTab: 0 +[15:18.10.520] Received Ctrl+Clic message (launch something from the terminal): for +[15:18.10.524] BEGIN WMNewTab: 0 +[15:18.10.524] WMNewTab: FormClick +[15:18.10.524] WMNewTab: LooseFocus +[15:18.10.524] END WMNewTab: 0 +[15:18.10.663] BEGIN WMNewTab: 0 +[15:18.10.663] WMNewTab: FormClick +[15:18.10.663] WMNewTab: LooseFocus +[15:18.10.667] END WMNewTab: 0 +[15:18.10.792] BEGIN WMNewTab: 0 +[15:18.10.792] WMNewTab: FormClick +[15:18.10.792] WMNewTab: LooseFocus +[15:18.10.792] END WMNewTab: 0 +[15:18.10.919] BEGIN WMNewTab: 0 +[15:18.10.919] WMNewTab: FormClick +[15:18.10.919] WMNewTab: LooseFocus +[15:18.10.921] END WMNewTab: 0 + +[15:18.11.541] BEGIN WMNewTab: 20 +[15:18.11.541] END WMNewTab: 20 + + +[15:18.12.961] BEGIN WMNewTab: 20 +[15:18.12.961] END WMNewTab: 20 + + +[15:18.14.381] BEGIN WMNewTab: 20 +[15:18.14.381] END WMNewTab: 20 + + +[15:18.15.795] BEGIN WMNewTab: 20 +[15:18.15.795] END WMNewTab: 20 + + +[15:18.17.159] BEGIN WMNewTab: 0 +[15:18.17.159] WMNewTab: FormClick +[15:18.17.159] WMNewTab: LooseFocus +[15:18.17.160] END WMNewTab: 0 +[15:18.17.210] BEGIN WMNewTab: 20 +[15:18.17.210] END WMNewTab: 20 +[15:18.17.286] BEGIN WMNewTab: 0 +[15:18.17.286] WMNewTab: FormClick +[15:18.17.286] WMNewTab: LooseFocus +[15:18.17.286] END WMNewTab: 0 +[15:18.17.393] Received Ctrl+Clic message (launch something from the terminal): +[15:18.17.396] BEGIN WMNewTab: 0 +[15:18.17.396] WMNewTab: FormClick +[15:18.17.396] WMNewTab: LooseFocus +[15:18.17.396] END WMNewTab: 0 +[15:18.17.503] BEGIN WMNewTab: 0 +[15:18.17.503] WMNewTab: FormClick +[15:18.17.503] WMNewTab: LooseFocus +[15:18.17.506] END WMNewTab: 0 +[15:18.17.592] BEGIN WMNewTab: 0 +[15:18.17.592] WMNewTab: FormClick +[15:18.17.592] WMNewTab: LooseFocus +[15:18.17.593] END WMNewTab: 0 +[15:18.17.720] BEGIN WMNewTab: 0 +[15:18.17.720] WMNewTab: FormClick +[15:18.17.720] WMNewTab: LooseFocus +[15:18.17.724] END WMNewTab: 0 +[15:18.17.833] BEGIN WMNewTab: 0 +[15:18.17.833] WMNewTab: FormClick +[15:18.17.833] WMNewTab: LooseFocus +[15:18.17.833] END WMNewTab: 0 +[15:18.17.880] BEGIN WMNewTab: 0 +[15:18.17.880] WMNewTab: FormClick +[15:18.17.880] WMNewTab: LooseFocus +[15:18.17.880] END WMNewTab: 0 +[15:18.17.988] Received Ctrl+Clic message (launch something from the terminal): +[15:18.18.030] BEGIN WMNewTab: 0 +[15:18.18.030] WMNewTab: FormClick +[15:18.18.030] WMNewTab: LooseFocus +[15:18.18.030] END WMNewTab: 0 +[15:18.18.071] BEGIN WMNewTab: 0 +[15:18.18.071] WMNewTab: FormClick +[15:18.18.071] WMNewTab: LooseFocus +[15:18.18.074] END WMNewTab: 0 +[15:18.18.225] BEGIN WMNewTab: 0 +[15:18.18.225] WMNewTab: FormClick +[15:18.18.225] WMNewTab: LooseFocus +[15:18.18.225] END WMNewTab: 0 +[15:18.18.263] BEGIN WMNewTab: 0 +[15:18.18.263] WMNewTab: FormClick +[15:18.18.263] WMNewTab: LooseFocus +[15:18.18.266] END WMNewTab: 0 +[15:18.18.627] BEGIN WMNewTab: 20 +[15:18.18.627] END WMNewTab: 20 +[15:18.18.856] BEGIN WMNewTab: 0 +[15:18.18.856] WMNewTab: FormClick +[15:18.18.856] WMNewTab: LooseFocus +[15:18.18.856] END WMNewTab: 0 +[15:18.18.992] BEGIN WMNewTab: 0 +[15:18.18.992] WMNewTab: FormClick +[15:18.18.992] WMNewTab: LooseFocus +[15:18.18.993] END WMNewTab: 0 +[15:18.19.099] Received Ctrl+Clic message (launch something from the terminal): + +[15:18.20.044] BEGIN WMNewTab: 20 +[15:18.20.044] END WMNewTab: 20 + + +[15:18.21.265] BEGIN WMNewTab: 0 +[15:18.21.265] WMNewTab: FormClick +[15:18.21.265] WMNewTab: LooseFocus +[15:18.21.265] END WMNewTab: 0 +[15:18.21.400] BEGIN WMNewTab: 0 +[15:18.21.400] WMNewTab: FormClick +[15:18.21.400] WMNewTab: LooseFocus +[15:18.21.400] END WMNewTab: 0 +[15:18.21.461] BEGIN WMNewTab: 20 +[15:18.21.461] END WMNewTab: 20 +[15:18.21.506] Received Ctrl+Clic message (launch something from the terminal): +[15:18.21.769] BEGIN WMNewTab: 0 +[15:18.21.769] WMNewTab: FormClick +[15:18.21.769] WMNewTab: LooseFocus +[15:18.21.769] END WMNewTab: 0 +[15:18.21.879] BEGIN WMNewTab: 0 +[15:18.21.879] WMNewTab: FormClick +[15:18.21.879] WMNewTab: LooseFocus +[15:18.21.879] END WMNewTab: 0 +[15:18.21.982] Received Ctrl+Clic message (launch something from the terminal): +[15:18.22.089] BEGIN WMNewTab: 0 +[15:18.22.089] WMNewTab: FormClick +[15:18.22.089] WMNewTab: LooseFocus +[15:18.22.089] END WMNewTab: 0 +[15:18.22.138] BEGIN WMNewTab: 0 +[15:18.22.138] WMNewTab: FormClick +[15:18.22.138] WMNewTab: LooseFocus +[15:18.22.140] END WMNewTab: 0 +[15:18.22.287] BEGIN WMNewTab: 0 +[15:18.22.287] WMNewTab: FormClick +[15:18.22.287] WMNewTab: LooseFocus +[15:18.22.287] END WMNewTab: 0 +[15:18.22.424] BEGIN WMNewTab: 0 +[15:18.22.424] WMNewTab: FormClick +[15:18.22.424] WMNewTab: LooseFocus +[15:18.22.428] END WMNewTab: 0 + +[15:18.22.871] BEGIN WMNewTab: 0 +[15:18.22.871] WMNewTab: FormClick +[15:18.22.871] WMNewTab: LooseFocus +[15:18.22.871] END WMNewTab: 0 +[15:18.22.881] BEGIN WMNewTab: 20 +[15:18.22.881] END WMNewTab: 20 +[15:18.22.975] BEGIN WMNewTab: 0 +[15:18.22.975] WMNewTab: FormClick +[15:18.22.975] WMNewTab: LooseFocus +[15:18.22.975] END WMNewTab: 0 +[15:18.23.078] Received Ctrl+Clic message (launch something from the terminal): +[15:18.23.296] BEGIN WMNewTab: 0 +[15:18.23.296] WMNewTab: FormClick +[15:18.23.296] WMNewTab: LooseFocus +[15:18.23.296] END WMNewTab: 0 +[15:18.23.351] BEGIN WMNewTab: 0 +[15:18.23.351] WMNewTab: FormClick +[15:18.23.351] WMNewTab: LooseFocus +[15:18.23.354] END WMNewTab: 0 +[15:18.23.712] BEGIN WMNewTab: 0 +[15:18.23.712] WMNewTab: FormClick +[15:18.23.712] WMNewTab: LooseFocus +[15:18.23.712] END WMNewTab: 0 +[15:18.23.824] BEGIN WMNewTab: 0 +[15:18.23.824] WMNewTab: FormClick +[15:18.23.824] WMNewTab: LooseFocus +[15:18.23.827] END WMNewTab: 0 +[15:18.23.935] BEGIN WMNewTab: 0 +[15:18.23.935] WMNewTab: FormClick +[15:18.23.935] WMNewTab: LooseFocus +[15:18.23.936] END WMNewTab: 0 +[15:18.24.074] BEGIN WMNewTab: 0 +[15:18.24.074] WMNewTab: FormClick +[15:18.24.074] WMNewTab: LooseFocus +[15:18.24.074] END WMNewTab: 0 +[15:18.24.173] Received Ctrl+Clic message (launch something from the terminal): +[15:18.24.210] BEGIN WMNewTab: 0 +[15:18.24.210] WMNewTab: FormClick +[15:18.24.210] WMNewTab: LooseFocus +[15:18.24.210] END WMNewTab: 0 +[15:18.24.295] BEGIN WMNewTab: 20 +[15:18.24.295] END WMNewTab: 20 +[15:18.24.375] BEGIN WMNewTab: 0 +[15:18.24.375] WMNewTab: FormClick +[15:18.24.375] WMNewTab: LooseFocus +[15:18.24.377] END WMNewTab: 0 +[15:18.24.712] BEGIN WMNewTab: 0 +[15:18.24.712] WMNewTab: FormClick +[15:18.24.712] WMNewTab: LooseFocus +[15:18.24.713] END WMNewTab: 0 +[15:18.24.840] BEGIN WMNewTab: 0 +[15:18.24.840] WMNewTab: FormClick +[15:18.24.840] WMNewTab: LooseFocus +[15:18.24.840] END WMNewTab: 0 +[15:18.24.951] Received Ctrl+Clic message (launch something from the terminal): + +[15:18.25.714] BEGIN WMNewTab: 20 +[15:18.25.714] END WMNewTab: 20 + + +[15:18.27.133] BEGIN WMNewTab: 20 +[15:18.27.133] END WMNewTab: 20 + + +[15:18.28.552] BEGIN WMNewTab: 20 +[15:18.28.552] END WMNewTab: 20 +[15:18.28.569] BEGIN WMHotKey +[15:18.28.814] END WMHotKey +[15:18.28.897] BEGIN WMHotKey +[15:18.28.945] BEGIN TFormXterm.FormResize +[15:18.28.945] TFormXterm.FormResize: CenterBtnReattachTab +[15:18.28.945] TFormXterm.FormResize: SplitModeResize +[15:18.28.945] TFormXterm.FormResize: BtnSplitNo.Down +[15:18.28.945] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:18.28.945] BEGIN ResizeTerminal +[15:18.28.959] END ResizeTerminal +[15:18.28.959] TFormXterm.FormResize: AdaptSidebarArrows; +[15:18.28.959] BEGIN AdaptSidebarArrows +[15:18.28.959] END AdaptSidebarArrows +[15:18.28.959] TFormXterm.FormResize: AdaptTV2; +[15:18.28.959] END TFormXterm.FormResize +[15:18.28.959] BEGIN WMSize +[15:18.28.959] BEGIN TFormXterm.FormResize +[15:18.28.959] TFormXterm.FormResize: CenterBtnReattachTab +[15:18.28.959] TFormXterm.FormResize: SplitModeResize +[15:18.28.959] TFormXterm.FormResize: BtnSplitNo.Down +[15:18.28.959] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:18.28.959] BEGIN ResizeTerminal +[15:18.28.969] END ResizeTerminal +[15:18.28.969] TFormXterm.FormResize: AdaptSidebarArrows; +[15:18.28.969] BEGIN AdaptSidebarArrows +[15:18.28.969] END AdaptSidebarArrows +[15:18.28.969] TFormXterm.FormResize: AdaptTV2; +[15:18.28.969] END TFormXterm.FormResize +[15:18.28.969] END WMSize +[15:18.28.971] END WMHotKey + +[15:18.29.419] BEGIN WMHotKey +[15:18.29.456] END WMHotKey + +[15:18.29.963] BEGIN WMNewTab: 20 +[15:18.29.963] END WMNewTab: 20 + + +[15:18.31.379] BEGIN WMNewTab: 20 +[15:18.31.379] END WMNewTab: 20 + + +[15:18.32.790] BEGIN WMNewTab: 20 +[15:18.32.790] END WMNewTab: 20 + + +[15:18.34.203] BEGIN WMNewTab: 20 +[15:18.34.203] END WMNewTab: 20 + + +[15:18.35.616] BEGIN WMNewTab: 20 +[15:18.35.616] END WMNewTab: 20 + + +[15:18.37.029] BEGIN WMNewTab: 20 +[15:18.37.029] END WMNewTab: 20 + +[15:18.37.900] BEGIN TFormXterm.FormResize +[15:18.37.900] TFormXterm.FormResize: CenterBtnReattachTab +[15:18.37.900] TFormXterm.FormResize: SplitModeResize +[15:18.37.900] TFormXterm.FormResize: BtnSplitNo.Down +[15:18.37.900] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:18.37.900] BEGIN ResizeTerminal +[15:18.37.911] END ResizeTerminal +[15:18.37.911] TFormXterm.FormResize: AdaptSidebarArrows; +[15:18.37.911] BEGIN AdaptSidebarArrows +[15:18.37.911] END AdaptSidebarArrows +[15:18.37.911] TFormXterm.FormResize: AdaptTV2; +[15:18.37.911] END TFormXterm.FormResize +[15:18.37.911] BEGIN WMSize +[15:18.37.911] BEGIN TFormXterm.FormResize +[15:18.37.911] TFormXterm.FormResize: CenterBtnReattachTab +[15:18.37.911] TFormXterm.FormResize: SplitModeResize +[15:18.37.911] TFormXterm.FormResize: BtnSplitNo.Down +[15:18.37.911] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:18.37.911] BEGIN ResizeTerminal +[15:18.37.920] END ResizeTerminal +[15:18.37.920] TFormXterm.FormResize: AdaptSidebarArrows; +[15:18.37.920] BEGIN AdaptSidebarArrows +[15:18.37.920] END AdaptSidebarArrows +[15:18.37.920] TFormXterm.FormResize: AdaptTV2; +[15:18.37.920] END TFormXterm.FormResize +[15:18.37.920] END WMSize +[15:18.37.923] WMNewTab2_ReEnable_Timer1; +[15:18.37.923] WMNewTab2_ReEnable_Timer1_BIS; + +[15:18.38.446] BEGIN WMNewTab: 20 +[15:18.38.446] END WMNewTab: 20 + +[15:18.39.113] BEGIN WMNewTab: 0 +[15:18.39.113] WMNewTab: FormClick +[15:18.39.113] WMNewTab: LooseFocus +[15:18.39.114] END WMNewTab: 0 +[15:18.39.233] BEGIN WMNewTab: 0 +[15:18.39.233] WMNewTab: FormClick +[15:18.39.233] WMNewTab: LooseFocus +[15:18.39.233] END WMNewTab: 0 + +[15:18.39.760] BEGIN WMNewTab: 0 +[15:18.39.760] WMNewTab: FormClick +[15:18.39.760] WMNewTab: LooseFocus +[15:18.39.760] END WMNewTab: 0 +[15:18.39.861] BEGIN WMNewTab: 20 +[15:18.39.861] END WMNewTab: 20 +[15:18.39.904] BEGIN WMNewTab: 0 +[15:18.39.904] WMNewTab: FormClick +[15:18.39.904] WMNewTab: LooseFocus +[15:18.39.905] END WMNewTab: 0 + + +[15:18.41.280] BEGIN WMNewTab: 20 +[15:18.41.280] END WMNewTab: 20 + + +[15:18.42.695] BEGIN WMNewTab: 20 +[15:18.42.695] END WMNewTab: 20 + + +[15:18.44.112] BEGIN WMNewTab: 20 +[15:18.44.112] END WMNewTab: 20 + + +[15:18.45.530] BEGIN WMNewTab: 20 +[15:18.45.530] END WMNewTab: 20 + + +[15:18.46.942] BEGIN WMNewTab: 20 +[15:18.46.942] END WMNewTab: 20 + + +[15:18.48.355] BEGIN WMNewTab: 20 +[15:18.48.355] END WMNewTab: 20 +[15:18.48.617] BEGIN WMNewTab: 0 +[15:18.48.617] WMNewTab: FormClick +[15:18.48.617] WMNewTab: LooseFocus +[15:18.48.617] END WMNewTab: 0 +[15:18.48.800] BEGIN WMNewTab: 0 +[15:18.48.800] WMNewTab: FormClick +[15:18.48.800] WMNewTab: LooseFocus +[15:18.48.800] END WMNewTab: 0 + +[15:18.49.776] BEGIN WMNewTab: 20 +[15:18.49.776] END WMNewTab: 20 + +[15:18.50.729] BEGIN WMNewTab: 0 +[15:18.50.729] WMNewTab: FormClick +[15:18.50.729] WMNewTab: LooseFocus +[15:18.50.729] END WMNewTab: 0 +[15:18.50.845] BEGIN WMNewTab: 0 +[15:18.50.845] WMNewTab: FormClick +[15:18.50.845] WMNewTab: LooseFocus +[15:18.50.846] END WMNewTab: 0 +[15:18.51.191] BEGIN WMNewTab: 20 +[15:18.51.192] END WMNewTab: 20 + +[15:18.52.366] BEGIN CWD +[15:18.52.427] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:18.52.427] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:18.52.427] (SSH-Browser) END VerifySFTPConnection(1) +[15:18.52.427] END CWD +[15:18.52.429] BEGIN WMNewTab: 20 +[15:18.52.429] END WMNewTab: 20 +[15:18.52.442] BEGIN CWD +[15:18.52.502] END CWD +[15:18.52.533] BEGIN CWD +[15:18.52.593] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:18.52.593] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:18.52.593] (SSH-Browser) END VerifySFTPConnection(1) +[15:18.52.593] END CWD +[15:18.52.609] BEGIN CWD +[15:18.52.670] END CWD +[15:18.52.715] BEGIN CWD +[15:18.52.776] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:18.52.776] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:18.52.776] (SSH-Browser) END VerifySFTPConnection(1) +[15:18.52.776] END CWD +[15:18.52.792] BEGIN CWD +[15:18.52.852] END CWD +[15:18.52.914] BEGIN CWD +[15:18.52.975] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:18.52.975] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:18.52.975] (SSH-Browser) END VerifySFTPConnection(1) +[15:18.52.975] END CWD +[15:18.52.989] BEGIN CWD +[15:18.53.049] END CWD + +[15:18.53.993] BEGIN WMNewTab: 20 +[15:18.53.993] END WMNewTab: 20 +[15:18.54.262] BEGIN WMNewTab: 0 +[15:18.54.262] WMNewTab: FormClick +[15:18.54.262] WMNewTab: LooseFocus +[15:18.54.262] END WMNewTab: 0 +[15:18.54.408] BEGIN WMNewTab: 0 +[15:18.54.408] WMNewTab: FormClick +[15:18.54.408] WMNewTab: LooseFocus +[15:18.54.409] END WMNewTab: 0 + +[15:18.55.410] BEGIN WMNewTab: 20 +[15:18.55.410] END WMNewTab: 20 + + +[15:18.56.832] BEGIN WMNewTab: 20 +[15:18.56.832] END WMNewTab: 20 +[15:18.57.104] BEGIN WMNewTab: 48 +[15:18.57.104] 收到消息: SSH 会话部分关闭 (2) +[15:18.57.177] BEGIN TFormXterm.FormResize +[15:18.57.177] TFormXterm.FormResize: CenterBtnReattachTab +[15:18.57.178] TFormXterm.FormResize: SplitModeResize +[15:18.57.178] TFormXterm.FormResize: BtnSplitNo.Down +[15:18.57.182] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:18.57.182] BEGIN ResizeTerminal +[15:18.57.214] END ResizeTerminal +[15:18.57.214] TFormXterm.FormResize: AdaptSidebarArrows; +[15:18.57.214] BEGIN AdaptSidebarArrows +[15:18.57.214] END AdaptSidebarArrows +[15:18.57.214] TFormXterm.FormResize: AdaptTV2; +[15:18.57.214] END TFormXterm.FormResize +[15:18.57.214] BEGIN DisconnectSSH(1) +[15:18.57.214] (SSH-Browser) DisconnectSSH(1): (Socket.Active) and (SocketState<>SOCKET_STATE_CONNECTING) +[15:18.57.225] SetTitle(1, ); +[15:18.57.226] (SSH-Browser) ElSFTP1CloseConnection(1) +[15:18.57.226] (SSH-Browser) ElSFTP1Error(1): #103 - 连接被低层协议关闭 +[15:18.57.226] SFTPErr #103 附带说明 "连接被低层协议关闭" +[15:18.57.226] (SSH-Browser) ElSFTP1CloseConnection(1) +[15:18.57.226] BEGIN ElSSH1CloseConnection(1) +[15:18.57.226] END ElSSH1CloseConnection(1) +[15:18.57.226] (SSH-Browser) DisconnectSSH(1): Socket.Close; +[15:18.57.226] (SSH-Browser) BEGIN DesactiverPanel14 +[15:18.57.238] (SSH-Browser) END DesactiverPanel14 +[15:18.57.239] END DisconnectSSH(1) +[15:18.57.250] END WMNewTab: 48 + + +[15:19.00.465] BEGIN WMNewTab: 60 +[15:19.00.475] END WMNewTab: 60 + +[15:19.01.074] BEGIN WMNewTab: 60 +[15:19.01.074] END WMNewTab: 60 + +[15:19.01.692] BEGIN WMNewTab: 60 +[15:19.01.692] END WMNewTab: 60 + +[15:19.02.065] BEGIN WMNewTab: 0 +[15:19.02.065] WMNewTab: FormClick +[15:19.02.065] WMNewTab: LooseFocus +[15:19.02.065] END WMNewTab: 0 +[15:19.02.168] BEGIN WMNewTab: 0 +[15:19.02.168] WMNewTab: FormClick +[15:19.02.168] WMNewTab: LooseFocus +[15:19.02.168] END WMNewTab: 0 + +[15:19.02.674] BEGIN WMNewTab: 60 +[15:19.02.674] END WMNewTab: 60 + +[15:19.03.417] BEGIN WMNewTab: 60 +[15:19.03.417] END WMNewTab: 60 + +[15:19.04.495] BEGIN WMNewTab: 60 +[15:19.04.495] END WMNewTab: 60 +[15:19.04.782] Cts1MouseDown: FormClick +[15:19.04.788] Cts1ActiveTabChanged: New index = 2 +[15:19.04.788] BEGIN DisplayCurrentTab +[15:19.04.788] DisplayCurrentTab: FormClick +[15:19.04.788] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[15:19.04.788] (SSH-Browser) BEGIN ActiverPanel14 +[15:19.04.788] (SSH-Browser) BEGIN DesactiverPanel14 +[15:19.04.788] (SSH-Browser) END DesactiverPanel14 +[15:19.04.788] (SSH-Browser) END ActiverPanel14; +[15:19.04.801] DisplayCurrentTab: Cts1.BeginUpdate; +[15:19.04.801] DisplayCurrentTab: Cts1.EndUpdates +[15:19.04.815] DisplayCurrentTab: 显示所选标签页 +[15:19.04.832] DisplayCurrentTab: 隐藏其他标签页 +[15:19.04.834] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:19.04.836] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:19.04.836] DisplayCurrentTab: DistribuerLeFocus +[15:19.04.836] END DisplayCurrentTab +[15:19.04.847] BEGIN WMNewTab: 62 +[15:19.04.847] END WMNewTab: 62 + + + +[15:20.12.544] BEGIN WMNewTab: 0 +[15:20.12.544] WMNewTab: FormClick +[15:20.12.544] WMNewTab: LooseFocus +[15:20.12.544] END WMNewTab: 0 +[15:20.12.646] BEGIN WMNewTab: 0 +[15:20.12.646] WMNewTab: FormClick +[15:20.12.646] WMNewTab: LooseFocus +[15:20.12.647] END WMNewTab: 0 + + + + + +[15:24.57.293] BEGIN WMNewTab: 0 +[15:24.57.293] WMNewTab: FormClick +[15:24.57.293] WMNewTab: LooseFocus +[15:24.57.294] END WMNewTab: 0 +[15:24.57.377] BEGIN WMNewTab: 0 +[15:24.57.377] WMNewTab: FormClick +[15:24.57.377] WMNewTab: LooseFocus +[15:24.57.377] END WMNewTab: 0 + + + +[15:25.12.000] Cts1MouseDown: FormClick +[15:25.12.005] Cts1ActiveTabChanged: New index = 1 +[15:25.12.005] BEGIN DisplayCurrentTab +[15:25.12.005] DisplayCurrentTab: FormClick +[15:25.12.005] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:25.12.005] (SSH-Browser) BEGIN ActiverPanel14 +[15:25.12.005] (SSH-Browser) BEGIN DesactiverPanel14 +[15:25.12.005] (SSH-Browser) END DesactiverPanel14 +[15:25.12.005] (SSH-Browser) END ActiverPanel14; +[15:25.12.019] DisplayCurrentTab: Cts1.BeginUpdate; +[15:25.12.019] DisplayCurrentTab: Cts1.EndUpdates +[15:25.12.033] DisplayCurrentTab: 显示所选标签页 +[15:25.12.036] DisplayCurrentTab: 隐藏其他标签页 +[15:25.12.038] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:25.12.040] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:25.12.040] DisplayCurrentTab: DistribuerLeFocus +[15:25.12.040] END DisplayCurrentTab + +[15:25.13.134] BEGIN WMNewTab: 62 +[15:25.13.134] END WMNewTab: 62 +[15:25.13.191] SetTitle(1, 192.168.127.10 (root)); +[15:25.13.261] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[15:25.13.261] 主机密钥与缓存中的密钥是一致的 +[15:25.13.269] BEGIN GetPassword +[15:25.13.269] BEGIN GetnSaveCredPassword +[15:25.13.270] END GetnSaveCredPassword +[15:25.13.270] END GetPassword + + +[15:25.16.669] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[15:25.16.669] BEGIN SauvegarderMotDePasseSSH +[15:25.16.669] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[15:25.16.669] SetTitle(1, root@192.168.127.10); +[15:25.16.669] +[15:25.16.669] (SSH-Browser) BEGIN ConnectSSH(1,192.168.127.10,root,) +[15:25.16.669] (SSH-Browser) ConnectSSH(1): 初始化 TabSFTP +[15:25.16.671] (SSH-Browser) ConnectSSH(1): 未使用代理 +[15:25.16.671] (SSH-Browser) ConnectSSH(1): 未提供密钥 --> 使用其他身份验证类型进行连接 +[15:25.16.672] (SSH-Browser) ConnectSSH(1): 已成功连接到 192.168.127.10. +[15:25.16.672] (SSH-Browser) ConnectSSH(1): SSH.Open +[15:25.16.672] (SSH-Browser) END ConnectSSH(1) +[15:25.16.672] BEGIN DisplayCurrentTab +[15:25.16.672] DisplayCurrentTab: FormClick +[15:25.16.672] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:25.16.672] (SSH-Browser) BEGIN ActiverPanel14 +[15:25.16.672] (SSH-Browser) BEGIN DesactiverPanel14 +[15:25.16.672] (SSH-Browser) END DesactiverPanel14 +[15:25.16.672] (SSH-Browser) END ActiverPanel14; +[15:25.16.685] DisplayCurrentTab: Cts1.BeginUpdate; +[15:25.16.685] DisplayCurrentTab: Cts1.EndUpdates +[15:25.16.698] DisplayCurrentTab: 显示所选标签页 +[15:25.16.698] DisplayCurrentTab: 隐藏其他标签页 +[15:25.16.699] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:25.16.699] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:25.16.699] DisplayCurrentTab: DistribuerLeFocus +[15:25.16.699] END DisplayCurrentTab +[15:25.16.699] BEGIN SavePassword +[15:25.16.699] END SavePassword +[15:25.16.699] END SauvegarderMotDePasseSSH +[15:25.16.699] BEGIN WMNewTab: 80 +[15:25.16.699] 收到消息: 正在启动远程监控 终端 #2 +[15:25.16.722] BEGIN TFormXterm.FormResize +[15:25.16.722] TFormXterm.FormResize: CenterBtnReattachTab +[15:25.16.723] TFormXterm.FormResize: SplitModeResize +[15:25.16.723] TFormXterm.FormResize: BtnSplitNo.Down +[15:25.16.724] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:25.16.724] BEGIN ResizeTerminal +[15:25.16.735] END ResizeTerminal +[15:25.16.735] TFormXterm.FormResize: AdaptSidebarArrows; +[15:25.16.735] BEGIN AdaptSidebarArrows +[15:25.16.735] END AdaptSidebarArrows +[15:25.16.735] TFormXterm.FormResize: AdaptTV2; +[15:25.16.737] END TFormXterm.FormResize +[15:25.16.757] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[15:25.16.757] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:25.16.774] ShellExecuteS: ShellExecuteEx 成功. +[15:25.16.774] ShellExecuteS: WaitForInputIdle 失败. +[15:25.16.774] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:25.16.774] END WMNewTab: 80 +[15:25.16.837] [MobaSCP2] Launching remote monitoring in normal mode +[15:25.16.837] [MobaSCP2] Multiplex=1 +[15:25.16.837] [MobaSCP2] HOSTNAME: 192.168.127.10 +[15:25.16.837] [MobaSCP2] USERNAME: root +[15:25.16.866] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[15:25.16.866] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[15:25.16.866] (SSH-Browser) 主机密钥指纹信息 (Sha256): 2b:ca:32:12:87:5d:69:9e:24:78:db:b7:f5:ec:40:a8:c2:4b:0c:47:27:72:0a:10:19:c4:4f:43:cf:7c:05:be +[15:25.16.866] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[15:25.16.866] (SSH-Browser) END GetSftpOnValidateStatus +[15:25.16.908] [MobaSCP2] Using SCP1 +[15:25.16.908] [MobaSCP2] Connected to 192.168.127.10 +[15:25.16.931] +[15:25.16.931] (SSH-Browser) ElSSH1AuthenticationStart(1, 134) +[15:25.16.931] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[15:25.16.931] (SSH-Browser) 服务器支持以下认证方式: +[15:25.16.931] (SSH-Browser) . PUBLICKEYAGENT +[15:25.16.931] (SSH-Browser) . PUBLICKEY +[15:25.16.931] (SSH-Browser) . PASSWORD +[15:25.16.931] (SSH-Browser) 客户端支持以下认证方式: +[15:25.16.931] (SSH-Browser) . PUBLICKEYAGENT +[15:25.16.931] (SSH-Browser) . PUBLICKEY +[15:25.16.931] (SSH-Browser) . RHOSTS +[15:25.16.931] (SSH-Browser) . HOSTBASED +[15:25.16.931] (SSH-Browser) . PASSWORD +[15:25.16.931] (SSH-Browser) . KEYBOARD +[15:25.16.931] +[15:25.16.931] +[15:25.16.931] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEY) +[15:25.16.931] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEYAGENT) +[15:25.16.931] (SSH-Browser) ElSSH1AuthenticationAttempt(1, PASSWORD) + +[15:25.17.311] (SSH-Browser) ElSSH1AuthenticationSuccess(1) +[15:25.17.311] (SSH-Browser) ElSSH1OpenConnection(1) +[15:25.17.311] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[15:25.17.311] +[15:25.17.618] (SSH-Browser) BEGIN ElSFTP1OpenConnection(1) +[15:25.17.618] (SSH-Browser) ElSFTP1OpenConnection(1): SFTP 已正确连接 +[15:25.17.618] (SSH-Browser) ElSFTP1OpenConnection(1): ActiverPanel14 +[15:25.17.618] (SSH-Browser) BEGIN ActiverPanel14 +[15:25.17.618] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:25.17.622] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:25.17.622] (SSH-Browser) ActiverPanel14: 列出远程目录 +[15:25.17.622] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[15:25.17.623] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[15:25.17.651] (SSH-Browser) END ActiverPanel14; +[15:25.17.687] (SSH-Browser) ElSFTP1OpenConnection(1): 已成功打开连接 --> 正在退出 +[15:25.17.687] (SSH-Browser) END ElSFTP1OpenConnection(1) +[15:25.18.017] BEGIN TFormXterm.FormResize +[15:25.18.017] TFormXterm.FormResize: CenterBtnReattachTab +[15:25.18.017] TFormXterm.FormResize: SplitModeResize +[15:25.18.017] TFormXterm.FormResize: BtnSplitNo.Down +[15:25.18.017] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:25.18.017] BEGIN ResizeTerminal +[15:25.18.017] END ResizeTerminal +[15:25.18.017] TFormXterm.FormResize: AdaptSidebarArrows; +[15:25.18.017] BEGIN AdaptSidebarArrows +[15:25.18.017] END AdaptSidebarArrows +[15:25.18.017] TFormXterm.FormResize: AdaptTV2; +[15:25.18.017] END TFormXterm.FormResize +[15:25.18.149] BEGIN WMNewTab: 20 +[15:25.18.149] END WMNewTab: 20 + + +[15:25.19.565] BEGIN WMNewTab: 20 +[15:25.19.565] END WMNewTab: 20 + + +[15:25.20.980] BEGIN WMNewTab: 20 +[15:25.20.980] END WMNewTab: 20 + + +[15:25.22.398] BEGIN WMNewTab: 20 +[15:25.22.398] END WMNewTab: 20 + + +[15:25.23.814] BEGIN WMNewTab: 20 +[15:25.23.814] END WMNewTab: 20 + + +[15:25.25.231] BEGIN WMNewTab: 20 +[15:25.25.231] END WMNewTab: 20 + + +[15:25.26.649] BEGIN WMNewTab: 20 +[15:25.26.649] END WMNewTab: 20 + + +[15:25.28.067] BEGIN WMNewTab: 20 +[15:25.28.067] END WMNewTab: 20 + + +[15:25.29.486] BEGIN WMNewTab: 20 +[15:25.29.486] END WMNewTab: 20 + + +[15:25.30.904] BEGIN WMNewTab: 20 +[15:25.30.904] END WMNewTab: 20 + + +[15:25.32.313] BEGIN WMNewTab: 20 +[15:25.32.313] END WMNewTab: 20 + + +[15:25.33.727] BEGIN WMNewTab: 20 +[15:25.33.727] END WMNewTab: 20 + + +[15:25.35.138] BEGIN WMNewTab: 20 +[15:25.35.138] END WMNewTab: 20 + + +[15:25.36.552] BEGIN WMNewTab: 20 +[15:25.36.552] END WMNewTab: 20 + + +[15:25.37.963] BEGIN WMNewTab: 20 +[15:25.37.963] END WMNewTab: 20 + + +[15:25.39.374] BEGIN WMNewTab: 20 +[15:25.39.374] END WMNewTab: 20 + + +[15:25.40.790] BEGIN WMNewTab: 20 +[15:25.40.790] END WMNewTab: 20 + + +[15:25.42.197] BEGIN WMNewTab: 20 +[15:25.42.197] END WMNewTab: 20 + + +[15:25.43.616] BEGIN WMNewTab: 20 +[15:25.43.616] END WMNewTab: 20 + + +[15:25.45.031] BEGIN WMNewTab: 20 +[15:25.45.031] END WMNewTab: 20 + + +[15:25.46.446] BEGIN WMNewTab: 20 +[15:25.46.446] END WMNewTab: 20 + + +[15:25.47.858] BEGIN WMNewTab: 20 +[15:25.47.858] END WMNewTab: 20 + + +[15:25.49.277] BEGIN WMNewTab: 20 +[15:25.49.277] END WMNewTab: 20 + + +[15:25.50.705] BEGIN WMNewTab: 20 +[15:25.50.705] END WMNewTab: 20 + + +[15:25.52.103] BEGIN WMNewTab: 20 +[15:25.52.103] END WMNewTab: 20 + + +[15:25.53.521] BEGIN WMNewTab: 20 +[15:25.53.521] END WMNewTab: 20 + + +[15:25.54.938] BEGIN WMNewTab: 20 +[15:25.54.938] END WMNewTab: 20 + + +[15:25.56.352] BEGIN WMNewTab: 20 +[15:25.56.352] END WMNewTab: 20 + + +[15:25.57.770] BEGIN WMNewTab: 20 +[15:25.57.770] END WMNewTab: 20 + + +[15:25.59.180] BEGIN WMNewTab: 20 +[15:25.59.180] END WMNewTab: 20 + + +[15:26.00.594] BEGIN WMNewTab: 20 +[15:26.00.594] END WMNewTab: 20 + + +[15:26.02.012] BEGIN WMNewTab: 20 +[15:26.02.012] END WMNewTab: 20 + + +[15:26.03.424] BEGIN WMNewTab: 20 +[15:26.03.424] END WMNewTab: 20 + + +[15:26.04.835] BEGIN WMNewTab: 20 +[15:26.04.835] END WMNewTab: 20 + + +[15:26.06.252] BEGIN WMNewTab: 20 +[15:26.06.252] END WMNewTab: 20 + + +[15:26.07.670] BEGIN WMNewTab: 20 +[15:26.07.670] END WMNewTab: 20 + + +[15:26.09.084] BEGIN WMNewTab: 20 +[15:26.09.084] END WMNewTab: 20 + + +[15:26.10.492] BEGIN WMNewTab: 20 +[15:26.10.492] END WMNewTab: 20 + + +[15:26.11.910] BEGIN WMNewTab: 20 +[15:26.11.910] END WMNewTab: 20 + + +[15:26.13.322] BEGIN WMNewTab: 20 +[15:26.13.322] END WMNewTab: 20 + + +[15:26.14.737] BEGIN WMNewTab: 20 +[15:26.14.737] END WMNewTab: 20 + + +[15:26.16.152] BEGIN WMNewTab: 20 +[15:26.16.152] END WMNewTab: 20 +[15:26.16.232] BEGIN WMNewTab: 31 +[15:26.16.232] END WMNewTab: 31 +[15:26.16.233] BEGIN WMNewTab: 0 +[15:26.16.233] WMNewTab: FormClick +[15:26.16.233] WMNewTab: LooseFocus +[15:26.16.233] END WMNewTab: 0 + + +[15:26.17.573] BEGIN WMNewTab: 20 +[15:26.17.573] END WMNewTab: 20 +[15:26.17.832] BEGIN CWD +[15:26.17.832] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:26.17.832] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:26.17.832] (SSH-Browser) END VerifySFTPConnection(1) +[15:26.17.832] END CWD +[15:26.17.907] (SSH-Browser) ElCommandSSHTunnel1Open +[15:26.17.936] (SSH-Browser) ExecuteCommandData +[15:26.17.968] (SSH-Browser) ExecuteCommandData +[15:26.17.998] (SSH-Browser) ExecuteCommandData +[15:26.18.028] (SSH-Browser) ExecuteCommandData +[15:26.18.060] (SSH-Browser) ExecuteCommandData +[15:26.18.090] (SSH-Browser) ExecuteCommandData +[15:26.18.183] (SSH-Browser) ExecuteCommandClose +[15:26.18.183] BEGIN CWD +[15:26.18.184] (CWD) TenterDeTrouverLeCWD: Minute=1 / Seconde=1 +[15:26.18.273] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:26.18.273] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:26.18.273] (SSH-Browser) END VerifySFTPConnection(1) +[15:26.18.273] END CWD +[15:26.18.303] BEGIN CWD +[15:26.18.364] END CWD + +[15:26.18.837] BEGIN WMNewTab: 20 +[15:26.18.837] END WMNewTab: 20 + + +[15:26.20.255] BEGIN WMNewTab: 20 +[15:26.20.255] END WMNewTab: 20 + + +[15:26.21.674] BEGIN WMNewTab: 20 +[15:26.21.674] END WMNewTab: 20 + +[15:26.22.122] BEGIN WMNewTab: 0 +[15:26.22.122] WMNewTab: FormClick +[15:26.22.122] WMNewTab: LooseFocus +[15:26.22.122] END WMNewTab: 0 +[15:26.22.264] BEGIN WMNewTab: 0 +[15:26.22.264] WMNewTab: FormClick +[15:26.22.264] WMNewTab: LooseFocus +[15:26.22.265] END WMNewTab: 0 +[15:26.22.392] BEGIN WMNewTab: 0 +[15:26.22.392] WMNewTab: FormClick +[15:26.22.392] WMNewTab: LooseFocus +[15:26.22.393] END WMNewTab: 0 +[15:26.22.528] BEGIN WMNewTab: 0 +[15:26.22.528] WMNewTab: FormClick +[15:26.22.528] WMNewTab: LooseFocus +[15:26.22.531] END WMNewTab: 0 +[15:26.22.660] BEGIN WMNewTab: 0 +[15:26.22.660] WMNewTab: FormClick +[15:26.22.660] WMNewTab: LooseFocus +[15:26.22.660] END WMNewTab: 0 +[15:26.22.792] BEGIN WMNewTab: 0 +[15:26.22.792] WMNewTab: FormClick +[15:26.22.792] WMNewTab: LooseFocus +[15:26.22.794] END WMNewTab: 0 +[15:26.22.981] BEGIN WMNewTab: 0 +[15:26.22.981] WMNewTab: FormClick +[15:26.22.981] WMNewTab: LooseFocus +[15:26.22.982] END WMNewTab: 0 +[15:26.23.093] BEGIN WMNewTab: 20 +[15:26.23.093] END WMNewTab: 20 +[15:26.23.104] BEGIN WMNewTab: 0 +[15:26.23.104] WMNewTab: FormClick +[15:26.23.104] WMNewTab: LooseFocus +[15:26.23.106] END WMNewTab: 0 + + +[15:26.24.511] BEGIN WMNewTab: 20 +[15:26.24.511] END WMNewTab: 20 + + +[15:26.25.930] BEGIN WMNewTab: 20 +[15:26.25.930] END WMNewTab: 20 + + +[15:26.27.347] BEGIN WMNewTab: 20 +[15:26.27.347] END WMNewTab: 20 + + +[15:26.28.758] BEGIN WMNewTab: 20 +[15:26.28.758] END WMNewTab: 20 + + +[15:26.30.173] BEGIN WMNewTab: 20 +[15:26.30.173] END WMNewTab: 20 + + +[15:26.31.590] BEGIN WMNewTab: 20 +[15:26.31.590] END WMNewTab: 20 + + +[15:26.33.004] BEGIN WMNewTab: 20 +[15:26.33.004] END WMNewTab: 20 + + +[15:26.34.420] BEGIN WMNewTab: 20 +[15:26.34.420] END WMNewTab: 20 + + +[15:26.35.838] BEGIN WMNewTab: 20 +[15:26.35.838] END WMNewTab: 20 + + +[15:26.37.258] BEGIN WMNewTab: 20 +[15:26.37.258] END WMNewTab: 20 + + +[15:26.38.674] BEGIN WMNewTab: 20 +[15:26.38.674] END WMNewTab: 20 + + +[15:26.40.085] BEGIN WMNewTab: 20 +[15:26.40.085] END WMNewTab: 20 + + +[15:26.41.496] BEGIN WMNewTab: 20 +[15:26.41.496] END WMNewTab: 20 + + +[15:26.42.912] BEGIN WMNewTab: 20 +[15:26.42.912] END WMNewTab: 20 + + +[15:26.44.323] BEGIN WMNewTab: 20 +[15:26.44.323] END WMNewTab: 20 + + +[15:26.45.744] BEGIN WMNewTab: 20 +[15:26.45.744] END WMNewTab: 20 + + +[15:26.47.162] BEGIN WMNewTab: 20 +[15:26.47.162] END WMNewTab: 20 + + +[15:26.48.577] BEGIN WMNewTab: 20 +[15:26.48.577] END WMNewTab: 20 + +[15:26.49.019] BEGIN WMNewTab: 0 +[15:26.49.019] WMNewTab: FormClick +[15:26.49.019] WMNewTab: LooseFocus +[15:26.49.019] END WMNewTab: 0 + +[15:26.49.993] BEGIN WMNewTab: 20 +[15:26.49.993] END WMNewTab: 20 + +[15:26.50.754] BEGIN WMNewTab: 0 +[15:26.50.754] WMNewTab: FormClick +[15:26.50.754] WMNewTab: LooseFocus +[15:26.50.757] END WMNewTab: 0 + +[15:26.51.410] BEGIN WMNewTab: 20 +[15:26.51.410] END WMNewTab: 20 + + +[15:26.52.824] BEGIN WMNewTab: 20 +[15:26.52.824] END WMNewTab: 20 + + +[15:26.54.243] BEGIN WMNewTab: 20 +[15:26.54.243] END WMNewTab: 20 + + +[15:26.55.661] BEGIN WMNewTab: 20 +[15:26.55.661] END WMNewTab: 20 + + +[15:26.57.081] BEGIN WMNewTab: 20 +[15:26.57.081] END WMNewTab: 20 + + +[15:26.58.483] BEGIN WMNewTab: 20 +[15:26.58.483] END WMNewTab: 20 + + +[15:26.59.893] BEGIN WMNewTab: 20 +[15:26.59.893] END WMNewTab: 20 + + +[15:27.01.308] BEGIN WMNewTab: 20 +[15:27.01.308] END WMNewTab: 20 + + +[15:27.02.727] BEGIN WMNewTab: 20 +[15:27.02.727] END WMNewTab: 20 + + +[15:27.04.145] BEGIN WMNewTab: 20 +[15:27.04.145] END WMNewTab: 20 + + +[15:27.05.561] BEGIN WMNewTab: 20 +[15:27.05.561] END WMNewTab: 20 + + +[15:27.06.976] BEGIN WMNewTab: 20 +[15:27.06.976] END WMNewTab: 20 + + +[15:27.08.389] BEGIN WMNewTab: 20 +[15:27.08.389] END WMNewTab: 20 + + +[15:27.09.804] BEGIN WMNewTab: 20 +[15:27.09.804] END WMNewTab: 20 + + +[15:27.11.223] BEGIN WMNewTab: 20 +[15:27.11.223] END WMNewTab: 20 + + +[15:27.12.637] BEGIN WMNewTab: 20 +[15:27.12.637] END WMNewTab: 20 + + +[15:27.14.055] BEGIN WMNewTab: 20 +[15:27.14.055] END WMNewTab: 20 + + +[15:27.15.501] BEGIN WMNewTab: 20 +[15:27.15.501] END WMNewTab: 20 + + +[15:27.16.924] BEGIN WMNewTab: 20 +[15:27.16.924] END WMNewTab: 20 + + +[15:27.18.341] BEGIN WMNewTab: 20 +[15:27.18.341] END WMNewTab: 20 + + +[15:27.19.761] BEGIN WMNewTab: 20 +[15:27.19.761] END WMNewTab: 20 + + +[15:27.21.184] BEGIN WMNewTab: 20 +[15:27.21.184] END WMNewTab: 20 + + +[15:27.22.598] BEGIN WMNewTab: 20 +[15:27.22.598] END WMNewTab: 20 + + +[15:27.24.014] BEGIN WMNewTab: 20 +[15:27.24.014] END WMNewTab: 20 + + +[15:27.25.430] BEGIN WMNewTab: 20 +[15:27.25.430] END WMNewTab: 20 + + +[15:27.26.841] BEGIN WMNewTab: 20 +[15:27.26.841] END WMNewTab: 20 + + +[15:27.28.258] BEGIN WMNewTab: 20 +[15:27.28.258] END WMNewTab: 20 + + +[15:27.29.672] BEGIN WMNewTab: 20 +[15:27.29.672] END WMNewTab: 20 + + +[15:27.31.086] BEGIN WMNewTab: 20 +[15:27.31.086] END WMNewTab: 20 + + +[15:27.32.497] BEGIN WMNewTab: 20 +[15:27.32.497] END WMNewTab: 20 + + +[15:27.33.914] BEGIN WMNewTab: 20 +[15:27.33.914] END WMNewTab: 20 + + +[15:27.35.329] BEGIN WMNewTab: 20 +[15:27.35.329] END WMNewTab: 20 + + +[15:27.36.745] BEGIN WMNewTab: 20 +[15:27.36.745] END WMNewTab: 20 + + +[15:27.38.152] BEGIN WMNewTab: 20 +[15:27.38.152] END WMNewTab: 20 + + +[15:27.39.564] BEGIN WMNewTab: 20 +[15:27.39.564] END WMNewTab: 20 + + +[15:27.41.028] BEGIN WMNewTab: 20 +[15:27.41.028] END WMNewTab: 20 + + +[15:27.42.444] BEGIN WMNewTab: 20 +[15:27.42.444] END WMNewTab: 20 + + +[15:27.43.863] BEGIN WMNewTab: 20 +[15:27.43.863] END WMNewTab: 20 + + +[15:27.45.276] BEGIN WMNewTab: 20 +[15:27.45.276] END WMNewTab: 20 + + +[15:27.46.682] BEGIN WMNewTab: 20 +[15:27.46.682] END WMNewTab: 20 + + +[15:27.48.100] BEGIN WMNewTab: 20 +[15:27.48.100] END WMNewTab: 20 + + +[15:27.49.513] BEGIN WMNewTab: 20 +[15:27.49.513] END WMNewTab: 20 + + +[15:27.50.929] BEGIN WMNewTab: 20 +[15:27.50.929] END WMNewTab: 20 + +[15:27.51.515] BEGIN WMNewTab: 0 +[15:27.51.515] WMNewTab: FormClick +[15:27.51.515] WMNewTab: LooseFocus +[15:27.51.515] END WMNewTab: 0 +[15:27.51.642] BEGIN WMNewTab: 0 +[15:27.51.642] WMNewTab: FormClick +[15:27.51.642] WMNewTab: LooseFocus +[15:27.51.643] END WMNewTab: 0 + +[15:27.52.345] BEGIN WMNewTab: 20 +[15:27.52.345] END WMNewTab: 20 + + +[15:27.53.759] BEGIN WMNewTab: 20 +[15:27.53.759] END WMNewTab: 20 + + +[15:27.55.177] BEGIN WMNewTab: 20 +[15:27.55.177] END WMNewTab: 20 + +[15:27.55.811] BEGIN WMNewTab: 0 +[15:27.55.811] WMNewTab: FormClick +[15:27.55.811] WMNewTab: LooseFocus +[15:27.55.811] END WMNewTab: 0 +[15:27.55.938] BEGIN WMNewTab: 0 +[15:27.55.938] WMNewTab: FormClick +[15:27.55.938] WMNewTab: LooseFocus +[15:27.55.939] END WMNewTab: 0 + +[15:27.56.591] BEGIN WMNewTab: 20 +[15:27.56.591] END WMNewTab: 20 + + +[15:27.58.007] BEGIN WMNewTab: 20 +[15:27.58.007] END WMNewTab: 20 + +[15:27.58.815] BEGIN CWD +[15:27.58.875] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:27.58.875] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:27.58.875] (SSH-Browser) END VerifySFTPConnection(1) +[15:27.58.875] END CWD +[15:27.58.982] BEGIN CWD +[15:27.59.043] END CWD + +[15:27.59.515] BEGIN WMNewTab: 20 +[15:27.59.515] END WMNewTab: 20 + + +[15:28.00.929] BEGIN WMNewTab: 20 +[15:28.00.929] END WMNewTab: 20 + + +[15:28.02.348] BEGIN WMNewTab: 20 +[15:28.02.348] END WMNewTab: 20 + + +[15:28.03.760] BEGIN WMNewTab: 20 +[15:28.03.760] END WMNewTab: 20 + + +[15:28.05.175] BEGIN WMNewTab: 20 +[15:28.05.175] END WMNewTab: 20 + + +[15:28.06.586] BEGIN WMNewTab: 20 +[15:28.06.586] END WMNewTab: 20 + + +[15:28.07.994] BEGIN WMNewTab: 20 +[15:28.07.994] END WMNewTab: 20 + + +[15:28.09.407] BEGIN WMNewTab: 20 +[15:28.09.407] END WMNewTab: 20 + + +[15:28.10.822] BEGIN WMNewTab: 20 +[15:28.10.822] END WMNewTab: 20 + + +[15:28.12.235] BEGIN WMNewTab: 20 +[15:28.12.235] END WMNewTab: 20 + + +[15:28.13.651] BEGIN WMNewTab: 20 +[15:28.13.651] END WMNewTab: 20 + + +[15:28.15.075] BEGIN WMNewTab: 20 +[15:28.15.075] END WMNewTab: 20 + + +[15:28.16.492] BEGIN WMNewTab: 20 +[15:28.16.492] END WMNewTab: 20 +[15:28.16.708] BEGIN WMNewTab: 0 +[15:28.16.708] WMNewTab: FormClick +[15:28.16.708] WMNewTab: LooseFocus +[15:28.16.708] END WMNewTab: 0 +[15:28.16.823] BEGIN WMNewTab: 0 +[15:28.16.823] WMNewTab: FormClick +[15:28.16.823] WMNewTab: LooseFocus +[15:28.16.824] END WMNewTab: 0 + +[15:28.17.905] BEGIN WMNewTab: 20 +[15:28.17.905] END WMNewTab: 20 + + +[15:28.19.323] BEGIN WMNewTab: 20 +[15:28.19.323] END WMNewTab: 20 + + +[15:28.20.741] BEGIN WMNewTab: 20 +[15:28.20.741] END WMNewTab: 20 + + +[15:28.22.154] BEGIN WMNewTab: 20 +[15:28.22.154] END WMNewTab: 20 + + +[15:28.23.571] BEGIN WMNewTab: 20 +[15:28.23.571] END WMNewTab: 20 +[15:28.23.864] BEGIN WMNewTab: 0 +[15:28.23.864] WMNewTab: FormClick +[15:28.23.864] WMNewTab: LooseFocus +[15:28.23.864] END WMNewTab: 0 + +[15:28.24.987] BEGIN WMNewTab: 20 +[15:28.24.987] END WMNewTab: 20 + + +[15:28.26.399] BEGIN WMNewTab: 20 +[15:28.26.399] END WMNewTab: 20 +[15:28.26.627] BEGIN WMNewTab: 0 +[15:28.26.627] WMNewTab: FormClick +[15:28.26.628] WMNewTab: LooseFocus +[15:28.26.630] END WMNewTab: 0 + +[15:28.27.029] BEGIN WMNewTab: 0 +[15:28.27.029] WMNewTab: FormClick +[15:28.27.029] WMNewTab: LooseFocus +[15:28.27.029] END WMNewTab: 0 +[15:28.27.152] BEGIN WMNewTab: 0 +[15:28.27.152] WMNewTab: FormClick +[15:28.27.152] WMNewTab: LooseFocus +[15:28.27.152] END WMNewTab: 0 + +[15:28.27.813] BEGIN WMNewTab: 20 +[15:28.27.813] END WMNewTab: 20 + + +[15:28.29.232] BEGIN WMNewTab: 20 +[15:28.29.232] END WMNewTab: 20 + + +[15:28.30.646] BEGIN WMNewTab: 20 +[15:28.30.646] END WMNewTab: 20 + + +[15:28.32.072] BEGIN WMNewTab: 20 +[15:28.32.072] END WMNewTab: 20 + + +[15:28.33.480] BEGIN WMNewTab: 20 +[15:28.33.480] END WMNewTab: 20 + + +[15:28.34.892] BEGIN WMNewTab: 20 +[15:28.34.892] END WMNewTab: 20 + + +[15:28.36.307] BEGIN WMNewTab: 20 +[15:28.36.307] END WMNewTab: 20 + +[15:28.36.892] BEGIN WMNewTab: 0 +[15:28.36.892] WMNewTab: FormClick +[15:28.36.892] WMNewTab: LooseFocus +[15:28.36.892] END WMNewTab: 0 + +[15:28.37.724] BEGIN WMNewTab: 20 +[15:28.37.724] END WMNewTab: 20 +[15:28.37.984] BEGIN WMNewTab: 0 +[15:28.37.984] WMNewTab: FormClick +[15:28.37.984] WMNewTab: LooseFocus +[15:28.37.987] END WMNewTab: 0 + +[15:28.39.139] BEGIN WMNewTab: 20 +[15:28.39.139] END WMNewTab: 20 + + +[15:28.40.551] BEGIN WMNewTab: 20 +[15:28.40.551] END WMNewTab: 20 + + +[15:28.41.962] BEGIN WMNewTab: 20 +[15:28.41.962] END WMNewTab: 20 + + +[15:28.43.375] BEGIN WMNewTab: 20 +[15:28.43.375] END WMNewTab: 20 + + +[15:28.44.787] BEGIN WMNewTab: 20 +[15:28.44.787] END WMNewTab: 20 + + +[15:28.46.200] BEGIN WMNewTab: 20 +[15:28.46.200] END WMNewTab: 20 + + +[15:28.47.616] BEGIN WMNewTab: 20 +[15:28.47.616] END WMNewTab: 20 + + +[15:28.49.030] BEGIN WMNewTab: 20 +[15:28.49.030] END WMNewTab: 20 + + +[15:28.50.467] BEGIN WMNewTab: 20 +[15:28.50.467] END WMNewTab: 20 + + +[15:28.51.869] BEGIN WMNewTab: 20 +[15:28.51.869] END WMNewTab: 20 + +[15:28.52.433] BEGIN WMNewTab: 0 +[15:28.52.433] WMNewTab: FormClick +[15:28.52.433] WMNewTab: LooseFocus +[15:28.52.433] END WMNewTab: 0 +[15:28.52.536] BEGIN WMNewTab: 0 +[15:28.52.536] WMNewTab: FormClick +[15:28.52.536] WMNewTab: LooseFocus +[15:28.52.537] END WMNewTab: 0 + +[15:28.53.286] BEGIN CWD +[15:28.53.286] BEGIN WMNewTab: 20 +[15:28.53.286] END WMNewTab: 20 +[15:28.53.346] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:28.53.346] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:28.53.346] (SSH-Browser) END VerifySFTPConnection(1) +[15:28.53.346] END CWD +[15:28.53.362] BEGIN CWD +[15:28.53.424] END CWD + + +[15:28.54.840] BEGIN WMNewTab: 20 +[15:28.54.840] END WMNewTab: 20 + + +[15:28.56.253] BEGIN WMNewTab: 20 +[15:28.56.253] END WMNewTab: 20 + + +[15:28.57.676] BEGIN WMNewTab: 20 +[15:28.57.676] END WMNewTab: 20 + + +[15:28.59.091] BEGIN WMNewTab: 20 +[15:28.59.091] END WMNewTab: 20 + + +[15:29.00.503] BEGIN WMNewTab: 20 +[15:29.00.503] END WMNewTab: 20 + + +[15:29.01.919] BEGIN WMNewTab: 20 +[15:29.01.919] END WMNewTab: 20 + + +[15:29.03.337] BEGIN WMNewTab: 20 +[15:29.03.337] END WMNewTab: 20 + + +[15:29.04.751] BEGIN WMNewTab: 20 +[15:29.04.751] END WMNewTab: 20 + + +[15:29.06.171] BEGIN WMNewTab: 20 +[15:29.06.171] END WMNewTab: 20 + + +[15:29.07.589] BEGIN WMNewTab: 20 +[15:29.07.589] END WMNewTab: 20 + + +[15:29.09.009] BEGIN WMNewTab: 20 +[15:29.09.009] END WMNewTab: 20 + + +[15:29.10.319] BEGIN CWD +[15:29.10.379] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:29.10.379] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:29.10.379] (SSH-Browser) END VerifySFTPConnection(1) +[15:29.10.379] END CWD +[15:29.10.426] BEGIN WMNewTab: 20 +[15:29.10.426] END WMNewTab: 20 +[15:29.10.457] BEGIN CWD +[15:29.10.518] END CWD + + +[15:29.11.934] BEGIN WMNewTab: 20 +[15:29.11.934] END WMNewTab: 20 + + +[15:29.13.356] BEGIN WMNewTab: 20 +[15:29.13.356] END WMNewTab: 20 + +[15:29.13.766] BEGIN CWD +[15:29.13.826] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:29.13.826] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:29.13.826] (SSH-Browser) END VerifySFTPConnection(1) +[15:29.13.826] END CWD +[15:29.13.856] BEGIN CWD +[15:29.13.916] END CWD + +[15:29.14.862] BEGIN WMNewTab: 20 +[15:29.14.862] END WMNewTab: 20 + + +[15:29.16.278] BEGIN WMNewTab: 20 +[15:29.16.278] END WMNewTab: 20 + + +[15:29.17.696] BEGIN WMNewTab: 20 +[15:29.17.696] END WMNewTab: 20 + + +[15:29.19.110] BEGIN WMNewTab: 20 +[15:29.19.110] END WMNewTab: 20 + + +[15:29.20.523] BEGIN WMNewTab: 20 +[15:29.20.523] END WMNewTab: 20 + + +[15:29.21.939] BEGIN WMNewTab: 20 +[15:29.21.939] END WMNewTab: 20 + + +[15:29.23.359] BEGIN WMNewTab: 20 +[15:29.23.359] END WMNewTab: 20 + + +[15:29.24.768] BEGIN WMNewTab: 20 +[15:29.24.768] END WMNewTab: 20 + +[15:29.25.819] GetMinWidth = 1848 +[15:29.25.820] BEGIN TFormXterm.FormResize +[15:29.25.820] TFormXterm.FormResize: CenterBtnReattachTab +[15:29.25.823] TFormXterm.FormResize: SplitModeResize +[15:29.25.823] TFormXterm.FormResize: BtnSplitNo.Down +[15:29.25.824] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:29.25.824] BEGIN ResizeTerminal +[15:29.25.842] END ResizeTerminal +[15:29.25.842] TFormXterm.FormResize: AdaptSidebarArrows; +[15:29.25.842] BEGIN AdaptSidebarArrows +[15:29.25.842] END AdaptSidebarArrows +[15:29.25.842] TFormXterm.FormResize: AdaptTV2; +[15:29.25.842] END TFormXterm.FormResize +[15:29.25.934] GetMinWidth = 1860 +[15:29.25.937] BEGIN TFormXterm.FormResize +[15:29.25.937] TFormXterm.FormResize: CenterBtnReattachTab +[15:29.25.944] TFormXterm.FormResize: SplitModeResize +[15:29.25.944] TFormXterm.FormResize: BtnSplitNo.Down +[15:29.25.944] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:29.25.944] BEGIN ResizeTerminal +[15:29.25.969] END ResizeTerminal +[15:29.25.969] TFormXterm.FormResize: AdaptSidebarArrows; +[15:29.25.969] BEGIN AdaptSidebarArrows +[15:29.25.969] END AdaptSidebarArrows +[15:29.25.969] TFormXterm.FormResize: AdaptTV2; +[15:29.25.969] END TFormXterm.FormResize +[15:29.26.050] GetMinWidth = 1867 +[15:29.26.050] BEGIN TFormXterm.FormResize +[15:29.26.050] TFormXterm.FormResize: CenterBtnReattachTab +[15:29.26.054] TFormXterm.FormResize: SplitModeResize +[15:29.26.054] TFormXterm.FormResize: BtnSplitNo.Down +[15:29.26.054] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:29.26.054] BEGIN ResizeTerminal +[15:29.26.082] END ResizeTerminal +[15:29.26.082] TFormXterm.FormResize: AdaptSidebarArrows; +[15:29.26.082] BEGIN AdaptSidebarArrows +[15:29.26.082] END AdaptSidebarArrows +[15:29.26.082] TFormXterm.FormResize: AdaptTV2; +[15:29.26.082] END TFormXterm.FormResize +[15:29.26.151] GetMinWidth = 1868 +[15:29.26.151] BEGIN TFormXterm.FormResize +[15:29.26.151] TFormXterm.FormResize: CenterBtnReattachTab +[15:29.26.155] TFormXterm.FormResize: SplitModeResize +[15:29.26.155] TFormXterm.FormResize: BtnSplitNo.Down +[15:29.26.156] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:29.26.156] BEGIN ResizeTerminal +[15:29.26.176] BEGIN WMNewTab: 20 +[15:29.26.176] END WMNewTab: 20 +[15:29.26.180] END ResizeTerminal +[15:29.26.180] TFormXterm.FormResize: AdaptSidebarArrows; +[15:29.26.180] BEGIN AdaptSidebarArrows +[15:29.26.180] END AdaptSidebarArrows +[15:29.26.180] TFormXterm.FormResize: AdaptTV2; +[15:29.26.180] END TFormXterm.FormResize +[15:29.26.181] GetMinWidth = 1868 +[15:29.26.181] BEGIN TFormXterm.FormResize +[15:29.26.181] TFormXterm.FormResize: CenterBtnReattachTab +[15:29.26.181] TFormXterm.FormResize: SplitModeResize +[15:29.26.181] TFormXterm.FormResize: BtnSplitNo.Down +[15:29.26.181] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:29.26.181] BEGIN ResizeTerminal +[15:29.26.182] END ResizeTerminal +[15:29.26.182] TFormXterm.FormResize: AdaptSidebarArrows; +[15:29.26.182] BEGIN AdaptSidebarArrows +[15:29.26.182] END AdaptSidebarArrows +[15:29.26.182] TFormXterm.FormResize: AdaptTV2; +[15:29.26.182] END TFormXterm.FormResize +[15:29.26.394] BEGIN WMNewTab: 0 +[15:29.26.394] WMNewTab: FormClick +[15:29.26.394] WMNewTab: LooseFocus +[15:29.26.398] END WMNewTab: 0 +[15:29.26.745] BEGIN WMNewTab: 0 +[15:29.26.745] WMNewTab: FormClick +[15:29.26.745] WMNewTab: LooseFocus +[15:29.26.749] END WMNewTab: 0 + +[15:29.27.591] BEGIN WMNewTab: 20 +[15:29.27.591] END WMNewTab: 20 + + +[15:29.29.006] BEGIN WMNewTab: 20 +[15:29.29.006] END WMNewTab: 20 + + +[15:29.30.427] BEGIN WMNewTab: 20 +[15:29.30.427] END WMNewTab: 20 + + +[15:29.31.642] BEGIN WMNewTab: 0 +[15:29.31.642] WMNewTab: FormClick +[15:29.31.642] WMNewTab: LooseFocus +[15:29.31.642] END WMNewTab: 0 +[15:29.31.713] BEGIN WMNewTab: 0 +[15:29.31.713] WMNewTab: FormClick +[15:29.31.713] WMNewTab: LooseFocus +[15:29.31.713] END WMNewTab: 0 +[15:29.31.849] BEGIN WMNewTab: 20 +[15:29.31.849] END WMNewTab: 20 + + +[15:29.33.265] BEGIN WMNewTab: 20 +[15:29.33.265] END WMNewTab: 20 + + +[15:29.34.680] BEGIN WMNewTab: 20 +[15:29.34.680] END WMNewTab: 20 + + +[15:29.36.096] BEGIN WMNewTab: 20 +[15:29.36.096] END WMNewTab: 20 + + +[15:29.37.509] BEGIN WMNewTab: 20 +[15:29.37.509] END WMNewTab: 20 + +[15:29.38.466] BEGIN CWD +[15:29.38.526] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:29.38.526] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:29.38.526] (SSH-Browser) END VerifySFTPConnection(1) +[15:29.38.526] END CWD +[15:29.38.544] BEGIN CWD +[15:29.38.604] END CWD +[15:29.38.860] BEGIN CWD +[15:29.38.921] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:29.38.921] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:29.38.921] (SSH-Browser) END VerifySFTPConnection(1) +[15:29.38.921] END CWD +[15:29.38.922] BEGIN WMNewTab: 20 +[15:29.38.922] END WMNewTab: 20 +[15:29.38.937] BEGIN CWD +[15:29.38.998] END CWD +[15:29.39.074] BEGIN CWD +[15:29.39.135] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:29.39.135] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:29.39.135] (SSH-Browser) END VerifySFTPConnection(1) +[15:29.39.135] END CWD +[15:29.39.148] BEGIN CWD +[15:29.39.208] END CWD + +[15:29.40.148] BEGIN WMNewTab: 20 +[15:29.40.148] END WMNewTab: 20 + + +[15:29.41.560] BEGIN WMNewTab: 20 +[15:29.41.560] END WMNewTab: 20 + + +[15:29.42.970] BEGIN WMNewTab: 20 +[15:29.42.970] END WMNewTab: 20 + + +[15:29.44.391] BEGIN WMNewTab: 20 +[15:29.44.391] END WMNewTab: 20 + +[15:29.45.035] BEGIN WMNewTab: 0 +[15:29.45.035] WMNewTab: FormClick +[15:29.45.035] WMNewTab: LooseFocus +[15:29.45.035] END WMNewTab: 0 + +[15:29.45.506] BEGIN WMNewTab: 0 +[15:29.45.506] WMNewTab: FormClick +[15:29.45.506] WMNewTab: LooseFocus +[15:29.45.508] END WMNewTab: 0 +[15:29.45.809] BEGIN WMNewTab: 20 +[15:29.45.809] END WMNewTab: 20 + + +[15:29.47.228] BEGIN WMNewTab: 20 +[15:29.47.228] END WMNewTab: 20 + + +[15:29.48.641] BEGIN WMNewTab: 20 +[15:29.48.641] END WMNewTab: 20 + + +[15:29.50.054] BEGIN WMNewTab: 20 +[15:29.50.054] END WMNewTab: 20 + + +[15:29.51.466] BEGIN WMNewTab: 20 +[15:29.51.466] END WMNewTab: 20 + + +[15:29.52.877] BEGIN WMNewTab: 20 +[15:29.52.877] END WMNewTab: 20 + + +[15:29.54.293] BEGIN WMNewTab: 20 +[15:29.54.293] END WMNewTab: 20 + + +[15:29.55.710] BEGIN WMNewTab: 20 +[15:29.55.710] END WMNewTab: 20 + + +[15:29.57.122] BEGIN WMNewTab: 20 +[15:29.57.122] END WMNewTab: 20 + + +[15:29.58.536] BEGIN WMNewTab: 20 +[15:29.58.536] END WMNewTab: 20 + +[15:29.59.523] BEGIN WMSysCommand (minimize/restore) +[15:29.59.553] BEGIN WMSize +[15:29.59.553] END WMSize +[15:29.59.584] END WMSysCommand + +[15:29.59.950] BEGIN WMNewTab: 20 +[15:29.59.950] END WMNewTab: 20 + + +[15:30.01.365] BEGIN WMNewTab: 20 +[15:30.01.365] END WMNewTab: 20 + + +[15:30.02.779] BEGIN WMNewTab: 20 +[15:30.02.779] END WMNewTab: 20 + + +[15:30.04.196] BEGIN WMNewTab: 20 +[15:30.04.196] END WMNewTab: 20 + + +[15:30.05.608] BEGIN WMNewTab: 20 +[15:30.05.608] END WMNewTab: 20 + + +[15:30.07.023] BEGIN WMNewTab: 20 +[15:30.07.023] END WMNewTab: 20 + + +[15:30.08.443] BEGIN WMNewTab: 20 +[15:30.08.443] END WMNewTab: 20 + + +[15:30.09.854] BEGIN WMNewTab: 20 +[15:30.09.854] END WMNewTab: 20 + + +[15:30.11.271] BEGIN WMNewTab: 20 +[15:30.11.271] END WMNewTab: 20 + + +[15:30.12.689] BEGIN WMNewTab: 20 +[15:30.12.689] END WMNewTab: 20 + + +[15:30.14.129] BEGIN WMNewTab: 20 +[15:30.14.129] END WMNewTab: 20 + + +[15:30.15.529] BEGIN WMNewTab: 20 +[15:30.15.529] END WMNewTab: 20 + + +[15:30.16.945] BEGIN WMNewTab: 20 +[15:30.16.945] END WMNewTab: 20 + + +[15:30.18.284] BEGIN WMSysCommand (minimize/restore) +[15:30.18.284] BEGIN WMNewTab: 0 +[15:30.18.284] WMNewTab: FormClick +[15:30.18.284] WMNewTab: LooseFocus +[15:30.18.285] END WMNewTab: 0 +[15:30.18.385] BEGIN WMSize +[15:30.18.385] BEGIN TFormXterm.FormResize +[15:30.18.385] TFormXterm.FormResize: CenterBtnReattachTab +[15:30.18.385] TFormXterm.FormResize: SplitModeResize +[15:30.18.385] TFormXterm.FormResize: BtnSplitNo.Down +[15:30.18.385] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:30.18.385] BEGIN ResizeTerminal +[15:30.18.385] BEGIN WMNewTab: 20 +[15:30.18.385] END WMNewTab: 20 +[15:30.18.386] END ResizeTerminal +[15:30.18.386] TFormXterm.FormResize: AdaptSidebarArrows; +[15:30.18.386] BEGIN AdaptSidebarArrows +[15:30.18.386] END AdaptSidebarArrows +[15:30.18.386] TFormXterm.FormResize: AdaptTV2; +[15:30.18.386] END TFormXterm.FormResize +[15:30.18.386] END WMSize +[15:30.18.390] END WMSysCommand +[15:30.18.740] BEGIN WMNewTab: 0 +[15:30.18.740] WMNewTab: FormClick +[15:30.18.740] WMNewTab: LooseFocus +[15:30.18.740] END WMNewTab: 0 +[15:30.18.851] BEGIN WMNewTab: 0 +[15:30.18.851] WMNewTab: FormClick +[15:30.18.851] WMNewTab: LooseFocus +[15:30.18.853] END WMNewTab: 0 + +[15:30.19.788] BEGIN WMNewTab: 20 +[15:30.19.788] END WMNewTab: 20 + + +[15:30.21.204] BEGIN WMNewTab: 20 +[15:30.21.204] END WMNewTab: 20 + + +[15:30.22.624] BEGIN WMNewTab: 20 +[15:30.22.624] END WMNewTab: 20 +[15:30.22.977] BEGIN CWD +[15:30.23.037] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:30.23.037] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:30.23.037] (SSH-Browser) END VerifySFTPConnection(1) +[15:30.23.037] END CWD +[15:30.23.129] BEGIN CWD +[15:30.23.191] END CWD + +[15:30.24.134] BEGIN WMNewTab: 20 +[15:30.24.134] END WMNewTab: 20 + + +[15:30.25.553] BEGIN WMNewTab: 20 +[15:30.25.553] END WMNewTab: 20 + + +[15:30.26.968] BEGIN WMNewTab: 20 +[15:30.26.968] END WMNewTab: 20 + + +[15:30.28.412] BEGIN WMNewTab: 20 +[15:30.28.412] END WMNewTab: 20 + + +[15:30.29.821] BEGIN WMNewTab: 20 +[15:30.29.821] END WMNewTab: 20 + + +[15:30.31.240] BEGIN WMNewTab: 20 +[15:30.31.240] END WMNewTab: 20 + + +[15:30.32.656] BEGIN WMNewTab: 20 +[15:30.32.656] END WMNewTab: 20 + + +[15:30.34.069] BEGIN WMNewTab: 20 +[15:30.34.069] END WMNewTab: 20 + + +[15:30.35.486] BEGIN WMNewTab: 20 +[15:30.35.486] END WMNewTab: 20 + + +[15:30.36.901] BEGIN WMNewTab: 20 +[15:30.36.902] END WMNewTab: 20 + + +[15:30.38.326] BEGIN WMNewTab: 20 +[15:30.38.326] END WMNewTab: 20 + +[15:30.38.997] BEGIN CWD +[15:30.39.058] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:30.39.058] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:30.39.058] (SSH-Browser) END VerifySFTPConnection(1) +[15:30.39.058] END CWD +[15:30.39.073] BEGIN CWD +[15:30.39.133] END CWD + +[15:30.39.594] BEGIN WMNewTab: 20 +[15:30.39.594] END WMNewTab: 20 + + +[15:30.41.012] BEGIN WMNewTab: 20 +[15:30.41.012] END WMNewTab: 20 + + +[15:30.42.432] BEGIN WMNewTab: 20 +[15:30.42.433] END WMNewTab: 20 + + +[15:30.43.854] BEGIN WMNewTab: 20 +[15:30.43.854] END WMNewTab: 20 + +[15:30.44.613] BEGIN CWD +[15:30.44.673] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:30.44.673] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:30.44.673] (SSH-Browser) END VerifySFTPConnection(1) +[15:30.44.673] END CWD +[15:30.44.678] BEGIN CWD +[15:30.44.738] END CWD + +[15:30.45.210] BEGIN WMNewTab: 20 +[15:30.45.210] END WMNewTab: 20 + + +[15:30.46.631] BEGIN WMNewTab: 20 +[15:30.46.631] END WMNewTab: 20 + + +[15:30.48.051] BEGIN WMNewTab: 20 +[15:30.48.051] END WMNewTab: 20 + + +[15:30.49.462] BEGIN WMNewTab: 20 +[15:30.49.462] END WMNewTab: 20 +[15:30.49.583] BEGIN CWD +[15:30.49.643] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:30.49.643] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:30.49.643] (SSH-Browser) END VerifySFTPConnection(1) +[15:30.49.643] END CWD +[15:30.49.659] BEGIN CWD +[15:30.49.721] END CWD + +[15:30.50.665] BEGIN WMNewTab: 20 +[15:30.50.665] END WMNewTab: 20 + + +[15:30.52.084] BEGIN WMNewTab: 20 +[15:30.52.084] END WMNewTab: 20 + + +[15:30.53.504] BEGIN WMNewTab: 20 +[15:30.53.504] END WMNewTab: 20 + +[15:30.54.015] BEGIN CWD +[15:30.54.075] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:30.54.075] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:30.54.075] (SSH-Browser) END VerifySFTPConnection(1) +[15:30.54.075] END CWD +[15:30.54.081] BEGIN CWD +[15:30.54.141] END CWD + +[15:30.55.090] BEGIN WMNewTab: 20 +[15:30.55.090] END WMNewTab: 20 + + +[15:30.56.507] BEGIN WMNewTab: 20 +[15:30.56.507] END WMNewTab: 20 +[15:30.56.507] BEGIN CWD +[15:30.56.567] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:30.56.567] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:30.56.567] (SSH-Browser) END VerifySFTPConnection(1) +[15:30.56.567] END CWD +[15:30.56.582] BEGIN CWD +[15:30.56.642] END CWD + + +[15:30.58.082] BEGIN WMNewTab: 20 +[15:30.58.082] END WMNewTab: 20 + + +[15:30.59.486] BEGIN WMNewTab: 20 +[15:30.59.486] END WMNewTab: 20 + +[15:31.00.149] BEGIN WMNewTab: 0 +[15:31.00.149] WMNewTab: FormClick +[15:31.00.149] WMNewTab: LooseFocus +[15:31.00.149] END WMNewTab: 0 + +[15:31.00.902] BEGIN WMNewTab: 20 +[15:31.00.902] END WMNewTab: 20 + +[15:31.01.356] BEGIN WMNewTab: 0 +[15:31.01.356] WMNewTab: FormClick +[15:31.01.356] WMNewTab: LooseFocus +[15:31.01.358] END WMNewTab: 0 + +[15:31.02.312] BEGIN WMNewTab: 20 +[15:31.02.312] END WMNewTab: 20 + +[15:31.02.694] BEGIN WMNewTab: 0 +[15:31.02.694] WMNewTab: FormClick +[15:31.02.694] WMNewTab: LooseFocus +[15:31.02.698] END WMNewTab: 0 +[15:31.02.780] BEGIN WMNewTab: 0 +[15:31.02.780] WMNewTab: FormClick +[15:31.02.780] WMNewTab: LooseFocus +[15:31.02.781] END WMNewTab: 0 + +[15:31.03.731] BEGIN WMNewTab: 20 +[15:31.03.731] END WMNewTab: 20 + +[15:31.04.349] BEGIN WMNewTab: 0 +[15:31.04.349] WMNewTab: FormClick +[15:31.04.349] WMNewTab: LooseFocus +[15:31.04.349] END WMNewTab: 0 + +[15:31.05.144] BEGIN WMNewTab: 20 +[15:31.05.144] END WMNewTab: 20 + +[15:31.05.604] BEGIN WMNewTab: 0 +[15:31.05.604] WMNewTab: FormClick +[15:31.05.604] WMNewTab: LooseFocus +[15:31.05.607] END WMNewTab: 0 + +[15:31.06.557] BEGIN WMNewTab: 20 +[15:31.06.557] END WMNewTab: 20 + + +[15:31.07.972] BEGIN WMNewTab: 20 +[15:31.07.972] END WMNewTab: 20 + + +[15:31.09.386] BEGIN WMNewTab: 20 +[15:31.09.386] END WMNewTab: 20 + + +[15:31.10.799] BEGIN WMNewTab: 20 +[15:31.10.799] END WMNewTab: 20 + + +[15:31.12.214] BEGIN WMNewTab: 20 +[15:31.12.214] END WMNewTab: 20 + + +[15:31.13.627] BEGIN WMNewTab: 20 +[15:31.13.627] END WMNewTab: 20 + + +[15:31.15.044] BEGIN WMNewTab: 20 +[15:31.15.044] END WMNewTab: 20 + + +[15:31.16.456] BEGIN WMNewTab: 20 +[15:31.16.456] END WMNewTab: 20 + + +[15:31.17.874] BEGIN WMNewTab: 20 +[15:31.17.874] END WMNewTab: 20 + + +[15:31.19.292] BEGIN WMNewTab: 20 +[15:31.19.292] END WMNewTab: 20 + + +[15:31.20.705] BEGIN WMNewTab: 20 +[15:31.20.705] END WMNewTab: 20 +[15:31.20.813] BEGIN WMNewTab: 0 +[15:31.20.813] WMNewTab: FormClick +[15:31.20.813] WMNewTab: LooseFocus +[15:31.20.813] END WMNewTab: 0 +[15:31.20.956] BEGIN WMNewTab: 0 +[15:31.20.956] WMNewTab: FormClick +[15:31.20.956] WMNewTab: LooseFocus +[15:31.20.957] END WMNewTab: 0 + +[15:31.22.120] BEGIN WMNewTab: 20 +[15:31.22.120] END WMNewTab: 20 + + +[15:31.23.533] BEGIN WMNewTab: 20 +[15:31.23.533] END WMNewTab: 20 + + +[15:31.24.950] BEGIN WMNewTab: 20 +[15:31.24.950] END WMNewTab: 20 + +[15:31.25.697] BEGIN CWD +[15:31.25.758] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:31.25.758] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:31.25.758] (SSH-Browser) END VerifySFTPConnection(1) +[15:31.25.758] END CWD +[15:31.25.772] BEGIN CWD +[15:31.25.833] END CWD + +[15:31.26.306] BEGIN WMNewTab: 20 +[15:31.26.306] END WMNewTab: 20 + + +[15:31.27.722] BEGIN WMNewTab: 20 +[15:31.27.722] END WMNewTab: 20 + + +[15:31.29.135] BEGIN WMNewTab: 20 +[15:31.29.135] END WMNewTab: 20 + + +[15:31.30.545] BEGIN WMNewTab: 20 +[15:31.30.545] END WMNewTab: 20 + + +[15:31.31.960] BEGIN WMNewTab: 20 +[15:31.31.960] END WMNewTab: 20 + + +[15:31.33.375] BEGIN WMNewTab: 20 +[15:31.33.375] END WMNewTab: 20 + + +[15:31.34.818] BEGIN WMNewTab: 20 +[15:31.34.818] END WMNewTab: 20 + + +[15:31.36.226] BEGIN WMNewTab: 20 +[15:31.36.226] END WMNewTab: 20 +[15:31.36.426] BEGIN WMNewTab: 0 +[15:31.36.426] WMNewTab: FormClick +[15:31.36.426] WMNewTab: LooseFocus +[15:31.36.426] END WMNewTab: 0 +[15:31.36.426] BEGIN WMNewTab: 31 +[15:31.36.426] END WMNewTab: 31 +[15:31.36.541] BEGIN WMNewTab: 0 +[15:31.36.541] WMNewTab: FormClick +[15:31.36.541] WMNewTab: LooseFocus +[15:31.36.542] END WMNewTab: 0 + +[15:31.37.364] BEGIN CWD +[15:31.37.425] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:31.37.425] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:31.37.425] (SSH-Browser) END VerifySFTPConnection(1) +[15:31.37.425] END CWD +[15:31.37.431] BEGIN CWD +[15:31.37.492] END CWD +[15:31.37.492] BEGIN WMNewTab: 20 +[15:31.37.492] END WMNewTab: 20 + + +[15:31.38.902] BEGIN WMNewTab: 20 +[15:31.38.902] END WMNewTab: 20 + + +[15:31.40.315] BEGIN WMNewTab: 20 +[15:31.40.315] END WMNewTab: 20 + + +[15:31.41.738] BEGIN WMNewTab: 20 +[15:31.41.738] END WMNewTab: 20 + + +[15:31.43.156] BEGIN WMNewTab: 20 +[15:31.43.156] END WMNewTab: 20 + +[15:31.43.623] BEGIN WMNewTab: 0 +[15:31.43.623] WMNewTab: FormClick +[15:31.43.623] WMNewTab: LooseFocus +[15:31.43.623] END WMNewTab: 0 +[15:31.43.623] BEGIN WMNewTab: 31 +[15:31.43.623] END WMNewTab: 31 +[15:31.43.741] BEGIN WMNewTab: 0 +[15:31.43.741] WMNewTab: FormClick +[15:31.43.741] WMNewTab: LooseFocus +[15:31.43.742] END WMNewTab: 0 + +[15:31.44.370] BEGIN CWD +[15:31.44.430] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:31.44.430] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:31.44.430] (SSH-Browser) END VerifySFTPConnection(1) +[15:31.44.430] END CWD +[15:31.44.431] BEGIN WMNewTab: 20 +[15:31.44.431] END WMNewTab: 20 +[15:31.44.444] BEGIN CWD +[15:31.44.505] END CWD + + +[15:31.45.920] BEGIN WMNewTab: 20 +[15:31.45.920] END WMNewTab: 20 + + +[15:31.47.336] BEGIN WMNewTab: 20 +[15:31.47.336] END WMNewTab: 20 + + +[15:31.48.750] BEGIN WMNewTab: 20 +[15:31.48.750] END WMNewTab: 20 + +[15:31.49.440] BEGIN WMNewTab: 0 +[15:31.49.440] WMNewTab: FormClick +[15:31.49.440] WMNewTab: LooseFocus +[15:31.49.440] END WMNewTab: 0 +[15:31.49.440] BEGIN WMNewTab: 31 +[15:31.49.440] END WMNewTab: 31 +[15:31.49.514] BEGIN WMNewTab: 0 +[15:31.49.514] WMNewTab: FormClick +[15:31.49.514] WMNewTab: LooseFocus +[15:31.49.515] END WMNewTab: 0 + +[15:31.50.168] BEGIN WMNewTab: 20 +[15:31.50.169] END WMNewTab: 20 + +[15:31.50.750] BEGIN CWD +[15:31.50.810] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:31.50.810] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:31.50.810] (SSH-Browser) END VerifySFTPConnection(1) +[15:31.50.810] END CWD +[15:31.50.825] BEGIN CWD +[15:31.50.885] END CWD + +[15:31.51.829] BEGIN WMNewTab: 20 +[15:31.51.829] END WMNewTab: 20 + + +[15:31.53.241] BEGIN WMNewTab: 20 +[15:31.53.241] END WMNewTab: 20 + + +[15:31.54.652] BEGIN WMNewTab: 20 +[15:31.54.652] END WMNewTab: 20 + + +[15:31.56.069] BEGIN WMNewTab: 20 +[15:31.56.069] END WMNewTab: 20 + +[15:31.56.958] BEGIN WMNewTab: 0 +[15:31.56.958] WMNewTab: FormClick +[15:31.56.958] WMNewTab: LooseFocus +[15:31.56.958] END WMNewTab: 0 + +[15:31.57.487] BEGIN WMNewTab: 20 +[15:31.57.487] END WMNewTab: 20 + + +[15:31.58.905] BEGIN WMNewTab: 20 +[15:31.58.905] END WMNewTab: 20 + +[15:31.59.721] BEGIN WMNewTab: 0 +[15:31.59.721] WMNewTab: FormClick +[15:31.59.722] WMNewTab: LooseFocus +[15:31.59.724] END WMNewTab: 0 + +[15:32.00.338] BEGIN WMNewTab: 20 +[15:32.00.338] END WMNewTab: 20 + + +[15:32.01.738] BEGIN WMNewTab: 20 +[15:32.01.738] END WMNewTab: 20 + + +[15:32.03.149] BEGIN WMNewTab: 20 +[15:32.03.149] END WMNewTab: 20 + + +[15:32.04.562] BEGIN WMNewTab: 20 +[15:32.04.562] END WMNewTab: 20 + + +[15:32.05.980] BEGIN WMNewTab: 20 +[15:32.05.980] END WMNewTab: 20 + + +[15:32.07.391] BEGIN WMNewTab: 20 +[15:32.07.391] END WMNewTab: 20 + + +[15:32.08.804] BEGIN WMNewTab: 20 +[15:32.08.804] END WMNewTab: 20 + + +[15:32.10.215] BEGIN WMNewTab: 20 +[15:32.10.215] END WMNewTab: 20 + + +[15:32.11.625] BEGIN WMNewTab: 20 +[15:32.11.625] END WMNewTab: 20 + + +[15:32.13.039] BEGIN WMNewTab: 20 +[15:32.13.039] END WMNewTab: 20 + + +[15:32.14.449] BEGIN WMNewTab: 20 +[15:32.14.449] END WMNewTab: 20 + + +[15:32.15.860] BEGIN WMNewTab: 20 +[15:32.15.860] END WMNewTab: 20 + + +[15:32.17.279] BEGIN WMNewTab: 20 +[15:32.17.279] END WMNewTab: 20 + + +[15:32.18.713] BEGIN WMNewTab: 20 +[15:32.18.713] END WMNewTab: 20 + + +[15:32.20.129] BEGIN WMNewTab: 20 +[15:32.20.129] END WMNewTab: 20 + + +[15:32.21.547] BEGIN WMNewTab: 20 +[15:32.21.547] END WMNewTab: 20 + + +[15:32.22.964] BEGIN WMNewTab: 20 +[15:32.22.964] END WMNewTab: 20 + + +[15:32.24.384] BEGIN WMNewTab: 20 +[15:32.24.384] END WMNewTab: 20 + + +[15:32.25.801] BEGIN WMNewTab: 20 +[15:32.25.801] END WMNewTab: 20 + + +[15:32.27.215] BEGIN WMNewTab: 20 +[15:32.27.215] END WMNewTab: 20 + + +[15:32.28.630] BEGIN WMNewTab: 20 +[15:32.28.630] END WMNewTab: 20 + +[15:32.29.286] BEGIN WMNewTab: 0 +[15:32.29.286] WMNewTab: FormClick +[15:32.29.286] WMNewTab: LooseFocus +[15:32.29.286] END WMNewTab: 0 +[15:32.29.286] BEGIN WMNewTab: 31 +[15:32.29.286] END WMNewTab: 31 +[15:32.29.354] BEGIN WMNewTab: 0 +[15:32.29.354] WMNewTab: FormClick +[15:32.29.354] WMNewTab: LooseFocus +[15:32.29.355] END WMNewTab: 0 + +[15:32.30.043] BEGIN WMNewTab: 20 +[15:32.30.043] END WMNewTab: 20 +[15:32.30.284] BEGIN CWD +[15:32.30.345] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:32.30.345] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:32.30.345] (SSH-Browser) END VerifySFTPConnection(1) +[15:32.30.345] END CWD +[15:32.30.360] BEGIN CWD +[15:32.30.421] END CWD + +[15:32.31.366] BEGIN WMNewTab: 20 +[15:32.31.366] END WMNewTab: 20 + + +[15:32.32.783] BEGIN WMNewTab: 20 +[15:32.32.783] END WMNewTab: 20 + + +[15:32.34.197] BEGIN WMNewTab: 20 +[15:32.34.197] END WMNewTab: 20 + + +[15:32.35.620] BEGIN WMNewTab: 20 +[15:32.35.620] END WMNewTab: 20 + + +[15:32.37.038] BEGIN WMNewTab: 20 +[15:32.37.038] END WMNewTab: 20 + + +[15:32.38.450] BEGIN WMNewTab: 20 +[15:32.38.450] END WMNewTab: 20 + +[15:32.39.035] BEGIN WMNewTab: 0 +[15:32.39.035] WMNewTab: FormClick +[15:32.39.035] WMNewTab: LooseFocus +[15:32.39.035] END WMNewTab: 0 +[15:32.39.035] BEGIN WMNewTab: 31 +[15:32.39.035] END WMNewTab: 31 +[15:32.39.163] BEGIN WMNewTab: 0 +[15:32.39.163] WMNewTab: FormClick +[15:32.39.163] WMNewTab: LooseFocus +[15:32.39.163] END WMNewTab: 0 + +[15:32.39.746] BEGIN CWD +[15:32.39.806] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:32.39.806] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:32.39.806] (SSH-Browser) END VerifySFTPConnection(1) +[15:32.39.806] END CWD +[15:32.39.868] BEGIN WMNewTab: 20 +[15:32.39.868] END WMNewTab: 20 +[15:32.39.897] BEGIN CWD +[15:32.39.959] END CWD + + +[15:32.41.378] BEGIN WMNewTab: 20 +[15:32.41.378] END WMNewTab: 20 + + +[15:32.42.789] BEGIN WMNewTab: 20 +[15:32.42.789] END WMNewTab: 20 + + +[15:32.44.216] BEGIN WMNewTab: 20 +[15:32.44.216] END WMNewTab: 20 + +[15:32.44.987] BEGIN WMNewTab: 0 +[15:32.44.987] WMNewTab: FormClick +[15:32.44.987] WMNewTab: LooseFocus +[15:32.44.987] END WMNewTab: 0 +[15:32.44.987] BEGIN WMNewTab: 31 +[15:32.44.987] END WMNewTab: 31 +[15:32.45.091] BEGIN WMNewTab: 0 +[15:32.45.091] WMNewTab: FormClick +[15:32.45.091] WMNewTab: LooseFocus +[15:32.45.091] END WMNewTab: 0 + +[15:32.45.628] BEGIN WMNewTab: 20 +[15:32.45.628] END WMNewTab: 20 +[15:32.45.898] BEGIN CWD +[15:32.45.958] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:32.45.958] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:32.45.958] (SSH-Browser) END VerifySFTPConnection(1) +[15:32.45.958] END CWD +[15:32.45.976] BEGIN CWD +[15:32.46.036] END CWD + +[15:32.46.984] BEGIN WMNewTab: 20 +[15:32.46.984] END WMNewTab: 20 + + +[15:32.48.399] BEGIN WMNewTab: 20 +[15:32.48.399] END WMNewTab: 20 + + +[15:32.49.810] BEGIN WMNewTab: 20 +[15:32.49.810] END WMNewTab: 20 + + +[15:32.51.228] BEGIN WMNewTab: 20 +[15:32.51.228] END WMNewTab: 20 + +[15:32.52.106] BEGIN WMNewTab: 0 +[15:32.52.106] WMNewTab: FormClick +[15:32.52.106] WMNewTab: LooseFocus +[15:32.52.106] END WMNewTab: 0 +[15:32.52.106] BEGIN WMNewTab: 31 +[15:32.52.106] END WMNewTab: 31 +[15:32.52.195] BEGIN WMNewTab: 0 +[15:32.52.195] WMNewTab: FormClick +[15:32.52.195] WMNewTab: LooseFocus +[15:32.52.196] END WMNewTab: 0 + +[15:32.52.641] BEGIN WMNewTab: 20 +[15:32.52.641] END WMNewTab: 20 +[15:32.52.733] BEGIN CWD +[15:32.52.794] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:32.52.794] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:32.52.794] (SSH-Browser) END VerifySFTPConnection(1) +[15:32.52.794] END CWD +[15:32.52.808] BEGIN CWD +[15:32.52.869] END CWD + + +[15:32.54.285] BEGIN WMNewTab: 20 +[15:32.54.285] END WMNewTab: 20 + + +[15:32.55.700] BEGIN WMNewTab: 20 +[15:32.55.700] END WMNewTab: 20 + + +[15:32.57.113] BEGIN WMNewTab: 20 +[15:32.57.113] END WMNewTab: 20 + + +[15:32.58.524] BEGIN WMNewTab: 20 +[15:32.58.524] END WMNewTab: 20 + + +[15:32.59.944] BEGIN WMNewTab: 20 +[15:32.59.944] END WMNewTab: 20 + + +[15:33.01.359] BEGIN WMNewTab: 20 +[15:33.01.359] END WMNewTab: 20 + + +[15:33.02.780] BEGIN WMNewTab: 20 +[15:33.02.780] END WMNewTab: 20 + + +[15:33.04.196] BEGIN WMNewTab: 20 +[15:33.04.196] END WMNewTab: 20 +[15:33.04.204] BEGIN WMNewTab: 0 +[15:33.04.204] WMNewTab: FormClick +[15:33.04.204] WMNewTab: LooseFocus +[15:33.04.205] END WMNewTab: 0 +[15:33.04.205] BEGIN WMNewTab: 31 +[15:33.04.205] END WMNewTab: 31 +[15:33.04.299] BEGIN WMNewTab: 0 +[15:33.04.299] WMNewTab: FormClick +[15:33.04.299] WMNewTab: LooseFocus +[15:33.04.300] END WMNewTab: 0 + +[15:33.04.907] BEGIN CWD +[15:33.04.968] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:33.04.968] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:33.04.968] (SSH-Browser) END VerifySFTPConnection(1) +[15:33.04.968] END CWD +[15:33.04.986] BEGIN CWD +[15:33.05.046] END CWD + +[15:33.05.517] BEGIN WMNewTab: 20 +[15:33.05.517] END WMNewTab: 20 + + +[15:33.06.927] BEGIN WMNewTab: 20 +[15:33.06.927] END WMNewTab: 20 + + +[15:33.08.341] BEGIN WMNewTab: 20 +[15:33.08.341] END WMNewTab: 20 + + +[15:33.09.572] BEGIN WMNewTab: 0 +[15:33.09.572] WMNewTab: FormClick +[15:33.09.572] WMNewTab: LooseFocus +[15:33.09.572] END WMNewTab: 0 +[15:33.09.572] BEGIN WMNewTab: 31 +[15:33.09.572] END WMNewTab: 31 +[15:33.09.691] BEGIN WMNewTab: 0 +[15:33.09.691] WMNewTab: FormClick +[15:33.09.691] WMNewTab: LooseFocus +[15:33.09.693] END WMNewTab: 0 +[15:33.09.752] BEGIN WMNewTab: 20 +[15:33.09.752] END WMNewTab: 20 + +[15:33.10.239] BEGIN CWD +[15:33.10.299] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:33.10.299] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:33.10.299] (SSH-Browser) END VerifySFTPConnection(1) +[15:33.10.299] END CWD +[15:33.10.316] BEGIN CWD +[15:33.10.376] END CWD + +[15:33.11.318] BEGIN WMNewTab: 20 +[15:33.11.318] END WMNewTab: 20 + + +[15:33.12.731] BEGIN WMNewTab: 20 +[15:33.12.731] END WMNewTab: 20 + + +[15:33.14.148] BEGIN WMNewTab: 20 +[15:33.14.148] END WMNewTab: 20 + + +[15:33.15.562] BEGIN WMNewTab: 20 +[15:33.15.562] END WMNewTab: 20 + + +[15:33.16.979] BEGIN WMNewTab: 20 +[15:33.16.979] END WMNewTab: 20 + + +[15:33.18.392] BEGIN WMNewTab: 20 +[15:33.18.392] END WMNewTab: 20 + + +[15:33.19.807] BEGIN WMNewTab: 20 +[15:33.19.807] END WMNewTab: 20 + + +[15:33.21.225] BEGIN WMNewTab: 20 +[15:33.21.225] END WMNewTab: 20 + + +[15:33.22.641] BEGIN WMNewTab: 20 +[15:33.22.641] END WMNewTab: 20 + + +[15:33.24.056] BEGIN WMNewTab: 20 +[15:33.24.056] END WMNewTab: 20 + + +[15:33.25.479] BEGIN WMNewTab: 20 +[15:33.25.479] END WMNewTab: 20 + + +[15:33.26.897] BEGIN WMNewTab: 20 +[15:33.26.897] END WMNewTab: 20 + + +[15:33.28.316] BEGIN WMNewTab: 20 +[15:33.28.316] END WMNewTab: 20 + + +[15:33.29.735] BEGIN WMNewTab: 20 +[15:33.29.735] END WMNewTab: 20 + + +[15:33.31.167] BEGIN WMNewTab: 20 +[15:33.31.167] END WMNewTab: 20 + + +[15:33.32.577] BEGIN WMNewTab: 20 +[15:33.32.577] END WMNewTab: 20 + + +[15:33.33.993] BEGIN WMNewTab: 20 +[15:33.33.993] END WMNewTab: 20 + + +[15:33.35.402] BEGIN WMNewTab: 20 +[15:33.35.402] END WMNewTab: 20 + + +[15:33.36.818] BEGIN WMNewTab: 20 +[15:33.36.818] END WMNewTab: 20 + +[15:33.38.004] BEGIN WMNewTab: 0 +[15:33.38.004] WMNewTab: FormClick +[15:33.38.004] WMNewTab: LooseFocus +[15:33.38.004] END WMNewTab: 0 +[15:33.38.004] BEGIN WMNewTab: 31 +[15:33.38.004] END WMNewTab: 31 +[15:33.38.229] BEGIN WMNewTab: 20 +[15:33.38.229] END WMNewTab: 20 + + +[15:33.39.460] BEGIN CWD +[15:33.39.520] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:33.39.520] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:33.39.520] (SSH-Browser) END VerifySFTPConnection(1) +[15:33.39.520] END CWD +[15:33.39.522] BEGIN WMNewTab: 20 +[15:33.39.522] END WMNewTab: 20 +[15:33.39.536] BEGIN CWD +[15:33.39.598] END CWD + + +[15:33.41.012] BEGIN WMNewTab: 20 +[15:33.41.012] END WMNewTab: 20 + + +[15:33.42.427] BEGIN WMNewTab: 20 +[15:33.42.427] END WMNewTab: 20 + + +[15:33.43.837] BEGIN WMNewTab: 20 +[15:33.43.837] END WMNewTab: 20 + + +[15:33.45.248] BEGIN WMNewTab: 20 +[15:33.45.248] END WMNewTab: 20 + + +[15:33.46.659] BEGIN WMNewTab: 20 +[15:33.46.659] END WMNewTab: 20 + + +[15:33.48.071] BEGIN WMNewTab: 20 +[15:33.48.071] END WMNewTab: 20 + + +[15:33.49.484] BEGIN WMNewTab: 20 +[15:33.49.484] END WMNewTab: 20 + + +[15:33.50.901] BEGIN WMNewTab: 20 +[15:33.50.901] END WMNewTab: 20 + + +[15:33.52.312] BEGIN WMNewTab: 20 +[15:33.52.312] END WMNewTab: 20 + + +[15:33.53.730] BEGIN WMNewTab: 20 +[15:33.53.730] END WMNewTab: 20 + + +[15:33.55.149] BEGIN WMNewTab: 20 +[15:33.55.149] END WMNewTab: 20 + + +[15:33.56.564] BEGIN WMNewTab: 20 +[15:33.56.564] END WMNewTab: 20 + + +[15:33.57.982] BEGIN WMNewTab: 20 +[15:33.57.982] END WMNewTab: 20 + + +[15:33.59.401] BEGIN WMNewTab: 20 +[15:33.59.401] END WMNewTab: 20 + + +[15:34.00.819] BEGIN WMNewTab: 20 +[15:34.00.819] END WMNewTab: 20 + + +[15:34.02.234] BEGIN WMNewTab: 20 +[15:34.02.234] END WMNewTab: 20 + +[15:34.02.599] BEGIN WMSysCommand (minimize/restore) +[15:34.02.622] BEGIN WMSize +[15:34.02.622] END WMSize +[15:34.02.645] END WMSysCommand + +[15:34.03.644] BEGIN WMNewTab: 20 +[15:34.03.644] END WMNewTab: 20 + + +[15:34.05.062] BEGIN WMNewTab: 20 +[15:34.05.062] END WMNewTab: 20 + + +[15:34.06.481] BEGIN WMNewTab: 20 +[15:34.06.481] END WMNewTab: 20 + + +[15:34.07.905] BEGIN WMNewTab: 20 +[15:34.07.905] END WMNewTab: 20 + + +[15:34.09.311] BEGIN WMNewTab: 20 +[15:34.09.311] END WMNewTab: 20 + +[15:34.10.486] BEGIN WMSysCommand (minimize/restore) +[15:34.10.487] BEGIN WMNewTab: 0 +[15:34.10.487] WMNewTab: FormClick +[15:34.10.487] WMNewTab: LooseFocus +[15:34.10.487] END WMNewTab: 0 +[15:34.10.587] BEGIN WMSize +[15:34.10.587] BEGIN TFormXterm.FormResize +[15:34.10.587] TFormXterm.FormResize: CenterBtnReattachTab +[15:34.10.587] TFormXterm.FormResize: SplitModeResize +[15:34.10.587] TFormXterm.FormResize: BtnSplitNo.Down +[15:34.10.587] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:34.10.587] BEGIN ResizeTerminal +[15:34.10.588] END ResizeTerminal +[15:34.10.588] TFormXterm.FormResize: AdaptSidebarArrows; +[15:34.10.588] BEGIN AdaptSidebarArrows +[15:34.10.588] END AdaptSidebarArrows +[15:34.10.588] TFormXterm.FormResize: AdaptTV2; +[15:34.10.590] END TFormXterm.FormResize +[15:34.10.590] END WMSize +[15:34.10.594] END WMSysCommand +[15:34.10.725] BEGIN WMNewTab: 20 +[15:34.10.725] END WMNewTab: 20 + + +[15:34.12.141] BEGIN WMNewTab: 20 +[15:34.12.141] END WMNewTab: 20 + + +[15:34.13.559] BEGIN WMNewTab: 20 +[15:34.13.559] END WMNewTab: 20 + + +[15:34.14.976] BEGIN WMNewTab: 20 +[15:34.14.976] END WMNewTab: 20 + + +[15:34.16.390] BEGIN WMNewTab: 20 +[15:34.16.390] END WMNewTab: 20 + + +[15:34.17.809] BEGIN WMNewTab: 20 +[15:34.17.809] END WMNewTab: 20 + + +[15:34.19.227] BEGIN WMNewTab: 20 +[15:34.19.227] END WMNewTab: 20 + + +[15:34.20.642] BEGIN WMNewTab: 20 +[15:34.20.642] END WMNewTab: 20 + + +[15:34.22.056] BEGIN WMNewTab: 20 +[15:34.22.056] END WMNewTab: 20 + + +[15:34.23.471] BEGIN WMNewTab: 20 +[15:34.23.471] END WMNewTab: 20 + + +[15:34.24.886] BEGIN WMNewTab: 20 +[15:34.24.886] END WMNewTab: 20 + + +[15:34.26.302] BEGIN WMNewTab: 20 +[15:34.26.302] END WMNewTab: 20 + + +[15:34.27.718] BEGIN WMNewTab: 20 +[15:34.27.718] END WMNewTab: 20 + + +[15:34.29.142] BEGIN WMNewTab: 20 +[15:34.29.142] END WMNewTab: 20 + + +[15:34.30.559] BEGIN WMNewTab: 20 +[15:34.30.559] END WMNewTab: 20 + + +[15:34.31.974] BEGIN WMNewTab: 20 +[15:34.31.974] END WMNewTab: 20 + + +[15:34.33.408] BEGIN WMNewTab: 20 +[15:34.33.408] END WMNewTab: 20 + + +[15:34.34.813] BEGIN WMNewTab: 20 +[15:34.34.813] END WMNewTab: 20 + + +[15:34.36.232] BEGIN WMNewTab: 20 +[15:34.36.232] END WMNewTab: 20 + + +[15:34.37.652] BEGIN WMNewTab: 20 +[15:34.37.652] END WMNewTab: 20 + + +[15:34.39.065] BEGIN WMNewTab: 20 +[15:34.39.065] END WMNewTab: 20 + + +[15:34.40.480] BEGIN WMNewTab: 20 +[15:34.40.480] END WMNewTab: 20 + + +[15:34.41.902] BEGIN WMNewTab: 20 +[15:34.41.902] END WMNewTab: 20 + + +[15:34.43.313] BEGIN WMNewTab: 20 +[15:34.43.313] END WMNewTab: 20 + + +[15:34.44.727] BEGIN WMNewTab: 20 +[15:34.44.727] END WMNewTab: 20 + + +[15:34.46.144] BEGIN WMNewTab: 20 +[15:34.46.144] END WMNewTab: 20 + + +[15:34.47.562] BEGIN WMNewTab: 20 +[15:34.47.562] END WMNewTab: 20 + + +[15:34.48.978] BEGIN WMNewTab: 20 +[15:34.48.978] END WMNewTab: 20 + + +[15:34.50.398] BEGIN WMNewTab: 20 +[15:34.50.398] END WMNewTab: 20 + + +[15:34.51.816] BEGIN WMNewTab: 20 +[15:34.51.816] END WMNewTab: 20 + + +[15:34.53.235] BEGIN WMNewTab: 20 +[15:34.53.235] END WMNewTab: 20 + + +[15:34.54.650] BEGIN WMNewTab: 20 +[15:34.54.650] END WMNewTab: 20 + + +[15:34.56.071] BEGIN WMNewTab: 20 +[15:34.56.071] END WMNewTab: 20 + + +[15:34.57.485] BEGIN WMNewTab: 20 +[15:34.57.485] END WMNewTab: 20 + + +[15:34.58.919] BEGIN WMNewTab: 20 +[15:34.58.919] END WMNewTab: 20 + + +[15:35.00.333] BEGIN WMNewTab: 20 +[15:35.00.333] END WMNewTab: 20 + + +[15:35.01.751] BEGIN WMNewTab: 20 +[15:35.01.751] END WMNewTab: 20 + + +[15:35.03.165] BEGIN WMNewTab: 20 +[15:35.03.165] END WMNewTab: 20 + + +[15:35.04.578] BEGIN WMNewTab: 20 +[15:35.04.578] END WMNewTab: 20 + + +[15:35.06.001] BEGIN WMNewTab: 20 +[15:35.06.001] END WMNewTab: 20 + + +[15:35.07.413] BEGIN WMNewTab: 20 +[15:35.07.413] END WMNewTab: 20 + + +[15:35.08.830] BEGIN WMNewTab: 20 +[15:35.08.830] END WMNewTab: 20 + + +[15:35.10.244] BEGIN WMNewTab: 20 +[15:35.10.244] END WMNewTab: 20 + + +[15:35.11.662] BEGIN WMNewTab: 20 +[15:35.11.662] END WMNewTab: 20 + + +[15:35.13.077] BEGIN WMNewTab: 20 +[15:35.13.077] END WMNewTab: 20 + + +[15:35.14.493] BEGIN WMNewTab: 20 +[15:35.14.493] END WMNewTab: 20 + + +[15:35.15.909] BEGIN WMNewTab: 20 +[15:35.15.909] END WMNewTab: 20 + + +[15:35.17.331] BEGIN WMNewTab: 20 +[15:35.17.331] END WMNewTab: 20 + + +[15:35.18.744] BEGIN WMNewTab: 20 +[15:35.18.744] END WMNewTab: 20 + + +[15:35.20.161] BEGIN WMNewTab: 20 +[15:35.20.161] END WMNewTab: 20 + + +[15:35.21.568] BEGIN WMNewTab: 20 +[15:35.21.568] END WMNewTab: 20 + + +[15:35.22.979] BEGIN WMNewTab: 20 +[15:35.22.979] END WMNewTab: 20 + + +[15:35.24.393] BEGIN WMNewTab: 20 +[15:35.24.393] END WMNewTab: 20 + + +[15:35.25.808] BEGIN WMNewTab: 20 +[15:35.25.808] END WMNewTab: 20 + + +[15:35.27.225] BEGIN WMNewTab: 20 +[15:35.27.225] END WMNewTab: 20 + + +[15:35.28.638] BEGIN WMNewTab: 20 +[15:35.28.638] END WMNewTab: 20 + + +[15:35.30.051] BEGIN WMNewTab: 20 +[15:35.30.051] END WMNewTab: 20 + + +[15:35.31.463] BEGIN WMNewTab: 20 +[15:35.31.463] END WMNewTab: 20 + + +[15:35.32.877] BEGIN WMNewTab: 20 +[15:35.32.877] END WMNewTab: 20 + + +[15:35.34.289] BEGIN WMNewTab: 20 +[15:35.34.289] END WMNewTab: 20 + + +[15:35.35.728] BEGIN WMNewTab: 20 +[15:35.35.728] END WMNewTab: 20 + + +[15:35.37.129] BEGIN WMNewTab: 20 +[15:35.37.129] END WMNewTab: 20 + + +[15:35.38.404] BEGIN WMNewTab: 0 +[15:35.38.404] WMNewTab: FormClick +[15:35.38.404] WMNewTab: LooseFocus +[15:35.38.404] END WMNewTab: 0 +[15:35.38.531] BEGIN WMNewTab: 0 +[15:35.38.531] WMNewTab: FormClick +[15:35.38.531] WMNewTab: LooseFocus +[15:35.38.533] END WMNewTab: 0 +[15:35.38.546] BEGIN WMNewTab: 20 +[15:35.38.546] END WMNewTab: 20 + + +[15:35.39.960] BEGIN WMNewTab: 20 +[15:35.39.960] END WMNewTab: 20 + + +[15:35.41.375] BEGIN WMNewTab: 20 +[15:35.41.375] END WMNewTab: 20 + + +[15:35.42.793] BEGIN WMNewTab: 20 +[15:35.42.793] END WMNewTab: 20 + +[15:35.43.857] BEGIN CWD +[15:35.43.919] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:35.43.919] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:35.43.919] (SSH-Browser) END VerifySFTPConnection(1) +[15:35.43.919] END CWD +[15:35.43.933] BEGIN CWD +[15:35.43.994] END CWD + +[15:35.44.469] BEGIN WMNewTab: 20 +[15:35.44.469] END WMNewTab: 20 + + +[15:35.45.702] BEGIN CWD +[15:35.45.763] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:35.45.763] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:35.45.763] (SSH-Browser) END VerifySFTPConnection(1) +[15:35.45.763] END CWD +[15:35.45.764] BEGIN WMNewTab: 20 +[15:35.45.764] END WMNewTab: 20 +[15:35.45.779] BEGIN CWD +[15:35.45.840] END CWD + +[15:35.46.684] BEGIN WMNewTab: 31 +[15:35.46.684] END WMNewTab: 31 +[15:35.46.684] BEGIN WMNewTab: 0 +[15:35.46.684] WMNewTab: FormClick +[15:35.46.684] WMNewTab: LooseFocus +[15:35.46.684] END WMNewTab: 0 + +[15:35.47.254] BEGIN WMNewTab: 20 +[15:35.47.254] END WMNewTab: 20 + + +[15:35.48.671] BEGIN WMNewTab: 20 +[15:35.48.671] END WMNewTab: 20 + + +[15:35.50.092] BEGIN WMNewTab: 20 +[15:35.50.092] END WMNewTab: 20 + + +[15:35.51.510] BEGIN WMNewTab: 20 +[15:35.51.510] END WMNewTab: 20 + + +[15:35.52.924] BEGIN WMNewTab: 20 +[15:35.52.924] END WMNewTab: 20 + + +[15:35.54.334] BEGIN WMNewTab: 20 +[15:35.54.334] END WMNewTab: 20 + + +[15:35.55.766] BEGIN WMNewTab: 20 +[15:35.55.766] END WMNewTab: 20 + + +[15:35.57.184] BEGIN WMNewTab: 20 +[15:35.57.184] END WMNewTab: 20 + +[15:35.58.245] BEGIN WMNewTab: 0 +[15:35.58.245] WMNewTab: FormClick +[15:35.58.245] WMNewTab: LooseFocus +[15:35.58.245] END WMNewTab: 0 +[15:35.58.380] BEGIN WMNewTab: 0 +[15:35.58.380] WMNewTab: FormClick +[15:35.58.380] WMNewTab: LooseFocus +[15:35.58.380] END WMNewTab: 0 +[15:35.58.595] BEGIN WMNewTab: 20 +[15:35.58.595] END WMNewTab: 20 + + +[15:36.00.013] BEGIN WMNewTab: 20 +[15:36.00.013] END WMNewTab: 20 + +[15:36.00.565] BEGIN CWD +[15:36.00.625] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:36.00.625] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:36.00.625] (SSH-Browser) END VerifySFTPConnection(1) +[15:36.00.625] END CWD +[15:36.00.641] BEGIN CWD +[15:36.00.702] END CWD + +[15:36.01.645] BEGIN WMNewTab: 20 +[15:36.01.645] END WMNewTab: 20 +[15:36.01.948] BEGIN CWD +[15:36.02.009] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:36.02.009] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:36.02.009] (SSH-Browser) END VerifySFTPConnection(1) +[15:36.02.009] END CWD +[15:36.02.024] BEGIN CWD +[15:36.02.086] END CWD + +[15:36.03.025] BEGIN WMNewTab: 20 +[15:36.03.025] END WMNewTab: 20 + + +[15:36.04.441] BEGIN WMNewTab: 20 +[15:36.04.441] END WMNewTab: 20 + + +[15:36.05.854] BEGIN WMNewTab: 20 +[15:36.05.854] END WMNewTab: 20 + + +[15:36.07.264] BEGIN WMNewTab: 20 +[15:36.07.264] END WMNewTab: 20 +[15:36.07.468] BEGIN WMNewTab: 0 +[15:36.07.468] WMNewTab: FormClick +[15:36.07.468] WMNewTab: LooseFocus +[15:36.07.468] END WMNewTab: 0 +[15:36.07.468] BEGIN WMNewTab: 31 +[15:36.07.468] END WMNewTab: 31 +[15:36.07.568] BEGIN WMNewTab: 0 +[15:36.07.568] WMNewTab: FormClick +[15:36.07.568] WMNewTab: LooseFocus +[15:36.07.569] END WMNewTab: 0 + +[15:36.08.325] BEGIN CWD +[15:36.08.386] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:36.08.386] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:36.08.386] (SSH-Browser) END VerifySFTPConnection(1) +[15:36.08.386] END CWD +[15:36.08.421] BEGIN CWD +[15:36.08.482] END CWD +[15:36.08.482] BEGIN WMNewTab: 20 +[15:36.08.482] END WMNewTab: 20 + + +[15:36.09.896] BEGIN WMNewTab: 20 +[15:36.09.896] END WMNewTab: 20 + + +[15:36.11.310] BEGIN WMNewTab: 20 +[15:36.11.310] END WMNewTab: 20 + +[15:36.11.973] BEGIN WMNewTab: 0 +[15:36.11.973] WMNewTab: FormClick +[15:36.11.973] WMNewTab: LooseFocus +[15:36.11.973] END WMNewTab: 0 +[15:36.11.973] BEGIN WMNewTab: 31 +[15:36.11.973] END WMNewTab: 31 +[15:36.12.044] BEGIN WMNewTab: 0 +[15:36.12.044] WMNewTab: FormClick +[15:36.12.044] WMNewTab: LooseFocus +[15:36.12.044] END WMNewTab: 0 + +[15:36.12.631] BEGIN CWD +[15:36.12.692] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:36.12.692] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:36.12.692] (SSH-Browser) END VerifySFTPConnection(1) +[15:36.12.692] END CWD +[15:36.12.724] BEGIN WMNewTab: 20 +[15:36.12.724] END WMNewTab: 20 +[15:36.12.753] BEGIN CWD +[15:36.12.813] END CWD + + +[15:36.14.229] BEGIN WMNewTab: 20 +[15:36.14.229] END WMNewTab: 20 + + +[15:36.15.639] BEGIN WMNewTab: 20 +[15:36.15.639] END WMNewTab: 20 + + +[15:36.17.057] BEGIN WMNewTab: 20 +[15:36.17.057] END WMNewTab: 20 + + +[15:36.18.473] BEGIN WMNewTab: 20 +[15:36.18.473] END WMNewTab: 20 + + +[15:36.19.890] BEGIN WMNewTab: 20 +[15:36.19.890] END WMNewTab: 20 + + +[15:36.21.304] BEGIN WMNewTab: 20 +[15:36.21.304] END WMNewTab: 20 + +[15:36.22.389] BEGIN WMNewTab: 0 +[15:36.22.389] WMNewTab: FormClick +[15:36.22.389] WMNewTab: LooseFocus +[15:36.22.389] END WMNewTab: 0 +[15:36.22.525] BEGIN WMNewTab: 0 +[15:36.22.525] WMNewTab: FormClick +[15:36.22.525] WMNewTab: LooseFocus +[15:36.22.525] END WMNewTab: 0 +[15:36.22.724] BEGIN WMNewTab: 20 +[15:36.22.724] END WMNewTab: 20 + + +[15:36.24.144] BEGIN WMNewTab: 20 +[15:36.24.144] END WMNewTab: 20 + +[15:36.24.676] BEGIN CWD +[15:36.24.769] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:36.24.769] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:36.24.769] (SSH-Browser) END VerifySFTPConnection(1) +[15:36.24.769] END CWD +[15:36.24.783] BEGIN CWD +[15:36.24.843] END CWD + +[15:36.25.788] BEGIN WMNewTab: 20 +[15:36.25.788] END WMNewTab: 20 + +[15:36.26.983] BEGIN CWD +[15:36.27.044] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:36.27.044] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:36.27.044] (SSH-Browser) END VerifySFTPConnection(1) +[15:36.27.044] END CWD +[15:36.27.046] BEGIN WMNewTab: 20 +[15:36.27.046] END WMNewTab: 20 +[15:36.27.053] BEGIN CWD +[15:36.27.113] END CWD + + +[15:36.28.532] BEGIN WMNewTab: 20 +[15:36.28.532] END WMNewTab: 20 + + +[15:36.29.950] BEGIN WMNewTab: 20 +[15:36.29.950] END WMNewTab: 20 + + +[15:36.31.369] BEGIN WMNewTab: 20 +[15:36.31.369] END WMNewTab: 20 + + +[15:36.32.786] BEGIN WMNewTab: 20 +[15:36.32.786] END WMNewTab: 20 + + +[15:36.34.200] BEGIN WMNewTab: 20 +[15:36.34.200] END WMNewTab: 20 + + +[15:36.35.616] BEGIN WMNewTab: 20 +[15:36.35.616] END WMNewTab: 20 + +[15:36.36.265] BEGIN WMNewTab: 0 +[15:36.36.265] WMNewTab: FormClick +[15:36.36.265] WMNewTab: LooseFocus +[15:36.36.265] END WMNewTab: 0 + +[15:36.37.026] BEGIN WMNewTab: 20 +[15:36.37.026] END WMNewTab: 20 + +[15:36.38.157] BEGIN WMNewTab: 0 +[15:36.38.157] WMNewTab: FormClick +[15:36.38.157] WMNewTab: LooseFocus +[15:36.38.160] END WMNewTab: 0 +[15:36.38.441] BEGIN WMNewTab: 20 +[15:36.38.441] END WMNewTab: 20 + + +[15:36.39.857] BEGIN WMNewTab: 20 +[15:36.39.857] END WMNewTab: 20 + + +[15:36.41.270] BEGIN WMNewTab: 20 +[15:36.41.270] END WMNewTab: 20 + + +[15:36.42.686] BEGIN WMNewTab: 20 +[15:36.42.686] END WMNewTab: 20 + + +[15:36.44.105] BEGIN WMNewTab: 20 +[15:36.44.105] END WMNewTab: 20 + + +[15:36.45.513] BEGIN WMNewTab: 20 +[15:36.45.513] END WMNewTab: 20 + + +[15:36.46.927] BEGIN WMNewTab: 20 +[15:36.46.927] END WMNewTab: 20 + + +[15:36.48.343] BEGIN WMNewTab: 20 +[15:36.48.343] END WMNewTab: 20 + + +[15:36.49.758] BEGIN WMNewTab: 20 +[15:36.49.758] END WMNewTab: 20 + + +[15:36.51.168] BEGIN WMNewTab: 20 +[15:36.51.168] END WMNewTab: 20 + + +[15:36.52.581] BEGIN WMNewTab: 20 +[15:36.52.581] END WMNewTab: 20 + + +[15:36.54.001] BEGIN WMNewTab: 20 +[15:36.54.001] END WMNewTab: 20 + + +[15:36.55.414] BEGIN WMNewTab: 20 +[15:36.55.414] END WMNewTab: 20 + + +[15:36.56.827] BEGIN WMNewTab: 20 +[15:36.56.827] END WMNewTab: 20 + + +[15:36.58.237] BEGIN WMNewTab: 20 +[15:36.58.237] END WMNewTab: 20 + + +[15:36.59.653] BEGIN WMNewTab: 20 +[15:36.59.653] END WMNewTab: 20 + + +[15:37.01.066] BEGIN WMNewTab: 20 +[15:37.01.066] END WMNewTab: 20 + + +[15:37.02.476] BEGIN WMNewTab: 20 +[15:37.02.476] END WMNewTab: 20 + + +[15:37.03.890] BEGIN WMNewTab: 20 +[15:37.03.890] END WMNewTab: 20 +[15:37.03.991] BEGIN WMNewTab: 0 +[15:37.03.991] WMNewTab: FormClick +[15:37.03.991] WMNewTab: LooseFocus +[15:37.03.991] END WMNewTab: 0 +[15:37.04.119] BEGIN WMNewTab: 0 +[15:37.04.119] WMNewTab: FormClick +[15:37.04.119] WMNewTab: LooseFocus +[15:37.04.119] END WMNewTab: 0 + +[15:37.05.294] BEGIN CWD +[15:37.05.307] BEGIN WMNewTab: 20 +[15:37.05.307] END WMNewTab: 20 +[15:37.05.354] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:37.05.354] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:37.05.354] (SSH-Browser) END VerifySFTPConnection(1) +[15:37.05.354] END CWD +[15:37.05.368] BEGIN CWD +[15:37.05.428] END CWD + +[15:37.05.862] BEGIN WMNewTab: 0 +[15:37.05.862] WMNewTab: FormClick +[15:37.05.862] WMNewTab: LooseFocus +[15:37.05.862] END WMNewTab: 0 +[15:37.05.862] BEGIN WMNewTab: 31 +[15:37.05.862] END WMNewTab: 31 +[15:37.05.998] BEGIN WMNewTab: 0 +[15:37.05.998] WMNewTab: FormClick +[15:37.05.998] WMNewTab: LooseFocus +[15:37.05.998] END WMNewTab: 0 + +[15:37.06.767] BEGIN CWD +[15:37.06.828] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:37.06.828] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:37.06.828] (SSH-Browser) END VerifySFTPConnection(1) +[15:37.06.828] END CWD +[15:37.06.845] BEGIN WMNewTab: 20 +[15:37.06.845] END WMNewTab: 20 +[15:37.06.874] BEGIN CWD +[15:37.06.935] END CWD + + +[15:37.08.351] BEGIN WMNewTab: 20 +[15:37.08.351] END WMNewTab: 20 + + +[15:37.09.765] BEGIN WMNewTab: 20 +[15:37.09.765] END WMNewTab: 20 + + +[15:37.11.184] BEGIN WMNewTab: 20 +[15:37.11.184] END WMNewTab: 20 + +[15:37.11.758] BEGIN WMNewTab: 0 +[15:37.11.758] WMNewTab: FormClick +[15:37.11.758] WMNewTab: LooseFocus +[15:37.11.758] END WMNewTab: 0 +[15:37.11.758] BEGIN WMNewTab: 31 +[15:37.11.758] END WMNewTab: 31 +[15:37.11.863] BEGIN WMNewTab: 0 +[15:37.11.863] WMNewTab: FormClick +[15:37.11.863] WMNewTab: LooseFocus +[15:37.11.863] END WMNewTab: 0 + +[15:37.12.416] BEGIN CWD +[15:37.12.476] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:37.12.476] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:37.12.476] (SSH-Browser) END VerifySFTPConnection(1) +[15:37.12.476] END CWD +[15:37.12.477] BEGIN WMNewTab: 20 +[15:37.12.477] END WMNewTab: 20 +[15:37.12.492] BEGIN CWD +[15:37.12.553] END CWD + + +[15:37.13.961] BEGIN WMNewTab: 20 +[15:37.13.961] END WMNewTab: 20 + + +[15:37.15.372] BEGIN WMNewTab: 20 +[15:37.15.372] END WMNewTab: 20 + +[15:37.16.278] BEGIN WMNewTab: 0 +[15:37.16.278] WMNewTab: FormClick +[15:37.16.278] WMNewTab: LooseFocus +[15:37.16.280] END WMNewTab: 0 +[15:37.16.280] BEGIN WMNewTab: 31 +[15:37.16.280] END WMNewTab: 31 +[15:37.16.373] BEGIN WMNewTab: 0 +[15:37.16.373] WMNewTab: FormClick +[15:37.16.373] WMNewTab: LooseFocus +[15:37.16.374] END WMNewTab: 0 + +[15:37.16.815] BEGIN WMNewTab: 20 +[15:37.16.815] END WMNewTab: 20 +[15:37.16.957] BEGIN CWD +[15:37.17.017] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:37.17.017] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:37.17.017] (SSH-Browser) END VerifySFTPConnection(1) +[15:37.17.017] END CWD +[15:37.17.033] BEGIN CWD +[15:37.17.094] END CWD + +[15:37.18.036] BEGIN WMNewTab: 20 +[15:37.18.036] END WMNewTab: 20 + + +[15:37.19.448] BEGIN WMNewTab: 20 +[15:37.19.448] END WMNewTab: 20 + + +[15:37.20.866] BEGIN WMNewTab: 20 +[15:37.20.866] END WMNewTab: 20 +[15:37.21.158] BEGIN WMNewTab: 0 +[15:37.21.158] WMNewTab: FormClick +[15:37.21.158] WMNewTab: LooseFocus +[15:37.21.158] END WMNewTab: 0 +[15:37.21.158] BEGIN WMNewTab: 31 +[15:37.21.158] END WMNewTab: 31 +[15:37.21.253] BEGIN WMNewTab: 0 +[15:37.21.253] WMNewTab: FormClick +[15:37.21.253] WMNewTab: LooseFocus +[15:37.21.254] END WMNewTab: 0 + +[15:37.21.946] BEGIN CWD +[15:37.22.007] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:37.22.007] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:37.22.007] (SSH-Browser) END VerifySFTPConnection(1) +[15:37.22.007] END CWD +[15:37.22.022] BEGIN CWD +[15:37.22.083] END CWD +[15:37.22.083] BEGIN WMNewTab: 20 +[15:37.22.083] END WMNewTab: 20 + + +[15:37.23.504] BEGIN WMNewTab: 20 +[15:37.23.504] END WMNewTab: 20 + + +[15:37.24.920] BEGIN WMNewTab: 20 +[15:37.24.920] END WMNewTab: 20 + + +[15:37.26.337] BEGIN WMNewTab: 20 +[15:37.26.337] END WMNewTab: 20 + + +[15:37.27.755] BEGIN WMNewTab: 20 +[15:37.27.755] END WMNewTab: 20 + + +[15:37.29.171] BEGIN WMNewTab: 20 +[15:37.29.171] END WMNewTab: 20 + +[15:37.29.751] BEGIN WMNewTab: 0 +[15:37.29.751] WMNewTab: FormClick +[15:37.29.751] WMNewTab: LooseFocus +[15:37.29.751] END WMNewTab: 0 + +[15:37.30.585] BEGIN WMNewTab: 20 +[15:37.30.585] END WMNewTab: 20 + + +[15:37.31.790] BEGIN WMNewTab: 0 +[15:37.31.790] WMNewTab: FormClick +[15:37.31.790] WMNewTab: LooseFocus +[15:37.31.793] END WMNewTab: 0 +[15:37.32.001] BEGIN WMNewTab: 20 +[15:37.32.001] END WMNewTab: 20 + + +[15:37.33.418] BEGIN WMNewTab: 20 +[15:37.33.418] END WMNewTab: 20 + + +[15:37.34.833] BEGIN WMNewTab: 20 +[15:37.34.833] END WMNewTab: 20 + + +[15:37.36.245] BEGIN WMNewTab: 20 +[15:37.36.245] END WMNewTab: 20 + + +[15:37.37.656] BEGIN WMNewTab: 20 +[15:37.37.656] END WMNewTab: 20 + + +[15:37.39.069] BEGIN WMNewTab: 20 +[15:37.39.069] END WMNewTab: 20 + + +[15:37.40.484] BEGIN WMNewTab: 20 +[15:37.40.484] END WMNewTab: 20 + + +[15:37.41.899] BEGIN WMNewTab: 20 +[15:37.41.899] END WMNewTab: 20 + + +[15:37.43.308] BEGIN WMNewTab: 20 +[15:37.43.308] END WMNewTab: 20 + + +[15:37.44.722] BEGIN WMNewTab: 20 +[15:37.44.722] END WMNewTab: 20 + + +[15:37.46.141] BEGIN WMNewTab: 20 +[15:37.46.141] END WMNewTab: 20 + + +[15:37.47.554] BEGIN WMNewTab: 20 +[15:37.47.554] END WMNewTab: 20 + + +[15:37.48.967] BEGIN WMNewTab: 20 +[15:37.48.967] END WMNewTab: 20 + + +[15:37.50.382] BEGIN WMNewTab: 20 +[15:37.50.382] END WMNewTab: 20 + + +[15:37.51.797] BEGIN WMNewTab: 20 +[15:37.51.797] END WMNewTab: 20 + + +[15:37.53.207] BEGIN WMNewTab: 20 +[15:37.53.207] END WMNewTab: 20 + + +[15:37.54.622] BEGIN WMNewTab: 20 +[15:37.54.622] END WMNewTab: 20 + + +[15:37.56.033] BEGIN WMNewTab: 20 +[15:37.56.033] END WMNewTab: 20 + + +[15:37.57.443] BEGIN WMNewTab: 20 +[15:37.57.443] END WMNewTab: 20 + + +[15:37.58.856] BEGIN WMNewTab: 20 +[15:37.58.856] END WMNewTab: 20 + + +[15:38.00.271] BEGIN WMNewTab: 20 +[15:38.00.271] END WMNewTab: 20 + + +[15:38.01.685] BEGIN WMNewTab: 20 +[15:38.01.685] END WMNewTab: 20 + +[15:38.02.253] BEGIN WMNewTab: 0 +[15:38.02.253] WMNewTab: FormClick +[15:38.02.253] WMNewTab: LooseFocus +[15:38.02.253] END WMNewTab: 0 +[15:38.02.376] BEGIN WMNewTab: 0 +[15:38.02.376] WMNewTab: FormClick +[15:38.02.376] WMNewTab: LooseFocus +[15:38.02.377] END WMNewTab: 0 + +[15:38.03.099] BEGIN WMNewTab: 20 +[15:38.03.099] END WMNewTab: 20 + + +[15:38.04.518] BEGIN WMNewTab: 20 +[15:38.04.518] END WMNewTab: 20 + +[15:38.05.066] BEGIN CWD +[15:38.05.126] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.05.126] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.05.126] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.05.126] END CWD +[15:38.05.140] BEGIN CWD +[15:38.05.202] END CWD + +[15:38.06.143] BEGIN WMNewTab: 20 +[15:38.06.143] END WMNewTab: 20 +[15:38.06.173] BEGIN CWD +[15:38.06.234] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.06.234] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.06.234] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.06.234] END CWD +[15:38.06.249] BEGIN CWD +[15:38.06.310] END CWD + +[15:38.06.996] BEGIN WMNewTab: 0 +[15:38.06.996] WMNewTab: FormClick +[15:38.06.996] WMNewTab: LooseFocus +[15:38.06.997] END WMNewTab: 0 +[15:38.06.997] BEGIN WMNewTab: 31 +[15:38.06.997] END WMNewTab: 31 +[15:38.07.106] BEGIN WMNewTab: 0 +[15:38.07.106] WMNewTab: FormClick +[15:38.07.106] WMNewTab: LooseFocus +[15:38.07.107] END WMNewTab: 0 + +[15:38.07.678] BEGIN CWD +[15:38.07.723] BEGIN WMNewTab: 20 +[15:38.07.723] END WMNewTab: 20 +[15:38.07.739] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.07.739] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.07.739] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.07.739] END CWD +[15:38.07.753] BEGIN CWD +[15:38.07.814] END CWD + + +[15:38.09.222] BEGIN WMNewTab: 20 +[15:38.09.222] END WMNewTab: 20 + + +[15:38.10.641] BEGIN WMNewTab: 20 +[15:38.10.641] END WMNewTab: 20 +[15:38.10.915] BEGIN WMNewTab: 0 +[15:38.10.915] WMNewTab: FormClick +[15:38.10.915] WMNewTab: LooseFocus +[15:38.10.915] END WMNewTab: 0 +[15:38.11.000] BEGIN WMNewTab: 0 +[15:38.11.000] WMNewTab: FormClick +[15:38.11.000] WMNewTab: LooseFocus +[15:38.11.001] END WMNewTab: 0 + +[15:38.11.389] BEGIN CWD +[15:38.11.450] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.11.450] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.11.450] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.11.450] END CWD +[15:38.11.464] BEGIN CWD +[15:38.11.525] END CWD + +[15:38.11.997] BEGIN WMNewTab: 20 +[15:38.11.997] END WMNewTab: 20 + + +[15:38.13.412] BEGIN WMNewTab: 20 +[15:38.13.412] END WMNewTab: 20 + + +[15:38.14.827] BEGIN WMNewTab: 20 +[15:38.14.827] END WMNewTab: 20 + + +[15:38.16.244] BEGIN WMNewTab: 20 +[15:38.16.244] END WMNewTab: 20 + +[15:38.16.998] BEGIN WMNewTab: 0 +[15:38.16.998] WMNewTab: FormClick +[15:38.16.998] WMNewTab: LooseFocus +[15:38.16.998] END WMNewTab: 0 +[15:38.16.998] BEGIN WMNewTab: 31 +[15:38.16.998] END WMNewTab: 31 +[15:38.17.067] BEGIN WMNewTab: 0 +[15:38.17.067] WMNewTab: FormClick +[15:38.17.067] WMNewTab: LooseFocus +[15:38.17.068] END WMNewTab: 0 + +[15:38.17.665] BEGIN WMNewTab: 20 +[15:38.17.665] END WMNewTab: 20 +[15:38.17.727] BEGIN CWD +[15:38.17.787] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.17.787] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.17.787] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.17.787] END CWD +[15:38.17.802] BEGIN CWD +[15:38.17.862] END CWD + + +[15:38.19.280] BEGIN WMNewTab: 20 +[15:38.19.280] END WMNewTab: 20 + + +[15:38.20.697] BEGIN WMNewTab: 20 +[15:38.20.697] END WMNewTab: 20 + + +[15:38.22.036] BEGIN WMNewTab: 0 +[15:38.22.036] WMNewTab: FormClick +[15:38.22.036] WMNewTab: LooseFocus +[15:38.22.036] END WMNewTab: 0 +[15:38.22.036] BEGIN WMNewTab: 31 +[15:38.22.036] END WMNewTab: 31 +[15:38.22.112] BEGIN WMNewTab: 20 +[15:38.22.112] END WMNewTab: 20 +[15:38.22.149] BEGIN WMNewTab: 0 +[15:38.22.149] WMNewTab: FormClick +[15:38.22.149] WMNewTab: LooseFocus +[15:38.22.149] END WMNewTab: 0 + +[15:38.22.751] BEGIN CWD +[15:38.22.812] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.22.812] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.22.812] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.22.812] END CWD +[15:38.22.828] BEGIN CWD +[15:38.22.890] END CWD + +[15:38.23.358] BEGIN WMNewTab: 20 +[15:38.23.358] END WMNewTab: 20 + + +[15:38.24.772] BEGIN WMNewTab: 20 +[15:38.24.772] END WMNewTab: 20 + + +[15:38.26.189] BEGIN WMNewTab: 20 +[15:38.26.189] END WMNewTab: 20 + +[15:38.27.004] BEGIN WMNewTab: 0 +[15:38.27.004] WMNewTab: FormClick +[15:38.27.004] WMNewTab: LooseFocus +[15:38.27.005] END WMNewTab: 0 +[15:38.27.005] BEGIN WMNewTab: 31 +[15:38.27.005] END WMNewTab: 31 +[15:38.27.076] BEGIN WMNewTab: 0 +[15:38.27.076] WMNewTab: FormClick +[15:38.27.076] WMNewTab: LooseFocus +[15:38.27.077] END WMNewTab: 0 + +[15:38.27.600] BEGIN WMNewTab: 20 +[15:38.27.600] END WMNewTab: 20 +[15:38.27.676] BEGIN CWD +[15:38.27.736] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.27.736] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.27.736] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.27.736] END CWD +[15:38.27.753] BEGIN CWD +[15:38.27.813] END CWD + + +[15:38.29.230] BEGIN WMNewTab: 20 +[15:38.29.230] END WMNewTab: 20 + + +[15:38.30.646] BEGIN WMNewTab: 20 +[15:38.30.646] END WMNewTab: 20 + +[15:38.31.637] BEGIN WMNewTab: 0 +[15:38.31.637] WMNewTab: FormClick +[15:38.31.637] WMNewTab: LooseFocus +[15:38.31.637] END WMNewTab: 0 +[15:38.31.637] BEGIN WMNewTab: 31 +[15:38.31.637] END WMNewTab: 31 +[15:38.31.708] BEGIN WMNewTab: 0 +[15:38.31.708] WMNewTab: FormClick +[15:38.31.708] WMNewTab: LooseFocus +[15:38.31.709] END WMNewTab: 0 +[15:38.32.061] BEGIN WMNewTab: 20 +[15:38.32.061] END WMNewTab: 20 +[15:38.32.350] BEGIN CWD +[15:38.32.411] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.32.411] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.32.411] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.32.411] END CWD +[15:38.32.428] BEGIN CWD +[15:38.32.489] END CWD + +[15:38.33.438] BEGIN WMNewTab: 20 +[15:38.33.438] END WMNewTab: 20 + + +[15:38.34.842] BEGIN WMNewTab: 20 +[15:38.34.842] END WMNewTab: 20 + + +[15:38.36.255] BEGIN WMNewTab: 20 +[15:38.36.255] END WMNewTab: 20 + +[15:38.36.724] BEGIN WMNewTab: 31 +[15:38.36.724] END WMNewTab: 31 +[15:38.36.724] BEGIN WMNewTab: 0 +[15:38.36.724] WMNewTab: FormClick +[15:38.36.724] WMNewTab: LooseFocus +[15:38.36.726] END WMNewTab: 0 +[15:38.36.796] BEGIN WMNewTab: 0 +[15:38.36.796] WMNewTab: FormClick +[15:38.36.796] WMNewTab: LooseFocus +[15:38.36.797] END WMNewTab: 0 + +[15:38.37.374] BEGIN CWD +[15:38.37.461] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.37.461] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.37.461] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.37.462] END CWD +[15:38.37.463] BEGIN WMNewTab: 20 +[15:38.37.463] END WMNewTab: 20 +[15:38.37.472] BEGIN CWD +[15:38.37.532] END CWD + + +[15:38.38.945] BEGIN WMNewTab: 20 +[15:38.38.945] END WMNewTab: 20 + + +[15:38.40.362] BEGIN WMNewTab: 20 +[15:38.40.362] END WMNewTab: 20 + +[15:38.41.542] BEGIN WMNewTab: 0 +[15:38.41.542] WMNewTab: FormClick +[15:38.41.542] WMNewTab: LooseFocus +[15:38.41.542] END WMNewTab: 0 +[15:38.41.542] BEGIN WMNewTab: 31 +[15:38.41.542] END WMNewTab: 31 +[15:38.41.625] BEGIN WMNewTab: 0 +[15:38.41.625] WMNewTab: FormClick +[15:38.41.625] WMNewTab: LooseFocus +[15:38.41.627] END WMNewTab: 0 +[15:38.41.778] BEGIN WMNewTab: 20 +[15:38.41.778] END WMNewTab: 20 + +[15:38.42.281] BEGIN CWD +[15:38.42.341] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.42.341] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.42.341] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.42.341] END CWD +[15:38.42.358] BEGIN CWD +[15:38.42.418] END CWD + +[15:38.43.363] BEGIN WMNewTab: 20 +[15:38.43.363] END WMNewTab: 20 + + +[15:38.44.777] BEGIN WMNewTab: 20 +[15:38.44.777] END WMNewTab: 20 + + +[15:38.46.194] BEGIN WMNewTab: 20 +[15:38.46.194] END WMNewTab: 20 + + +[15:38.47.610] BEGIN WMNewTab: 20 +[15:38.47.610] END WMNewTab: 20 + + +[15:38.49.025] BEGIN WMNewTab: 20 +[15:38.49.025] END WMNewTab: 20 + + +[15:38.50.442] BEGIN WMNewTab: 20 +[15:38.50.442] END WMNewTab: 20 + + +[15:38.51.862] BEGIN WMNewTab: 20 +[15:38.51.862] END WMNewTab: 20 + + +[15:38.53.277] BEGIN WMNewTab: 20 +[15:38.53.277] END WMNewTab: 20 + +[15:38.53.670] BEGIN WMNewTab: 0 +[15:38.53.670] WMNewTab: FormClick +[15:38.53.670] WMNewTab: LooseFocus +[15:38.53.670] END WMNewTab: 0 +[15:38.53.670] BEGIN WMNewTab: 31 +[15:38.53.670] END WMNewTab: 31 +[15:38.53.812] BEGIN WMNewTab: 0 +[15:38.53.812] WMNewTab: FormClick +[15:38.53.812] WMNewTab: LooseFocus +[15:38.53.813] END WMNewTab: 0 + +[15:38.54.544] BEGIN CWD +[15:38.54.605] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:38.54.605] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:38.54.605] (SSH-Browser) END VerifySFTPConnection(1) +[15:38.54.605] END CWD +[15:38.54.696] BEGIN WMNewTab: 20 +[15:38.54.696] END WMNewTab: 20 +[15:38.54.725] BEGIN CWD +[15:38.54.808] END CWD + + +[15:38.56.215] BEGIN WMNewTab: 20 +[15:38.56.215] END WMNewTab: 20 + + +[15:38.57.625] BEGIN WMNewTab: 20 +[15:38.57.625] END WMNewTab: 20 + + +[15:38.59.039] BEGIN WMNewTab: 20 +[15:38.59.039] END WMNewTab: 20 + + +[15:39.00.447] BEGIN WMNewTab: 20 +[15:39.00.447] END WMNewTab: 20 + + +[15:39.01.869] BEGIN WMNewTab: 20 +[15:39.01.869] END WMNewTab: 20 + + +[15:39.03.292] BEGIN WMNewTab: 20 +[15:39.03.292] END WMNewTab: 20 + + +[15:39.04.710] BEGIN WMNewTab: 20 +[15:39.04.710] END WMNewTab: 20 + + +[15:39.06.131] BEGIN WMNewTab: 20 +[15:39.06.131] END WMNewTab: 20 + + +[15:39.07.553] BEGIN WMNewTab: 20 +[15:39.07.553] END WMNewTab: 20 + + +[15:39.08.969] BEGIN WMNewTab: 20 +[15:39.08.969] END WMNewTab: 20 +[15:39.08.998] BEGIN WMNewTab: 31 +[15:39.08.998] END WMNewTab: 31 +[15:39.08.998] BEGIN WMNewTab: 0 +[15:39.08.998] WMNewTab: FormClick +[15:39.08.998] WMNewTab: LooseFocus +[15:39.08.998] END WMNewTab: 0 +[15:39.09.125] BEGIN WMNewTab: 0 +[15:39.09.125] WMNewTab: FormClick +[15:39.09.125] WMNewTab: LooseFocus +[15:39.09.126] END WMNewTab: 0 + +[15:39.09.794] BEGIN CWD +[15:39.09.855] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:39.09.855] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:39.09.855] (SSH-Browser) END VerifySFTPConnection(1) +[15:39.09.855] END CWD +[15:39.09.946] BEGIN CWD +[15:39.10.007] END CWD + +[15:39.10.479] BEGIN WMNewTab: 20 +[15:39.10.479] END WMNewTab: 20 + + +[15:39.11.894] BEGIN WMNewTab: 20 +[15:39.11.894] END WMNewTab: 20 + + +[15:39.13.303] BEGIN WMNewTab: 20 +[15:39.13.303] END WMNewTab: 20 + + +[15:39.14.519] BEGIN WMNewTab: 0 +[15:39.14.519] WMNewTab: FormClick +[15:39.14.519] WMNewTab: LooseFocus +[15:39.14.519] END WMNewTab: 0 +[15:39.14.519] BEGIN WMNewTab: 31 +[15:39.14.519] END WMNewTab: 31 +[15:39.14.631] BEGIN WMNewTab: 0 +[15:39.14.631] WMNewTab: FormClick +[15:39.14.631] WMNewTab: LooseFocus +[15:39.14.632] END WMNewTab: 0 +[15:39.14.722] BEGIN WMNewTab: 20 +[15:39.14.722] END WMNewTab: 20 + +[15:39.15.303] BEGIN CWD +[15:39.15.364] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:39.15.364] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:39.15.364] (SSH-Browser) END VerifySFTPConnection(1) +[15:39.15.364] END CWD +[15:39.15.379] BEGIN CWD +[15:39.15.439] END CWD + +[15:39.16.384] BEGIN WMNewTab: 20 +[15:39.16.384] END WMNewTab: 20 + + +[15:39.17.803] BEGIN WMNewTab: 20 +[15:39.17.803] END WMNewTab: 20 +[15:39.17.936] GetMinWidth = 1864 +[15:39.17.936] BEGIN TFormXterm.FormResize +[15:39.17.936] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.17.940] TFormXterm.FormResize: SplitModeResize +[15:39.17.940] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.17.941] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.17.941] BEGIN ResizeTerminal +[15:39.17.942] END ResizeTerminal +[15:39.17.942] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.17.942] BEGIN AdaptSidebarArrows +[15:39.17.942] END AdaptSidebarArrows +[15:39.17.942] TFormXterm.FormResize: AdaptTV2; +[15:39.17.942] END TFormXterm.FormResize +[15:39.18.033] GetMinWidth = 1845 +[15:39.18.033] BEGIN TFormXterm.FormResize +[15:39.18.033] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.18.037] TFormXterm.FormResize: SplitModeResize +[15:39.18.037] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.18.038] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.18.038] BEGIN ResizeTerminal +[15:39.18.050] END ResizeTerminal +[15:39.18.050] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.18.050] BEGIN AdaptSidebarArrows +[15:39.18.050] END AdaptSidebarArrows +[15:39.18.050] TFormXterm.FormResize: AdaptTV2; +[15:39.18.050] END TFormXterm.FormResize +[15:39.18.140] GetMinWidth = 1821 +[15:39.18.141] BEGIN TFormXterm.FormResize +[15:39.18.141] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.18.145] TFormXterm.FormResize: SplitModeResize +[15:39.18.145] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.18.146] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.18.146] BEGIN ResizeTerminal +[15:39.18.156] END ResizeTerminal +[15:39.18.156] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.18.156] BEGIN AdaptSidebarArrows +[15:39.18.156] END AdaptSidebarArrows +[15:39.18.156] TFormXterm.FormResize: AdaptTV2; +[15:39.18.156] END TFormXterm.FormResize +[15:39.18.234] GetMinWidth = 1793 +[15:39.18.234] BEGIN TFormXterm.FormResize +[15:39.18.234] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.18.238] TFormXterm.FormResize: SplitModeResize +[15:39.18.238] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.18.240] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.18.240] BEGIN ResizeTerminal +[15:39.18.241] END ResizeTerminal +[15:39.18.241] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.18.241] BEGIN AdaptSidebarArrows +[15:39.18.241] END AdaptSidebarArrows +[15:39.18.241] TFormXterm.FormResize: AdaptTV2; +[15:39.18.241] END TFormXterm.FormResize +[15:39.18.387] GetMinWidth = 1794 +[15:39.18.387] BEGIN TFormXterm.FormResize +[15:39.18.387] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.18.392] TFormXterm.FormResize: SplitModeResize +[15:39.18.392] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.18.392] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.18.392] BEGIN ResizeTerminal +[15:39.18.402] END ResizeTerminal +[15:39.18.402] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.18.402] BEGIN AdaptSidebarArrows +[15:39.18.402] END AdaptSidebarArrows +[15:39.18.402] TFormXterm.FormResize: AdaptTV2; +[15:39.18.402] END TFormXterm.FormResize +[15:39.18.486] GetMinWidth = 1827 +[15:39.18.486] BEGIN TFormXterm.FormResize +[15:39.18.486] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.18.491] TFormXterm.FormResize: SplitModeResize +[15:39.18.491] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.18.491] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.18.491] BEGIN ResizeTerminal +[15:39.18.501] END ResizeTerminal +[15:39.18.501] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.18.501] BEGIN AdaptSidebarArrows +[15:39.18.501] END AdaptSidebarArrows +[15:39.18.501] TFormXterm.FormResize: AdaptTV2; +[15:39.18.501] END TFormXterm.FormResize +[15:39.18.594] GetMinWidth = 1891 +[15:39.18.594] BEGIN TFormXterm.FormResize +[15:39.18.594] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.18.600] TFormXterm.FormResize: SplitModeResize +[15:39.18.600] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.18.600] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.18.600] BEGIN ResizeTerminal +[15:39.18.623] END ResizeTerminal +[15:39.18.623] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.18.623] BEGIN AdaptSidebarArrows +[15:39.18.623] END AdaptSidebarArrows +[15:39.18.623] TFormXterm.FormResize: AdaptTV2; +[15:39.18.623] END TFormXterm.FormResize +[15:39.18.714] GetMinWidth = 1907 +[15:39.18.714] BEGIN TFormXterm.FormResize +[15:39.18.714] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.18.723] TFormXterm.FormResize: SplitModeResize +[15:39.18.723] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.18.724] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.18.724] BEGIN ResizeTerminal +[15:39.18.735] END ResizeTerminal +[15:39.18.735] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.18.735] BEGIN AdaptSidebarArrows +[15:39.18.735] END AdaptSidebarArrows +[15:39.18.735] TFormXterm.FormResize: AdaptTV2; +[15:39.18.735] END TFormXterm.FormResize +[15:39.18.870] GetMinWidth = 1907 +[15:39.18.870] BEGIN TFormXterm.FormResize +[15:39.18.870] TFormXterm.FormResize: CenterBtnReattachTab +[15:39.18.870] TFormXterm.FormResize: SplitModeResize +[15:39.18.870] TFormXterm.FormResize: BtnSplitNo.Down +[15:39.18.870] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:39.18.870] BEGIN ResizeTerminal +[15:39.18.871] END ResizeTerminal +[15:39.18.871] TFormXterm.FormResize: AdaptSidebarArrows; +[15:39.18.871] BEGIN AdaptSidebarArrows +[15:39.18.871] END AdaptSidebarArrows +[15:39.18.871] TFormXterm.FormResize: AdaptTV2; +[15:39.18.871] END TFormXterm.FormResize +[15:39.19.217] BEGIN WMNewTab: 20 +[15:39.19.217] END WMNewTab: 20 + + +[15:39.20.633] BEGIN WMNewTab: 20 +[15:39.20.633] END WMNewTab: 20 + + +[15:39.22.050] BEGIN WMNewTab: 20 +[15:39.22.050] END WMNewTab: 20 + + +[15:39.23.467] BEGIN WMNewTab: 20 +[15:39.23.467] END WMNewTab: 20 + + +[15:39.24.879] BEGIN WMNewTab: 20 +[15:39.24.879] END WMNewTab: 20 + + +[15:39.26.299] BEGIN WMNewTab: 20 +[15:39.26.299] END WMNewTab: 20 + + +[15:39.27.712] BEGIN WMNewTab: 20 +[15:39.27.712] END WMNewTab: 20 +[15:39.27.822] BEGIN WMNewTab: 0 +[15:39.27.822] WMNewTab: FormClick +[15:39.27.822] WMNewTab: LooseFocus +[15:39.27.822] END WMNewTab: 0 + + +[15:39.29.130] BEGIN WMNewTab: 20 +[15:39.29.130] END WMNewTab: 20 + +[15:39.30.070] BEGIN WMNewTab: 0 +[15:39.30.070] WMNewTab: FormClick +[15:39.30.070] WMNewTab: LooseFocus +[15:39.30.070] END WMNewTab: 0 + +[15:39.30.545] BEGIN WMNewTab: 20 +[15:39.30.545] END WMNewTab: 20 + + +[15:39.31.962] BEGIN WMNewTab: 20 +[15:39.31.962] END WMNewTab: 20 + + +[15:39.33.376] BEGIN WMNewTab: 20 +[15:39.33.376] END WMNewTab: 20 + + +[15:39.34.790] BEGIN WMNewTab: 20 +[15:39.34.790] END WMNewTab: 20 + + +[15:39.36.205] BEGIN WMNewTab: 20 +[15:39.36.205] END WMNewTab: 20 + + +[15:39.37.623] BEGIN WMNewTab: 20 +[15:39.37.623] END WMNewTab: 20 + +[15:39.38.374] BEGIN WMNewTab: 0 +[15:39.38.374] WMNewTab: FormClick +[15:39.38.374] WMNewTab: LooseFocus +[15:39.38.374] END WMNewTab: 0 +[15:39.38.477] BEGIN WMNewTab: 0 +[15:39.38.477] WMNewTab: FormClick +[15:39.38.477] WMNewTab: LooseFocus +[15:39.38.478] END WMNewTab: 0 + +[15:39.39.036] BEGIN WMNewTab: 20 +[15:39.39.036] END WMNewTab: 20 + + +[15:39.40.455] BEGIN WMNewTab: 20 +[15:39.40.455] END WMNewTab: 20 + + +[15:39.41.868] BEGIN WMNewTab: 20 +[15:39.41.868] END WMNewTab: 20 + + +[15:39.43.282] BEGIN WMNewTab: 20 +[15:39.43.282] END WMNewTab: 20 + + +[15:39.44.699] BEGIN WMNewTab: 20 +[15:39.44.699] END WMNewTab: 20 + + +[15:39.46.117] BEGIN WMNewTab: 20 +[15:39.46.117] END WMNewTab: 20 + + +[15:39.47.531] BEGIN WMNewTab: 20 +[15:39.47.531] END WMNewTab: 20 + + +[15:39.48.944] BEGIN WMNewTab: 20 +[15:39.48.944] END WMNewTab: 20 + + +[15:39.50.359] BEGIN WMNewTab: 20 +[15:39.50.359] END WMNewTab: 20 + + +[15:39.51.767] BEGIN WMNewTab: 20 +[15:39.51.767] END WMNewTab: 20 + +[15:39.52.686] BEGIN WMNewTab: 0 +[15:39.52.686] WMNewTab: FormClick +[15:39.52.686] WMNewTab: LooseFocus +[15:39.52.686] END WMNewTab: 0 +[15:39.52.687] BEGIN WMNewTab: 31 +[15:39.52.687] END WMNewTab: 31 + +[15:39.53.177] BEGIN WMNewTab: 20 +[15:39.53.177] END WMNewTab: 20 + + +[15:39.54.590] BEGIN WMNewTab: 20 +[15:39.54.590] END WMNewTab: 20 +[15:39.54.787] BEGIN CWD +[15:39.54.848] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:39.54.848] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:39.54.848] (SSH-Browser) END VerifySFTPConnection(1) +[15:39.54.848] END CWD +[15:39.54.864] BEGIN CWD +[15:39.54.924] END CWD + +[15:39.55.774] BEGIN WMNewTab: 0 +[15:39.55.774] WMNewTab: FormClick +[15:39.55.774] WMNewTab: LooseFocus +[15:39.55.775] END WMNewTab: 0 +[15:39.55.870] BEGIN WMNewTab: 20 +[15:39.55.870] END WMNewTab: 20 +[15:39.55.894] BEGIN WMNewTab: 0 +[15:39.55.894] WMNewTab: FormClick +[15:39.55.894] WMNewTab: LooseFocus +[15:39.55.896] END WMNewTab: 0 + + +[15:39.57.286] BEGIN WMNewTab: 20 +[15:39.57.286] END WMNewTab: 20 + + +[15:39.58.707] BEGIN WMNewTab: 20 +[15:39.58.707] END WMNewTab: 20 + +[15:39.59.358] BEGIN WMNewTab: 0 +[15:39.59.358] WMNewTab: FormClick +[15:39.59.358] WMNewTab: LooseFocus +[15:39.59.359] END WMNewTab: 0 +[15:39.59.494] BEGIN WMNewTab: 0 +[15:39.59.494] WMNewTab: FormClick +[15:39.59.494] WMNewTab: LooseFocus +[15:39.59.495] END WMNewTab: 0 + +[15:40.00.116] BEGIN WMNewTab: 20 +[15:40.00.116] END WMNewTab: 20 + + +[15:40.01.531] BEGIN WMNewTab: 20 +[15:40.01.531] END WMNewTab: 20 + +[15:40.02.171] BEGIN CWD +[15:40.02.232] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:40.02.232] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:40.02.232] (SSH-Browser) END VerifySFTPConnection(1) +[15:40.02.232] END CWD +[15:40.02.246] BEGIN CWD +[15:40.02.308] END CWD + +[15:40.02.779] BEGIN WMNewTab: 20 +[15:40.02.779] END WMNewTab: 20 + +[15:40.03.267] BEGIN CWD +[15:40.03.328] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:40.03.328] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:40.03.328] (SSH-Browser) END VerifySFTPConnection(1) +[15:40.03.328] END CWD +[15:40.03.343] BEGIN CWD +[15:40.03.403] END CWD + +[15:40.04.279] BEGIN WMNewTab: 0 +[15:40.04.279] WMNewTab: FormClick +[15:40.04.279] WMNewTab: LooseFocus +[15:40.04.279] END WMNewTab: 0 +[15:40.04.279] BEGIN WMNewTab: 31 +[15:40.04.279] END WMNewTab: 31 +[15:40.04.347] BEGIN WMNewTab: 20 +[15:40.04.347] END WMNewTab: 20 + + +[15:40.05.767] BEGIN WMNewTab: 20 +[15:40.05.767] END WMNewTab: 20 + +[15:40.06.207] BEGIN CWD +[15:40.06.267] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:40.06.267] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:40.06.267] (SSH-Browser) END VerifySFTPConnection(1) +[15:40.06.267] END CWD +[15:40.06.305] BEGIN CWD +[15:40.06.366] END CWD + +[15:40.07.325] BEGIN WMNewTab: 20 +[15:40.07.325] END WMNewTab: 20 + +[15:40.07.856] BEGIN WMNewTab: 0 +[15:40.07.856] WMNewTab: FormClick +[15:40.07.856] WMNewTab: LooseFocus +[15:40.07.857] END WMNewTab: 0 + +[15:40.08.731] BEGIN WMNewTab: 20 +[15:40.08.731] END WMNewTab: 20 + + +[15:40.10.015] BEGIN WMNewTab: 0 +[15:40.10.015] WMNewTab: FormClick +[15:40.10.015] WMNewTab: LooseFocus +[15:40.10.018] END WMNewTab: 0 +[15:40.10.147] BEGIN WMNewTab: 20 +[15:40.10.147] END WMNewTab: 20 + + +[15:40.11.561] BEGIN WMNewTab: 20 +[15:40.11.561] END WMNewTab: 20 + + +[15:40.12.969] BEGIN WMNewTab: 20 +[15:40.12.969] END WMNewTab: 20 + + +[15:40.14.379] BEGIN WMNewTab: 20 +[15:40.14.379] END WMNewTab: 20 + +[15:40.15.168] Cts1MouseDown: FormClick + +[15:40.15.790] BEGIN WMNewTab: 20 +[15:40.15.790] END WMNewTab: 20 +[15:40.15.905] Cts1MouseDown: FormClick +[15:40.15.907] Cts1ActiveTabChanged: New index = 2 +[15:40.15.907] BEGIN DisplayCurrentTab +[15:40.15.907] DisplayCurrentTab: FormClick +[15:40.15.907] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[15:40.15.907] (SSH-Browser) BEGIN ActiverPanel14 +[15:40.15.907] (SSH-Browser) BEGIN DesactiverPanel14 +[15:40.15.920] (SSH-Browser) END DesactiverPanel14 +[15:40.15.920] (SSH-Browser) END ActiverPanel14; +[15:40.16.040] BEGIN TFormXterm.FormResize +[15:40.16.040] TFormXterm.FormResize: CenterBtnReattachTab +[15:40.16.041] TFormXterm.FormResize: SplitModeResize +[15:40.16.041] TFormXterm.FormResize: BtnSplitNo.Down +[15:40.16.042] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:40.16.042] BEGIN ResizeTerminal +[15:40.16.045] END ResizeTerminal +[15:40.16.045] TFormXterm.FormResize: AdaptSidebarArrows; +[15:40.16.045] BEGIN AdaptSidebarArrows +[15:40.16.045] END AdaptSidebarArrows +[15:40.16.045] TFormXterm.FormResize: AdaptTV2; +[15:40.16.045] END TFormXterm.FormResize +[15:40.16.045] DisplayCurrentTab: Cts1.BeginUpdate; +[15:40.16.045] DisplayCurrentTab: Cts1.EndUpdates +[15:40.16.060] DisplayCurrentTab: 显示所选标签页 +[15:40.16.063] DisplayCurrentTab: 隐藏其他标签页 +[15:40.16.072] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:40.16.074] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:40.16.074] DisplayCurrentTab: DistribuerLeFocus +[15:40.16.075] END DisplayCurrentTab +[15:40.16.431] BEGIN WMNewTab: 0 +[15:40.16.431] WMNewTab: FormClick +[15:40.16.432] WMNewTab: LooseFocus +[15:40.16.432] END WMNewTab: 0 +[15:40.16.542] BEGIN WMNewTab: 0 +[15:40.16.542] WMNewTab: FormClick +[15:40.16.542] WMNewTab: LooseFocus +[15:40.16.544] END WMNewTab: 0 + +[15:40.17.201] BEGIN WMNewTab: 20 +[15:40.17.201] END WMNewTab: 20 + + +[15:40.18.613] BEGIN WMNewTab: 20 +[15:40.18.613] END WMNewTab: 20 + + +[15:40.20.034] BEGIN WMNewTab: 20 +[15:40.20.034] END WMNewTab: 20 + + +[15:40.21.448] BEGIN WMNewTab: 20 +[15:40.21.448] END WMNewTab: 20 + + +[15:40.22.862] BEGIN WMNewTab: 20 +[15:40.22.862] END WMNewTab: 20 + + +[15:40.24.280] BEGIN WMNewTab: 20 +[15:40.24.280] END WMNewTab: 20 + + +[15:40.25.699] BEGIN WMNewTab: 20 +[15:40.25.699] END WMNewTab: 20 + + +[15:40.27.116] BEGIN WMNewTab: 20 +[15:40.27.116] END WMNewTab: 20 + + +[15:40.28.531] BEGIN WMNewTab: 20 +[15:40.28.531] END WMNewTab: 20 + + +[15:40.29.944] BEGIN WMNewTab: 20 +[15:40.29.944] END WMNewTab: 20 + + +[15:40.31.356] BEGIN WMNewTab: 20 +[15:40.31.356] END WMNewTab: 20 + + +[15:40.32.771] BEGIN WMNewTab: 20 +[15:40.32.771] END WMNewTab: 20 + + +[15:40.34.181] BEGIN WMNewTab: 20 +[15:40.34.181] END WMNewTab: 20 + + +[15:40.35.597] BEGIN WMNewTab: 20 +[15:40.35.597] END WMNewTab: 20 + + +[15:40.37.012] BEGIN WMNewTab: 20 +[15:40.37.012] END WMNewTab: 20 + + +[15:40.38.426] BEGIN WMNewTab: 20 +[15:40.38.426] END WMNewTab: 20 + + +[15:40.39.847] BEGIN WMNewTab: 20 +[15:40.39.847] END WMNewTab: 20 + + +[15:40.41.262] BEGIN WMNewTab: 20 +[15:40.41.262] END WMNewTab: 20 + + +[15:40.42.675] BEGIN WMNewTab: 20 +[15:40.42.675] END WMNewTab: 20 + + +[15:40.44.089] BEGIN WMNewTab: 20 +[15:40.44.089] END WMNewTab: 20 + + +[15:40.45.504] BEGIN WMNewTab: 20 +[15:40.45.504] END WMNewTab: 20 + + +[15:40.46.913] BEGIN WMNewTab: 20 +[15:40.46.913] END WMNewTab: 20 + +[15:40.47.861] Cts1MouseDown: FormClick +[15:40.47.866] Cts1ActiveTabChanged: New index = 1 +[15:40.47.866] BEGIN DisplayCurrentTab +[15:40.47.867] DisplayCurrentTab: FormClick +[15:40.47.867] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:40.47.867] (SSH-Browser) BEGIN ActiverPanel14 +[15:40.47.867] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:40.47.871] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:40.47.871] (SSH-Browser) ActiverPanel14: 列出远程目录 +[15:40.47.871] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[15:40.47.872] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[15:40.47.898] (SSH-Browser) END ActiverPanel14; +[15:40.47.918] BEGIN TFormXterm.FormResize +[15:40.47.918] TFormXterm.FormResize: CenterBtnReattachTab +[15:40.47.919] TFormXterm.FormResize: SplitModeResize +[15:40.47.919] TFormXterm.FormResize: BtnSplitNo.Down +[15:40.47.919] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:40.47.919] BEGIN ResizeTerminal +[15:40.47.922] END ResizeTerminal +[15:40.47.922] TFormXterm.FormResize: AdaptSidebarArrows; +[15:40.47.922] BEGIN AdaptSidebarArrows +[15:40.47.922] END AdaptSidebarArrows +[15:40.47.922] TFormXterm.FormResize: AdaptTV2; +[15:40.47.922] END TFormXterm.FormResize +[15:40.47.923] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[15:40.47.923] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:40.47.939] ShellExecuteS: ShellExecuteEx 成功. +[15:40.47.939] ShellExecuteS: WaitForInputIdle 失败. +[15:40.47.939] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:40.47.939] DisplayCurrentTab: Cts1.BeginUpdate; +[15:40.47.939] DisplayCurrentTab: Cts1.EndUpdates +[15:40.47.955] DisplayCurrentTab: 显示所选标签页 +[15:40.47.956] DisplayCurrentTab: 隐藏其他标签页 +[15:40.47.976] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:40.47.978] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:40.47.978] DisplayCurrentTab: DistribuerLeFocus +[15:40.47.978] END DisplayCurrentTab +[15:40.47.998] [MobaSCP2] Launching remote monitoring in normal mode +[15:40.47.999] [MobaSCP2] Multiplex=1 +[15:40.47.999] [MobaSCP2] HOSTNAME: 192.168.127.10 +[15:40.47.999] [MobaSCP2] USERNAME: root +[15:40.48.036] [MobaSCP2] Using SCP1 +[15:40.48.036] [MobaSCP2] Connected to 192.168.127.10 +[15:40.48.326] BEGIN WMNewTab: 20 +[15:40.48.326] END WMNewTab: 20 + +[15:40.48.720] BEGIN WMNewTab: 0 +[15:40.48.720] WMNewTab: FormClick +[15:40.48.720] WMNewTab: LooseFocus +[15:40.48.720] END WMNewTab: 0 +[15:40.48.720] BEGIN WMNewTab: 31 +[15:40.48.720] END WMNewTab: 31 +[15:40.48.817] BEGIN WMNewTab: 0 +[15:40.48.817] WMNewTab: FormClick +[15:40.48.817] WMNewTab: LooseFocus +[15:40.48.817] END WMNewTab: 0 +[15:40.49.151] BEGIN TFormXterm.FormResize +[15:40.49.151] TFormXterm.FormResize: CenterBtnReattachTab +[15:40.49.151] TFormXterm.FormResize: SplitModeResize +[15:40.49.151] TFormXterm.FormResize: BtnSplitNo.Down +[15:40.49.151] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:40.49.151] BEGIN ResizeTerminal +[15:40.49.151] END ResizeTerminal +[15:40.49.151] TFormXterm.FormResize: AdaptSidebarArrows; +[15:40.49.151] BEGIN AdaptSidebarArrows +[15:40.49.151] END AdaptSidebarArrows +[15:40.49.151] TFormXterm.FormResize: AdaptTV2; +[15:40.49.151] END TFormXterm.FormResize + +[15:40.49.746] BEGIN WMNewTab: 20 +[15:40.49.746] END WMNewTab: 20 + + +[15:40.51.165] BEGIN WMNewTab: 20 +[15:40.51.165] END WMNewTab: 20 + + +[15:40.52.587] BEGIN WMNewTab: 20 +[15:40.52.587] END WMNewTab: 20 + + +[15:40.54.010] BEGIN WMNewTab: 20 +[15:40.54.010] END WMNewTab: 20 +[15:40.54.085] BEGIN CWD +[15:40.54.146] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:40.54.146] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:40.54.146] (SSH-Browser) END VerifySFTPConnection(1) +[15:40.54.146] END CWD +[15:40.54.163] BEGIN CWD +[15:40.54.224] END CWD + +[15:40.54.787] BEGIN CWD +[15:40.54.848] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:40.54.848] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:40.54.848] (SSH-Browser) END VerifySFTPConnection(1) +[15:40.54.848] END CWD +[15:40.54.862] BEGIN CWD +[15:40.54.924] END CWD + +[15:40.55.396] BEGIN WMNewTab: 20 +[15:40.55.396] END WMNewTab: 20 +[15:40.55.464] BEGIN WMNewTab: 0 +[15:40.55.464] WMNewTab: FormClick +[15:40.55.465] WMNewTab: LooseFocus +[15:40.55.465] END WMNewTab: 0 +[15:40.55.465] BEGIN WMNewTab: 31 +[15:40.55.465] END WMNewTab: 31 +[15:40.55.600] BEGIN WMNewTab: 0 +[15:40.55.600] WMNewTab: FormClick +[15:40.55.600] WMNewTab: LooseFocus +[15:40.55.600] END WMNewTab: 0 + +[15:40.56.375] BEGIN CWD +[15:40.56.436] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:40.56.436] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:40.56.436] (SSH-Browser) END VerifySFTPConnection(1) +[15:40.56.436] END CWD +[15:40.56.452] BEGIN CWD +[15:40.56.513] END CWD + +[15:40.56.984] BEGIN WMNewTab: 20 +[15:40.56.984] END WMNewTab: 20 + + +[15:40.58.399] BEGIN WMNewTab: 20 +[15:40.58.399] END WMNewTab: 20 + + +[15:40.59.817] BEGIN WMNewTab: 20 +[15:40.59.817] END WMNewTab: 20 + + +[15:41.01.229] BEGIN WMNewTab: 20 +[15:41.01.229] END WMNewTab: 20 +[15:41.01.285] BEGIN WMNewTab: 0 +[15:41.01.285] WMNewTab: FormClick +[15:41.01.285] WMNewTab: LooseFocus +[15:41.01.285] END WMNewTab: 0 +[15:41.01.285] BEGIN WMNewTab: 31 +[15:41.01.285] END WMNewTab: 31 +[15:41.01.371] BEGIN WMNewTab: 0 +[15:41.01.371] WMNewTab: FormClick +[15:41.01.371] WMNewTab: LooseFocus +[15:41.01.373] END WMNewTab: 0 + +[15:41.02.124] BEGIN CWD +[15:41.02.185] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:41.02.185] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:41.02.185] (SSH-Browser) END VerifySFTPConnection(1) +[15:41.02.185] END CWD +[15:41.02.197] BEGIN CWD +[15:41.02.259] END CWD + +[15:41.02.729] BEGIN WMNewTab: 20 +[15:41.02.729] END WMNewTab: 20 + +[15:41.03.583] BEGIN WMNewTab: 0 +[15:41.03.583] WMNewTab: FormClick +[15:41.03.583] WMNewTab: LooseFocus +[15:41.03.583] END WMNewTab: 0 + +[15:41.04.146] BEGIN WMNewTab: 20 +[15:41.04.146] END WMNewTab: 20 +[15:41.04.335] BEGIN WMNewTab: 0 +[15:41.04.335] WMNewTab: FormClick +[15:41.04.335] WMNewTab: LooseFocus +[15:41.04.339] END WMNewTab: 0 + + +[15:41.05.567] BEGIN WMNewTab: 20 +[15:41.05.567] END WMNewTab: 20 + + +[15:41.06.979] BEGIN WMNewTab: 20 +[15:41.06.979] END WMNewTab: 20 + + +[15:41.08.395] BEGIN WMNewTab: 20 +[15:41.08.395] END WMNewTab: 20 + + +[15:41.09.807] BEGIN WMNewTab: 20 +[15:41.09.807] END WMNewTab: 20 + + +[15:41.11.220] BEGIN WMNewTab: 20 +[15:41.11.220] END WMNewTab: 20 + + +[15:41.12.635] BEGIN WMNewTab: 20 +[15:41.12.635] END WMNewTab: 20 + + +[15:41.14.057] BEGIN WMNewTab: 20 +[15:41.14.057] END WMNewTab: 20 + + +[15:41.15.472] BEGIN WMNewTab: 20 +[15:41.15.472] END WMNewTab: 20 + + +[15:41.16.887] BEGIN WMNewTab: 20 +[15:41.16.887] END WMNewTab: 20 + + +[15:41.18.307] BEGIN WMNewTab: 20 +[15:41.18.307] END WMNewTab: 20 + + +[15:41.19.743] BEGIN WMNewTab: 20 +[15:41.19.743] END WMNewTab: 20 + + +[15:41.21.153] BEGIN WMNewTab: 20 +[15:41.21.153] END WMNewTab: 20 + + +[15:41.22.566] BEGIN WMNewTab: 20 +[15:41.22.566] END WMNewTab: 20 + + +[15:41.23.978] BEGIN WMNewTab: 20 +[15:41.23.978] END WMNewTab: 20 + + +[15:41.25.390] BEGIN WMNewTab: 20 +[15:41.25.390] END WMNewTab: 20 + + +[15:41.26.804] BEGIN WMNewTab: 20 +[15:41.26.804] END WMNewTab: 20 + + +[15:41.28.221] BEGIN WMNewTab: 20 +[15:41.28.221] END WMNewTab: 20 + +[15:41.29.076] BEGIN WMNewTab: 0 +[15:41.29.076] WMNewTab: FormClick +[15:41.29.078] WMNewTab: LooseFocus +[15:41.29.078] END WMNewTab: 0 +[15:41.29.228] BEGIN WMNewTab: 0 +[15:41.29.228] WMNewTab: FormClick +[15:41.29.228] WMNewTab: LooseFocus +[15:41.29.229] END WMNewTab: 0 + +[15:41.29.637] BEGIN WMNewTab: 20 +[15:41.29.637] END WMNewTab: 20 + + +[15:41.31.050] BEGIN WMNewTab: 20 +[15:41.31.050] END WMNewTab: 20 + + +[15:41.32.469] BEGIN WMNewTab: 20 +[15:41.32.469] END WMNewTab: 20 + +[15:41.33.337] BEGIN CWD +[15:41.33.398] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:41.33.398] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:41.33.398] (SSH-Browser) END VerifySFTPConnection(1) +[15:41.33.398] END CWD +[15:41.33.443] BEGIN CWD +[15:41.33.503] END CWD + +[15:41.33.976] BEGIN WMNewTab: 20 +[15:41.33.976] END WMNewTab: 20 + + +[15:41.35.198] BEGIN WMNewTab: 0 +[15:41.35.198] WMNewTab: FormClick +[15:41.35.198] WMNewTab: LooseFocus +[15:41.35.198] END WMNewTab: 0 +[15:41.35.198] BEGIN WMNewTab: 31 +[15:41.35.198] END WMNewTab: 31 +[15:41.35.396] BEGIN WMNewTab: 20 +[15:41.35.396] END WMNewTab: 20 + + +[15:41.36.815] BEGIN WMNewTab: 20 +[15:41.36.815] END WMNewTab: 20 + + +[15:41.38.227] BEGIN WMNewTab: 20 +[15:41.38.227] END WMNewTab: 20 + + +[15:41.39.644] BEGIN WMNewTab: 20 +[15:41.39.644] END WMNewTab: 20 + + +[15:41.41.056] BEGIN WMNewTab: 20 +[15:41.41.056] END WMNewTab: 20 + + +[15:41.42.462] BEGIN WMNewTab: 20 +[15:41.42.462] END WMNewTab: 20 + + +[15:41.43.877] BEGIN WMNewTab: 20 +[15:41.43.877] END WMNewTab: 20 + + +[15:41.45.294] BEGIN WMNewTab: 20 +[15:41.45.294] END WMNewTab: 20 + + +[15:41.46.712] BEGIN WMNewTab: 20 +[15:41.46.712] END WMNewTab: 20 + + +[15:41.48.128] BEGIN WMNewTab: 20 +[15:41.48.128] END WMNewTab: 20 + + +[15:41.49.542] BEGIN WMNewTab: 20 +[15:41.49.542] END WMNewTab: 20 + + +[15:41.50.954] BEGIN WMNewTab: 20 +[15:41.50.954] END WMNewTab: 20 + + +[15:41.52.368] BEGIN WMNewTab: 20 +[15:41.52.368] END WMNewTab: 20 + + +[15:41.53.782] BEGIN WMNewTab: 20 +[15:41.53.782] END WMNewTab: 20 + +[15:41.54.933] BEGIN WMNewTab: 0 +[15:41.54.933] WMNewTab: FormClick +[15:41.54.933] WMNewTab: LooseFocus +[15:41.54.933] END WMNewTab: 0 +[15:41.54.933] BEGIN WMNewTab: 31 +[15:41.54.933] END WMNewTab: 31 +[15:41.55.202] BEGIN WMNewTab: 20 +[15:41.55.202] END WMNewTab: 20 + + +[15:41.56.620] BEGIN WMNewTab: 20 +[15:41.56.620] END WMNewTab: 20 +[15:41.56.635] BEGIN CWD +[15:41.56.695] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:41.56.695] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:41.56.695] (SSH-Browser) END VerifySFTPConnection(1) +[15:41.56.695] END CWD +[15:41.56.712] BEGIN CWD +[15:41.56.772] END CWD + + +[15:41.58.185] BEGIN WMNewTab: 20 +[15:41.58.185] END WMNewTab: 20 + + +[15:41.59.600] BEGIN WMNewTab: 20 +[15:41.59.600] END WMNewTab: 20 + + +[15:42.01.015] BEGIN WMNewTab: 20 +[15:42.01.015] END WMNewTab: 20 + + +[15:42.02.431] BEGIN WMNewTab: 20 +[15:42.02.431] END WMNewTab: 20 + +[15:42.03.383] BEGIN WMNewTab: 0 +[15:42.03.383] WMNewTab: FormClick +[15:42.03.383] WMNewTab: LooseFocus +[15:42.03.383] END WMNewTab: 0 +[15:42.03.383] BEGIN WMNewTab: 31 +[15:42.03.383] END WMNewTab: 31 + +[15:42.03.841] BEGIN WMNewTab: 20 +[15:42.03.841] END WMNewTab: 20 + +[15:42.04.981] BEGIN CWD +[15:42.05.041] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.05.041] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.05.041] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.05.041] END CWD +[15:42.05.056] BEGIN CWD +[15:42.05.116] END CWD +[15:42.05.116] BEGIN WMNewTab: 20 +[15:42.05.116] END WMNewTab: 20 + + +[15:42.06.520] BEGIN WMNewTab: 20 +[15:42.06.520] END WMNewTab: 20 + +[15:42.07.004] BEGIN CWD +[15:42.07.065] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.07.065] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.07.065] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.07.065] END CWD +[15:42.07.080] BEGIN CWD +[15:42.07.140] END CWD + +[15:42.08.079] BEGIN WMNewTab: 20 +[15:42.08.079] END WMNewTab: 20 + + +[15:42.09.302] BEGIN CWD +[15:42.09.363] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.09.363] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.09.363] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.09.363] END CWD +[15:42.09.366] BEGIN WMNewTab: 20 +[15:42.09.366] END WMNewTab: 20 +[15:42.09.379] BEGIN CWD +[15:42.09.440] END CWD + + +[15:42.10.857] BEGIN WMNewTab: 20 +[15:42.10.857] END WMNewTab: 20 + + +[15:42.12.272] BEGIN WMNewTab: 20 +[15:42.12.272] END WMNewTab: 20 + + +[15:42.13.692] BEGIN WMNewTab: 20 +[15:42.13.692] END WMNewTab: 20 + + +[15:42.15.109] BEGIN WMNewTab: 20 +[15:42.15.109] END WMNewTab: 20 +[15:42.15.400] BEGIN CWD +[15:42.15.460] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.15.460] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.15.460] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.15.460] END CWD +[15:42.15.475] BEGIN CWD +[15:42.15.535] END CWD + +[15:42.16.435] BEGIN CWD +[15:42.16.480] BEGIN WMNewTab: 20 +[15:42.16.480] END WMNewTab: 20 +[15:42.16.496] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.16.496] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.16.496] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.16.496] END CWD +[15:42.16.510] BEGIN CWD +[15:42.16.571] END CWD + +[15:42.17.302] BEGIN CWD +[15:42.17.362] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.17.362] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.17.362] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.17.362] END CWD +[15:42.17.377] BEGIN CWD +[15:42.17.437] END CWD + +[15:42.17.909] BEGIN WMNewTab: 20 +[15:42.17.909] END WMNewTab: 20 + + +[15:42.19.328] BEGIN WMNewTab: 20 +[15:42.19.328] END WMNewTab: 20 + + +[15:42.20.739] BEGIN WMNewTab: 20 +[15:42.20.739] END WMNewTab: 20 + + +[15:42.22.156] BEGIN WMNewTab: 20 +[15:42.22.156] END WMNewTab: 20 + + +[15:42.23.569] BEGIN WMNewTab: 20 +[15:42.23.569] END WMNewTab: 20 +[15:42.23.615] BEGIN WMNewTab: 0 +[15:42.23.615] WMNewTab: FormClick +[15:42.23.615] WMNewTab: LooseFocus +[15:42.23.615] END WMNewTab: 0 +[15:42.23.615] BEGIN WMNewTab: 31 +[15:42.23.615] END WMNewTab: 31 + + +[15:42.25.003] BEGIN WMNewTab: 20 +[15:42.25.003] END WMNewTab: 20 + + +[15:42.26.415] BEGIN WMNewTab: 20 +[15:42.26.415] END WMNewTab: 20 + +[15:42.27.485] BEGIN CWD +[15:42.27.546] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.27.546] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.27.546] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.27.546] END CWD +[15:42.27.560] BEGIN CWD +[15:42.27.620] END CWD +[15:42.27.620] BEGIN WMNewTab: 20 +[15:42.27.620] END WMNewTab: 20 + + +[15:42.29.039] BEGIN WMNewTab: 20 +[15:42.29.039] END WMNewTab: 20 + + +[15:42.30.455] BEGIN WMNewTab: 20 +[15:42.30.455] END WMNewTab: 20 + + +[15:42.31.874] BEGIN WMNewTab: 20 +[15:42.31.874] END WMNewTab: 20 + + +[15:42.33.289] BEGIN WMNewTab: 20 +[15:42.33.289] END WMNewTab: 20 + + +[15:42.34.708] BEGIN WMNewTab: 20 +[15:42.34.708] END WMNewTab: 20 + + +[15:42.36.131] BEGIN WMNewTab: 20 +[15:42.36.131] END WMNewTab: 20 + + +[15:42.37.546] BEGIN WMNewTab: 20 +[15:42.37.546] END WMNewTab: 20 + + +[15:42.38.968] BEGIN WMNewTab: 20 +[15:42.38.968] END WMNewTab: 20 + +[15:42.39.501] BEGIN CWD +[15:42.39.562] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.39.562] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.39.562] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.39.562] END CWD +[15:42.39.577] BEGIN CWD +[15:42.39.637] END CWD + +[15:42.40.582] BEGIN WMNewTab: 20 +[15:42.40.582] END WMNewTab: 20 + + +[15:42.41.999] BEGIN WMNewTab: 20 +[15:42.41.999] END WMNewTab: 20 + + +[15:42.43.440] BEGIN WMNewTab: 20 +[15:42.43.440] END WMNewTab: 20 + +[15:42.44.552] sListView1Click: FormClick +[15:42.44.648] (SSH-Browser) BEGIN OpenDir(1) +[15:42.44.648] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.44.648] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.44.648] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.44.648] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:42.44.698] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/../); +[15:42.44.698] (SSH-Browser) END OpenDir(1) +[15:42.44.702] BEGIN WMNewTab: 20 +[15:42.44.702] END WMNewTab: 20 +[15:42.44.716] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:42.44.716] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/) +[15:42.44.747] (SSH-Browser) ElSFTP1OpenFile(1) +[15:42.44.747] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:42.44.808] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:42.44.808] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:42.44.808] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:42.44.808] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:42.44.808] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:42.44.808] (SSH-Browser) END VerifySFTPConnection(1) +[15:42.44.808] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:42.44.808] (SSH-Browser) END CloseCurrentHandle(1) +[15:42.44.808] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:42.44.808] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=26 +[15:42.44.808] (SSH-Browser) 对项目进行排序 +[15:42.44.808] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:42.44.816] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:42.44.838] (SSH-Browser) ElSFTP1Success(1) + + +[15:42.46.261] BEGIN WMNewTab: 20 +[15:42.46.261] END WMNewTab: 20 + + +[15:42.47.674] BEGIN WMNewTab: 20 +[15:42.47.674] END WMNewTab: 20 + + +[15:42.49.113] BEGIN WMNewTab: 20 +[15:42.49.113] END WMNewTab: 20 + + +[15:42.50.533] BEGIN WMNewTab: 20 +[15:42.50.533] END WMNewTab: 20 + + +[15:42.51.957] BEGIN WMNewTab: 20 +[15:42.51.957] END WMNewTab: 20 + + +[15:42.53.356] BEGIN WMNewTab: 20 +[15:42.53.356] END WMNewTab: 20 + +[15:42.54.151] BEGIN WMNewTab: 0 +[15:42.54.151] WMNewTab: FormClick +[15:42.54.151] WMNewTab: LooseFocus +[15:42.54.155] END WMNewTab: 0 + +[15:42.54.715] BEGIN WMNewTab: 0 +[15:42.54.715] WMNewTab: FormClick +[15:42.54.715] WMNewTab: LooseFocus +[15:42.54.716] END WMNewTab: 0 +[15:42.54.771] BEGIN WMNewTab: 20 +[15:42.54.771] END WMNewTab: 20 +[15:42.54.864] BEGIN WMNewTab: 0 +[15:42.54.864] WMNewTab: FormClick +[15:42.54.864] WMNewTab: LooseFocus +[15:42.54.864] END WMNewTab: 0 +[15:42.54.943] BEGIN WMNewTab: 0 +[15:42.54.943] WMNewTab: FormClick +[15:42.54.943] WMNewTab: LooseFocus +[15:42.54.944] END WMNewTab: 0 + + +[15:42.56.188] BEGIN WMNewTab: 20 +[15:42.56.188] END WMNewTab: 20 + + +[15:42.57.607] BEGIN WMNewTab: 20 +[15:42.57.607] END WMNewTab: 20 + + +[15:42.59.031] BEGIN WMNewTab: 20 +[15:42.59.031] END WMNewTab: 20 + + +[15:43.00.449] BEGIN WMNewTab: 20 +[15:43.00.449] END WMNewTab: 20 + + +[15:43.01.876] BEGIN WMNewTab: 20 +[15:43.01.876] END WMNewTab: 20 + + +[15:43.03.289] BEGIN WMNewTab: 20 +[15:43.03.289] END WMNewTab: 20 + + +[15:43.04.717] BEGIN WMNewTab: 20 +[15:43.04.717] END WMNewTab: 20 + +[15:43.05.712] sListView1Click: FormClick +[15:43.05.817] (SSH-Browser) BEGIN OpenDir(1) +[15:43.05.817] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.05.817] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.05.817] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.05.817] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:43.05.818] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/); +[15:43.05.818] (SSH-Browser) END OpenDir(1) +[15:43.05.832] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:43.05.832] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc) +[15:43.05.883] (SSH-Browser) ElSFTP1OpenFile(1) +[15:43.05.883] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:43.05.927] BEGIN WMNewTab: 20 +[15:43.05.927] END WMNewTab: 20 +[15:43.06.030] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:43.06.030] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:43.06.030] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:43.06.030] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.06.030] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.06.030] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.06.030] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:43.06.030] (SSH-Browser) END CloseCurrentHandle(1) +[15:43.06.030] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:43.06.030] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=233 +[15:43.06.034] (SSH-Browser) 对项目进行排序 +[15:43.06.035] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:43.06.050] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:43.06.117] (SSH-Browser) ElSFTP1Success(1) + + +[15:43.07.542] BEGIN WMNewTab: 20 +[15:43.07.542] END WMNewTab: 20 + + +[15:43.08.971] BEGIN WMNewTab: 20 +[15:43.08.971] END WMNewTab: 20 + + +[15:43.10.373] BEGIN WMNewTab: 20 +[15:43.10.373] END WMNewTab: 20 + + +[15:43.11.806] BEGIN WMNewTab: 20 +[15:43.11.806] END WMNewTab: 20 + + +[15:43.13.218] BEGIN WMNewTab: 20 +[15:43.13.218] END WMNewTab: 20 + + +[15:43.14.629] BEGIN WMNewTab: 20 +[15:43.14.629] END WMNewTab: 20 + + +[15:43.16.044] BEGIN WMNewTab: 20 +[15:43.16.044] END WMNewTab: 20 + + +[15:43.17.460] BEGIN WMNewTab: 20 +[15:43.17.460] END WMNewTab: 20 + + +[15:43.18.884] BEGIN WMNewTab: 20 +[15:43.18.884] END WMNewTab: 20 + +[15:43.19.952] +[15:43.19.952] +[15:43.19.952] BEGIN TForm1.MobaInputDialog +[15:43.19.958] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[15:43.19.958] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=Form4.Handle; +[15:43.19.959] TForm1.MobaInputDialog: FormInputDialog.ShowModal +[15:43.20.296] BEGIN WMNewTab: 20 +[15:43.20.296] END WMNewTab: 20 + + +[15:43.21.710] BEGIN WMNewTab: 20 +[15:43.21.710] END WMNewTab: 20 +[15:43.21.999] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[15:43.21.999] END TForm1.MobaInputDialog +[15:43.21.999] +[15:43.21.999] +[15:43.21.999] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.21.999] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.21.999] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.21.999] (SSH-Browser) MakeDirectory1Click: SFTP.MakeDirectory(/etc/ppp) +[15:43.22.015] (SSH-Browser) ElSFTP1Success(1) +[15:43.22.015] (SSH-Browser) BEGIN OpenDir(1) +[15:43.22.015] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.22.015] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.22.015] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.22.015] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:43.22.021] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/); +[15:43.22.021] (SSH-Browser) END OpenDir(1) +[15:43.22.046] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:43.22.046] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc) +[15:43.22.075] (SSH-Browser) ElSFTP1OpenFile(1) +[15:43.22.075] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:43.22.214] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:43.22.214] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:43.22.214] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:43.22.214] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.22.214] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.22.214] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.22.214] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:43.22.214] (SSH-Browser) END CloseCurrentHandle(1) +[15:43.22.214] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:43.22.214] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=234 +[15:43.22.216] (SSH-Browser) 对项目进行排序 +[15:43.22.216] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:43.22.226] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:43.22.274] (SSH-Browser) ElSFTP1Success(1) + +[15:43.23.257] BEGIN WMNewTab: 20 +[15:43.23.257] END WMNewTab: 20 + + +[15:43.24.668] BEGIN WMNewTab: 20 +[15:43.24.668] END WMNewTab: 20 +[15:43.24.883] sListView1Click: FormClick +[15:43.24.968] (SSH-Browser) BEGIN OpenDir(1) +[15:43.24.968] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.24.968] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.24.968] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.24.968] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:43.25.018] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/ppp/); +[15:43.25.018] (SSH-Browser) END OpenDir(1) +[15:43.25.032] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:43.25.032] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc/ppp) +[15:43.25.064] (SSH-Browser) ElSFTP1OpenFile(1) +[15:43.25.064] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:43.25.126] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:43.25.126] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:43.25.126] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:43.25.126] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.25.126] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.25.126] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.25.126] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:43.25.127] (SSH-Browser) END CloseCurrentHandle(1) +[15:43.25.127] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:43.25.127] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=2 +[15:43.25.127] (SSH-Browser) 对项目进行排序 +[15:43.25.127] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:43.25.134] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:43.25.157] (SSH-Browser) ElSFTP1Success(1) + +[15:43.26.101] BEGIN WMNewTab: 20 +[15:43.26.101] END WMNewTab: 20 + +[15:43.27.100] BEGIN WMNewTab: 0 +[15:43.27.100] WMNewTab: FormClick +[15:43.27.100] WMNewTab: LooseFocus +[15:43.27.102] END WMNewTab: 0 + +[15:43.27.516] BEGIN WMNewTab: 20 +[15:43.27.516] END WMNewTab: 20 + + +[15:43.28.864] BEGIN WMNewTab: 0 +[15:43.28.864] WMNewTab: FormClick +[15:43.28.864] WMNewTab: LooseFocus +[15:43.28.868] END WMNewTab: 0 +[15:43.28.932] BEGIN WMNewTab: 20 +[15:43.28.932] END WMNewTab: 20 + + +[15:43.30.351] BEGIN WMNewTab: 20 +[15:43.30.351] END WMNewTab: 20 +[15:43.30.593] +[15:43.30.593] +[15:43.30.593] BEGIN TForm1.MobaInputDialog +[15:43.30.594] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[15:43.30.594] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=0; +[15:43.30.595] TForm1.MobaInputDialog: FormInputDialog.ShowModal + +[15:43.31.763] BEGIN WMNewTab: 20 +[15:43.31.763] END WMNewTab: 20 + + +[15:43.33.176] BEGIN WMNewTab: 20 +[15:43.33.176] END WMNewTab: 20 +[15:43.33.397] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[15:43.33.397] END TForm1.MobaInputDialog +[15:43.33.397] +[15:43.33.397] +[15:43.33.397] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.33.397] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.33.397] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.33.397] (SSH-Browser) MakeDirectory1Click: SFTP.MakeDirectory(/etc/ppp/peers) +[15:43.33.409] (SSH-Browser) ElSFTP1Success(1) +[15:43.33.409] (SSH-Browser) BEGIN OpenDir(1) +[15:43.33.409] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.33.409] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.33.410] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.33.410] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:43.33.411] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/ppp/); +[15:43.33.411] (SSH-Browser) END OpenDir(1) +[15:43.33.451] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:43.33.451] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc/ppp) +[15:43.33.483] (SSH-Browser) ElSFTP1OpenFile(1) +[15:43.33.483] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:43.33.543] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:43.33.543] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:43.33.543] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:43.33.543] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.33.543] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.33.543] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.33.543] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:43.33.543] (SSH-Browser) END CloseCurrentHandle(1) +[15:43.33.543] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:43.33.543] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[15:43.33.543] (SSH-Browser) 对项目进行排序 +[15:43.33.543] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:43.33.547] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:43.33.573] (SSH-Browser) ElSFTP1Success(1) + +[15:43.34.225] sListView1Click: FormClick +[15:43.34.517] BEGIN WMNewTab: 20 +[15:43.34.517] END WMNewTab: 20 +[15:43.34.857] sListView1Click: FormClick +[15:43.34.930] (SSH-Browser) BEGIN OpenDir(1) +[15:43.34.930] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.34.930] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.34.930] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.34.930] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:43.34.964] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/ppp/peers/); +[15:43.34.964] (SSH-Browser) END OpenDir(1) +[15:43.35.021] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:43.35.021] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc/ppp/peers) +[15:43.35.051] (SSH-Browser) ElSFTP1OpenFile(1) +[15:43.35.051] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:43.35.113] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:43.35.113] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:43.35.113] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:43.35.113] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.35.113] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.35.113] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.35.113] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:43.35.113] (SSH-Browser) END CloseCurrentHandle(1) +[15:43.35.113] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:43.35.113] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=2 +[15:43.35.113] (SSH-Browser) 对项目进行排序 +[15:43.35.113] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:43.35.121] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:43.35.143] (SSH-Browser) ElSFTP1Success(1) + +[15:43.36.087] BEGIN WMNewTab: 20 +[15:43.36.087] END WMNewTab: 20 +[15:43.36.425] BEGIN WMNewTab: 0 +[15:43.36.425] WMNewTab: FormClick +[15:43.36.425] WMNewTab: LooseFocus +[15:43.36.428] END WMNewTab: 0 + +[15:43.37.004] BEGIN WMNewTab: 0 +[15:43.37.004] WMNewTab: FormClick +[15:43.37.004] WMNewTab: LooseFocus +[15:43.37.008] END WMNewTab: 0 +[15:43.37.329] BEGIN WMNewTab: 0 +[15:43.37.329] WMNewTab: FormClick +[15:43.37.329] WMNewTab: LooseFocus +[15:43.37.329] END WMNewTab: 0 +[15:43.37.441] BEGIN WMNewTab: 0 +[15:43.37.441] WMNewTab: FormClick +[15:43.37.441] WMNewTab: LooseFocus +[15:43.37.442] END WMNewTab: 0 +[15:43.37.537] BEGIN WMNewTab: 20 +[15:43.37.537] END WMNewTab: 20 +[15:43.37.770] BEGIN WMNewTab: 0 +[15:43.37.770] WMNewTab: FormClick +[15:43.37.770] WMNewTab: LooseFocus +[15:43.37.770] END WMNewTab: 0 + +[15:43.38.176] BEGIN WMNewTab: 0 +[15:43.38.176] WMNewTab: FormClick +[15:43.38.176] WMNewTab: LooseFocus +[15:43.38.178] END WMNewTab: 0 +[15:43.38.313] BEGIN WMNewTab: 0 +[15:43.38.313] WMNewTab: FormClick +[15:43.38.313] WMNewTab: LooseFocus +[15:43.38.314] END WMNewTab: 0 +[15:43.38.416] BEGIN WMNewTab: 0 +[15:43.38.416] WMNewTab: FormClick +[15:43.38.416] WMNewTab: LooseFocus +[15:43.38.417] END WMNewTab: 0 + +[15:43.38.958] BEGIN WMNewTab: 20 +[15:43.38.958] END WMNewTab: 20 + +[15:43.39.337] BEGIN WMNewTab: 0 +[15:43.39.337] WMNewTab: FormClick +[15:43.39.337] WMNewTab: LooseFocus +[15:43.39.337] END WMNewTab: 0 + +[15:43.40.375] BEGIN WMNewTab: 20 +[15:43.40.375] END WMNewTab: 20 + +[15:43.41.344] BEGIN WMNewTab: 0 +[15:43.41.344] WMNewTab: FormClick +[15:43.41.344] WMNewTab: LooseFocus +[15:43.41.349] END WMNewTab: 0 + +[15:43.41.796] BEGIN WMNewTab: 20 +[15:43.41.796] END WMNewTab: 20 + + +[15:43.43.221] BEGIN WMNewTab: 20 +[15:43.43.221] END WMNewTab: 20 + +[15:43.43.585] +[15:43.43.585] +[15:43.43.585] BEGIN TForm1.MobaInputDialog +[15:43.43.586] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[15:43.43.586] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=Form4.Handle; +[15:43.43.587] TForm1.MobaInputDialog: FormInputDialog.ShowModal + +[15:43.44.634] BEGIN WMNewTab: 20 +[15:43.44.634] END WMNewTab: 20 +[15:43.44.994] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[15:43.44.994] END TForm1.MobaInputDialog +[15:43.44.994] +[15:43.44.994] +[15:43.44.994] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.44.994] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.44.994] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.44.994] (SSH-Browser) NewFile1Click: SFTP.CreateFile(/etc/ppp/peers/sim7600) +[15:43.45.015] (SSH-Browser) ElSFTP1OpenFile(1) +[15:43.45.015] (SSH-Browser) ElSFTP1OpenFile(1): CloseCurrentHandle +[15:43.45.015] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:43.45.015] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.45.015] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.45.015] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.45.015] (SSH-Browser) END CloseCurrentHandle(1) +[15:43.45.015] (SSH-Browser) BEGIN OpenDir(1) +[15:43.45.015] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.45.015] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.45.015] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.45.015] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:43.45.018] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/ppp/peers/); +[15:43.45.018] (SSH-Browser) END OpenDir(1) +[15:43.45.043] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:43.45.043] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc/ppp/peers) +[15:43.45.073] (SSH-Browser) ElSFTP1OpenFile(1) +[15:43.45.073] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:43.45.135] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:43.45.135] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:43.45.135] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:43.45.135] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.45.135] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.45.135] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.45.135] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:43.45.135] (SSH-Browser) END CloseCurrentHandle(1) +[15:43.45.135] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:43.45.135] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[15:43.45.135] (SSH-Browser) 对项目进行排序 +[15:43.45.135] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:43.45.138] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:43.45.166] (SSH-Browser) ElSFTP1Success(1) + +[15:43.46.112] BEGIN WMNewTab: 20 +[15:43.46.112] END WMNewTab: 20 +[15:43.46.236] BEGIN WMNewTab: 0 +[15:43.46.236] WMNewTab: FormClick +[15:43.46.236] WMNewTab: LooseFocus +[15:43.46.236] END WMNewTab: 0 +[15:43.46.345] BEGIN WMNewTab: 0 +[15:43.46.345] WMNewTab: FormClick +[15:43.46.345] WMNewTab: LooseFocus +[15:43.46.345] END WMNewTab: 0 + +[15:43.47.278] BEGIN CWD +[15:43.47.339] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.47.339] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.47.339] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.47.339] END CWD +[15:43.47.340] BEGIN WMNewTab: 20 +[15:43.47.340] END WMNewTab: 20 +[15:43.47.354] BEGIN CWD +[15:43.47.416] (CWD) OpenDir(/root); +[15:43.47.416] (SSH-Browser) BEGIN OpenDir(1) +[15:43.47.416] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.47.416] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.47.416] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.47.416] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:43.47.417] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root); +[15:43.47.417] (SSH-Browser) END OpenDir(1) +[15:43.47.417] END CWD +[15:43.47.445] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:43.47.445] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[15:43.47.475] (SSH-Browser) ElSFTP1OpenFile(1) +[15:43.47.475] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:43.47.537] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:43.47.537] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:43.47.537] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:43.47.537] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.47.537] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.47.537] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.47.537] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:43.47.537] (SSH-Browser) END CloseCurrentHandle(1) +[15:43.47.537] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:43.47.537] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=16 +[15:43.47.537] (SSH-Browser) 对项目进行排序 +[15:43.47.537] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:43.47.540] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:43.47.567] (SSH-Browser) ElSFTP1Success(1) + +[15:43.48.289] BEGIN WMNewTab: 0 +[15:43.48.289] WMNewTab: FormClick +[15:43.48.289] WMNewTab: LooseFocus +[15:43.48.289] END WMNewTab: 0 +[15:43.48.289] BEGIN WMNewTab: 31 +[15:43.48.289] END WMNewTab: 31 +[15:43.48.388] BEGIN WMNewTab: 0 +[15:43.48.388] WMNewTab: FormClick +[15:43.48.388] WMNewTab: LooseFocus +[15:43.48.389] END WMNewTab: 0 + +[15:43.48.983] BEGIN WMNewTab: 20 +[15:43.48.983] END WMNewTab: 20 + + +[15:43.50.404] BEGIN WMNewTab: 20 +[15:43.50.404] END WMNewTab: 20 + + +[15:43.51.828] BEGIN WMNewTab: 20 +[15:43.51.828] END WMNewTab: 20 + + +[15:43.53.230] BEGIN WMNewTab: 20 +[15:43.53.230] END WMNewTab: 20 +[15:43.53.469] BEGIN WMNewTab: 31 +[15:43.53.469] END WMNewTab: 31 +[15:43.53.469] BEGIN WMNewTab: 0 +[15:43.53.469] WMNewTab: FormClick +[15:43.53.469] WMNewTab: LooseFocus +[15:43.53.469] END WMNewTab: 0 + +[15:43.54.640] BEGIN WMNewTab: 20 +[15:43.54.640] END WMNewTab: 20 + +[15:43.55.112] BEGIN CWD +[15:43.55.172] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.55.172] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.55.172] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.55.172] END CWD +[15:43.55.188] BEGIN CWD +[15:43.55.249] END CWD + +[15:43.56.196] BEGIN WMNewTab: 20 +[15:43.56.196] END WMNewTab: 20 + +[15:43.57.292] BEGIN CWD +[15:43.57.352] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:43.57.352] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:43.57.352] (SSH-Browser) END VerifySFTPConnection(1) +[15:43.57.352] END CWD +[15:43.57.368] BEGIN CWD +[15:43.57.429] END CWD +[15:43.57.429] BEGIN WMNewTab: 20 +[15:43.57.429] END WMNewTab: 20 + + +[15:43.58.848] BEGIN WMNewTab: 20 +[15:43.58.848] END WMNewTab: 20 + + +[15:44.00.260] BEGIN WMNewTab: 20 +[15:44.00.260] END WMNewTab: 20 + + +[15:44.01.677] BEGIN WMNewTab: 20 +[15:44.01.677] END WMNewTab: 20 + + +[15:44.03.092] BEGIN WMNewTab: 20 +[15:44.03.092] END WMNewTab: 20 + + +[15:44.04.506] BEGIN WMNewTab: 20 +[15:44.04.506] END WMNewTab: 20 + +[15:44.05.653] BEGIN WMNewTab: 0 +[15:44.05.653] WMNewTab: FormClick +[15:44.05.653] WMNewTab: LooseFocus +[15:44.05.653] END WMNewTab: 0 +[15:44.05.653] BEGIN WMNewTab: 31 +[15:44.05.653] END WMNewTab: 31 +[15:44.05.920] BEGIN WMNewTab: 20 +[15:44.05.920] END WMNewTab: 20 + + +[15:44.07.332] BEGIN WMNewTab: 20 +[15:44.07.332] END WMNewTab: 20 +[15:44.07.441] BEGIN CWD +[15:44.07.501] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.07.501] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.07.501] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.07.501] END CWD +[15:44.07.517] BEGIN CWD +[15:44.07.578] END CWD + + +[15:44.08.990] BEGIN WMNewTab: 20 +[15:44.08.990] END WMNewTab: 20 + + +[15:44.10.410] BEGIN WMNewTab: 20 +[15:44.10.410] END WMNewTab: 20 + + +[15:44.11.832] BEGIN WMNewTab: 20 +[15:44.11.832] END WMNewTab: 20 + + +[15:44.13.243] BEGIN WMNewTab: 20 +[15:44.13.243] END WMNewTab: 20 + + +[15:44.14.659] BEGIN WMNewTab: 20 +[15:44.14.659] END WMNewTab: 20 + +[15:44.15.409] sListView1Click: FormClick + +[15:44.15.775] sListView1Click: FormClick +[15:44.15.870] (SSH-Browser) BEGIN OpenDir(1) +[15:44.15.870] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.15.870] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.15.870] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.15.870] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:44.15.891] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/../); +[15:44.15.892] (SSH-Browser) END OpenDir(1) +[15:44.15.894] BEGIN WMNewTab: 20 +[15:44.15.894] END WMNewTab: 20 +[15:44.15.905] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:44.15.905] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/) +[15:44.15.935] (SSH-Browser) ElSFTP1OpenFile(1) +[15:44.15.935] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:44.15.997] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:44.15.997] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:44.15.997] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:44.15.997] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.15.997] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.15.997] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.15.997] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:44.15.998] (SSH-Browser) END CloseCurrentHandle(1) +[15:44.15.998] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:44.15.998] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=26 +[15:44.15.998] (SSH-Browser) 对项目进行排序 +[15:44.15.998] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:44.16.005] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:44.16.042] (SSH-Browser) ElSFTP1Success(1) + +[15:44.17.055] sListView1Click: FormClick +[15:44.17.120] (SSH-Browser) BEGIN OpenDir(1) +[15:44.17.120] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.17.120] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.17.120] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.17.120] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:44.17.121] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/); +[15:44.17.121] (SSH-Browser) END OpenDir(1) +[15:44.17.124] BEGIN WMNewTab: 20 +[15:44.17.124] END WMNewTab: 20 +[15:44.17.134] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:44.17.134] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc) +[15:44.17.164] (SSH-Browser) ElSFTP1OpenFile(1) +[15:44.17.164] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:44.17.332] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:44.17.332] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:44.17.332] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:44.17.332] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.17.332] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.17.332] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.17.332] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:44.17.332] (SSH-Browser) END CloseCurrentHandle(1) +[15:44.17.332] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:44.17.332] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=234 +[15:44.17.334] (SSH-Browser) 对项目进行排序 +[15:44.17.334] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:44.17.341] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:44.17.390] (SSH-Browser) ElSFTP1Success(1) + +[15:44.18.353] BEGIN WMNewTab: 20 +[15:44.18.353] END WMNewTab: 20 + +[15:44.19.134] BEGIN WMNewTab: 0 +[15:44.19.134] WMNewTab: FormClick +[15:44.19.134] WMNewTab: LooseFocus +[15:44.19.138] END WMNewTab: 0 + +[15:44.19.763] BEGIN WMNewTab: 20 +[15:44.19.763] END WMNewTab: 20 + +[15:44.20.781] BEGIN WMNewTab: 0 +[15:44.20.781] WMNewTab: FormClick +[15:44.20.781] WMNewTab: LooseFocus +[15:44.20.784] END WMNewTab: 0 + +[15:44.21.179] BEGIN WMNewTab: 20 +[15:44.21.179] END WMNewTab: 20 + + +[15:44.22.582] (SSH-Browser) BEGIN OpenDir(1) +[15:44.22.582] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.22.582] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.22.582] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.22.582] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:44.22.586] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/); +[15:44.22.586] (SSH-Browser) END OpenDir(1) +[15:44.22.596] BEGIN WMNewTab: 20 +[15:44.22.596] END WMNewTab: 20 +[15:44.22.627] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:44.22.627] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc) +[15:44.22.657] (SSH-Browser) ElSFTP1OpenFile(1) +[15:44.22.657] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:44.22.793] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:44.22.793] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:44.22.793] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:44.22.793] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.22.793] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.22.793] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.22.793] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:44.22.793] (SSH-Browser) END CloseCurrentHandle(1) +[15:44.22.793] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:44.22.793] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=234 +[15:44.22.795] (SSH-Browser) 对项目进行排序 +[15:44.22.795] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:44.22.823] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:44.22.870] (SSH-Browser) ElSFTP1Success(1) + +[15:44.23.526] +[15:44.23.526] +[15:44.23.526] BEGIN TForm1.MobaInputDialog +[15:44.23.527] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[15:44.23.527] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=0; +[15:44.23.528] TForm1.MobaInputDialog: FormInputDialog.ShowModal +[15:44.23.815] BEGIN WMNewTab: 20 +[15:44.23.815] END WMNewTab: 20 + + +[15:44.25.084] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[15:44.25.084] END TForm1.MobaInputDialog +[15:44.25.084] +[15:44.25.084] +[15:44.25.084] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.25.084] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.25.084] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.25.084] (SSH-Browser) MakeDirectory1Click: SFTP.MakeDirectory(/etc/chatscripts) +[15:44.25.087] BEGIN WMNewTab: 20 +[15:44.25.087] END WMNewTab: 20 +[15:44.25.090] (SSH-Browser) ElSFTP1Success(1) +[15:44.25.090] (SSH-Browser) BEGIN OpenDir(1) +[15:44.25.090] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.25.090] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.25.090] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.25.090] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:44.25.095] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/); +[15:44.25.095] (SSH-Browser) END OpenDir(1) +[15:44.25.121] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:44.25.121] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc) +[15:44.25.151] (SSH-Browser) ElSFTP1OpenFile(1) +[15:44.25.151] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:44.25.287] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:44.25.287] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:44.25.287] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:44.25.287] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.25.287] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.25.287] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.25.287] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:44.25.287] (SSH-Browser) END CloseCurrentHandle(1) +[15:44.25.287] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:44.25.287] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=235 +[15:44.25.289] (SSH-Browser) 对项目进行排序 +[15:44.25.289] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:44.25.298] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:44.25.349] (SSH-Browser) ElSFTP1Success(1) + +[15:44.26.209] BEGIN WMNewTab: 0 +[15:44.26.209] WMNewTab: FormClick +[15:44.26.209] WMNewTab: LooseFocus +[15:44.26.210] END WMNewTab: 0 +[15:44.26.294] BEGIN WMNewTab: 20 +[15:44.26.294] END WMNewTab: 20 + +[15:44.26.686] BEGIN WMNewTab: 0 +[15:44.26.686] WMNewTab: FormClick +[15:44.26.686] WMNewTab: LooseFocus +[15:44.26.690] END WMNewTab: 0 +[15:44.27.004] BEGIN WMNewTab: 0 +[15:44.27.004] WMNewTab: FormClick +[15:44.27.004] WMNewTab: LooseFocus +[15:44.27.004] END WMNewTab: 0 +[15:44.27.142] BEGIN WMNewTab: 0 +[15:44.27.142] WMNewTab: FormClick +[15:44.27.142] WMNewTab: LooseFocus +[15:44.27.143] END WMNewTab: 0 + +[15:44.27.514] BEGIN WMNewTab: 0 +[15:44.27.514] WMNewTab: FormClick +[15:44.27.514] WMNewTab: LooseFocus +[15:44.27.514] END WMNewTab: 0 +[15:44.27.711] BEGIN WMNewTab: 20 +[15:44.27.711] END WMNewTab: 20 + + +[15:44.29.132] BEGIN WMNewTab: 20 +[15:44.29.132] END WMNewTab: 20 + +[15:44.29.517] BEGIN WMNewTab: 0 +[15:44.29.517] WMNewTab: FormClick +[15:44.29.517] WMNewTab: LooseFocus +[15:44.29.521] END WMNewTab: 0 + +[15:44.30.547] BEGIN WMNewTab: 20 +[15:44.30.547] END WMNewTab: 20 +[15:44.30.678] sListView1Click: FormClick +[15:44.30.744] (SSH-Browser) BEGIN OpenDir(1) +[15:44.30.744] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.30.744] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.30.744] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.30.744] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:44.30.748] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/chatscripts/); +[15:44.30.748] (SSH-Browser) END OpenDir(1) +[15:44.30.764] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:44.30.764] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc/chatscripts) +[15:44.30.792] (SSH-Browser) ElSFTP1OpenFile(1) +[15:44.30.792] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:44.30.853] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:44.30.853] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:44.30.853] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:44.30.853] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.30.853] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.30.853] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.30.853] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:44.30.853] (SSH-Browser) END CloseCurrentHandle(1) +[15:44.30.853] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:44.30.853] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=2 +[15:44.30.853] (SSH-Browser) 对项目进行排序 +[15:44.30.853] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:44.30.861] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:44.30.887] (SSH-Browser) ElSFTP1Success(1) + +[15:44.31.814] +[15:44.31.814] +[15:44.31.814] BEGIN TForm1.MobaInputDialog +[15:44.31.815] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[15:44.31.815] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=Form4.Handle; +[15:44.31.815] TForm1.MobaInputDialog: FormInputDialog.ShowModal +[15:44.31.849] BEGIN WMNewTab: 20 +[15:44.31.849] END WMNewTab: 20 + + +[15:44.33.145] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[15:44.33.145] END TForm1.MobaInputDialog +[15:44.33.145] +[15:44.33.145] +[15:44.33.145] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.33.145] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.33.145] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.33.145] (SSH-Browser) NewFile1Click: SFTP.CreateFile(/etc/chatscripts/sim7600) +[15:44.33.147] BEGIN WMNewTab: 20 +[15:44.33.147] END WMNewTab: 20 +[15:44.33.151] (SSH-Browser) ElSFTP1OpenFile(1) +[15:44.33.151] (SSH-Browser) ElSFTP1OpenFile(1): CloseCurrentHandle +[15:44.33.151] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:44.33.151] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.33.151] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.33.151] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.33.151] (SSH-Browser) END CloseCurrentHandle(1) +[15:44.33.151] (SSH-Browser) BEGIN OpenDir(1) +[15:44.33.151] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.33.151] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.33.151] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.33.151] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:44.33.152] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/etc/chatscripts/); +[15:44.33.152] (SSH-Browser) END OpenDir(1) +[15:44.33.181] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:44.33.181] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/etc/chatscripts) +[15:44.33.213] (SSH-Browser) ElSFTP1OpenFile(1) +[15:44.33.213] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:44.33.273] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:44.33.273] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:44.33.273] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:44.33.273] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.33.273] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.33.273] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.33.273] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:44.33.273] (SSH-Browser) END CloseCurrentHandle(1) +[15:44.33.273] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:44.33.273] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[15:44.33.273] (SSH-Browser) 对项目进行排序 +[15:44.33.273] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:44.33.276] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:44.33.303] (SSH-Browser) ElSFTP1Success(1) + +[15:44.34.495] BEGIN WMNewTab: 0 +[15:44.34.495] WMNewTab: FormClick +[15:44.34.495] WMNewTab: LooseFocus +[15:44.34.498] END WMNewTab: 0 +[15:44.34.613] BEGIN WMNewTab: 0 +[15:44.34.613] WMNewTab: FormClick +[15:44.34.613] WMNewTab: LooseFocus +[15:44.34.613] END WMNewTab: 0 +[15:44.34.717] BEGIN WMNewTab: 20 +[15:44.34.717] END WMNewTab: 20 +[15:44.34.965] BEGIN CWD +[15:44.35.026] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.35.026] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.35.026] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.35.026] END CWD +[15:44.35.035] BEGIN CWD +[15:44.35.095] (CWD) OpenDir(/root); +[15:44.35.096] (SSH-Browser) BEGIN OpenDir(1) +[15:44.35.096] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.35.096] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.35.096] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.35.096] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[15:44.35.096] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root); +[15:44.35.096] (SSH-Browser) END OpenDir(1) +[15:44.35.096] END CWD +[15:44.35.128] (SSH-Browser) ElSFTP1AbsolutePath(1) +[15:44.35.128] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[15:44.35.158] (SSH-Browser) ElSFTP1OpenFile(1) +[15:44.35.158] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[15:44.35.218] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[15:44.35.218] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[15:44.35.218] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[15:44.35.218] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.35.218] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.35.218] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.35.218] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[15:44.35.218] (SSH-Browser) END CloseCurrentHandle(1) +[15:44.35.218] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[15:44.35.218] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=16 +[15:44.35.218] (SSH-Browser) 对项目进行排序 +[15:44.35.218] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[15:44.35.221] (SSH-Browser) END CopySFTPFileListToListView(1) +[15:44.35.249] (SSH-Browser) ElSFTP1Success(1) + +[15:44.36.193] BEGIN WMNewTab: 20 +[15:44.36.193] END WMNewTab: 20 + + +[15:44.37.611] BEGIN WMNewTab: 20 +[15:44.37.611] END WMNewTab: 20 + + +[15:44.39.025] BEGIN WMNewTab: 20 +[15:44.39.025] END WMNewTab: 20 + +[15:44.39.727] BEGIN WMNewTab: 31 +[15:44.39.727] END WMNewTab: 31 +[15:44.39.727] BEGIN WMNewTab: 0 +[15:44.39.727] WMNewTab: FormClick +[15:44.39.727] WMNewTab: LooseFocus +[15:44.39.727] END WMNewTab: 0 + +[15:44.40.443] BEGIN WMNewTab: 20 +[15:44.40.443] END WMNewTab: 20 + + +[15:44.41.850] BEGIN WMNewTab: 20 +[15:44.41.850] END WMNewTab: 20 + + +[15:44.43.258] BEGIN WMNewTab: 20 +[15:44.43.258] END WMNewTab: 20 + + +[15:44.44.672] BEGIN WMNewTab: 20 +[15:44.44.672] END WMNewTab: 20 + +[15:44.45.540] BEGIN CWD +[15:44.45.600] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.45.600] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.45.600] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.45.600] END CWD +[15:44.45.647] BEGIN CWD +[15:44.45.709] END CWD + +[15:44.46.182] BEGIN WMNewTab: 20 +[15:44.46.182] END WMNewTab: 20 + + +[15:44.47.599] BEGIN WMNewTab: 20 +[15:44.47.599] END WMNewTab: 20 + + +[15:44.49.010] BEGIN WMNewTab: 20 +[15:44.49.010] END WMNewTab: 20 + + +[15:44.50.431] BEGIN WMNewTab: 20 +[15:44.50.431] END WMNewTab: 20 + +[15:44.51.582] BEGIN WMNewTab: 0 +[15:44.51.582] WMNewTab: FormClick +[15:44.51.582] WMNewTab: LooseFocus +[15:44.51.584] END WMNewTab: 0 +[15:44.51.584] BEGIN WMNewTab: 31 +[15:44.51.584] END WMNewTab: 31 +[15:44.51.849] BEGIN WMNewTab: 20 +[15:44.51.849] END WMNewTab: 20 + +[15:44.52.790] BEGIN CWD +[15:44.52.850] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:44.52.850] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:44.52.850] (SSH-Browser) END VerifySFTPConnection(1) +[15:44.52.850] END CWD +[15:44.52.867] BEGIN CWD +[15:44.52.928] END CWD + +[15:44.53.402] BEGIN WMNewTab: 20 +[15:44.53.402] END WMNewTab: 20 + + +[15:44.54.816] BEGIN WMNewTab: 20 +[15:44.54.816] END WMNewTab: 20 + + +[15:44.56.230] BEGIN WMNewTab: 20 +[15:44.56.230] END WMNewTab: 20 + + +[15:44.57.651] BEGIN WMNewTab: 20 +[15:44.57.651] END WMNewTab: 20 + + +[15:44.59.069] BEGIN WMNewTab: 20 +[15:44.59.069] END WMNewTab: 20 +[15:44.59.160] BEGIN WMNewTab: 0 +[15:44.59.160] WMNewTab: FormClick +[15:44.59.160] WMNewTab: LooseFocus +[15:44.59.160] END WMNewTab: 0 + + +[15:45.00.484] BEGIN WMNewTab: 20 +[15:45.00.485] END WMNewTab: 20 + +[15:45.01.686] BEGIN WMNewTab: 0 +[15:45.01.686] WMNewTab: FormClick +[15:45.01.686] WMNewTab: LooseFocus +[15:45.01.689] END WMNewTab: 0 +[15:45.01.901] BEGIN WMNewTab: 20 +[15:45.01.901] END WMNewTab: 20 + + +[15:45.03.316] BEGIN WMNewTab: 20 +[15:45.03.316] END WMNewTab: 20 + + +[15:45.04.727] BEGIN WMNewTab: 20 +[15:45.04.727] END WMNewTab: 20 + + +[15:45.06.143] BEGIN WMNewTab: 20 +[15:45.06.143] END WMNewTab: 20 + + +[15:45.07.550] BEGIN WMNewTab: 20 +[15:45.07.550] END WMNewTab: 20 + + +[15:45.08.965] BEGIN WMNewTab: 20 +[15:45.08.965] END WMNewTab: 20 + + +[15:45.10.403] BEGIN WMNewTab: 20 +[15:45.10.403] END WMNewTab: 20 + +[15:45.11.599] BEGIN WMNewTab: 31 +[15:45.11.599] END WMNewTab: 31 +[15:45.11.599] BEGIN WMNewTab: 0 +[15:45.11.599] WMNewTab: FormClick +[15:45.11.599] WMNewTab: LooseFocus +[15:45.11.599] END WMNewTab: 0 +[15:45.11.813] BEGIN WMNewTab: 20 +[15:45.11.813] END WMNewTab: 20 + + +[15:45.13.227] BEGIN WMNewTab: 20 +[15:45.13.227] END WMNewTab: 20 + +[15:45.13.608] BEGIN CWD +[15:45.13.669] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:45.13.669] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:45.13.669] (SSH-Browser) END VerifySFTPConnection(1) +[15:45.13.669] END CWD +[15:45.13.732] BEGIN CWD +[15:45.13.792] END CWD + +[15:45.14.733] BEGIN WMNewTab: 20 +[15:45.14.733] END WMNewTab: 20 + + +[15:45.16.145] BEGIN WMNewTab: 20 +[15:45.16.145] END WMNewTab: 20 + + +[15:45.17.563] BEGIN WMNewTab: 20 +[15:45.17.563] END WMNewTab: 20 + + +[15:45.18.982] BEGIN WMNewTab: 20 +[15:45.18.982] END WMNewTab: 20 + + +[15:45.20.398] BEGIN WMNewTab: 20 +[15:45.20.398] END WMNewTab: 20 + + +[15:45.21.816] BEGIN WMNewTab: 20 +[15:45.21.816] END WMNewTab: 20 + + +[15:45.23.240] BEGIN WMNewTab: 20 +[15:45.23.240] END WMNewTab: 20 + + +[15:45.24.654] BEGIN WMNewTab: 20 +[15:45.24.654] END WMNewTab: 20 + + +[15:45.26.068] BEGIN WMNewTab: 20 +[15:45.26.068] END WMNewTab: 20 + + +[15:45.27.485] BEGIN WMNewTab: 20 +[15:45.27.485] END WMNewTab: 20 + + +[15:45.28.902] BEGIN WMNewTab: 20 +[15:45.28.902] END WMNewTab: 20 + + +[15:45.30.323] BEGIN WMNewTab: 20 +[15:45.30.323] END WMNewTab: 20 + + +[15:45.31.743] BEGIN WMNewTab: 20 +[15:45.31.743] END WMNewTab: 20 + + +[15:45.33.161] BEGIN WMNewTab: 20 +[15:45.33.161] END WMNewTab: 20 + + +[15:45.34.577] BEGIN WMNewTab: 20 +[15:45.34.577] END WMNewTab: 20 + + +[15:45.35.996] BEGIN WMNewTab: 20 +[15:45.35.996] END WMNewTab: 20 + + +[15:45.37.409] BEGIN WMNewTab: 20 +[15:45.37.409] END WMNewTab: 20 + + +[15:45.38.825] BEGIN WMNewTab: 20 +[15:45.38.825] END WMNewTab: 20 + + +[15:45.40.238] BEGIN WMNewTab: 20 +[15:45.40.238] END WMNewTab: 20 + + +[15:45.41.655] BEGIN WMNewTab: 20 +[15:45.41.655] END WMNewTab: 20 + + +[15:45.43.079] BEGIN WMNewTab: 20 +[15:45.43.079] END WMNewTab: 20 + + +[15:45.44.495] BEGIN WMNewTab: 20 +[15:45.44.495] END WMNewTab: 20 + + +[15:45.45.914] BEGIN WMNewTab: 20 +[15:45.45.914] END WMNewTab: 20 + + +[15:45.47.332] BEGIN WMNewTab: 20 +[15:45.47.333] END WMNewTab: 20 + + +[15:45.48.752] BEGIN WMNewTab: 20 +[15:45.48.752] END WMNewTab: 20 + + +[15:45.50.171] BEGIN WMNewTab: 20 +[15:45.50.171] END WMNewTab: 20 + + +[15:45.51.590] BEGIN WMNewTab: 20 +[15:45.51.590] END WMNewTab: 20 + + +[15:45.53.008] BEGIN WMNewTab: 20 +[15:45.53.008] END WMNewTab: 20 + + +[15:45.54.427] BEGIN WMNewTab: 20 +[15:45.54.427] END WMNewTab: 20 + + +[15:45.55.845] BEGIN WMNewTab: 20 +[15:45.55.845] END WMNewTab: 20 + + +[15:45.57.273] BEGIN WMNewTab: 20 +[15:45.57.273] END WMNewTab: 20 + + +[15:45.58.691] BEGIN WMNewTab: 20 +[15:45.58.691] END WMNewTab: 20 + + +[15:46.00.110] BEGIN WMNewTab: 20 +[15:46.00.110] END WMNewTab: 20 + + +[15:46.01.538] BEGIN WMNewTab: 20 +[15:46.01.538] END WMNewTab: 20 + + +[15:46.02.951] BEGIN WMNewTab: 20 +[15:46.02.951] END WMNewTab: 20 + + +[15:46.04.396] BEGIN WMNewTab: 20 +[15:46.04.396] END WMNewTab: 20 + + +[15:46.05.819] BEGIN WMNewTab: 20 +[15:46.05.819] END WMNewTab: 20 + + +[15:46.07.240] BEGIN WMNewTab: 20 +[15:46.07.240] END WMNewTab: 20 + + +[15:46.08.662] BEGIN WMNewTab: 20 +[15:46.08.662] END WMNewTab: 20 + + +[15:46.10.084] BEGIN WMNewTab: 20 +[15:46.10.084] END WMNewTab: 20 + + +[15:46.11.522] BEGIN WMNewTab: 20 +[15:46.11.522] END WMNewTab: 20 + + +[15:46.12.932] BEGIN WMNewTab: 20 +[15:46.12.932] END WMNewTab: 20 + + +[15:46.14.350] BEGIN WMNewTab: 20 +[15:46.14.350] END WMNewTab: 20 + + +[15:46.15.768] BEGIN WMNewTab: 20 +[15:46.15.768] END WMNewTab: 20 + + +[15:46.17.188] BEGIN WMNewTab: 20 +[15:46.17.188] END WMNewTab: 20 + + +[15:46.18.606] BEGIN WMNewTab: 20 +[15:46.18.606] END WMNewTab: 20 + + +[15:46.20.023] BEGIN WMNewTab: 20 +[15:46.20.023] END WMNewTab: 20 + + +[15:46.21.440] BEGIN WMNewTab: 20 +[15:46.21.440] END WMNewTab: 20 + + +[15:46.22.858] BEGIN WMNewTab: 20 +[15:46.22.858] END WMNewTab: 20 + + +[15:46.24.279] BEGIN WMNewTab: 20 +[15:46.24.279] END WMNewTab: 20 + + +[15:46.25.690] BEGIN WMNewTab: 20 +[15:46.25.690] END WMNewTab: 20 + + +[15:46.27.110] BEGIN WMNewTab: 20 +[15:46.27.110] END WMNewTab: 20 + + +[15:46.28.524] BEGIN WMNewTab: 20 +[15:46.28.524] END WMNewTab: 20 + + +[15:46.29.941] BEGIN WMNewTab: 20 +[15:46.29.941] END WMNewTab: 20 + + +[15:46.31.358] BEGIN WMNewTab: 20 +[15:46.31.358] END WMNewTab: 20 + + +[15:46.32.783] BEGIN WMNewTab: 20 +[15:46.32.783] END WMNewTab: 20 + + +[15:46.34.198] BEGIN WMNewTab: 20 +[15:46.34.198] END WMNewTab: 20 + + +[15:46.35.614] BEGIN WMNewTab: 20 +[15:46.35.614] END WMNewTab: 20 + + +[15:46.37.035] BEGIN WMNewTab: 20 +[15:46.37.035] END WMNewTab: 20 +[15:46.37.066] BEGIN WMNewTab: 0 +[15:46.37.066] WMNewTab: FormClick +[15:46.37.066] WMNewTab: LooseFocus +[15:46.37.066] END WMNewTab: 0 +[15:46.37.257] BEGIN WMNewTab: 0 +[15:46.37.257] WMNewTab: FormClick +[15:46.37.257] WMNewTab: LooseFocus +[15:46.37.260] END WMNewTab: 0 + +[15:46.38.450] BEGIN WMNewTab: 20 +[15:46.38.450] END WMNewTab: 20 + + +[15:46.39.867] BEGIN WMNewTab: 20 +[15:46.39.867] END WMNewTab: 20 + + +[15:46.41.283] BEGIN WMNewTab: 20 +[15:46.41.283] END WMNewTab: 20 + + +[15:46.42.699] BEGIN WMNewTab: 20 +[15:46.42.699] END WMNewTab: 20 + + +[15:46.44.121] BEGIN WMNewTab: 20 +[15:46.44.121] END WMNewTab: 20 + + +[15:46.45.530] BEGIN WMNewTab: 20 +[15:46.45.530] END WMNewTab: 20 + + +[15:46.46.949] BEGIN WMNewTab: 20 +[15:46.46.949] END WMNewTab: 20 + + +[15:46.48.365] BEGIN WMNewTab: 20 +[15:46.48.365] END WMNewTab: 20 + + +[15:46.49.618] BEGIN WMNewTab: 0 +[15:46.49.618] WMNewTab: FormClick +[15:46.49.618] WMNewTab: LooseFocus +[15:46.49.619] END WMNewTab: 0 +[15:46.49.738] BEGIN WMNewTab: 0 +[15:46.49.738] WMNewTab: FormClick +[15:46.49.738] WMNewTab: LooseFocus +[15:46.49.741] END WMNewTab: 0 +[15:46.49.780] BEGIN WMNewTab: 20 +[15:46.49.780] END WMNewTab: 20 + + +[15:46.51.199] BEGIN WMNewTab: 20 +[15:46.51.199] END WMNewTab: 20 + + +[15:46.52.618] BEGIN WMNewTab: 20 +[15:46.52.618] END WMNewTab: 20 + + +[15:46.54.040] BEGIN WMNewTab: 20 +[15:46.54.040] END WMNewTab: 20 + + +[15:46.55.462] BEGIN WMNewTab: 20 +[15:46.55.462] END WMNewTab: 20 + + +[15:46.56.878] BEGIN WMNewTab: 20 +[15:46.56.878] END WMNewTab: 20 + +[15:46.57.987] BEGIN WMNewTab: 0 +[15:46.57.987] WMNewTab: FormClick +[15:46.57.987] WMNewTab: LooseFocus +[15:46.57.987] END WMNewTab: 0 +[15:46.58.130] BEGIN WMNewTab: 0 +[15:46.58.130] WMNewTab: FormClick +[15:46.58.130] WMNewTab: LooseFocus +[15:46.58.131] END WMNewTab: 0 +[15:46.58.299] BEGIN WMNewTab: 20 +[15:46.58.299] END WMNewTab: 20 + + +[15:46.59.718] BEGIN WMNewTab: 20 +[15:46.59.718] END WMNewTab: 20 + + +[15:47.01.135] BEGIN WMNewTab: 20 +[15:47.01.135] END WMNewTab: 20 + + +[15:47.02.552] BEGIN WMNewTab: 20 +[15:47.02.552] END WMNewTab: 20 + + +[15:47.03.970] BEGIN WMNewTab: 20 +[15:47.03.970] END WMNewTab: 20 + + +[15:47.05.387] BEGIN WMNewTab: 20 +[15:47.05.387] END WMNewTab: 20 + + +[15:47.06.800] BEGIN WMNewTab: 20 +[15:47.06.800] END WMNewTab: 20 + + +[15:47.08.215] BEGIN WMNewTab: 20 +[15:47.08.215] END WMNewTab: 20 + + +[15:47.09.629] BEGIN WMNewTab: 20 +[15:47.09.629] END WMNewTab: 20 + + +[15:47.11.046] BEGIN WMNewTab: 20 +[15:47.11.046] END WMNewTab: 20 + + +[15:47.12.459] BEGIN WMNewTab: 20 +[15:47.12.459] END WMNewTab: 20 + + +[15:47.13.880] BEGIN WMNewTab: 20 +[15:47.13.880] END WMNewTab: 20 + + +[15:47.15.297] BEGIN WMNewTab: 20 +[15:47.15.297] END WMNewTab: 20 + + +[15:47.16.740] BEGIN WMNewTab: 20 +[15:47.16.740] END WMNewTab: 20 + + +[15:47.18.152] BEGIN WMNewTab: 20 +[15:47.18.152] END WMNewTab: 20 + + +[15:47.19.579] BEGIN WMNewTab: 20 +[15:47.19.579] END WMNewTab: 20 + + +[15:47.20.995] BEGIN WMNewTab: 20 +[15:47.20.995] END WMNewTab: 20 + + +[15:47.22.416] BEGIN WMNewTab: 20 +[15:47.22.416] END WMNewTab: 20 + + +[15:47.23.831] BEGIN WMNewTab: 20 +[15:47.23.831] END WMNewTab: 20 + + +[15:47.25.249] BEGIN WMNewTab: 20 +[15:47.25.249] END WMNewTab: 20 + + +[15:47.26.667] BEGIN WMNewTab: 20 +[15:47.26.667] END WMNewTab: 20 + + +[15:47.28.081] BEGIN WMNewTab: 20 +[15:47.28.081] END WMNewTab: 20 + + +[15:47.29.501] BEGIN WMNewTab: 20 +[15:47.29.501] END WMNewTab: 20 + + +[15:47.30.925] BEGIN WMNewTab: 20 +[15:47.30.925] END WMNewTab: 20 + + +[15:47.32.344] BEGIN WMNewTab: 20 +[15:47.32.344] END WMNewTab: 20 + + +[15:47.33.760] BEGIN WMNewTab: 20 +[15:47.33.760] END WMNewTab: 20 + + +[15:47.35.176] BEGIN WMNewTab: 20 +[15:47.35.176] END WMNewTab: 20 + + +[15:47.36.594] BEGIN WMNewTab: 20 +[15:47.36.594] END WMNewTab: 20 + + +[15:47.38.010] BEGIN WMNewTab: 20 +[15:47.38.010] END WMNewTab: 20 + + +[15:47.39.429] BEGIN WMNewTab: 20 +[15:47.39.429] END WMNewTab: 20 + + +[15:47.40.851] BEGIN WMNewTab: 20 +[15:47.40.851] END WMNewTab: 20 + + +[15:47.42.268] BEGIN WMNewTab: 20 +[15:47.42.268] END WMNewTab: 20 + + +[15:47.43.680] BEGIN WMNewTab: 20 +[15:47.43.680] END WMNewTab: 20 + + +[15:47.45.064] BEGIN WMNewTab: 0 +[15:47.45.064] WMNewTab: FormClick +[15:47.45.064] WMNewTab: LooseFocus +[15:47.45.065] END WMNewTab: 0 +[15:47.45.097] BEGIN WMNewTab: 20 +[15:47.45.097] END WMNewTab: 20 +[15:47.45.167] BEGIN WMNewTab: 0 +[15:47.45.167] WMNewTab: FormClick +[15:47.45.167] WMNewTab: LooseFocus +[15:47.45.168] END WMNewTab: 0 + + +[15:47.46.522] BEGIN WMNewTab: 20 +[15:47.46.522] END WMNewTab: 20 + + +[15:47.47.943] BEGIN WMNewTab: 20 +[15:47.47.943] END WMNewTab: 20 + + +[15:47.49.364] BEGIN WMNewTab: 20 +[15:47.49.364] END WMNewTab: 20 + + +[15:47.50.779] BEGIN WMNewTab: 20 +[15:47.50.779] END WMNewTab: 20 + + +[15:47.52.200] BEGIN WMNewTab: 20 +[15:47.52.200] END WMNewTab: 20 + + +[15:47.53.621] BEGIN WMNewTab: 20 +[15:47.53.621] END WMNewTab: 20 + + +[15:47.55.040] BEGIN WMNewTab: 20 +[15:47.55.040] END WMNewTab: 20 + + +[15:47.56.459] BEGIN WMNewTab: 20 +[15:47.56.459] END WMNewTab: 20 + + +[15:47.57.878] BEGIN WMNewTab: 20 +[15:47.57.878] END WMNewTab: 20 + + +[15:47.59.296] BEGIN WMNewTab: 20 +[15:47.59.296] END WMNewTab: 20 + + +[15:48.00.709] BEGIN WMNewTab: 20 +[15:48.00.709] END WMNewTab: 20 + + +[15:48.02.131] BEGIN WMNewTab: 20 +[15:48.02.131] END WMNewTab: 20 + + +[15:48.03.552] BEGIN WMNewTab: 20 +[15:48.03.552] END WMNewTab: 20 + + +[15:48.04.823] BEGIN CWD +[15:48.04.883] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:48.04.883] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:48.04.883] (SSH-Browser) END VerifySFTPConnection(1) +[15:48.04.883] END CWD +[15:48.04.976] BEGIN WMNewTab: 20 +[15:48.04.976] END WMNewTab: 20 +[15:48.05.006] BEGIN CWD +[15:48.05.067] END CWD + + +[15:48.06.483] BEGIN WMNewTab: 20 +[15:48.06.483] END WMNewTab: 20 + + +[15:48.07.890] BEGIN WMNewTab: 20 +[15:48.07.890] END WMNewTab: 20 + + +[15:48.09.297] BEGIN WMNewTab: 20 +[15:48.09.297] END WMNewTab: 20 + + +[15:48.10.704] BEGIN WMNewTab: 20 +[15:48.10.704] END WMNewTab: 20 + + +[15:48.12.123] BEGIN WMNewTab: 20 +[15:48.12.123] END WMNewTab: 20 + + +[15:48.13.540] BEGIN WMNewTab: 20 +[15:48.13.540] END WMNewTab: 20 + + +[15:48.14.948] BEGIN WMNewTab: 20 +[15:48.14.948] END WMNewTab: 20 + + +[15:48.16.367] BEGIN WMNewTab: 20 +[15:48.16.367] END WMNewTab: 20 + + +[15:48.17.780] BEGIN WMNewTab: 20 +[15:48.17.780] END WMNewTab: 20 + +[15:48.18.497] BEGIN WMNewTab: 0 +[15:48.18.497] WMNewTab: FormClick +[15:48.18.497] WMNewTab: LooseFocus +[15:48.18.497] END WMNewTab: 0 + +[15:48.19.202] BEGIN WMNewTab: 20 +[15:48.19.202] END WMNewTab: 20 + + +[15:48.20.624] BEGIN WMNewTab: 20 +[15:48.20.624] END WMNewTab: 20 +[15:48.20.792] BEGIN WMNewTab: 0 +[15:48.20.792] WMNewTab: FormClick +[15:48.20.792] WMNewTab: LooseFocus +[15:48.20.795] END WMNewTab: 0 + + +[15:48.22.038] BEGIN WMNewTab: 20 +[15:48.22.038] END WMNewTab: 20 + + +[15:48.23.450] BEGIN WMNewTab: 20 +[15:48.23.450] END WMNewTab: 20 + + +[15:48.24.860] BEGIN WMNewTab: 20 +[15:48.24.860] END WMNewTab: 20 + + +[15:48.26.275] BEGIN WMNewTab: 20 +[15:48.26.275] END WMNewTab: 20 + + +[15:48.27.688] BEGIN WMNewTab: 20 +[15:48.27.688] END WMNewTab: 20 + + +[15:48.29.098] BEGIN WMNewTab: 20 +[15:48.29.098] END WMNewTab: 20 + + +[15:48.30.511] BEGIN WMNewTab: 20 +[15:48.30.511] END WMNewTab: 20 + + +[15:48.31.930] BEGIN WMNewTab: 20 +[15:48.31.930] END WMNewTab: 20 + + +[15:48.33.338] BEGIN WMNewTab: 20 +[15:48.33.338] END WMNewTab: 20 + + +[15:48.34.750] BEGIN WMNewTab: 20 +[15:48.34.750] END WMNewTab: 20 + + +[15:48.36.164] BEGIN WMNewTab: 20 +[15:48.36.164] END WMNewTab: 20 + + +[15:48.37.577] BEGIN WMNewTab: 20 +[15:48.37.577] END WMNewTab: 20 + + +[15:48.38.992] BEGIN WMNewTab: 20 +[15:48.38.992] END WMNewTab: 20 + +[15:48.39.985] BEGIN WMNewTab: 0 +[15:48.39.985] WMNewTab: FormClick +[15:48.39.985] WMNewTab: LooseFocus +[15:48.39.985] END WMNewTab: 0 +[15:48.39.985] BEGIN WMNewTab: 31 +[15:48.39.985] END WMNewTab: 31 + +[15:48.40.408] BEGIN WMNewTab: 20 +[15:48.40.408] END WMNewTab: 20 + + +[15:48.41.824] BEGIN WMNewTab: 20 +[15:48.41.824] END WMNewTab: 20 +[15:48.41.991] BEGIN CWD +[15:48.42.052] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:48.42.052] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:48.42.052] (SSH-Browser) END VerifySFTPConnection(1) +[15:48.42.052] END CWD +[15:48.42.067] BEGIN CWD +[15:48.42.127] END CWD + +[15:48.43.077] BEGIN WMNewTab: 20 +[15:48.43.077] END WMNewTab: 20 + + +[15:48.44.491] BEGIN WMNewTab: 20 +[15:48.44.491] END WMNewTab: 20 + +[15:48.44.961] BEGIN WMNewTab: 0 +[15:48.44.961] WMNewTab: FormClick +[15:48.44.961] WMNewTab: LooseFocus +[15:48.44.962] END WMNewTab: 0 + +[15:48.45.910] BEGIN WMNewTab: 20 +[15:48.45.910] END WMNewTab: 20 + + +[15:48.47.331] BEGIN WMNewTab: 20 +[15:48.47.331] END WMNewTab: 20 + +[15:48.48.154] BEGIN WMNewTab: 0 +[15:48.48.154] WMNewTab: FormClick +[15:48.48.154] WMNewTab: LooseFocus +[15:48.48.154] END WMNewTab: 0 + +[15:48.48.746] BEGIN WMNewTab: 20 +[15:48.48.746] END WMNewTab: 20 + + +[15:48.50.162] BEGIN WMNewTab: 20 +[15:48.50.162] END WMNewTab: 20 + + +[15:48.51.577] BEGIN WMNewTab: 20 +[15:48.51.577] END WMNewTab: 20 + + +[15:48.52.991] BEGIN WMNewTab: 20 +[15:48.52.991] END WMNewTab: 20 + + +[15:48.54.405] BEGIN WMNewTab: 20 +[15:48.54.405] END WMNewTab: 20 + + +[15:48.55.817] BEGIN WMNewTab: 20 +[15:48.55.817] END WMNewTab: 20 + + +[15:48.57.227] BEGIN WMNewTab: 20 +[15:48.57.227] END WMNewTab: 20 + + +[15:48.58.638] BEGIN WMNewTab: 20 +[15:48.58.638] END WMNewTab: 20 + + +[15:49.00.059] BEGIN WMNewTab: 20 +[15:49.00.059] END WMNewTab: 20 + + +[15:49.01.471] BEGIN WMNewTab: 20 +[15:49.01.471] END WMNewTab: 20 + + +[15:49.02.881] BEGIN WMNewTab: 20 +[15:49.02.881] END WMNewTab: 20 + + +[15:49.04.300] BEGIN WMNewTab: 20 +[15:49.04.300] END WMNewTab: 20 + + +[15:49.05.722] BEGIN WMNewTab: 20 +[15:49.05.722] END WMNewTab: 20 + + +[15:49.07.136] BEGIN WMNewTab: 20 +[15:49.07.136] END WMNewTab: 20 + + +[15:49.08.548] BEGIN WMNewTab: 20 +[15:49.08.548] END WMNewTab: 20 + + +[15:49.09.963] BEGIN WMNewTab: 20 +[15:49.09.963] END WMNewTab: 20 + + +[15:49.11.378] BEGIN WMNewTab: 20 +[15:49.11.378] END WMNewTab: 20 + + +[15:49.12.795] BEGIN WMNewTab: 20 +[15:49.12.795] END WMNewTab: 20 + +[15:49.13.258] BEGIN WMNewTab: 0 +[15:49.13.258] WMNewTab: FormClick +[15:49.13.258] WMNewTab: LooseFocus +[15:49.13.258] END WMNewTab: 0 +[15:49.13.258] BEGIN WMNewTab: 31 +[15:49.13.258] END WMNewTab: 31 + +[15:49.14.209] BEGIN WMNewTab: 20 +[15:49.14.209] END WMNewTab: 20 + + +[15:49.15.628] BEGIN WMNewTab: 20 +[15:49.15.628] END WMNewTab: 20 + +[15:49.16.370] BEGIN WMNewTab: 0 +[15:49.16.370] WMNewTab: FormClick +[15:49.16.370] WMNewTab: LooseFocus +[15:49.16.370] END WMNewTab: 0 +[15:49.16.480] BEGIN WMNewTab: 0 +[15:49.16.480] WMNewTab: FormClick +[15:49.16.480] WMNewTab: LooseFocus +[15:49.16.482] END WMNewTab: 0 + +[15:49.16.875] BEGIN WMNewTab: 0 +[15:49.16.875] WMNewTab: FormClick +[15:49.16.875] WMNewTab: LooseFocus +[15:49.16.875] END WMNewTab: 0 +[15:49.16.986] BEGIN WMNewTab: 0 +[15:49.16.986] WMNewTab: FormClick +[15:49.16.986] WMNewTab: LooseFocus +[15:49.16.987] END WMNewTab: 0 +[15:49.17.046] BEGIN WMNewTab: 20 +[15:49.17.046] END WMNewTab: 20 + + +[15:49.18.463] BEGIN WMNewTab: 20 +[15:49.18.463] END WMNewTab: 20 + + +[15:49.19.873] BEGIN WMNewTab: 20 +[15:49.19.873] END WMNewTab: 20 + + +[15:49.21.090] BEGIN WMNewTab: 31 +[15:49.21.090] END WMNewTab: 31 +[15:49.21.090] BEGIN WMNewTab: 0 +[15:49.21.090] WMNewTab: FormClick +[15:49.21.090] WMNewTab: LooseFocus +[15:49.21.090] END WMNewTab: 0 +[15:49.21.154] BEGIN WMNewTab: 0 +[15:49.21.154] WMNewTab: FormClick +[15:49.21.154] WMNewTab: LooseFocus +[15:49.21.155] END WMNewTab: 0 +[15:49.21.281] BEGIN WMNewTab: 20 +[15:49.21.281] END WMNewTab: 20 + +[15:49.21.826] BEGIN CWD +[15:49.21.887] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:49.21.887] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:49.21.887] (SSH-Browser) END VerifySFTPConnection(1) +[15:49.21.887] END CWD +[15:49.21.901] BEGIN CWD +[15:49.21.962] END CWD + +[15:49.22.900] BEGIN WMNewTab: 20 +[15:49.22.900] END WMNewTab: 20 + + +[15:49.24.307] BEGIN WMNewTab: 20 +[15:49.24.307] END WMNewTab: 20 + + +[15:49.25.722] BEGIN WMNewTab: 20 +[15:49.25.722] END WMNewTab: 20 + +[15:49.26.554] BEGIN WMNewTab: 0 +[15:49.26.554] WMNewTab: FormClick +[15:49.26.554] WMNewTab: LooseFocus +[15:49.26.555] END WMNewTab: 0 +[15:49.26.555] BEGIN WMNewTab: 31 +[15:49.26.555] END WMNewTab: 31 +[15:49.26.657] BEGIN WMNewTab: 0 +[15:49.26.657] WMNewTab: FormClick +[15:49.26.657] WMNewTab: LooseFocus +[15:49.26.658] END WMNewTab: 0 + +[15:49.27.136] BEGIN WMNewTab: 20 +[15:49.27.136] END WMNewTab: 20 +[15:49.27.301] BEGIN CWD +[15:49.27.361] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:49.27.361] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:49.27.361] (SSH-Browser) END VerifySFTPConnection(1) +[15:49.27.361] END CWD +[15:49.27.365] BEGIN CWD +[15:49.27.425] END CWD + +[15:49.28.376] BEGIN WMNewTab: 20 +[15:49.28.376] END WMNewTab: 20 + + +[15:49.29.793] BEGIN WMNewTab: 20 +[15:49.29.793] END WMNewTab: 20 + + +[15:49.31.207] BEGIN WMNewTab: 20 +[15:49.31.207] END WMNewTab: 20 + + +[15:49.32.626] BEGIN WMNewTab: 20 +[15:49.32.626] END WMNewTab: 20 + + +[15:49.33.953] BEGIN WMNewTab: 0 +[15:49.33.953] WMNewTab: FormClick +[15:49.33.953] WMNewTab: LooseFocus +[15:49.33.953] END WMNewTab: 0 +[15:49.34.038] BEGIN WMNewTab: 20 +[15:49.34.038] END WMNewTab: 20 + + +[15:49.35.452] BEGIN WMNewTab: 20 +[15:49.35.452] END WMNewTab: 20 + +[15:49.36.546] BEGIN WMNewTab: 0 +[15:49.36.546] WMNewTab: FormClick +[15:49.36.546] WMNewTab: LooseFocus +[15:49.36.546] END WMNewTab: 0 +[15:49.36.872] BEGIN WMNewTab: 20 +[15:49.36.872] END WMNewTab: 20 + + +[15:49.38.291] BEGIN WMNewTab: 20 +[15:49.38.291] END WMNewTab: 20 + + +[15:49.39.703] BEGIN WMNewTab: 20 +[15:49.39.703] END WMNewTab: 20 + + +[15:49.41.118] BEGIN WMNewTab: 20 +[15:49.41.118] END WMNewTab: 20 + + +[15:49.42.532] BEGIN WMNewTab: 20 +[15:49.42.532] END WMNewTab: 20 + + +[15:49.43.943] BEGIN WMNewTab: 20 +[15:49.43.943] END WMNewTab: 20 + + +[15:49.45.353] BEGIN WMNewTab: 20 +[15:49.45.353] END WMNewTab: 20 + + +[15:49.46.768] BEGIN WMNewTab: 20 +[15:49.46.768] END WMNewTab: 20 + + +[15:49.48.183] BEGIN WMNewTab: 20 +[15:49.48.183] END WMNewTab: 20 + + +[15:49.49.599] BEGIN WMNewTab: 20 +[15:49.49.599] END WMNewTab: 20 + + +[15:49.51.011] BEGIN WMNewTab: 20 +[15:49.51.011] END WMNewTab: 20 + + +[15:49.52.420] BEGIN WMNewTab: 20 +[15:49.52.420] END WMNewTab: 20 + + +[15:49.53.836] BEGIN WMNewTab: 20 +[15:49.53.836] END WMNewTab: 20 + + +[15:49.55.254] BEGIN WMNewTab: 20 +[15:49.55.254] END WMNewTab: 20 + + +[15:49.56.665] BEGIN WMNewTab: 20 +[15:49.56.665] END WMNewTab: 20 + + +[15:49.58.080] BEGIN WMNewTab: 20 +[15:49.58.080] END WMNewTab: 20 + + +[15:49.59.498] BEGIN WMNewTab: 20 +[15:49.59.498] END WMNewTab: 20 + + +[15:50.00.909] BEGIN WMNewTab: 20 +[15:50.00.909] END WMNewTab: 20 + + +[15:50.02.323] BEGIN WMNewTab: 20 +[15:50.02.323] END WMNewTab: 20 + + +[15:50.03.735] BEGIN WMNewTab: 20 +[15:50.03.735] END WMNewTab: 20 + + +[15:50.05.146] BEGIN WMNewTab: 20 +[15:50.05.146] END WMNewTab: 20 + + +[15:50.06.566] BEGIN WMNewTab: 20 +[15:50.06.566] END WMNewTab: 20 + + +[15:50.07.980] BEGIN WMNewTab: 20 +[15:50.07.980] END WMNewTab: 20 + + +[15:50.09.397] BEGIN WMNewTab: 20 +[15:50.09.397] END WMNewTab: 20 +[15:50.09.535] BEGIN WMNewTab: 0 +[15:50.09.535] WMNewTab: FormClick +[15:50.09.535] WMNewTab: LooseFocus +[15:50.09.535] END WMNewTab: 0 +[15:50.09.535] BEGIN WMNewTab: 31 +[15:50.09.535] END WMNewTab: 31 + + +[15:50.10.806] BEGIN WMNewTab: 20 +[15:50.10.806] END WMNewTab: 20 + +[15:50.11.611] Cts1MouseDown: FormClick +[15:50.11.615] Cts1ActiveTabChanged: New index = 2 +[15:50.11.615] BEGIN DisplayCurrentTab +[15:50.11.615] DisplayCurrentTab: FormClick +[15:50.11.615] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[15:50.11.615] (SSH-Browser) BEGIN ActiverPanel14 +[15:50.11.615] (SSH-Browser) BEGIN DesactiverPanel14 +[15:50.11.628] (SSH-Browser) END DesactiverPanel14 +[15:50.11.628] (SSH-Browser) END ActiverPanel14; +[15:50.11.735] BEGIN TFormXterm.FormResize +[15:50.11.735] TFormXterm.FormResize: CenterBtnReattachTab +[15:50.11.736] TFormXterm.FormResize: SplitModeResize +[15:50.11.736] TFormXterm.FormResize: BtnSplitNo.Down +[15:50.11.736] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:50.11.736] BEGIN ResizeTerminal +[15:50.11.740] END ResizeTerminal +[15:50.11.740] TFormXterm.FormResize: AdaptSidebarArrows; +[15:50.11.740] BEGIN AdaptSidebarArrows +[15:50.11.740] END AdaptSidebarArrows +[15:50.11.740] TFormXterm.FormResize: AdaptTV2; +[15:50.11.740] END TFormXterm.FormResize +[15:50.11.740] DisplayCurrentTab: Cts1.BeginUpdate; +[15:50.11.740] DisplayCurrentTab: Cts1.EndUpdates +[15:50.11.755] DisplayCurrentTab: 显示所选标签页 +[15:50.11.757] DisplayCurrentTab: 隐藏其他标签页 +[15:50.11.773] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:50.11.776] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:50.11.776] DisplayCurrentTab: DistribuerLeFocus +[15:50.11.777] END DisplayCurrentTab + +[15:50.12.167] BEGIN WMNewTab: 0 +[15:50.12.167] WMNewTab: FormClick +[15:50.12.167] WMNewTab: LooseFocus +[15:50.12.167] END WMNewTab: 0 +[15:50.12.167] BEGIN WMNewTab: 31 +[15:50.12.167] END WMNewTab: 31 +[15:50.12.216] BEGIN WMNewTab: 20 +[15:50.12.216] END WMNewTab: 20 + + +[15:50.13.628] BEGIN WMNewTab: 20 +[15:50.13.628] END WMNewTab: 20 + + +[15:50.15.041] BEGIN WMNewTab: 20 +[15:50.15.041] END WMNewTab: 20 + + +[15:50.16.455] BEGIN WMNewTab: 20 +[15:50.16.455] END WMNewTab: 20 + + +[15:50.17.870] BEGIN WMNewTab: 20 +[15:50.17.870] END WMNewTab: 20 + + +[15:50.19.284] BEGIN WMNewTab: 20 +[15:50.19.284] END WMNewTab: 20 + + +[15:50.20.701] BEGIN WMNewTab: 20 +[15:50.20.701] END WMNewTab: 20 + + +[15:50.22.113] BEGIN WMNewTab: 20 +[15:50.22.113] END WMNewTab: 20 + + +[15:50.23.530] BEGIN WMNewTab: 20 +[15:50.23.530] END WMNewTab: 20 + + +[15:50.24.942] BEGIN WMNewTab: 20 +[15:50.24.942] END WMNewTab: 20 + + +[15:50.26.354] BEGIN WMNewTab: 20 +[15:50.26.354] END WMNewTab: 20 + + +[15:50.27.771] BEGIN WMNewTab: 20 +[15:50.27.771] END WMNewTab: 20 + +[15:50.28.768] BEGIN WMNewTab: 0 +[15:50.28.768] WMNewTab: FormClick +[15:50.28.768] WMNewTab: LooseFocus +[15:50.28.769] END WMNewTab: 0 +[15:50.28.902] BEGIN WMNewTab: 0 +[15:50.28.902] WMNewTab: FormClick +[15:50.28.902] WMNewTab: LooseFocus +[15:50.28.903] END WMNewTab: 0 +[15:50.29.188] BEGIN WMNewTab: 20 +[15:50.29.188] END WMNewTab: 20 + + +[15:50.30.605] BEGIN WMNewTab: 20 +[15:50.30.605] END WMNewTab: 20 + + +[15:50.32.028] BEGIN WMNewTab: 20 +[15:50.32.028] END WMNewTab: 20 + + +[15:50.33.446] BEGIN WMNewTab: 20 +[15:50.33.446] END WMNewTab: 20 + + +[15:50.34.860] BEGIN WMNewTab: 20 +[15:50.34.860] END WMNewTab: 20 + +[15:50.35.919] BEGIN WMNewTab: 60 +[15:50.35.930] END WMNewTab: 60 +[15:50.36.276] BEGIN WMNewTab: 20 +[15:50.36.276] END WMNewTab: 20 + +[15:50.36.927] BEGIN WMNewTab: 60 +[15:50.36.927] END WMNewTab: 60 +[15:50.37.180] BEGIN WMNewTab: 0 +[15:50.37.180] WMNewTab: FormClick +[15:50.37.180] WMNewTab: LooseFocus +[15:50.37.180] END WMNewTab: 0 +[15:50.37.180] BEGIN WMNewTab: 31 +[15:50.37.180] END WMNewTab: 31 + +[15:50.37.693] BEGIN WMNewTab: 20 +[15:50.37.693] END WMNewTab: 20 + + +[15:50.39.114] BEGIN WMNewTab: 20 +[15:50.39.115] END WMNewTab: 20 + + +[15:50.40.535] BEGIN WMNewTab: 20 +[15:50.40.535] END WMNewTab: 20 + + +[15:50.41.955] BEGIN WMNewTab: 20 +[15:50.41.955] END WMNewTab: 20 + + +[15:50.43.372] BEGIN WMNewTab: 20 +[15:50.43.372] END WMNewTab: 20 + + +[15:50.44.791] BEGIN WMNewTab: 20 +[15:50.44.791] END WMNewTab: 20 + + +[15:50.46.209] BEGIN WMNewTab: 20 +[15:50.46.209] END WMNewTab: 20 + + +[15:50.47.627] BEGIN WMNewTab: 20 +[15:50.47.627] END WMNewTab: 20 + + +[15:50.49.048] BEGIN WMNewTab: 20 +[15:50.49.048] END WMNewTab: 20 + + +[15:50.50.464] BEGIN WMNewTab: 20 +[15:50.50.464] END WMNewTab: 20 + + +[15:50.51.878] BEGIN WMNewTab: 20 +[15:50.51.878] END WMNewTab: 20 + + +[15:50.53.294] BEGIN WMNewTab: 20 +[15:50.53.294] END WMNewTab: 20 + + +[15:50.54.709] BEGIN WMNewTab: 20 +[15:50.54.709] END WMNewTab: 20 + + +[15:50.56.125] BEGIN WMNewTab: 20 +[15:50.56.125] END WMNewTab: 20 + +[15:50.56.832] Cts1MouseDown: FormClick +[15:50.56.836] Cts1ActiveTabChanged: New index = 1 +[15:50.56.836] BEGIN DisplayCurrentTab +[15:50.56.836] DisplayCurrentTab: FormClick +[15:50.56.836] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:50.56.836] (SSH-Browser) BEGIN ActiverPanel14 +[15:50.56.836] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:50.56.841] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:50.56.841] (SSH-Browser) ActiverPanel14: 列出远程目录 +[15:50.56.841] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[15:50.56.841] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[15:50.56.869] (SSH-Browser) END ActiverPanel14; +[15:50.56.895] BEGIN TFormXterm.FormResize +[15:50.56.895] TFormXterm.FormResize: CenterBtnReattachTab +[15:50.56.895] TFormXterm.FormResize: SplitModeResize +[15:50.56.895] TFormXterm.FormResize: BtnSplitNo.Down +[15:50.56.896] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:50.56.896] BEGIN ResizeTerminal +[15:50.56.899] END ResizeTerminal +[15:50.56.899] TFormXterm.FormResize: AdaptSidebarArrows; +[15:50.56.899] BEGIN AdaptSidebarArrows +[15:50.56.899] END AdaptSidebarArrows +[15:50.56.899] TFormXterm.FormResize: AdaptTV2; +[15:50.56.899] END TFormXterm.FormResize +[15:50.56.899] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[15:50.56.899] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:50.56.901] BEGIN WMNewTab: 62 +[15:50.56.901] END WMNewTab: 62 +[15:50.56.914] ShellExecuteS: ShellExecuteEx 成功. +[15:50.56.914] ShellExecuteS: WaitForInputIdle 失败. +[15:50.56.914] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:50.56.914] DisplayCurrentTab: Cts1.BeginUpdate; +[15:50.56.914] DisplayCurrentTab: Cts1.EndUpdates +[15:50.56.935] DisplayCurrentTab: 显示所选标签页 +[15:50.56.938] DisplayCurrentTab: 隐藏其他标签页 +[15:50.56.954] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:50.56.956] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:50.56.956] DisplayCurrentTab: DistribuerLeFocus +[15:50.56.958] END DisplayCurrentTab +[15:50.56.978] [MobaSCP2] Launching remote monitoring in normal mode +[15:50.56.981] [MobaSCP2] Multiplex=1 +[15:50.56.982] [MobaSCP2] HOSTNAME: 192.168.127.10 +[15:50.56.982] [MobaSCP2] USERNAME: root +[15:50.57.025] [MobaSCP2] Using SCP1 +[15:50.57.025] [MobaSCP2] Connected to 192.168.127.10 +[15:50.57.289] BEGIN WMNewTab: 0 +[15:50.57.289] WMNewTab: FormClick +[15:50.57.289] WMNewTab: LooseFocus +[15:50.57.290] END WMNewTab: 0 +[15:50.57.391] BEGIN WMNewTab: 0 +[15:50.57.391] WMNewTab: FormClick +[15:50.57.391] WMNewTab: LooseFocus +[15:50.57.392] END WMNewTab: 0 +[15:50.57.543] BEGIN WMNewTab: 20 +[15:50.57.543] END WMNewTab: 20 + +[15:50.58.152] BEGIN TFormXterm.FormResize +[15:50.58.152] TFormXterm.FormResize: CenterBtnReattachTab +[15:50.58.152] TFormXterm.FormResize: SplitModeResize +[15:50.58.152] TFormXterm.FormResize: BtnSplitNo.Down +[15:50.58.152] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:50.58.152] BEGIN ResizeTerminal +[15:50.58.152] END ResizeTerminal +[15:50.58.152] TFormXterm.FormResize: AdaptSidebarArrows; +[15:50.58.152] BEGIN AdaptSidebarArrows +[15:50.58.152] END AdaptSidebarArrows +[15:50.58.152] TFormXterm.FormResize: AdaptTV2; +[15:50.58.152] END TFormXterm.FormResize +[15:50.58.472] BEGIN WMNewTab: 0 +[15:50.58.472] WMNewTab: FormClick +[15:50.58.472] WMNewTab: LooseFocus +[15:50.58.473] END WMNewTab: 0 +[15:50.58.473] BEGIN WMNewTab: 31 +[15:50.58.473] END WMNewTab: 31 + +[15:50.58.959] BEGIN WMNewTab: 20 +[15:50.58.959] END WMNewTab: 20 + + +[15:51.00.373] BEGIN WMNewTab: 20 +[15:51.00.373] END WMNewTab: 20 + +[15:51.01.486] BEGIN CWD +[15:51.01.546] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:51.01.546] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:51.01.546] (SSH-Browser) END VerifySFTPConnection(1) +[15:51.01.546] END CWD +[15:51.01.561] BEGIN CWD +[15:51.01.621] END CWD +[15:51.01.621] BEGIN WMNewTab: 20 +[15:51.01.621] END WMNewTab: 20 + +[15:51.02.297] BEGIN WMNewTab: 0 +[15:51.02.297] WMNewTab: FormClick +[15:51.02.297] WMNewTab: LooseFocus +[15:51.02.297] END WMNewTab: 0 +[15:51.02.297] BEGIN WMNewTab: 31 +[15:51.02.297] END WMNewTab: 31 + +[15:51.03.039] BEGIN WMNewTab: 20 +[15:51.03.039] END WMNewTab: 20 + +[15:51.04.116] BEGIN CWD +[15:51.04.204] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:51.04.204] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:51.04.204] (SSH-Browser) END VerifySFTPConnection(1) +[15:51.04.204] END CWD +[15:51.04.208] BEGIN CWD +[15:51.04.268] END CWD +[15:51.04.268] BEGIN WMNewTab: 20 +[15:51.04.268] END WMNewTab: 20 + + +[15:51.05.683] BEGIN WMNewTab: 20 +[15:51.05.683] END WMNewTab: 20 + +[15:51.06.641] Cts1MouseDown: FormClick + +[15:51.07.095] BEGIN WMNewTab: 20 +[15:51.07.095] END WMNewTab: 20 +[15:51.07.122] Cts1MouseDown: FormClick +[15:51.07.124] Cts1ActiveTabChanged: New index = 2 +[15:51.07.125] BEGIN DisplayCurrentTab +[15:51.07.125] DisplayCurrentTab: FormClick +[15:51.07.125] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[15:51.07.125] (SSH-Browser) BEGIN ActiverPanel14 +[15:51.07.125] (SSH-Browser) BEGIN DesactiverPanel14 +[15:51.07.139] (SSH-Browser) END DesactiverPanel14 +[15:51.07.139] (SSH-Browser) END ActiverPanel14; +[15:51.07.252] BEGIN TFormXterm.FormResize +[15:51.07.252] TFormXterm.FormResize: CenterBtnReattachTab +[15:51.07.253] TFormXterm.FormResize: SplitModeResize +[15:51.07.253] TFormXterm.FormResize: BtnSplitNo.Down +[15:51.07.253] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:51.07.253] BEGIN ResizeTerminal +[15:51.07.256] END ResizeTerminal +[15:51.07.256] TFormXterm.FormResize: AdaptSidebarArrows; +[15:51.07.256] BEGIN AdaptSidebarArrows +[15:51.07.256] END AdaptSidebarArrows +[15:51.07.256] TFormXterm.FormResize: AdaptTV2; +[15:51.07.256] END TFormXterm.FormResize +[15:51.07.256] DisplayCurrentTab: Cts1.BeginUpdate; +[15:51.07.256] DisplayCurrentTab: Cts1.EndUpdates +[15:51.07.271] DisplayCurrentTab: 显示所选标签页 +[15:51.07.272] DisplayCurrentTab: 隐藏其他标签页 +[15:51.07.285] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:51.07.286] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:51.07.286] DisplayCurrentTab: DistribuerLeFocus +[15:51.07.287] END DisplayCurrentTab + +[15:51.07.801] BEGIN WMNewTab: 0 +[15:51.07.801] WMNewTab: FormClick +[15:51.07.801] WMNewTab: LooseFocus +[15:51.07.801] END WMNewTab: 0 +[15:51.07.929] BEGIN WMNewTab: 0 +[15:51.07.929] WMNewTab: FormClick +[15:51.07.929] WMNewTab: LooseFocus +[15:51.07.930] END WMNewTab: 0 + +[15:51.08.513] BEGIN WMNewTab: 20 +[15:51.08.513] END WMNewTab: 20 + + +[15:51.09.925] BEGIN WMNewTab: 20 +[15:51.09.925] END WMNewTab: 20 + + +[15:51.11.338] BEGIN WMNewTab: 20 +[15:51.11.338] END WMNewTab: 20 + + +[15:51.12.752] BEGIN WMNewTab: 20 +[15:51.12.752] END WMNewTab: 20 + + +[15:51.14.152] Cts1MouseDown: FormClick +[15:51.14.157] Cts1ActiveTabChanged: New index = 1 +[15:51.14.157] BEGIN DisplayCurrentTab +[15:51.14.157] DisplayCurrentTab: FormClick +[15:51.14.157] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:51.14.157] (SSH-Browser) BEGIN ActiverPanel14 +[15:51.14.157] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:51.14.161] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:51.14.161] (SSH-Browser) ActiverPanel14: 列出远程目录 +[15:51.14.161] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[15:51.14.161] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[15:51.14.188] (SSH-Browser) END ActiverPanel14; +[15:51.14.215] BEGIN TFormXterm.FormResize +[15:51.14.215] TFormXterm.FormResize: CenterBtnReattachTab +[15:51.14.216] TFormXterm.FormResize: SplitModeResize +[15:51.14.216] TFormXterm.FormResize: BtnSplitNo.Down +[15:51.14.217] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:51.14.217] BEGIN ResizeTerminal +[15:51.14.217] BEGIN WMNewTab: 20 +[15:51.14.217] END WMNewTab: 20 +[15:51.14.220] END ResizeTerminal +[15:51.14.220] TFormXterm.FormResize: AdaptSidebarArrows; +[15:51.14.220] BEGIN AdaptSidebarArrows +[15:51.14.220] END AdaptSidebarArrows +[15:51.14.220] TFormXterm.FormResize: AdaptTV2; +[15:51.14.220] END TFormXterm.FormResize +[15:51.14.221] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[15:51.14.221] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:51.14.235] ShellExecuteS: ShellExecuteEx 成功. +[15:51.14.235] ShellExecuteS: WaitForInputIdle 失败. +[15:51.14.235] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:51.14.235] DisplayCurrentTab: Cts1.BeginUpdate; +[15:51.14.235] DisplayCurrentTab: Cts1.EndUpdates +[15:51.14.251] DisplayCurrentTab: 显示所选标签页 +[15:51.14.252] DisplayCurrentTab: 隐藏其他标签页 +[15:51.14.269] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:51.14.275] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:51.14.275] DisplayCurrentTab: DistribuerLeFocus +[15:51.14.275] END DisplayCurrentTab +[15:51.14.294] [MobaSCP2] Launching remote monitoring in normal mode +[15:51.14.297] [MobaSCP2] Multiplex=1 +[15:51.14.297] [MobaSCP2] HOSTNAME: 192.168.127.10 +[15:51.14.297] [MobaSCP2] USERNAME: root +[15:51.14.339] [MobaSCP2] Using SCP1 +[15:51.14.340] [MobaSCP2] Connected to 192.168.127.10 + +[15:51.15.450] BEGIN TFormXterm.FormResize +[15:51.15.450] TFormXterm.FormResize: CenterBtnReattachTab +[15:51.15.450] TFormXterm.FormResize: SplitModeResize +[15:51.15.450] TFormXterm.FormResize: BtnSplitNo.Down +[15:51.15.450] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:51.15.450] BEGIN ResizeTerminal +[15:51.15.451] END ResizeTerminal +[15:51.15.451] TFormXterm.FormResize: AdaptSidebarArrows; +[15:51.15.451] BEGIN AdaptSidebarArrows +[15:51.15.451] END AdaptSidebarArrows +[15:51.15.451] TFormXterm.FormResize: AdaptTV2; +[15:51.15.451] END TFormXterm.FormResize +[15:51.15.457] BEGIN WMNewTab: 0 +[15:51.15.457] WMNewTab: FormClick +[15:51.15.457] WMNewTab: LooseFocus +[15:51.15.457] END WMNewTab: 0 +[15:51.15.627] BEGIN WMNewTab: 20 +[15:51.15.627] END WMNewTab: 20 +[15:51.15.985] BEGIN WMNewTab: 0 +[15:51.15.985] WMNewTab: FormClick +[15:51.15.985] WMNewTab: LooseFocus +[15:51.15.987] END WMNewTab: 0 + +[15:51.17.046] BEGIN WMNewTab: 20 +[15:51.17.046] END WMNewTab: 20 + + +[15:51.18.461] BEGIN WMNewTab: 20 +[15:51.18.461] END WMNewTab: 20 + + +[15:51.19.880] BEGIN WMNewTab: 20 +[15:51.19.880] END WMNewTab: 20 + + +[15:51.21.297] BEGIN WMNewTab: 20 +[15:51.21.297] END WMNewTab: 20 + + +[15:51.22.712] BEGIN WMNewTab: 20 +[15:51.22.712] END WMNewTab: 20 + + +[15:51.24.123] BEGIN WMNewTab: 20 +[15:51.24.123] END WMNewTab: 20 + + +[15:51.25.533] BEGIN WMNewTab: 20 +[15:51.25.533] END WMNewTab: 20 + +[15:51.26.671] BEGIN TFormXterm.FormResize +[15:51.26.671] TFormXterm.FormResize: CenterBtnReattachTab +[15:51.26.676] TFormXterm.FormResize: SplitModeResize +[15:51.26.676] TFormXterm.FormResize: BtnSplitNo.Down +[15:51.26.676] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:51.26.676] BEGIN ResizeTerminal +[15:51.26.685] END ResizeTerminal +[15:51.26.685] TFormXterm.FormResize: AdaptSidebarArrows; +[15:51.26.685] BEGIN AdaptSidebarArrows +[15:51.26.685] END AdaptSidebarArrows +[15:51.26.685] TFormXterm.FormResize: AdaptTV2; +[15:51.26.685] END TFormXterm.FormResize +[15:51.26.685] BEGIN WMSize +[15:51.26.685] END WMSize +[15:51.26.953] BEGIN WMNewTab: 20 +[15:51.26.954] END WMNewTab: 20 + + +[15:51.28.371] BEGIN WMNewTab: 20 +[15:51.28.371] END WMNewTab: 20 + + +[15:51.29.784] BEGIN WMNewTab: 20 +[15:51.29.784] END WMNewTab: 20 + + +[15:51.31.197] BEGIN WMNewTab: 20 +[15:51.31.197] END WMNewTab: 20 + + +[15:51.32.611] BEGIN WMNewTab: 20 +[15:51.32.611] END WMNewTab: 20 + + +[15:51.34.027] BEGIN WMNewTab: 20 +[15:51.34.027] END WMNewTab: 20 + + +[15:51.35.445] BEGIN WMNewTab: 20 +[15:51.35.445] END WMNewTab: 20 + + +[15:51.36.863] BEGIN WMNewTab: 20 +[15:51.36.863] END WMNewTab: 20 + + +[15:51.38.272] BEGIN WMNewTab: 20 +[15:51.38.272] END WMNewTab: 20 + + +[15:51.39.685] BEGIN WMNewTab: 20 +[15:51.39.685] END WMNewTab: 20 + + +[15:51.41.107] BEGIN WMNewTab: 20 +[15:51.41.107] END WMNewTab: 20 + + +[15:51.42.532] BEGIN WMNewTab: 20 +[15:51.42.532] END WMNewTab: 20 + + +[15:51.43.951] BEGIN WMNewTab: 20 +[15:51.43.951] END WMNewTab: 20 + + +[15:51.45.372] BEGIN WMNewTab: 20 +[15:51.45.372] END WMNewTab: 20 + + +[15:51.46.786] BEGIN WMNewTab: 20 +[15:51.46.786] END WMNewTab: 20 + + +[15:51.48.202] BEGIN WMNewTab: 20 +[15:51.48.202] END WMNewTab: 20 + + +[15:51.49.622] BEGIN WMNewTab: 20 +[15:51.49.622] END WMNewTab: 20 + + +[15:51.51.032] BEGIN WMNewTab: 20 +[15:51.51.032] END WMNewTab: 20 + + +[15:51.52.451] BEGIN WMNewTab: 20 +[15:51.52.451] END WMNewTab: 20 + + +[15:51.53.872] BEGIN WMNewTab: 20 +[15:51.53.872] END WMNewTab: 20 + + +[15:51.55.288] BEGIN WMNewTab: 20 +[15:51.55.288] END WMNewTab: 20 + + +[15:51.56.710] BEGIN WMNewTab: 20 +[15:51.56.710] END WMNewTab: 20 + + +[15:51.58.130] BEGIN WMNewTab: 20 +[15:51.58.130] END WMNewTab: 20 + + +[15:51.59.547] BEGIN WMNewTab: 20 +[15:51.59.547] END WMNewTab: 20 + + +[15:52.00.961] BEGIN WMNewTab: 20 +[15:52.00.961] END WMNewTab: 20 + + +[15:52.02.388] BEGIN WMNewTab: 20 +[15:52.02.388] END WMNewTab: 20 + + +[15:52.03.810] BEGIN WMNewTab: 20 +[15:52.03.810] END WMNewTab: 20 + + +[15:52.05.210] BEGIN WMSysCommand (minimize/restore) +[15:52.05.211] BEGIN WMNewTab: 0 +[15:52.05.211] WMNewTab: FormClick +[15:52.05.211] WMNewTab: LooseFocus +[15:52.05.211] END WMNewTab: 0 +[15:52.05.305] BEGIN WMSize +[15:52.05.305] BEGIN TFormXterm.FormResize +[15:52.05.305] TFormXterm.FormResize: CenterBtnReattachTab +[15:52.05.314] TFormXterm.FormResize: SplitModeResize +[15:52.05.314] TFormXterm.FormResize: BtnSplitNo.Down +[15:52.05.315] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:52.05.315] BEGIN ResizeTerminal +[15:52.05.315] BEGIN WMNewTab: 20 +[15:52.05.315] END WMNewTab: 20 +[15:52.05.342] END ResizeTerminal +[15:52.05.342] TFormXterm.FormResize: AdaptSidebarArrows; +[15:52.05.342] BEGIN AdaptSidebarArrows +[15:52.05.342] END AdaptSidebarArrows +[15:52.05.342] TFormXterm.FormResize: AdaptTV2; +[15:52.05.342] END TFormXterm.FormResize +[15:52.05.342] END WMSize +[15:52.05.349] END WMSysCommand + +[15:52.05.875] BEGIN WMSysCommand (minimize/restore) +[15:52.05.894] BEGIN WMSize +[15:52.05.894] END WMSize +[15:52.05.925] END WMSysCommand + +[15:52.06.723] BEGIN WMNewTab: 20 +[15:52.06.723] END WMNewTab: 20 + + +[15:52.08.135] BEGIN WMNewTab: 20 +[15:52.08.135] END WMNewTab: 20 + + +[15:52.09.554] BEGIN WMNewTab: 20 +[15:52.09.554] END WMNewTab: 20 + + +[15:52.10.968] BEGIN WMNewTab: 20 +[15:52.10.968] END WMNewTab: 20 + + +[15:52.12.382] BEGIN WMNewTab: 20 +[15:52.12.382] END WMNewTab: 20 + + +[15:52.13.796] BEGIN WMNewTab: 20 +[15:52.13.796] END WMNewTab: 20 + + +[15:52.15.215] BEGIN WMNewTab: 20 +[15:52.15.215] END WMNewTab: 20 + + +[15:52.16.634] BEGIN WMNewTab: 20 +[15:52.16.634] END WMNewTab: 20 + + +[15:52.18.048] BEGIN WMNewTab: 20 +[15:52.18.048] END WMNewTab: 20 + + +[15:52.19.462] BEGIN WMNewTab: 20 +[15:52.19.462] END WMNewTab: 20 + + +[15:52.20.879] BEGIN WMNewTab: 20 +[15:52.20.879] END WMNewTab: 20 + + +[15:52.22.292] BEGIN WMNewTab: 20 +[15:52.22.292] END WMNewTab: 20 + + +[15:52.23.706] BEGIN WMNewTab: 20 +[15:52.23.706] END WMNewTab: 20 + + +[15:52.25.120] BEGIN WMNewTab: 20 +[15:52.25.120] END WMNewTab: 20 + + +[15:52.26.539] BEGIN WMNewTab: 20 +[15:52.26.539] END WMNewTab: 20 + + +[15:52.27.953] BEGIN WMNewTab: 20 +[15:52.27.953] END WMNewTab: 20 + + +[15:52.29.376] BEGIN WMNewTab: 20 +[15:52.29.376] END WMNewTab: 20 + + +[15:52.30.796] BEGIN WMNewTab: 20 +[15:52.30.796] END WMNewTab: 20 + + +[15:52.32.210] BEGIN WMNewTab: 20 +[15:52.32.210] END WMNewTab: 20 + + +[15:52.33.628] BEGIN WMNewTab: 20 +[15:52.33.628] END WMNewTab: 20 + + +[15:52.35.047] BEGIN WMNewTab: 20 +[15:52.35.047] END WMNewTab: 20 + + +[15:52.36.462] BEGIN WMNewTab: 20 +[15:52.36.462] END WMNewTab: 20 + + +[15:52.37.877] BEGIN WMNewTab: 20 +[15:52.37.877] END WMNewTab: 20 + + +[15:52.39.294] BEGIN WMNewTab: 20 +[15:52.39.294] END WMNewTab: 20 + + +[15:52.40.713] BEGIN WMNewTab: 20 +[15:52.40.713] END WMNewTab: 20 + + +[15:52.42.128] BEGIN WMNewTab: 20 +[15:52.42.128] END WMNewTab: 20 + + +[15:52.43.547] BEGIN WMNewTab: 20 +[15:52.43.547] END WMNewTab: 20 + + +[15:52.44.964] BEGIN WMNewTab: 20 +[15:52.44.964] END WMNewTab: 20 + + +[15:52.46.374] BEGIN WMNewTab: 20 +[15:52.46.374] END WMNewTab: 20 + + +[15:52.47.793] BEGIN WMNewTab: 20 +[15:52.47.793] END WMNewTab: 20 + + +[15:52.49.205] BEGIN WMNewTab: 20 +[15:52.49.205] END WMNewTab: 20 + + +[15:52.50.625] BEGIN WMNewTab: 20 +[15:52.50.625] END WMNewTab: 20 + + +[15:52.52.040] BEGIN WMNewTab: 20 +[15:52.52.040] END WMNewTab: 20 + + +[15:52.53.455] BEGIN WMNewTab: 20 +[15:52.53.455] END WMNewTab: 20 + + +[15:52.54.865] BEGIN WMNewTab: 20 +[15:52.54.865] END WMNewTab: 20 + + +[15:52.56.278] BEGIN WMNewTab: 20 +[15:52.56.278] END WMNewTab: 20 + + +[15:52.57.691] BEGIN WMNewTab: 20 +[15:52.57.691] END WMNewTab: 20 + + +[15:52.59.104] BEGIN WMNewTab: 20 +[15:52.59.104] END WMNewTab: 20 + + +[15:53.00.521] BEGIN WMNewTab: 20 +[15:53.00.521] END WMNewTab: 20 + + +[15:53.01.939] BEGIN WMNewTab: 20 +[15:53.01.939] END WMNewTab: 20 + + +[15:53.03.358] BEGIN WMNewTab: 20 +[15:53.03.358] END WMNewTab: 20 + + +[15:53.04.774] BEGIN WMNewTab: 20 +[15:53.04.774] END WMNewTab: 20 + + +[15:53.06.194] BEGIN WMNewTab: 20 +[15:53.06.194] END WMNewTab: 20 + + +[15:53.07.609] BEGIN WMNewTab: 20 +[15:53.07.609] END WMNewTab: 20 + + +[15:53.09.023] BEGIN WMNewTab: 20 +[15:53.09.023] END WMNewTab: 20 + + +[15:53.10.433] BEGIN WMNewTab: 20 +[15:53.10.433] END WMNewTab: 20 + + +[15:53.11.850] BEGIN WMNewTab: 20 +[15:53.11.850] END WMNewTab: 20 + + +[15:53.13.265] BEGIN WMNewTab: 20 +[15:53.13.265] END WMNewTab: 20 + + +[15:53.14.679] BEGIN WMNewTab: 20 +[15:53.14.679] END WMNewTab: 20 + + +[15:53.16.093] BEGIN WMNewTab: 20 +[15:53.16.093] END WMNewTab: 20 + + +[15:53.17.509] BEGIN WMNewTab: 20 +[15:53.17.509] END WMNewTab: 20 + + +[15:53.18.924] BEGIN WMNewTab: 20 +[15:53.18.924] END WMNewTab: 20 + + +[15:53.20.338] BEGIN WMNewTab: 20 +[15:53.20.338] END WMNewTab: 20 + + +[15:53.21.752] BEGIN WMNewTab: 20 +[15:53.21.752] END WMNewTab: 20 + + +[15:53.23.165] BEGIN WMNewTab: 20 +[15:53.23.165] END WMNewTab: 20 + + +[15:53.24.582] BEGIN WMNewTab: 20 +[15:53.24.582] END WMNewTab: 20 + + +[15:53.26.002] BEGIN WMNewTab: 20 +[15:53.26.002] END WMNewTab: 20 + + +[15:53.27.418] BEGIN WMNewTab: 20 +[15:53.27.418] END WMNewTab: 20 + + +[15:53.28.832] BEGIN WMNewTab: 20 +[15:53.28.832] END WMNewTab: 20 + + +[15:53.30.251] BEGIN WMNewTab: 20 +[15:53.30.251] END WMNewTab: 20 + + +[15:53.31.665] BEGIN WMNewTab: 20 +[15:53.31.665] END WMNewTab: 20 + + +[15:53.32.953] BEGIN WMSysCommand (minimize/restore) +[15:53.32.953] BEGIN WMNewTab: 0 +[15:53.32.953] WMNewTab: FormClick +[15:53.32.953] WMNewTab: LooseFocus +[15:53.32.954] END WMNewTab: 0 +[15:53.33.030] BEGIN WMSize +[15:53.33.030] BEGIN TFormXterm.FormResize +[15:53.33.030] TFormXterm.FormResize: CenterBtnReattachTab +[15:53.33.030] TFormXterm.FormResize: SplitModeResize +[15:53.33.030] TFormXterm.FormResize: BtnSplitNo.Down +[15:53.33.030] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:53.33.030] BEGIN ResizeTerminal +[15:53.33.031] END ResizeTerminal +[15:53.33.031] TFormXterm.FormResize: AdaptSidebarArrows; +[15:53.33.031] BEGIN AdaptSidebarArrows +[15:53.33.031] END AdaptSidebarArrows +[15:53.33.031] TFormXterm.FormResize: AdaptTV2; +[15:53.33.031] END TFormXterm.FormResize +[15:53.33.031] END WMSize +[15:53.33.034] END WMSysCommand +[15:53.33.079] BEGIN WMNewTab: 20 +[15:53.33.079] END WMNewTab: 20 + +[15:53.33.640] BEGIN WMNewTab: 0 +[15:53.33.640] WMNewTab: FormClick +[15:53.33.640] WMNewTab: LooseFocus +[15:53.33.640] END WMNewTab: 0 +[15:53.33.760] BEGIN WMNewTab: 0 +[15:53.33.760] WMNewTab: FormClick +[15:53.33.760] WMNewTab: LooseFocus +[15:53.33.760] END WMNewTab: 0 + +[15:53.34.498] BEGIN WMNewTab: 20 +[15:53.34.498] END WMNewTab: 20 + + +[15:53.35.908] BEGIN WMNewTab: 20 +[15:53.35.908] END WMNewTab: 20 + + +[15:53.37.321] BEGIN WMNewTab: 20 +[15:53.37.321] END WMNewTab: 20 + + +[15:53.38.737] BEGIN WMNewTab: 20 +[15:53.38.737] END WMNewTab: 20 + + +[15:53.40.151] BEGIN WMNewTab: 20 +[15:53.40.151] END WMNewTab: 20 + + +[15:53.41.559] BEGIN WMNewTab: 20 +[15:53.41.559] END WMNewTab: 20 + + +[15:53.42.971] BEGIN WMNewTab: 20 +[15:53.42.971] END WMNewTab: 20 + + +[15:53.44.379] BEGIN WMNewTab: 20 +[15:53.44.379] END WMNewTab: 20 + + +[15:53.45.790] BEGIN WMNewTab: 20 +[15:53.45.790] END WMNewTab: 20 + + +[15:53.47.198] BEGIN WMNewTab: 20 +[15:53.47.198] END WMNewTab: 20 + + +[15:53.48.605] BEGIN WMNewTab: 20 +[15:53.48.605] END WMNewTab: 20 + + +[15:53.50.012] BEGIN WMNewTab: 20 +[15:53.50.012] END WMNewTab: 20 + + +[15:53.51.421] BEGIN WMNewTab: 20 +[15:53.51.421] END WMNewTab: 20 + + +[15:53.52.835] BEGIN WMNewTab: 20 +[15:53.52.835] END WMNewTab: 20 + + +[15:53.54.248] BEGIN WMNewTab: 20 +[15:53.54.248] END WMNewTab: 20 + + +[15:53.55.658] BEGIN WMNewTab: 20 +[15:53.55.658] END WMNewTab: 20 + + +[15:53.57.065] BEGIN WMNewTab: 20 +[15:53.57.065] END WMNewTab: 20 + + +[15:53.58.473] BEGIN WMNewTab: 20 +[15:53.58.473] END WMNewTab: 20 + + +[15:53.59.882] BEGIN WMNewTab: 20 +[15:53.59.882] END WMNewTab: 20 + + +[15:54.01.298] BEGIN WMNewTab: 20 +[15:54.01.298] END WMNewTab: 20 + + +[15:54.02.706] BEGIN WMNewTab: 20 +[15:54.02.706] END WMNewTab: 20 + + +[15:54.04.114] BEGIN WMNewTab: 20 +[15:54.04.114] END WMNewTab: 20 + + +[15:54.05.526] BEGIN WMNewTab: 20 +[15:54.05.526] END WMNewTab: 20 + + +[15:54.06.941] BEGIN WMNewTab: 20 +[15:54.06.941] END WMNewTab: 20 + + +[15:54.08.354] BEGIN WMNewTab: 20 +[15:54.08.354] END WMNewTab: 20 + + +[15:54.09.764] BEGIN WMNewTab: 20 +[15:54.09.764] END WMNewTab: 20 + + +[15:54.11.173] BEGIN WMNewTab: 20 +[15:54.11.173] END WMNewTab: 20 + + +[15:54.12.584] BEGIN WMNewTab: 20 +[15:54.12.584] END WMNewTab: 20 + + +[15:54.14.005] BEGIN WMNewTab: 20 +[15:54.14.005] END WMNewTab: 20 + + +[15:54.15.416] BEGIN WMNewTab: 20 +[15:54.15.416] END WMNewTab: 20 + + +[15:54.16.824] BEGIN WMNewTab: 20 +[15:54.16.824] END WMNewTab: 20 + + +[15:54.18.235] BEGIN WMNewTab: 20 +[15:54.18.235] END WMNewTab: 20 + + +[15:54.19.648] BEGIN WMNewTab: 20 +[15:54.19.648] END WMNewTab: 20 + + +[15:54.21.061] BEGIN WMNewTab: 20 +[15:54.21.061] END WMNewTab: 20 + + +[15:54.22.469] BEGIN WMNewTab: 20 +[15:54.22.469] END WMNewTab: 20 + + +[15:54.23.883] BEGIN WMNewTab: 20 +[15:54.23.883] END WMNewTab: 20 + + +[15:54.25.290] BEGIN WMNewTab: 20 +[15:54.25.290] END WMNewTab: 20 + + +[15:54.26.703] BEGIN WMNewTab: 20 +[15:54.26.703] END WMNewTab: 20 + + +[15:54.28.105] BEGIN WMNewTab: 20 +[15:54.28.105] END WMNewTab: 20 + + +[15:54.29.515] BEGIN WMNewTab: 20 +[15:54.29.515] END WMNewTab: 20 + + +[15:54.30.922] BEGIN WMNewTab: 20 +[15:54.30.922] END WMNewTab: 20 + + +[15:54.32.334] BEGIN WMNewTab: 20 +[15:54.32.334] END WMNewTab: 20 + + +[15:54.33.745] BEGIN WMNewTab: 20 +[15:54.33.745] END WMNewTab: 20 + + +[15:54.35.158] BEGIN WMNewTab: 20 +[15:54.35.158] END WMNewTab: 20 + + +[15:54.36.566] BEGIN WMNewTab: 20 +[15:54.36.566] END WMNewTab: 20 + +[15:54.37.498] BEGIN WMNewTab: 0 +[15:54.37.498] WMNewTab: FormClick +[15:54.37.498] WMNewTab: LooseFocus +[15:54.37.498] END WMNewTab: 0 +[15:54.37.633] BEGIN WMNewTab: 0 +[15:54.37.633] WMNewTab: FormClick +[15:54.37.633] WMNewTab: LooseFocus +[15:54.37.634] END WMNewTab: 0 +[15:54.37.977] BEGIN WMNewTab: 20 +[15:54.37.977] END WMNewTab: 20 + + +[15:54.39.391] BEGIN WMNewTab: 20 +[15:54.39.391] END WMNewTab: 20 + + +[15:54.40.799] BEGIN WMNewTab: 20 +[15:54.40.799] END WMNewTab: 20 + + +[15:54.42.204] BEGIN WMNewTab: 20 +[15:54.42.204] END WMNewTab: 20 + + +[15:54.43.615] BEGIN WMNewTab: 20 +[15:54.43.615] END WMNewTab: 20 + + +[15:54.45.022] BEGIN WMNewTab: 20 +[15:54.45.022] END WMNewTab: 20 +[15:54.45.154] Cts1MouseDown: FormClick +[15:54.45.159] Cts1ActiveTabChanged: New index = 2 +[15:54.45.159] BEGIN DisplayCurrentTab +[15:54.45.159] DisplayCurrentTab: FormClick +[15:54.45.159] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[15:54.45.159] (SSH-Browser) BEGIN ActiverPanel14 +[15:54.45.159] (SSH-Browser) BEGIN DesactiverPanel14 +[15:54.45.172] (SSH-Browser) END DesactiverPanel14 +[15:54.45.172] (SSH-Browser) END ActiverPanel14; +[15:54.45.276] BEGIN TFormXterm.FormResize +[15:54.45.276] TFormXterm.FormResize: CenterBtnReattachTab +[15:54.45.277] TFormXterm.FormResize: SplitModeResize +[15:54.45.277] TFormXterm.FormResize: BtnSplitNo.Down +[15:54.45.277] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:54.45.277] BEGIN ResizeTerminal +[15:54.45.282] END ResizeTerminal +[15:54.45.282] TFormXterm.FormResize: AdaptSidebarArrows; +[15:54.45.282] BEGIN AdaptSidebarArrows +[15:54.45.282] END AdaptSidebarArrows +[15:54.45.282] TFormXterm.FormResize: AdaptTV2; +[15:54.45.282] END TFormXterm.FormResize +[15:54.45.282] DisplayCurrentTab: Cts1.BeginUpdate; +[15:54.45.282] DisplayCurrentTab: Cts1.EndUpdates +[15:54.45.295] DisplayCurrentTab: 显示所选标签页 +[15:54.45.296] DisplayCurrentTab: 隐藏其他标签页 +[15:54.45.308] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:54.45.311] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:54.45.311] DisplayCurrentTab: DistribuerLeFocus +[15:54.45.311] END DisplayCurrentTab + +[15:54.46.431] BEGIN WMNewTab: 20 +[15:54.46.431] END WMNewTab: 20 + + +[15:54.47.842] BEGIN WMNewTab: 20 +[15:54.47.842] END WMNewTab: 20 +[15:54.48.059] BEGIN WMNewTab: 0 +[15:54.48.059] WMNewTab: FormClick +[15:54.48.059] WMNewTab: LooseFocus +[15:54.48.059] END WMNewTab: 0 +[15:54.48.177] BEGIN WMNewTab: 0 +[15:54.48.177] WMNewTab: FormClick +[15:54.48.177] WMNewTab: LooseFocus +[15:54.48.178] END WMNewTab: 0 + +[15:54.49.255] BEGIN WMNewTab: 20 +[15:54.49.255] END WMNewTab: 20 + + +[15:54.50.667] BEGIN WMNewTab: 20 +[15:54.50.667] END WMNewTab: 20 + + +[15:54.52.074] BEGIN WMNewTab: 20 +[15:54.52.074] END WMNewTab: 20 + + +[15:54.53.491] BEGIN WMNewTab: 20 +[15:54.53.491] END WMNewTab: 20 + + +[15:54.54.899] BEGIN WMNewTab: 20 +[15:54.54.899] END WMNewTab: 20 + + +[15:54.56.315] BEGIN WMNewTab: 20 +[15:54.56.315] END WMNewTab: 20 + + +[15:54.57.725] BEGIN WMNewTab: 20 +[15:54.57.725] END WMNewTab: 20 + + +[15:54.59.134] BEGIN WMNewTab: 20 +[15:54.59.134] END WMNewTab: 20 + + +[15:55.00.547] BEGIN WMNewTab: 20 +[15:55.00.547] END WMNewTab: 20 + +[15:55.01.220] BEGIN WMNewTab: 0 +[15:55.01.220] WMNewTab: FormClick +[15:55.01.220] WMNewTab: LooseFocus +[15:55.01.220] END WMNewTab: 0 +[15:55.01.330] BEGIN WMNewTab: 0 +[15:55.01.330] WMNewTab: FormClick +[15:55.01.330] WMNewTab: LooseFocus +[15:55.01.330] END WMNewTab: 0 +[15:55.01.675] Cts1MouseDown: FormClick +[15:55.01.679] Cts1ActiveTabChanged: New index = 1 +[15:55.01.679] BEGIN DisplayCurrentTab +[15:55.01.679] DisplayCurrentTab: FormClick +[15:55.01.679] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:55.01.679] (SSH-Browser) BEGIN ActiverPanel14 +[15:55.01.679] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:55.01.683] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:55.01.683] (SSH-Browser) ActiverPanel14: 列出远程目录 +[15:55.01.683] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[15:55.01.683] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[15:55.01.713] (SSH-Browser) END ActiverPanel14; +[15:55.01.739] BEGIN TFormXterm.FormResize +[15:55.01.739] TFormXterm.FormResize: CenterBtnReattachTab +[15:55.01.739] TFormXterm.FormResize: SplitModeResize +[15:55.01.739] TFormXterm.FormResize: BtnSplitNo.Down +[15:55.01.740] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:55.01.740] BEGIN ResizeTerminal +[15:55.01.744] END ResizeTerminal +[15:55.01.744] TFormXterm.FormResize: AdaptSidebarArrows; +[15:55.01.744] BEGIN AdaptSidebarArrows +[15:55.01.744] END AdaptSidebarArrows +[15:55.01.744] TFormXterm.FormResize: AdaptTV2; +[15:55.01.744] END TFormXterm.FormResize +[15:55.01.753] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[15:55.01.753] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:55.01.768] ShellExecuteS: ShellExecuteEx 成功. +[15:55.01.768] ShellExecuteS: WaitForInputIdle 失败. +[15:55.01.768] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:55.01.768] DisplayCurrentTab: Cts1.BeginUpdate; +[15:55.01.768] DisplayCurrentTab: Cts1.EndUpdates +[15:55.01.784] DisplayCurrentTab: 显示所选标签页 +[15:55.01.786] DisplayCurrentTab: 隐藏其他标签页 +[15:55.01.795] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:55.01.803] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:55.01.803] DisplayCurrentTab: DistribuerLeFocus +[15:55.01.804] END DisplayCurrentTab +[15:55.01.834] [MobaSCP2] Launching remote monitoring in normal mode +[15:55.01.835] [MobaSCP2] Multiplex=1 +[15:55.01.835] [MobaSCP2] HOSTNAME: 192.168.127.10 +[15:55.01.835] [MobaSCP2] USERNAME: root +[15:55.01.879] [MobaSCP2] Using SCP1 +[15:55.01.879] [MobaSCP2] Connected to 192.168.127.10 +[15:55.01.963] BEGIN WMNewTab: 20 +[15:55.01.963] END WMNewTab: 20 +[15:55.02.171] BEGIN WMNewTab: 0 +[15:55.02.171] WMNewTab: FormClick +[15:55.02.171] WMNewTab: LooseFocus +[15:55.02.171] END WMNewTab: 0 +[15:55.02.291] BEGIN WMNewTab: 0 +[15:55.02.291] WMNewTab: FormClick +[15:55.02.291] WMNewTab: LooseFocus +[15:55.02.292] END WMNewTab: 0 + +[15:55.02.887] BEGIN CWD +[15:55.03.006] BEGIN TFormXterm.FormResize +[15:55.03.006] TFormXterm.FormResize: CenterBtnReattachTab +[15:55.03.006] TFormXterm.FormResize: SplitModeResize +[15:55.03.006] TFormXterm.FormResize: BtnSplitNo.Down +[15:55.03.006] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:55.03.006] BEGIN ResizeTerminal +[15:55.03.006] END ResizeTerminal +[15:55.03.007] TFormXterm.FormResize: AdaptSidebarArrows; +[15:55.03.007] BEGIN AdaptSidebarArrows +[15:55.03.007] END AdaptSidebarArrows +[15:55.03.007] TFormXterm.FormResize: AdaptTV2; +[15:55.03.007] END TFormXterm.FormResize +[15:55.03.014] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:55.03.014] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:55.03.014] (SSH-Browser) END VerifySFTPConnection(1) +[15:55.03.014] END CWD +[15:55.03.026] BEGIN CWD +[15:55.03.087] END CWD + +[15:55.03.558] BEGIN WMNewTab: 20 +[15:55.03.558] END WMNewTab: 20 + + +[15:55.04.978] BEGIN WMNewTab: 20 +[15:55.04.978] END WMNewTab: 20 +[15:55.05.219] BEGIN WMNewTab: 0 +[15:55.05.219] WMNewTab: FormClick +[15:55.05.219] WMNewTab: LooseFocus +[15:55.05.220] END WMNewTab: 0 + +[15:55.06.375] BEGIN WMNewTab: 20 +[15:55.06.375] END WMNewTab: 20 +[15:55.06.699] BEGIN WMNewTab: 0 +[15:55.06.699] WMNewTab: FormClick +[15:55.06.699] WMNewTab: LooseFocus +[15:55.06.702] END WMNewTab: 0 + +[15:55.07.788] BEGIN WMNewTab: 20 +[15:55.07.788] END WMNewTab: 20 + + +[15:55.09.200] BEGIN WMNewTab: 20 +[15:55.09.200] END WMNewTab: 20 + + +[15:55.10.610] BEGIN WMNewTab: 20 +[15:55.10.610] END WMNewTab: 20 + + +[15:55.12.022] BEGIN WMNewTab: 20 +[15:55.12.022] END WMNewTab: 20 + + +[15:55.13.436] BEGIN WMNewTab: 20 +[15:55.13.436] END WMNewTab: 20 + + +[15:55.14.842] BEGIN WMNewTab: 20 +[15:55.14.842] END WMNewTab: 20 + + +[15:55.16.256] BEGIN WMNewTab: 20 +[15:55.16.256] END WMNewTab: 20 + +[15:55.17.234] BEGIN WMNewTab: 0 +[15:55.17.234] WMNewTab: FormClick +[15:55.17.234] WMNewTab: LooseFocus +[15:55.17.234] END WMNewTab: 0 +[15:55.17.323] BEGIN WMNewTab: 0 +[15:55.17.323] WMNewTab: FormClick +[15:55.17.323] WMNewTab: LooseFocus +[15:55.17.324] END WMNewTab: 0 +[15:55.17.665] BEGIN WMNewTab: 20 +[15:55.17.665] END WMNewTab: 20 + +[15:55.18.275] Cts1MouseDown: FormClick + +[15:55.18.700] Cts1MouseDown: FormClick +[15:55.18.702] Cts1ActiveTabChanged: New index = 2 +[15:55.18.702] BEGIN DisplayCurrentTab +[15:55.18.702] DisplayCurrentTab: FormClick +[15:55.18.702] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[15:55.18.702] (SSH-Browser) BEGIN ActiverPanel14 +[15:55.18.702] (SSH-Browser) BEGIN DesactiverPanel14 +[15:55.18.716] (SSH-Browser) END DesactiverPanel14 +[15:55.18.716] (SSH-Browser) END ActiverPanel14; +[15:55.18.818] BEGIN TFormXterm.FormResize +[15:55.18.818] TFormXterm.FormResize: CenterBtnReattachTab +[15:55.18.819] TFormXterm.FormResize: SplitModeResize +[15:55.18.819] TFormXterm.FormResize: BtnSplitNo.Down +[15:55.18.820] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:55.18.820] BEGIN ResizeTerminal +[15:55.18.824] END ResizeTerminal +[15:55.18.824] TFormXterm.FormResize: AdaptSidebarArrows; +[15:55.18.824] BEGIN AdaptSidebarArrows +[15:55.18.824] END AdaptSidebarArrows +[15:55.18.824] TFormXterm.FormResize: AdaptTV2; +[15:55.18.824] END TFormXterm.FormResize +[15:55.18.824] DisplayCurrentTab: Cts1.BeginUpdate; +[15:55.18.824] DisplayCurrentTab: Cts1.EndUpdates +[15:55.18.839] DisplayCurrentTab: 显示所选标签页 +[15:55.18.841] DisplayCurrentTab: 隐藏其他标签页 +[15:55.18.853] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:55.18.856] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:55.18.856] DisplayCurrentTab: DistribuerLeFocus +[15:55.18.857] END DisplayCurrentTab +[15:55.19.071] BEGIN WMNewTab: 20 +[15:55.19.071] END WMNewTab: 20 + + +[15:55.20.482] BEGIN WMNewTab: 20 +[15:55.20.482] END WMNewTab: 20 + + +[15:55.21.903] BEGIN WMNewTab: 20 +[15:55.21.903] END WMNewTab: 20 + + +[15:55.23.314] BEGIN WMNewTab: 20 +[15:55.23.314] END WMNewTab: 20 + + +[15:55.24.725] BEGIN WMNewTab: 20 +[15:55.24.725] END WMNewTab: 20 + +[15:55.25.773] BEGIN WMNewTab: 0 +[15:55.25.773] WMNewTab: FormClick +[15:55.25.773] WMNewTab: LooseFocus +[15:55.25.773] END WMNewTab: 0 + +[15:55.26.135] BEGIN WMNewTab: 20 +[15:55.26.135] END WMNewTab: 20 +[15:55.26.315] BEGIN WMNewTab: 0 +[15:55.26.315] WMNewTab: FormClick +[15:55.26.315] WMNewTab: LooseFocus +[15:55.26.315] END WMNewTab: 0 +[15:55.26.660] BEGIN WMNewTab: 0 +[15:55.26.660] WMNewTab: FormClick +[15:55.26.660] WMNewTab: LooseFocus +[15:55.26.661] END WMNewTab: 0 +[15:55.26.763] BEGIN WMNewTab: 0 +[15:55.26.763] WMNewTab: FormClick +[15:55.26.763] WMNewTab: LooseFocus +[15:55.26.766] END WMNewTab: 0 + +[15:55.27.364] BEGIN WMNewTab: 0 +[15:55.27.364] WMNewTab: FormClick +[15:55.27.364] WMNewTab: LooseFocus +[15:55.27.364] END WMNewTab: 0 +[15:55.27.543] BEGIN WMNewTab: 20 +[15:55.27.543] END WMNewTab: 20 + + +[15:55.28.953] BEGIN WMNewTab: 20 +[15:55.28.953] END WMNewTab: 20 +[15:55.29.067] BEGIN WMNewTab: 0 +[15:55.29.067] WMNewTab: FormClick +[15:55.29.067] WMNewTab: LooseFocus +[15:55.29.071] END WMNewTab: 0 + + +[15:55.30.366] BEGIN WMNewTab: 20 +[15:55.30.366] END WMNewTab: 20 + + +[15:55.31.776] BEGIN WMNewTab: 20 +[15:55.31.776] END WMNewTab: 20 + + +[15:55.33.183] BEGIN WMNewTab: 20 +[15:55.33.183] END WMNewTab: 20 + + +[15:55.34.597] BEGIN WMNewTab: 20 +[15:55.34.597] END WMNewTab: 20 + + +[15:55.36.012] BEGIN WMNewTab: 20 +[15:55.36.012] END WMNewTab: 20 + + +[15:55.37.420] BEGIN WMNewTab: 20 +[15:55.37.420] END WMNewTab: 20 + + +[15:55.38.837] BEGIN WMNewTab: 20 +[15:55.38.837] END WMNewTab: 20 + + +[15:55.40.247] BEGIN WMNewTab: 20 +[15:55.40.247] END WMNewTab: 20 + + +[15:55.41.659] BEGIN WMNewTab: 20 +[15:55.41.659] END WMNewTab: 20 + + +[15:55.43.066] BEGIN WMNewTab: 20 +[15:55.43.066] END WMNewTab: 20 + +[15:55.44.043] BEGIN WMNewTab: 0 +[15:55.44.043] WMNewTab: FormClick +[15:55.44.043] WMNewTab: LooseFocus +[15:55.44.043] END WMNewTab: 0 +[15:55.44.100] BEGIN WMNewTab: 0 +[15:55.44.100] WMNewTab: FormClick +[15:55.44.100] WMNewTab: LooseFocus +[15:55.44.100] END WMNewTab: 0 + +[15:55.44.480] BEGIN WMNewTab: 20 +[15:55.44.480] END WMNewTab: 20 + + +[15:55.45.893] BEGIN WMNewTab: 20 +[15:55.45.893] END WMNewTab: 20 + + +[15:55.47.301] BEGIN WMNewTab: 20 +[15:55.47.301] END WMNewTab: 20 + + +[15:55.48.713] BEGIN WMNewTab: 20 +[15:55.48.713] END WMNewTab: 20 + + +[15:55.50.129] BEGIN WMNewTab: 20 +[15:55.50.129] END WMNewTab: 20 + + +[15:55.51.541] BEGIN WMNewTab: 20 +[15:55.51.541] END WMNewTab: 20 + +[15:55.52.708] Cts1MouseDown: FormClick +[15:55.52.713] Cts1ActiveTabChanged: New index = 1 +[15:55.52.713] BEGIN DisplayCurrentTab +[15:55.52.713] DisplayCurrentTab: FormClick +[15:55.52.713] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[15:55.52.713] (SSH-Browser) BEGIN ActiverPanel14 +[15:55.52.713] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[15:55.52.717] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[15:55.52.717] (SSH-Browser) ActiverPanel14: 列出远程目录 +[15:55.52.717] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[15:55.52.717] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[15:55.52.748] (SSH-Browser) END ActiverPanel14; +[15:55.52.770] BEGIN TFormXterm.FormResize +[15:55.52.770] TFormXterm.FormResize: CenterBtnReattachTab +[15:55.52.771] TFormXterm.FormResize: SplitModeResize +[15:55.52.771] TFormXterm.FormResize: BtnSplitNo.Down +[15:55.52.771] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:55.52.771] BEGIN ResizeTerminal +[15:55.52.776] END ResizeTerminal +[15:55.52.776] TFormXterm.FormResize: AdaptSidebarArrows; +[15:55.52.776] BEGIN AdaptSidebarArrows +[15:55.52.776] END AdaptSidebarArrows +[15:55.52.776] TFormXterm.FormResize: AdaptTV2; +[15:55.52.776] END TFormXterm.FormResize +[15:55.52.776] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[15:55.52.776] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:55.52.793] ShellExecuteS: ShellExecuteEx 成功. +[15:55.52.793] ShellExecuteS: WaitForInputIdle 失败. +[15:55.52.793] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[15:55.52.793] DisplayCurrentTab: Cts1.BeginUpdate; +[15:55.52.793] DisplayCurrentTab: Cts1.EndUpdates +[15:55.52.811] DisplayCurrentTab: 显示所选标签页 +[15:55.52.812] DisplayCurrentTab: 隐藏其他标签页 +[15:55.52.828] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[15:55.52.835] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[15:55.52.835] DisplayCurrentTab: DistribuerLeFocus +[15:55.52.835] END DisplayCurrentTab +[15:55.52.853] [MobaSCP2] Launching remote monitoring in normal mode +[15:55.52.857] [MobaSCP2] Multiplex=1 +[15:55.52.857] [MobaSCP2] HOSTNAME: 192.168.127.10 +[15:55.52.857] [MobaSCP2] USERNAME: root +[15:55.52.901] [MobaSCP2] Using SCP1 +[15:55.52.902] [MobaSCP2] Connected to 192.168.127.10 +[15:55.52.948] BEGIN WMNewTab: 20 +[15:55.52.948] END WMNewTab: 20 + +[15:55.53.739] BEGIN CWD +[15:55.53.800] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:55.53.800] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:55.53.800] (SSH-Browser) END VerifySFTPConnection(1) +[15:55.53.800] END CWD +[15:55.53.921] BEGIN CWD +[15:55.54.105] BEGIN TFormXterm.FormResize +[15:55.54.105] TFormXterm.FormResize: CenterBtnReattachTab +[15:55.54.105] TFormXterm.FormResize: SplitModeResize +[15:55.54.105] TFormXterm.FormResize: BtnSplitNo.Down +[15:55.54.105] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:55.54.105] BEGIN ResizeTerminal +[15:55.54.105] END ResizeTerminal +[15:55.54.105] TFormXterm.FormResize: AdaptSidebarArrows; +[15:55.54.105] BEGIN AdaptSidebarArrows +[15:55.54.105] END AdaptSidebarArrows +[15:55.54.105] TFormXterm.FormResize: AdaptTV2; +[15:55.54.105] END TFormXterm.FormResize +[15:55.54.113] END CWD + +[15:55.54.572] BEGIN WMNewTab: 20 +[15:55.54.572] END WMNewTab: 20 + + +[15:55.56.016] BEGIN WMNewTab: 20 +[15:55.56.016] END WMNewTab: 20 + + +[15:55.57.425] BEGIN WMNewTab: 20 +[15:55.57.425] END WMNewTab: 20 + + +[15:55.58.839] BEGIN WMNewTab: 20 +[15:55.58.839] END WMNewTab: 20 + + +[15:56.00.246] BEGIN WMNewTab: 20 +[15:56.00.246] END WMNewTab: 20 + + +[15:56.01.657] BEGIN WMNewTab: 20 +[15:56.01.657] END WMNewTab: 20 + + +[15:56.03.069] BEGIN WMNewTab: 20 +[15:56.03.069] END WMNewTab: 20 + + +[15:56.04.482] BEGIN WMNewTab: 20 +[15:56.04.482] END WMNewTab: 20 + + +[15:56.05.890] BEGIN WMNewTab: 20 +[15:56.05.890] END WMNewTab: 20 + + +[15:56.07.302] BEGIN WMNewTab: 20 +[15:56.07.302] END WMNewTab: 20 + + +[15:56.08.715] BEGIN WMNewTab: 20 +[15:56.08.715] END WMNewTab: 20 + + +[15:56.10.127] BEGIN WMNewTab: 20 +[15:56.10.127] END WMNewTab: 20 + + +[15:56.11.540] BEGIN WMNewTab: 20 +[15:56.11.540] END WMNewTab: 20 + + +[15:56.12.951] BEGIN WMNewTab: 20 +[15:56.12.951] END WMNewTab: 20 + + +[15:56.14.361] BEGIN WMNewTab: 20 +[15:56.14.361] END WMNewTab: 20 + + +[15:56.15.772] BEGIN WMNewTab: 20 +[15:56.15.772] END WMNewTab: 20 + + +[15:56.17.181] BEGIN WMNewTab: 20 +[15:56.17.181] END WMNewTab: 20 + + +[15:56.18.589] BEGIN WMNewTab: 20 +[15:56.18.589] END WMNewTab: 20 + + +[15:56.20.000] BEGIN WMNewTab: 20 +[15:56.20.000] END WMNewTab: 20 + + +[15:56.21.414] BEGIN WMNewTab: 20 +[15:56.21.414] END WMNewTab: 20 + + +[15:56.22.824] BEGIN WMNewTab: 20 +[15:56.22.824] END WMNewTab: 20 + + +[15:56.24.230] BEGIN WMNewTab: 20 +[15:56.24.230] END WMNewTab: 20 + + +[15:56.25.645] BEGIN WMNewTab: 20 +[15:56.25.645] END WMNewTab: 20 + + +[15:56.27.059] BEGIN WMNewTab: 20 +[15:56.27.059] END WMNewTab: 20 + + +[15:56.28.472] BEGIN WMNewTab: 20 +[15:56.28.472] END WMNewTab: 20 + + +[15:56.29.887] BEGIN WMNewTab: 20 +[15:56.29.887] END WMNewTab: 20 + +[15:56.30.713] BEGIN WMNewTab: 0 +[15:56.30.713] WMNewTab: FormClick +[15:56.30.713] WMNewTab: LooseFocus +[15:56.30.713] END WMNewTab: 0 +[15:56.30.754] BEGIN WMNewTab: 0 +[15:56.30.754] WMNewTab: FormClick +[15:56.30.754] WMNewTab: LooseFocus +[15:56.30.754] END WMNewTab: 0 + +[15:56.31.293] BEGIN WMNewTab: 20 +[15:56.31.293] END WMNewTab: 20 + + +[15:56.32.704] BEGIN WMNewTab: 20 +[15:56.32.704] END WMNewTab: 20 + + +[15:56.34.112] BEGIN WMNewTab: 20 +[15:56.34.112] END WMNewTab: 20 + +[15:56.35.105] BEGIN WMNewTab: 0 +[15:56.35.105] WMNewTab: FormClick +[15:56.35.105] WMNewTab: LooseFocus +[15:56.35.106] END WMNewTab: 0 + +[15:56.35.519] BEGIN WMNewTab: 20 +[15:56.35.519] END WMNewTab: 20 + + +[15:56.36.931] BEGIN WMNewTab: 20 +[15:56.36.931] END WMNewTab: 20 + + +[15:56.38.341] BEGIN WMNewTab: 0 +[15:56.38.341] WMNewTab: FormClick +[15:56.38.341] WMNewTab: LooseFocus +[15:56.38.342] END WMNewTab: 0 +[15:56.38.342] BEGIN WMNewTab: 20 +[15:56.38.342] END WMNewTab: 20 + + +[15:56.39.754] BEGIN WMNewTab: 20 +[15:56.39.754] END WMNewTab: 20 + + +[15:56.41.170] BEGIN WMNewTab: 20 +[15:56.41.170] END WMNewTab: 20 + + +[15:56.42.585] BEGIN WMNewTab: 20 +[15:56.42.585] END WMNewTab: 20 + + +[15:56.43.997] BEGIN WMNewTab: 20 +[15:56.43.997] END WMNewTab: 20 + +[15:56.45.090] BEGIN WMSysCommand (minimize/restore) +[15:56.45.115] BEGIN WMSize +[15:56.45.115] END WMSize +[15:56.45.134] END WMSysCommand +[15:56.45.400] BEGIN WMNewTab: 20 +[15:56.45.400] END WMNewTab: 20 + + +[15:56.46.810] BEGIN WMNewTab: 20 +[15:56.46.810] END WMNewTab: 20 + + +[15:56.48.225] BEGIN WMNewTab: 20 +[15:56.48.225] END WMNewTab: 20 + + +[15:56.49.637] BEGIN WMNewTab: 20 +[15:56.49.637] END WMNewTab: 20 + + +[15:56.51.043] BEGIN WMNewTab: 20 +[15:56.51.043] END WMNewTab: 20 + + +[15:56.52.448] BEGIN WMNewTab: 20 +[15:56.52.448] END WMNewTab: 20 + + +[15:56.53.860] BEGIN WMNewTab: 20 +[15:56.53.860] END WMNewTab: 20 + + +[15:56.55.271] BEGIN WMNewTab: 20 +[15:56.55.271] END WMNewTab: 20 + + +[15:56.56.679] BEGIN WMNewTab: 20 +[15:56.56.679] END WMNewTab: 20 + + +[15:56.58.088] BEGIN WMNewTab: 20 +[15:56.58.088] END WMNewTab: 20 + + +[15:56.59.498] BEGIN WMNewTab: 20 +[15:56.59.498] END WMNewTab: 20 + +[15:57.00.538] BEGIN WMSysCommand (minimize/restore) +[15:57.00.538] BEGIN WMNewTab: 0 +[15:57.00.538] WMNewTab: FormClick +[15:57.00.538] WMNewTab: LooseFocus +[15:57.00.538] END WMNewTab: 0 +[15:57.00.636] BEGIN WMSize +[15:57.00.636] BEGIN TFormXterm.FormResize +[15:57.00.636] TFormXterm.FormResize: CenterBtnReattachTab +[15:57.00.636] TFormXterm.FormResize: SplitModeResize +[15:57.00.636] TFormXterm.FormResize: BtnSplitNo.Down +[15:57.00.636] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[15:57.00.636] BEGIN ResizeTerminal +[15:57.00.637] END ResizeTerminal +[15:57.00.637] TFormXterm.FormResize: AdaptSidebarArrows; +[15:57.00.637] BEGIN AdaptSidebarArrows +[15:57.00.637] END AdaptSidebarArrows +[15:57.00.637] TFormXterm.FormResize: AdaptTV2; +[15:57.00.637] END TFormXterm.FormResize +[15:57.00.637] END WMSize +[15:57.00.640] END WMSysCommand +[15:57.00.810] BEGIN WMNewTab: 0 +[15:57.00.810] WMNewTab: FormClick +[15:57.00.810] WMNewTab: LooseFocus +[15:57.00.810] END WMNewTab: 0 +[15:57.00.906] BEGIN WMNewTab: 20 +[15:57.00.906] END WMNewTab: 20 +[15:57.00.929] BEGIN WMNewTab: 0 +[15:57.00.929] WMNewTab: FormClick +[15:57.00.929] WMNewTab: LooseFocus +[15:57.00.930] END WMNewTab: 0 + + +[15:57.02.317] BEGIN WMNewTab: 20 +[15:57.02.317] END WMNewTab: 20 +[15:57.02.563] BEGIN WMNewTab: 0 +[15:57.02.563] WMNewTab: FormClick +[15:57.02.563] WMNewTab: LooseFocus +[15:57.02.563] END WMNewTab: 0 +[15:57.02.563] BEGIN WMNewTab: 31 +[15:57.02.563] END WMNewTab: 31 + +[15:57.03.727] BEGIN WMNewTab: 20 +[15:57.03.727] END WMNewTab: 20 + +[15:57.04.722] BEGIN WMNewTab: 0 +[15:57.04.722] WMNewTab: FormClick +[15:57.04.722] WMNewTab: LooseFocus +[15:57.04.722] END WMNewTab: 0 +[15:57.04.722] BEGIN WMNewTab: 31 +[15:57.04.722] END WMNewTab: 31 + +[15:57.05.132] BEGIN WMNewTab: 20 +[15:57.05.132] END WMNewTab: 20 + + +[15:57.06.467] BEGIN CWD +[15:57.06.528] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[15:57.06.528] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[15:57.06.528] (SSH-Browser) END VerifySFTPConnection(1) +[15:57.06.528] END CWD +[15:57.06.543] BEGIN WMNewTab: 20 +[15:57.06.543] END WMNewTab: 20 +[15:57.06.573] BEGIN CWD +[15:57.06.634] END CWD + + +[15:57.08.045] BEGIN WMNewTab: 20 +[15:57.08.045] END WMNewTab: 20 + + +[15:57.09.456] BEGIN WMNewTab: 20 +[15:57.09.456] END WMNewTab: 20 + + +[15:57.10.866] BEGIN WMNewTab: 20 +[15:57.10.866] END WMNewTab: 20 + + +[15:57.12.279] BEGIN WMNewTab: 20 +[15:57.12.279] END WMNewTab: 20 + + +[15:57.13.692] BEGIN WMNewTab: 20 +[15:57.13.692] END WMNewTab: 20 + + +[15:57.15.097] BEGIN WMNewTab: 20 +[15:57.15.097] END WMNewTab: 20 + + +[15:57.16.514] BEGIN WMNewTab: 20 +[15:57.16.514] END WMNewTab: 20 + + +[15:57.17.927] BEGIN WMNewTab: 20 +[15:57.17.927] END WMNewTab: 20 + + +[15:57.19.337] BEGIN WMNewTab: 20 +[15:57.19.337] END WMNewTab: 20 + + +[15:57.20.768] BEGIN WMNewTab: 20 +[15:57.20.768] END WMNewTab: 20 + + +[15:57.22.172] BEGIN WMNewTab: 20 +[15:57.22.172] END WMNewTab: 20 + + +[15:57.23.585] BEGIN WMNewTab: 20 +[15:57.23.585] END WMNewTab: 20 + + +[15:57.24.998] BEGIN WMNewTab: 20 +[15:57.24.998] END WMNewTab: 20 + + +[15:57.26.404] BEGIN WMNewTab: 20 +[15:57.26.404] END WMNewTab: 20 + + +[15:57.27.815] BEGIN WMNewTab: 20 +[15:57.27.815] END WMNewTab: 20 + + +[15:57.29.230] BEGIN WMNewTab: 20 +[15:57.29.230] END WMNewTab: 20 + + +[15:57.30.642] BEGIN WMNewTab: 20 +[15:57.30.642] END WMNewTab: 20 + + +[15:57.32.054] BEGIN WMNewTab: 20 +[15:57.32.054] END WMNewTab: 20 + + +[15:57.33.466] BEGIN WMNewTab: 20 +[15:57.33.466] END WMNewTab: 20 + + +[15:57.34.880] BEGIN WMNewTab: 20 +[15:57.34.880] END WMNewTab: 20 + + +[15:57.36.287] BEGIN WMNewTab: 20 +[15:57.36.287] END WMNewTab: 20 + + +[15:57.37.696] BEGIN WMNewTab: 20 +[15:57.37.696] END WMNewTab: 20 + + +[15:57.39.117] BEGIN WMNewTab: 20 +[15:57.39.117] END WMNewTab: 20 + + +[15:57.40.533] BEGIN WMNewTab: 20 +[15:57.40.533] END WMNewTab: 20 + + +[15:57.41.950] BEGIN WMNewTab: 20 +[15:57.41.950] END WMNewTab: 20 + + +[15:57.43.360] BEGIN WMNewTab: 20 +[15:57.43.360] END WMNewTab: 20 + + +[15:57.44.771] BEGIN WMNewTab: 20 +[15:57.44.771] END WMNewTab: 20 + + +[15:57.46.181] BEGIN WMNewTab: 20 +[15:57.46.181] END WMNewTab: 20 + + +[15:57.47.590] BEGIN WMNewTab: 20 +[15:57.47.590] END WMNewTab: 20 + + +[15:57.49.000] BEGIN WMNewTab: 20 +[15:57.49.000] END WMNewTab: 20 + + +[15:57.50.411] BEGIN WMNewTab: 20 +[15:57.50.411] END WMNewTab: 20 + + +[15:57.51.820] BEGIN WMNewTab: 20 +[15:57.51.820] END WMNewTab: 20 + + +[15:57.53.226] BEGIN WMNewTab: 20 +[15:57.53.226] END WMNewTab: 20 + + +[15:57.54.640] BEGIN WMNewTab: 20 +[15:57.54.640] END WMNewTab: 20 + + +[15:57.56.047] BEGIN WMNewTab: 20 +[15:57.56.047] END WMNewTab: 20 + + +[15:57.57.490] BEGIN WMNewTab: 20 +[15:57.57.490] END WMNewTab: 20 + + +[15:57.58.892] BEGIN WMNewTab: 20 +[15:57.58.893] END WMNewTab: 20 + + +[15:58.00.303] BEGIN WMNewTab: 20 +[15:58.00.303] END WMNewTab: 20 + + +[15:58.01.713] BEGIN WMNewTab: 20 +[15:58.01.713] END WMNewTab: 20 + + +[15:58.03.119] BEGIN WMNewTab: 20 +[15:58.03.119] END WMNewTab: 20 + + +[15:58.04.532] BEGIN WMNewTab: 20 +[15:58.04.532] END WMNewTab: 20 + + +[15:58.05.939] BEGIN WMNewTab: 20 +[15:58.05.939] END WMNewTab: 20 + + +[15:58.07.349] BEGIN WMNewTab: 20 +[15:58.07.349] END WMNewTab: 20 + + +[15:58.08.758] BEGIN WMNewTab: 20 +[15:58.08.758] END WMNewTab: 20 + + +[15:58.10.160] BEGIN WMNewTab: 20 +[15:58.10.160] END WMNewTab: 20 + + +[15:58.11.568] BEGIN WMNewTab: 20 +[15:58.11.568] END WMNewTab: 20 + + +[15:58.12.976] BEGIN WMNewTab: 20 +[15:58.12.976] END WMNewTab: 20 + + +[15:58.14.387] BEGIN WMNewTab: 20 +[15:58.14.387] END WMNewTab: 20 + + +[15:58.15.802] BEGIN WMNewTab: 20 +[15:58.15.802] END WMNewTab: 20 + + +[15:58.17.213] BEGIN WMNewTab: 20 +[15:58.17.213] END WMNewTab: 20 + + +[15:58.18.625] BEGIN WMNewTab: 20 +[15:58.18.625] END WMNewTab: 20 + + +[15:58.20.040] BEGIN WMNewTab: 20 +[15:58.20.040] END WMNewTab: 20 + + +[15:58.21.454] BEGIN WMNewTab: 20 +[15:58.21.454] END WMNewTab: 20 + + +[15:58.22.862] BEGIN WMNewTab: 20 +[15:58.22.862] END WMNewTab: 20 + + +[15:58.24.272] BEGIN WMNewTab: 20 +[15:58.24.272] END WMNewTab: 20 + + +[15:58.25.692] BEGIN WMNewTab: 20 +[15:58.25.692] END WMNewTab: 20 + + +[15:58.27.104] BEGIN WMNewTab: 20 +[15:58.27.104] END WMNewTab: 20 + + +[15:58.28.515] BEGIN WMNewTab: 20 +[15:58.28.515] END WMNewTab: 20 + + +[15:58.29.929] BEGIN WMNewTab: 20 +[15:58.29.929] END WMNewTab: 20 + + +[15:58.31.342] BEGIN WMNewTab: 20 +[15:58.31.342] END WMNewTab: 20 + + +[15:58.32.752] BEGIN WMNewTab: 20 +[15:58.32.752] END WMNewTab: 20 + + +[15:58.34.156] BEGIN WMNewTab: 20 +[15:58.34.156] END WMNewTab: 20 + + +[15:58.35.569] BEGIN WMNewTab: 20 +[15:58.35.569] END WMNewTab: 20 + + +[15:58.36.977] BEGIN WMNewTab: 20 +[15:58.36.977] END WMNewTab: 20 + + +[15:58.38.390] BEGIN WMNewTab: 20 +[15:58.38.390] END WMNewTab: 20 + + +[15:58.39.804] BEGIN WMNewTab: 20 +[15:58.39.804] END WMNewTab: 20 + + +[15:58.41.214] BEGIN WMNewTab: 20 +[15:58.41.214] END WMNewTab: 20 + + +[15:58.42.621] BEGIN WMNewTab: 20 +[15:58.42.621] END WMNewTab: 20 + + +[15:58.44.033] BEGIN WMNewTab: 20 +[15:58.44.033] END WMNewTab: 20 + + +[15:58.45.473] BEGIN WMNewTab: 20 +[15:58.45.473] END WMNewTab: 20 + + +[15:58.46.880] BEGIN WMNewTab: 20 +[15:58.46.880] END WMNewTab: 20 + + +[15:58.48.290] BEGIN WMNewTab: 20 +[15:58.48.290] END WMNewTab: 20 + +[15:58.49.397] BEGIN WMSysCommand (minimize/restore) +[15:58.49.419] BEGIN WMSize +[15:58.49.419] END WMSize +[15:58.49.441] END WMSysCommand +[15:58.49.699] BEGIN WMNewTab: 20 +[15:58.49.699] END WMNewTab: 20 + + +[15:58.51.106] BEGIN WMNewTab: 20 +[15:58.51.106] END WMNewTab: 20 + + +[15:58.52.519] BEGIN WMNewTab: 20 +[15:58.52.519] END WMNewTab: 20 + + +[15:58.53.927] BEGIN WMNewTab: 20 +[15:58.53.927] END WMNewTab: 20 + + +[15:58.55.337] BEGIN WMNewTab: 20 +[15:58.55.337] END WMNewTab: 20 + + +[15:58.56.755] BEGIN WMNewTab: 20 +[15:58.56.755] END WMNewTab: 20 + + +[15:58.58.167] BEGIN WMNewTab: 20 +[15:58.58.167] END WMNewTab: 20 + + +[15:58.59.577] BEGIN WMNewTab: 20 +[15:58.59.577] END WMNewTab: 20 + + +[15:59.00.990] BEGIN WMNewTab: 20 +[15:59.00.990] END WMNewTab: 20 + + +[15:59.02.406] BEGIN WMNewTab: 20 +[15:59.02.406] END WMNewTab: 20 + + +[15:59.03.839] BEGIN WMNewTab: 20 +[15:59.03.839] END WMNewTab: 20 + + +[15:59.05.243] BEGIN WMNewTab: 20 +[15:59.05.243] END WMNewTab: 20 + + +[15:59.06.660] BEGIN WMNewTab: 20 +[15:59.06.660] END WMNewTab: 20 + + +[15:59.08.081] BEGIN WMNewTab: 20 +[15:59.08.081] END WMNewTab: 20 + + +[15:59.09.495] BEGIN WMNewTab: 20 +[15:59.09.495] END WMNewTab: 20 + + +[15:59.10.913] BEGIN WMNewTab: 20 +[15:59.10.913] END WMNewTab: 20 + + +[15:59.12.335] BEGIN WMNewTab: 20 +[15:59.12.335] END WMNewTab: 20 + + +[15:59.13.750] BEGIN WMNewTab: 20 +[15:59.13.750] END WMNewTab: 20 + + +[15:59.15.171] BEGIN WMNewTab: 20 +[15:59.15.171] END WMNewTab: 20 + + +[15:59.16.582] BEGIN WMNewTab: 20 +[15:59.16.582] END WMNewTab: 20 + + +[15:59.17.994] BEGIN WMNewTab: 20 +[15:59.17.994] END WMNewTab: 20 + + +[15:59.19.416] BEGIN WMNewTab: 20 +[15:59.19.416] END WMNewTab: 20 + + +[15:59.20.836] BEGIN WMNewTab: 20 +[15:59.20.836] END WMNewTab: 20 + + +[15:59.22.254] BEGIN WMNewTab: 20 +[15:59.22.254] END WMNewTab: 20 + + +[15:59.23.677] BEGIN WMNewTab: 20 +[15:59.23.677] END WMNewTab: 20 + + +[15:59.25.091] BEGIN WMNewTab: 20 +[15:59.25.091] END WMNewTab: 20 + + +[15:59.26.504] BEGIN WMNewTab: 20 +[15:59.26.504] END WMNewTab: 20 + + +[15:59.27.914] BEGIN WMNewTab: 20 +[15:59.27.914] END WMNewTab: 20 + + +[15:59.29.356] BEGIN WMNewTab: 20 +[15:59.29.356] END WMNewTab: 20 + + +[15:59.30.764] BEGIN WMNewTab: 20 +[15:59.30.764] END WMNewTab: 20 + + +[15:59.32.182] BEGIN WMNewTab: 20 +[15:59.32.182] END WMNewTab: 20 + + +[15:59.33.593] BEGIN WMNewTab: 20 +[15:59.33.593] END WMNewTab: 20 + + +[15:59.35.009] BEGIN WMNewTab: 20 +[15:59.35.009] END WMNewTab: 20 + + +[15:59.36.428] BEGIN WMNewTab: 20 +[15:59.36.428] END WMNewTab: 20 + + +[15:59.37.847] BEGIN WMNewTab: 20 +[15:59.37.847] END WMNewTab: 20 + + +[15:59.39.271] BEGIN WMNewTab: 20 +[15:59.39.271] END WMNewTab: 20 + + +[15:59.40.692] BEGIN WMNewTab: 20 +[15:59.40.692] END WMNewTab: 20 + + +[15:59.42.112] BEGIN WMNewTab: 20 +[15:59.42.112] END WMNewTab: 20 + + +[15:59.43.528] BEGIN WMNewTab: 20 +[15:59.43.528] END WMNewTab: 20 + + +[15:59.44.945] BEGIN WMNewTab: 20 +[15:59.44.945] END WMNewTab: 20 + + +[15:59.46.351] BEGIN WMNewTab: 20 +[15:59.46.351] END WMNewTab: 20 + + +[15:59.47.763] BEGIN WMNewTab: 20 +[15:59.47.763] END WMNewTab: 20 + + +[15:59.49.178] BEGIN WMNewTab: 20 +[15:59.49.178] END WMNewTab: 20 + + +[15:59.50.593] BEGIN WMNewTab: 20 +[15:59.50.593] END WMNewTab: 20 + + +[15:59.52.005] BEGIN WMNewTab: 20 +[15:59.52.005] END WMNewTab: 20 + + +[15:59.53.423] BEGIN WMNewTab: 20 +[15:59.53.423] END WMNewTab: 20 + + +[15:59.54.834] BEGIN WMNewTab: 20 +[15:59.54.834] END WMNewTab: 20 + + +[15:59.56.246] BEGIN WMNewTab: 20 +[15:59.56.246] END WMNewTab: 20 + + +[15:59.57.659] BEGIN WMNewTab: 20 +[15:59.57.659] END WMNewTab: 20 + + +[15:59.59.074] BEGIN WMNewTab: 20 +[15:59.59.074] END WMNewTab: 20 + + +[16:00.00.486] BEGIN WMNewTab: 20 +[16:00.00.486] END WMNewTab: 20 + + +[16:00.01.902] BEGIN WMNewTab: 20 +[16:00.01.902] END WMNewTab: 20 + + +[16:00.03.311] BEGIN WMNewTab: 20 +[16:00.03.311] END WMNewTab: 20 + + +[16:00.04.720] BEGIN WMNewTab: 20 +[16:00.04.720] END WMNewTab: 20 + + +[16:00.06.135] BEGIN WMNewTab: 20 +[16:00.06.135] END WMNewTab: 20 + + +[16:00.07.548] BEGIN WMNewTab: 20 +[16:00.07.548] END WMNewTab: 20 + + +[16:00.08.963] BEGIN WMNewTab: 20 +[16:00.08.963] END WMNewTab: 20 + + +[16:00.10.379] BEGIN WMNewTab: 20 +[16:00.10.379] END WMNewTab: 20 + + +[16:00.11.791] BEGIN WMNewTab: 20 +[16:00.11.792] END WMNewTab: 20 + + +[16:00.13.231] BEGIN WMNewTab: 20 +[16:00.13.231] END WMNewTab: 20 + + +[16:00.14.632] BEGIN WMNewTab: 20 +[16:00.14.632] END WMNewTab: 20 + + +[16:00.16.039] BEGIN WMNewTab: 20 +[16:00.16.039] END WMNewTab: 20 + + +[16:00.17.453] BEGIN WMNewTab: 20 +[16:00.17.453] END WMNewTab: 20 + + +[16:00.18.865] BEGIN WMNewTab: 20 +[16:00.18.865] END WMNewTab: 20 + + +[16:00.20.280] BEGIN WMNewTab: 20 +[16:00.20.280] END WMNewTab: 20 + + +[16:00.21.698] BEGIN WMNewTab: 20 +[16:00.21.698] END WMNewTab: 20 + + +[16:00.23.116] BEGIN WMNewTab: 20 +[16:00.23.116] END WMNewTab: 20 + + +[16:00.24.527] BEGIN WMNewTab: 20 +[16:00.24.527] END WMNewTab: 20 + + +[16:00.25.932] BEGIN WMNewTab: 20 +[16:00.25.932] END WMNewTab: 20 + + +[16:00.27.338] BEGIN WMNewTab: 20 +[16:00.27.338] END WMNewTab: 20 + + +[16:00.28.749] BEGIN WMNewTab: 20 +[16:00.28.749] END WMNewTab: 20 + + +[16:00.30.159] BEGIN WMNewTab: 20 +[16:00.30.159] END WMNewTab: 20 + + +[16:00.31.571] BEGIN WMNewTab: 20 +[16:00.31.571] END WMNewTab: 20 + + +[16:00.32.979] BEGIN WMNewTab: 20 +[16:00.32.979] END WMNewTab: 20 + + +[16:00.34.392] BEGIN WMNewTab: 20 +[16:00.34.392] END WMNewTab: 20 + + +[16:00.35.804] BEGIN WMNewTab: 20 +[16:00.35.804] END WMNewTab: 20 + + +[16:00.37.217] BEGIN WMNewTab: 20 +[16:00.37.217] END WMNewTab: 20 + + +[16:00.38.626] BEGIN WMNewTab: 20 +[16:00.38.626] END WMNewTab: 20 + + +[16:00.40.037] BEGIN WMNewTab: 20 +[16:00.40.037] END WMNewTab: 20 + + +[16:00.41.450] BEGIN WMNewTab: 20 +[16:00.41.450] END WMNewTab: 20 + + +[16:00.42.864] BEGIN WMNewTab: 20 +[16:00.42.864] END WMNewTab: 20 + + +[16:00.44.275] BEGIN WMNewTab: 20 +[16:00.44.275] END WMNewTab: 20 + + +[16:00.45.683] BEGIN WMNewTab: 20 +[16:00.45.683] END WMNewTab: 20 + + +[16:00.47.094] BEGIN WMNewTab: 20 +[16:00.47.094] END WMNewTab: 20 + + +[16:00.48.504] BEGIN WMNewTab: 20 +[16:00.48.504] END WMNewTab: 20 + + +[16:00.49.913] BEGIN WMNewTab: 20 +[16:00.49.913] END WMNewTab: 20 + + +[16:00.51.321] BEGIN WMNewTab: 20 +[16:00.51.321] END WMNewTab: 20 + + +[16:00.52.730] BEGIN WMNewTab: 20 +[16:00.52.730] END WMNewTab: 20 + + +[16:00.54.142] BEGIN WMNewTab: 20 +[16:00.54.142] END WMNewTab: 20 + + +[16:00.55.553] BEGIN WMNewTab: 20 +[16:00.55.553] END WMNewTab: 20 + + +[16:00.56.971] BEGIN WMNewTab: 20 +[16:00.56.971] END WMNewTab: 20 + + +[16:00.58.387] BEGIN WMNewTab: 20 +[16:00.58.387] END WMNewTab: 20 + + +[16:00.59.800] BEGIN WMNewTab: 20 +[16:00.59.800] END WMNewTab: 20 + + +[16:01.01.211] BEGIN WMNewTab: 20 +[16:01.01.211] END WMNewTab: 20 + + +[16:01.02.620] BEGIN WMNewTab: 20 +[16:01.02.620] END WMNewTab: 20 + + +[16:01.04.031] BEGIN WMNewTab: 20 +[16:01.04.031] END WMNewTab: 20 + + +[16:01.05.440] BEGIN WMNewTab: 20 +[16:01.05.440] END WMNewTab: 20 + + +[16:01.06.854] BEGIN WMNewTab: 20 +[16:01.06.854] END WMNewTab: 20 + + +[16:01.08.265] BEGIN WMNewTab: 20 +[16:01.08.265] END WMNewTab: 20 + + +[16:01.09.672] BEGIN WMNewTab: 20 +[16:01.09.672] END WMNewTab: 20 + + +[16:01.11.086] BEGIN WMNewTab: 20 +[16:01.11.086] END WMNewTab: 20 + + +[16:01.12.497] BEGIN WMNewTab: 20 +[16:01.12.497] END WMNewTab: 20 + + +[16:01.13.906] BEGIN WMNewTab: 20 +[16:01.13.906] END WMNewTab: 20 + + +[16:01.15.317] BEGIN WMNewTab: 20 +[16:01.15.317] END WMNewTab: 20 + + +[16:01.16.724] BEGIN WMNewTab: 20 +[16:01.16.724] END WMNewTab: 20 + + +[16:01.18.135] BEGIN WMNewTab: 20 +[16:01.18.135] END WMNewTab: 20 + + +[16:01.19.545] BEGIN WMNewTab: 20 +[16:01.19.545] END WMNewTab: 20 + + +[16:01.20.955] BEGIN WMNewTab: 20 +[16:01.20.955] END WMNewTab: 20 + + +[16:01.22.362] BEGIN WMNewTab: 20 +[16:01.22.362] END WMNewTab: 20 + + +[16:01.23.769] BEGIN WMNewTab: 20 +[16:01.23.769] END WMNewTab: 20 + + +[16:01.25.183] BEGIN WMNewTab: 20 +[16:01.25.183] END WMNewTab: 20 + + +[16:01.26.594] BEGIN WMNewTab: 20 +[16:01.26.594] END WMNewTab: 20 + + +[16:01.28.005] BEGIN WMNewTab: 20 +[16:01.28.005] END WMNewTab: 20 + + +[16:01.29.418] BEGIN WMNewTab: 20 +[16:01.29.418] END WMNewTab: 20 + + +[16:01.30.830] BEGIN WMNewTab: 20 +[16:01.30.830] END WMNewTab: 20 + + +[16:01.32.245] BEGIN WMNewTab: 20 +[16:01.32.245] END WMNewTab: 20 + + +[16:01.33.658] BEGIN WMNewTab: 20 +[16:01.33.658] END WMNewTab: 20 + + +[16:01.35.069] BEGIN WMNewTab: 20 +[16:01.35.069] END WMNewTab: 20 + + +[16:01.36.478] BEGIN WMNewTab: 20 +[16:01.36.478] END WMNewTab: 20 + + +[16:01.37.888] BEGIN WMNewTab: 20 +[16:01.37.888] END WMNewTab: 20 + + +[16:01.39.297] BEGIN WMNewTab: 20 +[16:01.39.297] END WMNewTab: 20 + + +[16:01.40.710] BEGIN WMNewTab: 20 +[16:01.40.710] END WMNewTab: 20 + + +[16:01.42.118] BEGIN WMNewTab: 20 +[16:01.42.118] END WMNewTab: 20 + + +[16:01.43.529] BEGIN WMNewTab: 20 +[16:01.43.529] END WMNewTab: 20 + + +[16:01.44.941] BEGIN WMNewTab: 20 +[16:01.44.941] END WMNewTab: 20 + + +[16:01.46.352] BEGIN WMNewTab: 20 +[16:01.46.352] END WMNewTab: 20 + + +[16:01.47.759] BEGIN WMNewTab: 20 +[16:01.47.759] END WMNewTab: 20 + + +[16:01.49.172] BEGIN WMNewTab: 20 +[16:01.49.172] END WMNewTab: 20 + + +[16:01.50.591] BEGIN WMNewTab: 20 +[16:01.50.591] END WMNewTab: 20 + + +[16:01.52.003] BEGIN WMNewTab: 20 +[16:01.52.003] END WMNewTab: 20 + + +[16:01.53.417] BEGIN WMNewTab: 20 +[16:01.53.417] END WMNewTab: 20 + + +[16:01.54.829] BEGIN WMNewTab: 20 +[16:01.54.829] END WMNewTab: 20 + + +[16:01.56.240] BEGIN WMNewTab: 20 +[16:01.56.240] END WMNewTab: 20 + + +[16:01.57.648] BEGIN WMNewTab: 20 +[16:01.57.648] END WMNewTab: 20 + + +[16:01.59.060] BEGIN WMNewTab: 20 +[16:01.59.060] END WMNewTab: 20 + + +[16:02.00.474] BEGIN WMNewTab: 20 +[16:02.00.474] END WMNewTab: 20 + + +[16:02.01.885] BEGIN WMNewTab: 20 +[16:02.01.885] END WMNewTab: 20 + + +[16:02.03.297] BEGIN WMNewTab: 20 +[16:02.03.297] END WMNewTab: 20 + + +[16:02.04.708] BEGIN WMNewTab: 20 +[16:02.04.709] END WMNewTab: 20 + + +[16:02.06.120] BEGIN WMNewTab: 20 +[16:02.06.120] END WMNewTab: 20 + + +[16:02.07.551] BEGIN WMNewTab: 20 +[16:02.07.551] END WMNewTab: 20 + + +[16:02.08.954] BEGIN WMNewTab: 20 +[16:02.08.954] END WMNewTab: 20 + + +[16:02.10.362] BEGIN WMNewTab: 20 +[16:02.10.362] END WMNewTab: 20 + + +[16:02.11.773] BEGIN WMNewTab: 20 +[16:02.11.773] END WMNewTab: 20 + + +[16:02.13.182] BEGIN WMNewTab: 20 +[16:02.13.182] END WMNewTab: 20 + + +[16:02.14.590] BEGIN WMNewTab: 20 +[16:02.14.590] END WMNewTab: 20 + + +[16:02.16.009] BEGIN WMNewTab: 20 +[16:02.16.009] END WMNewTab: 20 + + +[16:02.17.419] BEGIN WMNewTab: 20 +[16:02.17.419] END WMNewTab: 20 + + +[16:02.18.835] BEGIN WMNewTab: 20 +[16:02.18.835] END WMNewTab: 20 + + +[16:02.20.241] BEGIN WMNewTab: 20 +[16:02.20.241] END WMNewTab: 20 + + +[16:02.21.663] BEGIN WMNewTab: 20 +[16:02.21.663] END WMNewTab: 20 + + +[16:02.23.075] BEGIN WMNewTab: 20 +[16:02.23.075] END WMNewTab: 20 + + +[16:02.24.485] BEGIN WMNewTab: 20 +[16:02.24.485] END WMNewTab: 20 + + +[16:02.25.902] BEGIN WMNewTab: 20 +[16:02.25.902] END WMNewTab: 20 + + +[16:02.27.304] BEGIN WMNewTab: 20 +[16:02.27.304] END WMNewTab: 20 + + +[16:02.28.715] BEGIN WMNewTab: 20 +[16:02.28.715] END WMNewTab: 20 + + +[16:02.30.127] BEGIN WMNewTab: 20 +[16:02.30.127] END WMNewTab: 20 + + +[16:02.31.541] BEGIN WMNewTab: 20 +[16:02.31.541] END WMNewTab: 20 + + +[16:02.32.953] BEGIN WMNewTab: 20 +[16:02.32.953] END WMNewTab: 20 + + +[16:02.34.364] BEGIN WMNewTab: 20 +[16:02.34.364] END WMNewTab: 20 + + +[16:02.35.777] BEGIN WMNewTab: 20 +[16:02.35.777] END WMNewTab: 20 + + +[16:02.37.193] BEGIN WMNewTab: 20 +[16:02.37.193] END WMNewTab: 20 + + +[16:02.38.604] BEGIN WMNewTab: 20 +[16:02.38.604] END WMNewTab: 20 + + +[16:02.40.017] BEGIN WMNewTab: 20 +[16:02.40.017] END WMNewTab: 20 + + +[16:02.41.426] BEGIN WMNewTab: 20 +[16:02.41.426] END WMNewTab: 20 + + +[16:02.42.840] BEGIN WMNewTab: 20 +[16:02.42.840] END WMNewTab: 20 + + +[16:02.44.276] BEGIN WMNewTab: 20 +[16:02.44.276] END WMNewTab: 20 + + +[16:02.45.691] BEGIN WMNewTab: 20 +[16:02.45.691] END WMNewTab: 20 + + +[16:02.47.100] BEGIN WMNewTab: 20 +[16:02.47.100] END WMNewTab: 20 + + +[16:02.48.507] BEGIN WMNewTab: 20 +[16:02.48.507] END WMNewTab: 20 + + +[16:02.49.917] BEGIN WMNewTab: 20 +[16:02.49.917] END WMNewTab: 20 + + +[16:02.51.327] BEGIN WMNewTab: 20 +[16:02.51.327] END WMNewTab: 20 + + +[16:02.52.742] BEGIN WMNewTab: 20 +[16:02.52.742] END WMNewTab: 20 + + +[16:02.54.156] BEGIN WMNewTab: 20 +[16:02.54.156] END WMNewTab: 20 + + +[16:02.55.563] BEGIN WMNewTab: 20 +[16:02.55.563] END WMNewTab: 20 + + +[16:02.56.978] BEGIN WMNewTab: 20 +[16:02.56.978] END WMNewTab: 20 + + +[16:02.58.385] BEGIN WMNewTab: 20 +[16:02.58.385] END WMNewTab: 20 + + +[16:02.59.797] BEGIN WMNewTab: 20 +[16:02.59.797] END WMNewTab: 20 + + +[16:03.01.208] BEGIN WMNewTab: 20 +[16:03.01.208] END WMNewTab: 20 + + +[16:03.02.634] BEGIN WMNewTab: 20 +[16:03.02.634] END WMNewTab: 20 + + +[16:03.04.034] BEGIN WMNewTab: 20 +[16:03.04.034] END WMNewTab: 20 + + +[16:03.05.444] BEGIN WMNewTab: 20 +[16:03.05.444] END WMNewTab: 20 + + +[16:03.06.857] BEGIN WMNewTab: 20 +[16:03.06.857] END WMNewTab: 20 + + +[16:03.08.271] BEGIN WMNewTab: 20 +[16:03.08.271] END WMNewTab: 20 + + +[16:03.09.685] BEGIN WMNewTab: 20 +[16:03.09.685] END WMNewTab: 20 + + +[16:03.11.094] BEGIN WMNewTab: 20 +[16:03.11.094] END WMNewTab: 20 + + +[16:03.12.501] BEGIN WMNewTab: 20 +[16:03.12.501] END WMNewTab: 20 + + +[16:03.13.915] BEGIN WMNewTab: 20 +[16:03.13.915] END WMNewTab: 20 + + +[16:03.15.328] BEGIN WMNewTab: 20 +[16:03.15.328] END WMNewTab: 20 + + +[16:03.16.741] BEGIN WMNewTab: 20 +[16:03.16.741] END WMNewTab: 20 + + +[16:03.18.153] BEGIN WMNewTab: 20 +[16:03.18.153] END WMNewTab: 20 + + +[16:03.19.564] BEGIN WMNewTab: 20 +[16:03.19.564] END WMNewTab: 20 + + +[16:03.20.997] BEGIN WMNewTab: 20 +[16:03.20.997] END WMNewTab: 20 + + +[16:03.22.396] BEGIN WMNewTab: 20 +[16:03.22.396] END WMNewTab: 20 + + +[16:03.23.808] BEGIN WMNewTab: 20 +[16:03.23.808] END WMNewTab: 20 + + +[16:03.25.227] BEGIN WMNewTab: 20 +[16:03.25.227] END WMNewTab: 20 + + +[16:03.26.640] BEGIN WMNewTab: 20 +[16:03.26.640] END WMNewTab: 20 + + +[16:03.28.051] BEGIN WMNewTab: 20 +[16:03.28.051] END WMNewTab: 20 + + +[16:03.29.464] BEGIN WMNewTab: 20 +[16:03.29.464] END WMNewTab: 20 + + +[16:03.30.872] BEGIN WMNewTab: 20 +[16:03.30.872] END WMNewTab: 20 + + +[16:03.32.284] BEGIN WMNewTab: 20 +[16:03.32.284] END WMNewTab: 20 + + +[16:03.33.696] BEGIN WMNewTab: 20 +[16:03.33.696] END WMNewTab: 20 + + +[16:03.35.112] BEGIN WMNewTab: 20 +[16:03.35.112] END WMNewTab: 20 + + +[16:03.36.522] BEGIN WMNewTab: 20 +[16:03.36.522] END WMNewTab: 20 + + +[16:03.37.934] BEGIN WMNewTab: 20 +[16:03.37.934] END WMNewTab: 20 + + +[16:03.39.345] BEGIN WMNewTab: 20 +[16:03.39.345] END WMNewTab: 20 + + +[16:03.40.755] BEGIN WMNewTab: 20 +[16:03.40.755] END WMNewTab: 20 + + +[16:03.42.163] BEGIN WMNewTab: 20 +[16:03.42.163] END WMNewTab: 20 + + +[16:03.43.572] BEGIN WMNewTab: 20 +[16:03.43.572] END WMNewTab: 20 + + +[16:03.44.981] BEGIN WMNewTab: 20 +[16:03.44.981] END WMNewTab: 20 + + +[16:03.46.390] BEGIN WMNewTab: 20 +[16:03.46.390] END WMNewTab: 20 + + +[16:03.47.800] BEGIN WMNewTab: 20 +[16:03.47.800] END WMNewTab: 20 + + +[16:03.49.209] BEGIN WMNewTab: 20 +[16:03.49.209] END WMNewTab: 20 + + +[16:03.50.617] BEGIN WMNewTab: 20 +[16:03.50.617] END WMNewTab: 20 + + +[16:03.52.032] BEGIN WMNewTab: 20 +[16:03.52.032] END WMNewTab: 20 + + +[16:03.53.443] BEGIN WMNewTab: 20 +[16:03.53.443] END WMNewTab: 20 + + +[16:03.54.853] BEGIN WMNewTab: 20 +[16:03.54.853] END WMNewTab: 20 + + +[16:03.56.263] BEGIN WMNewTab: 20 +[16:03.56.263] END WMNewTab: 20 + + +[16:03.57.674] BEGIN WMNewTab: 20 +[16:03.57.674] END WMNewTab: 20 + + +[16:03.59.084] BEGIN WMNewTab: 20 +[16:03.59.084] END WMNewTab: 20 + + +[16:04.00.493] BEGIN WMNewTab: 20 +[16:04.00.493] END WMNewTab: 20 + + +[16:04.01.901] BEGIN WMNewTab: 20 +[16:04.01.901] END WMNewTab: 20 + + +[16:04.03.311] BEGIN WMNewTab: 20 +[16:04.03.311] END WMNewTab: 20 + +[16:04.03.948] BEGIN WMSysCommand (minimize/restore) +[16:04.03.948] BEGIN WMNewTab: 0 +[16:04.03.948] WMNewTab: FormClick +[16:04.03.948] WMNewTab: LooseFocus +[16:04.03.949] END WMNewTab: 0 +[16:04.04.018] BEGIN WMSize +[16:04.04.018] BEGIN TFormXterm.FormResize +[16:04.04.018] TFormXterm.FormResize: CenterBtnReattachTab +[16:04.04.018] TFormXterm.FormResize: SplitModeResize +[16:04.04.018] TFormXterm.FormResize: BtnSplitNo.Down +[16:04.04.018] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:04.04.018] BEGIN ResizeTerminal +[16:04.04.020] END ResizeTerminal +[16:04.04.020] TFormXterm.FormResize: AdaptSidebarArrows; +[16:04.04.020] BEGIN AdaptSidebarArrows +[16:04.04.020] END AdaptSidebarArrows +[16:04.04.020] TFormXterm.FormResize: AdaptTV2; +[16:04.04.020] END TFormXterm.FormResize +[16:04.04.020] END WMSize +[16:04.04.023] END WMSysCommand + +[16:04.04.723] BEGIN WMNewTab: 20 +[16:04.04.723] END WMNewTab: 20 + + +[16:04.06.133] BEGIN WMNewTab: 20 +[16:04.06.133] END WMNewTab: 20 + + +[16:04.07.541] BEGIN WMNewTab: 20 +[16:04.07.541] END WMNewTab: 20 + +[16:04.08.365] Cts1MouseDown: FormClick +[16:04.08.370] Cts1ActiveTabChanged: New index = 2 +[16:04.08.370] BEGIN DisplayCurrentTab +[16:04.08.370] DisplayCurrentTab: FormClick +[16:04.08.370] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:04.08.370] (SSH-Browser) BEGIN ActiverPanel14 +[16:04.08.370] (SSH-Browser) BEGIN DesactiverPanel14 +[16:04.08.384] (SSH-Browser) END DesactiverPanel14 +[16:04.08.384] (SSH-Browser) END ActiverPanel14; +[16:04.08.488] BEGIN TFormXterm.FormResize +[16:04.08.488] TFormXterm.FormResize: CenterBtnReattachTab +[16:04.08.489] TFormXterm.FormResize: SplitModeResize +[16:04.08.489] TFormXterm.FormResize: BtnSplitNo.Down +[16:04.08.490] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:04.08.490] BEGIN ResizeTerminal +[16:04.08.493] END ResizeTerminal +[16:04.08.493] TFormXterm.FormResize: AdaptSidebarArrows; +[16:04.08.493] BEGIN AdaptSidebarArrows +[16:04.08.493] END AdaptSidebarArrows +[16:04.08.493] TFormXterm.FormResize: AdaptTV2; +[16:04.08.493] END TFormXterm.FormResize +[16:04.08.493] DisplayCurrentTab: Cts1.BeginUpdate; +[16:04.08.493] DisplayCurrentTab: Cts1.EndUpdates +[16:04.08.507] DisplayCurrentTab: 显示所选标签页 +[16:04.08.508] DisplayCurrentTab: 隐藏其他标签页 +[16:04.08.521] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:04.08.524] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:04.08.524] DisplayCurrentTab: DistribuerLeFocus +[16:04.08.524] END DisplayCurrentTab + +[16:04.08.957] BEGIN WMNewTab: 20 +[16:04.08.957] END WMNewTab: 20 + + +[16:04.10.373] BEGIN WMNewTab: 20 +[16:04.10.373] END WMNewTab: 20 +[16:04.10.637] Cts1MouseDown: FormClick +[16:04.10.641] Cts1ActiveTabChanged: New index = 1 +[16:04.10.641] BEGIN DisplayCurrentTab +[16:04.10.641] DisplayCurrentTab: FormClick +[16:04.10.641] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:04.10.641] (SSH-Browser) BEGIN ActiverPanel14 +[16:04.10.641] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:04.10.645] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:04.10.645] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:04.10.645] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:04.10.646] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:04.10.673] (SSH-Browser) END ActiverPanel14; +[16:04.10.694] BEGIN TFormXterm.FormResize +[16:04.10.694] TFormXterm.FormResize: CenterBtnReattachTab +[16:04.10.695] TFormXterm.FormResize: SplitModeResize +[16:04.10.695] TFormXterm.FormResize: BtnSplitNo.Down +[16:04.10.696] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:04.10.696] BEGIN ResizeTerminal +[16:04.10.699] END ResizeTerminal +[16:04.10.699] TFormXterm.FormResize: AdaptSidebarArrows; +[16:04.10.699] BEGIN AdaptSidebarArrows +[16:04.10.699] END AdaptSidebarArrows +[16:04.10.699] TFormXterm.FormResize: AdaptTV2; +[16:04.10.699] END TFormXterm.FormResize +[16:04.10.699] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:04.10.699] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:04.10.716] ShellExecuteS: ShellExecuteEx 成功. +[16:04.10.716] ShellExecuteS: WaitForInputIdle 失败. +[16:04.10.716] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:04.10.716] DisplayCurrentTab: Cts1.BeginUpdate; +[16:04.10.716] DisplayCurrentTab: Cts1.EndUpdates +[16:04.10.731] DisplayCurrentTab: 显示所选标签页 +[16:04.10.734] DisplayCurrentTab: 隐藏其他标签页 +[16:04.10.746] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:04.10.752] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:04.10.752] DisplayCurrentTab: DistribuerLeFocus +[16:04.10.753] END DisplayCurrentTab +[16:04.10.779] [MobaSCP2] Launching remote monitoring in normal mode +[16:04.10.779] [MobaSCP2] Multiplex=1 +[16:04.10.779] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:04.10.780] [MobaSCP2] USERNAME: root +[16:04.10.824] [MobaSCP2] Using SCP1 +[16:04.10.824] [MobaSCP2] Connected to 192.168.127.10 +[16:04.11.086] BEGIN WMNewTab: 0 +[16:04.11.086] WMNewTab: FormClick +[16:04.11.086] WMNewTab: LooseFocus +[16:04.11.086] END WMNewTab: 0 +[16:04.11.188] BEGIN WMNewTab: 0 +[16:04.11.188] WMNewTab: FormClick +[16:04.11.188] WMNewTab: LooseFocus +[16:04.11.189] END WMNewTab: 0 + +[16:04.11.782] BEGIN WMNewTab: 20 +[16:04.11.782] END WMNewTab: 20 +[16:04.11.930] BEGIN TFormXterm.FormResize +[16:04.11.930] TFormXterm.FormResize: CenterBtnReattachTab +[16:04.11.930] TFormXterm.FormResize: SplitModeResize +[16:04.11.930] TFormXterm.FormResize: BtnSplitNo.Down +[16:04.11.930] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:04.11.930] BEGIN ResizeTerminal +[16:04.11.931] END ResizeTerminal +[16:04.11.931] TFormXterm.FormResize: AdaptSidebarArrows; +[16:04.11.931] BEGIN AdaptSidebarArrows +[16:04.11.931] END AdaptSidebarArrows +[16:04.11.931] TFormXterm.FormResize: AdaptTV2; +[16:04.11.931] END TFormXterm.FormResize + +[16:04.12.466] BEGIN CWD +[16:04.12.527] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:04.12.527] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:04.12.527] (SSH-Browser) END VerifySFTPConnection(1) +[16:04.12.527] END CWD +[16:04.12.543] BEGIN CWD +[16:04.12.604] END CWD + +[16:04.13.076] BEGIN WMNewTab: 20 +[16:04.13.076] END WMNewTab: 20 + + +[16:04.14.489] BEGIN WMNewTab: 20 +[16:04.14.489] END WMNewTab: 20 + + +[16:04.15.902] BEGIN WMNewTab: 20 +[16:04.15.902] END WMNewTab: 20 + + +[16:04.17.314] BEGIN WMNewTab: 20 +[16:04.17.314] END WMNewTab: 20 + + +[16:04.18.728] BEGIN WMNewTab: 20 +[16:04.18.728] END WMNewTab: 20 + + +[16:04.20.143] BEGIN WMNewTab: 20 +[16:04.20.143] END WMNewTab: 20 + + +[16:04.21.556] BEGIN WMNewTab: 20 +[16:04.21.556] END WMNewTab: 20 + + +[16:04.22.965] BEGIN WMNewTab: 20 +[16:04.22.965] END WMNewTab: 20 + + +[16:04.24.375] BEGIN WMNewTab: 20 +[16:04.24.375] END WMNewTab: 20 + + +[16:04.25.792] BEGIN WMNewTab: 20 +[16:04.25.792] END WMNewTab: 20 + + +[16:04.27.144] BEGIN WMNewTab: 0 +[16:04.27.144] WMNewTab: FormClick +[16:04.27.144] WMNewTab: LooseFocus +[16:04.27.144] END WMNewTab: 0 +[16:04.27.144] BEGIN WMNewTab: 31 +[16:04.27.144] END WMNewTab: 31 +[16:04.27.202] BEGIN WMNewTab: 20 +[16:04.27.202] END WMNewTab: 20 +[16:04.27.238] BEGIN WMNewTab: 0 +[16:04.27.238] WMNewTab: FormClick +[16:04.27.238] WMNewTab: LooseFocus +[16:04.27.238] END WMNewTab: 0 + +[16:04.27.915] BEGIN CWD +[16:04.27.975] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:04.27.975] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:04.27.975] (SSH-Browser) END VerifySFTPConnection(1) +[16:04.27.975] END CWD +[16:04.27.990] BEGIN CWD +[16:04.28.051] END CWD + +[16:04.28.520] BEGIN WMNewTab: 20 +[16:04.28.520] END WMNewTab: 20 + + +[16:04.29.937] BEGIN WMNewTab: 20 +[16:04.29.937] END WMNewTab: 20 + + +[16:04.31.349] BEGIN WMNewTab: 20 +[16:04.31.349] END WMNewTab: 20 + +[16:04.32.157] BEGIN WMNewTab: 0 +[16:04.32.157] WMNewTab: FormClick +[16:04.32.157] WMNewTab: LooseFocus +[16:04.32.158] END WMNewTab: 0 +[16:04.32.158] BEGIN WMNewTab: 31 +[16:04.32.158] END WMNewTab: 31 +[16:04.32.262] BEGIN WMNewTab: 0 +[16:04.32.262] WMNewTab: FormClick +[16:04.32.262] WMNewTab: LooseFocus +[16:04.32.262] END WMNewTab: 0 + +[16:04.32.763] BEGIN WMNewTab: 20 +[16:04.32.763] END WMNewTab: 20 +[16:04.32.954] BEGIN CWD +[16:04.33.015] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:04.33.015] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:04.33.015] (SSH-Browser) END VerifySFTPConnection(1) +[16:04.33.015] END CWD +[16:04.33.020] BEGIN CWD +[16:04.33.080] END CWD + +[16:04.34.023] BEGIN WMNewTab: 20 +[16:04.34.023] END WMNewTab: 20 + + +[16:04.35.436] BEGIN WMNewTab: 20 +[16:04.35.436] END WMNewTab: 20 + + +[16:04.36.845] BEGIN WMNewTab: 20 +[16:04.36.845] END WMNewTab: 20 +[16:04.37.198] BEGIN WMNewTab: 0 +[16:04.37.198] WMNewTab: FormClick +[16:04.37.198] WMNewTab: LooseFocus +[16:04.37.198] END WMNewTab: 0 +[16:04.37.198] BEGIN WMNewTab: 31 +[16:04.37.198] END WMNewTab: 31 +[16:04.37.277] BEGIN WMNewTab: 0 +[16:04.37.277] WMNewTab: FormClick +[16:04.37.277] WMNewTab: LooseFocus +[16:04.37.278] END WMNewTab: 0 + +[16:04.37.921] BEGIN CWD +[16:04.37.982] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:04.37.982] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:04.37.982] (SSH-Browser) END VerifySFTPConnection(1) +[16:04.37.982] END CWD +[16:04.37.997] BEGIN CWD +[16:04.38.057] END CWD +[16:04.38.057] BEGIN WMNewTab: 20 +[16:04.38.057] END WMNewTab: 20 + + +[16:04.39.467] BEGIN WMNewTab: 20 +[16:04.39.467] END WMNewTab: 20 + + +[16:04.40.879] BEGIN WMNewTab: 20 +[16:04.40.879] END WMNewTab: 20 + + +[16:04.42.288] BEGIN WMNewTab: 20 +[16:04.42.288] END WMNewTab: 20 + +[16:04.42.918] BEGIN WMNewTab: 0 +[16:04.42.918] WMNewTab: FormClick +[16:04.42.918] WMNewTab: LooseFocus +[16:04.42.919] END WMNewTab: 0 +[16:04.42.919] BEGIN WMNewTab: 31 +[16:04.42.919] END WMNewTab: 31 +[16:04.42.989] BEGIN WMNewTab: 0 +[16:04.42.989] WMNewTab: FormClick +[16:04.42.989] WMNewTab: LooseFocus +[16:04.42.990] END WMNewTab: 0 + +[16:04.43.570] BEGIN CWD +[16:04.43.630] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:04.43.630] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:04.43.630] (SSH-Browser) END VerifySFTPConnection(1) +[16:04.43.630] END CWD +[16:04.43.693] BEGIN WMNewTab: 20 +[16:04.43.693] END WMNewTab: 20 +[16:04.43.723] BEGIN CWD +[16:04.43.784] END CWD + + +[16:04.45.193] BEGIN WMNewTab: 20 +[16:04.45.193] END WMNewTab: 20 + + +[16:04.46.607] BEGIN WMNewTab: 20 +[16:04.46.607] END WMNewTab: 20 + +[16:04.47.751] BEGIN WMNewTab: 0 +[16:04.47.751] WMNewTab: FormClick +[16:04.47.751] WMNewTab: LooseFocus +[16:04.47.751] END WMNewTab: 0 +[16:04.47.751] BEGIN WMNewTab: 31 +[16:04.47.751] END WMNewTab: 31 +[16:04.47.837] BEGIN WMNewTab: 0 +[16:04.47.837] WMNewTab: FormClick +[16:04.47.837] WMNewTab: LooseFocus +[16:04.47.838] END WMNewTab: 0 +[16:04.48.019] BEGIN WMNewTab: 20 +[16:04.48.019] END WMNewTab: 20 + +[16:04.48.460] BEGIN CWD +[16:04.48.521] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:04.48.521] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:04.48.521] (SSH-Browser) END VerifySFTPConnection(1) +[16:04.48.521] END CWD +[16:04.48.537] BEGIN CWD +[16:04.48.622] END CWD + +[16:04.49.556] BEGIN WMNewTab: 20 +[16:04.49.556] END WMNewTab: 20 + + +[16:04.50.968] BEGIN WMNewTab: 20 +[16:04.50.968] END WMNewTab: 20 + + +[16:04.52.380] BEGIN WMNewTab: 20 +[16:04.52.380] END WMNewTab: 20 +[16:04.52.599] BEGIN WMNewTab: 31 +[16:04.52.599] END WMNewTab: 31 +[16:04.52.599] BEGIN WMNewTab: 0 +[16:04.52.599] WMNewTab: FormClick +[16:04.52.599] WMNewTab: LooseFocus +[16:04.52.600] END WMNewTab: 0 +[16:04.52.711] BEGIN WMNewTab: 0 +[16:04.52.711] WMNewTab: FormClick +[16:04.52.711] WMNewTab: LooseFocus +[16:04.52.711] END WMNewTab: 0 + +[16:04.53.216] BEGIN CWD +[16:04.53.276] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:04.53.276] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:04.53.276] (SSH-Browser) END VerifySFTPConnection(1) +[16:04.53.276] END CWD +[16:04.53.355] BEGIN CWD +[16:04.53.440] END CWD + +[16:04.53.899] BEGIN WMNewTab: 20 +[16:04.53.899] END WMNewTab: 20 + + +[16:04.55.312] BEGIN WMNewTab: 20 +[16:04.55.312] END WMNewTab: 20 + + +[16:04.56.723] BEGIN WMNewTab: 20 +[16:04.56.723] END WMNewTab: 20 + +[16:04.57.478] BEGIN WMNewTab: 0 +[16:04.57.478] WMNewTab: FormClick +[16:04.57.478] WMNewTab: LooseFocus +[16:04.57.478] END WMNewTab: 0 +[16:04.57.479] BEGIN WMNewTab: 31 +[16:04.57.479] END WMNewTab: 31 +[16:04.57.585] BEGIN WMNewTab: 0 +[16:04.57.585] WMNewTab: FormClick +[16:04.57.585] WMNewTab: LooseFocus +[16:04.57.585] END WMNewTab: 0 + +[16:04.58.132] BEGIN CWD +[16:04.58.135] BEGIN WMNewTab: 20 +[16:04.58.135] END WMNewTab: 20 +[16:04.58.192] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:04.58.192] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:04.58.192] (SSH-Browser) END VerifySFTPConnection(1) +[16:04.58.192] END CWD +[16:04.58.211] BEGIN CWD +[16:04.58.272] END CWD + + +[16:04.59.676] BEGIN WMNewTab: 20 +[16:04.59.676] END WMNewTab: 20 + + +[16:05.01.090] BEGIN WMNewTab: 20 +[16:05.01.090] END WMNewTab: 20 + +[16:05.01.727] BEGIN WMNewTab: 0 +[16:05.01.728] WMNewTab: FormClick +[16:05.01.728] WMNewTab: LooseFocus +[16:05.01.728] END WMNewTab: 0 +[16:05.01.728] BEGIN WMNewTab: 31 +[16:05.01.728] END WMNewTab: 31 +[16:05.01.798] BEGIN WMNewTab: 0 +[16:05.01.798] WMNewTab: FormClick +[16:05.01.798] WMNewTab: LooseFocus +[16:05.01.798] END WMNewTab: 0 + +[16:05.02.378] BEGIN CWD +[16:05.02.439] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:05.02.439] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:05.02.439] (SSH-Browser) END VerifySFTPConnection(1) +[16:05.02.439] END CWD +[16:05.02.500] BEGIN WMNewTab: 20 +[16:05.02.500] END WMNewTab: 20 +[16:05.02.530] BEGIN CWD +[16:05.02.591] END CWD + + +[16:05.04.004] BEGIN WMNewTab: 20 +[16:05.04.004] END WMNewTab: 20 + + +[16:05.05.414] BEGIN WMNewTab: 20 +[16:05.05.414] END WMNewTab: 20 + + +[16:05.06.830] BEGIN WMNewTab: 20 +[16:05.06.830] END WMNewTab: 20 + + +[16:05.08.237] BEGIN WMNewTab: 20 +[16:05.08.237] END WMNewTab: 20 + + +[16:05.09.651] BEGIN WMNewTab: 20 +[16:05.09.651] END WMNewTab: 20 + + +[16:05.11.066] BEGIN WMNewTab: 20 +[16:05.11.066] END WMNewTab: 20 + +[16:05.11.831] BEGIN WMNewTab: 0 +[16:05.11.831] WMNewTab: FormClick +[16:05.11.831] WMNewTab: LooseFocus +[16:05.11.832] END WMNewTab: 0 + +[16:05.12.255] BEGIN WMNewTab: 0 +[16:05.12.255] WMNewTab: FormClick +[16:05.12.255] WMNewTab: LooseFocus +[16:05.12.259] END WMNewTab: 0 +[16:05.12.359] BEGIN WMNewTab: 0 +[16:05.12.359] WMNewTab: FormClick +[16:05.12.359] WMNewTab: LooseFocus +[16:05.12.359] END WMNewTab: 0 +[16:05.12.470] BEGIN WMNewTab: 20 +[16:05.12.470] END WMNewTab: 20 +[16:05.12.486] BEGIN WMNewTab: 0 +[16:05.12.486] WMNewTab: FormClick +[16:05.12.486] WMNewTab: LooseFocus +[16:05.12.487] END WMNewTab: 0 + +[16:05.13.351] BEGIN WMNewTab: 0 +[16:05.13.351] WMNewTab: FormClick +[16:05.13.351] WMNewTab: LooseFocus +[16:05.13.351] END WMNewTab: 0 + +[16:05.13.880] BEGIN WMNewTab: 20 +[16:05.13.880] END WMNewTab: 20 + +[16:05.14.951] BEGIN WMNewTab: 0 +[16:05.14.951] WMNewTab: FormClick +[16:05.14.951] WMNewTab: LooseFocus +[16:05.14.953] END WMNewTab: 0 +[16:05.15.286] BEGIN WMNewTab: 20 +[16:05.15.286] END WMNewTab: 20 + + +[16:05.16.693] BEGIN WMNewTab: 20 +[16:05.16.693] END WMNewTab: 20 + + +[16:05.18.105] BEGIN WMNewTab: 20 +[16:05.18.105] END WMNewTab: 20 + + +[16:05.19.517] BEGIN WMNewTab: 20 +[16:05.19.517] END WMNewTab: 20 + + +[16:05.20.932] BEGIN WMNewTab: 20 +[16:05.20.932] END WMNewTab: 20 + + +[16:05.22.343] BEGIN WMNewTab: 20 +[16:05.22.343] END WMNewTab: 20 + + +[16:05.23.752] BEGIN WMNewTab: 20 +[16:05.23.752] END WMNewTab: 20 + + +[16:05.25.160] BEGIN WMNewTab: 20 +[16:05.25.160] END WMNewTab: 20 + + +[16:05.26.571] BEGIN WMNewTab: 20 +[16:05.26.571] END WMNewTab: 20 + + +[16:05.27.988] BEGIN WMNewTab: 20 +[16:05.27.988] END WMNewTab: 20 + + +[16:05.29.400] BEGIN WMNewTab: 20 +[16:05.29.400] END WMNewTab: 20 + + +[16:05.30.808] BEGIN WMNewTab: 20 +[16:05.30.808] END WMNewTab: 20 + + +[16:05.32.218] BEGIN WMNewTab: 20 +[16:05.32.218] END WMNewTab: 20 + + +[16:05.33.628] BEGIN WMNewTab: 20 +[16:05.33.628] END WMNewTab: 20 + + +[16:05.35.037] BEGIN WMNewTab: 20 +[16:05.35.037] END WMNewTab: 20 + + +[16:05.36.450] BEGIN WMNewTab: 20 +[16:05.36.450] END WMNewTab: 20 + +[16:05.37.448] Cts1MouseDown: FormClick +[16:05.37.453] Cts1ActiveTabChanged: New index = 2 +[16:05.37.453] BEGIN DisplayCurrentTab +[16:05.37.453] DisplayCurrentTab: FormClick +[16:05.37.453] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:05.37.453] (SSH-Browser) BEGIN ActiverPanel14 +[16:05.37.453] (SSH-Browser) BEGIN DesactiverPanel14 +[16:05.37.466] (SSH-Browser) END DesactiverPanel14 +[16:05.37.466] (SSH-Browser) END ActiverPanel14; +[16:05.37.574] BEGIN TFormXterm.FormResize +[16:05.37.574] TFormXterm.FormResize: CenterBtnReattachTab +[16:05.37.574] TFormXterm.FormResize: SplitModeResize +[16:05.37.574] TFormXterm.FormResize: BtnSplitNo.Down +[16:05.37.575] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:05.37.575] BEGIN ResizeTerminal +[16:05.37.579] END ResizeTerminal +[16:05.37.579] TFormXterm.FormResize: AdaptSidebarArrows; +[16:05.37.579] BEGIN AdaptSidebarArrows +[16:05.37.579] END AdaptSidebarArrows +[16:05.37.579] TFormXterm.FormResize: AdaptTV2; +[16:05.37.579] END TFormXterm.FormResize +[16:05.37.579] DisplayCurrentTab: Cts1.BeginUpdate; +[16:05.37.579] DisplayCurrentTab: Cts1.EndUpdates +[16:05.37.594] DisplayCurrentTab: 显示所选标签页 +[16:05.37.596] DisplayCurrentTab: 隐藏其他标签页 +[16:05.37.608] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:05.37.611] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:05.37.611] DisplayCurrentTab: DistribuerLeFocus +[16:05.37.611] END DisplayCurrentTab +[16:05.37.856] BEGIN WMNewTab: 20 +[16:05.37.856] END WMNewTab: 20 +[16:05.38.020] BEGIN WMNewTab: 0 +[16:05.38.020] WMNewTab: FormClick +[16:05.38.020] WMNewTab: LooseFocus +[16:05.38.020] END WMNewTab: 0 +[16:05.38.020] BEGIN WMNewTab: 31 +[16:05.38.020] END WMNewTab: 31 + +[16:05.39.194] BEGIN WMNewTab: 0 +[16:05.39.194] WMNewTab: FormClick +[16:05.39.194] WMNewTab: LooseFocus +[16:05.39.194] END WMNewTab: 0 +[16:05.39.194] BEGIN WMNewTab: 31 +[16:05.39.194] END WMNewTab: 31 +[16:05.39.266] BEGIN WMNewTab: 20 +[16:05.39.266] END WMNewTab: 20 + + +[16:05.40.676] BEGIN WMNewTab: 20 +[16:05.40.676] END WMNewTab: 20 + + +[16:05.42.082] BEGIN WMNewTab: 20 +[16:05.42.082] END WMNewTab: 20 + + +[16:05.43.490] BEGIN WMNewTab: 20 +[16:05.43.490] END WMNewTab: 20 + + +[16:05.44.898] BEGIN WMNewTab: 20 +[16:05.44.898] END WMNewTab: 20 + + +[16:05.46.305] BEGIN WMNewTab: 20 +[16:05.46.305] END WMNewTab: 20 + + +[16:05.47.718] BEGIN WMNewTab: 20 +[16:05.47.718] END WMNewTab: 20 + + +[16:05.49.129] BEGIN WMNewTab: 20 +[16:05.49.129] END WMNewTab: 20 + + +[16:05.50.541] BEGIN WMNewTab: 20 +[16:05.50.541] END WMNewTab: 20 + + +[16:05.51.948] BEGIN WMNewTab: 20 +[16:05.51.948] END WMNewTab: 20 + + +[16:05.53.356] BEGIN WMNewTab: 20 +[16:05.53.356] END WMNewTab: 20 + + +[16:05.54.636] BEGIN WMNewTab: 0 +[16:05.54.636] WMNewTab: FormClick +[16:05.54.636] WMNewTab: LooseFocus +[16:05.54.636] END WMNewTab: 0 +[16:05.54.636] BEGIN WMNewTab: 31 +[16:05.54.636] END WMNewTab: 31 +[16:05.54.767] BEGIN WMNewTab: 20 +[16:05.54.767] END WMNewTab: 20 + + +[16:05.56.175] BEGIN WMNewTab: 20 +[16:05.56.175] END WMNewTab: 20 + + +[16:05.57.587] BEGIN WMNewTab: 20 +[16:05.57.587] END WMNewTab: 20 + + +[16:05.59.000] BEGIN WMNewTab: 20 +[16:05.59.000] END WMNewTab: 20 + + +[16:06.00.409] BEGIN WMNewTab: 20 +[16:06.00.409] END WMNewTab: 20 + + +[16:06.01.816] BEGIN WMNewTab: 20 +[16:06.01.816] END WMNewTab: 20 + + +[16:06.03.228] BEGIN WMNewTab: 20 +[16:06.03.228] END WMNewTab: 20 + + +[16:06.04.635] BEGIN WMNewTab: 20 +[16:06.04.635] END WMNewTab: 20 + + +[16:06.06.052] BEGIN WMNewTab: 20 +[16:06.06.052] END WMNewTab: 20 + + +[16:06.07.467] BEGIN WMNewTab: 20 +[16:06.07.467] END WMNewTab: 20 + +[16:06.08.081] BEGIN WMNewTab: 0 +[16:06.08.081] WMNewTab: FormClick +[16:06.08.081] WMNewTab: LooseFocus +[16:06.08.081] END WMNewTab: 0 +[16:06.08.204] BEGIN WMNewTab: 0 +[16:06.08.204] WMNewTab: FormClick +[16:06.08.204] WMNewTab: LooseFocus +[16:06.08.204] END WMNewTab: 0 + +[16:06.08.885] BEGIN WMNewTab: 20 +[16:06.08.885] END WMNewTab: 20 +[16:06.09.034] BEGIN WMNewTab: 0 +[16:06.09.034] WMNewTab: FormClick +[16:06.09.034] WMNewTab: LooseFocus +[16:06.09.034] END WMNewTab: 0 +[16:06.09.254] BEGIN WMNewTab: 0 +[16:06.09.254] WMNewTab: FormClick +[16:06.09.254] WMNewTab: LooseFocus +[16:06.09.255] END WMNewTab: 0 + +[16:06.10.296] BEGIN WMNewTab: 20 +[16:06.10.296] END WMNewTab: 20 + + +[16:06.11.722] BEGIN WMNewTab: 20 +[16:06.11.722] END WMNewTab: 20 + + +[16:06.13.122] BEGIN WMNewTab: 20 +[16:06.13.122] END WMNewTab: 20 + + +[16:06.14.538] BEGIN WMNewTab: 20 +[16:06.14.538] END WMNewTab: 20 + + +[16:06.15.949] BEGIN WMNewTab: 20 +[16:06.15.949] END WMNewTab: 20 + + +[16:06.17.358] BEGIN WMNewTab: 20 +[16:06.17.358] END WMNewTab: 20 + + +[16:06.18.600] BEGIN WMNewTab: 0 +[16:06.18.600] WMNewTab: FormClick +[16:06.18.600] WMNewTab: LooseFocus +[16:06.18.601] END WMNewTab: 0 +[16:06.18.601] BEGIN WMNewTab: 31 +[16:06.18.601] END WMNewTab: 31 +[16:06.18.768] BEGIN WMNewTab: 20 +[16:06.18.768] END WMNewTab: 20 + + +[16:06.20.179] BEGIN WMNewTab: 20 +[16:06.20.179] END WMNewTab: 20 + + +[16:06.21.598] BEGIN WMNewTab: 20 +[16:06.21.598] END WMNewTab: 20 + + +[16:06.23.011] BEGIN WMNewTab: 20 +[16:06.23.011] END WMNewTab: 20 + + +[16:06.24.429] BEGIN WMNewTab: 20 +[16:06.24.429] END WMNewTab: 20 + + +[16:06.25.841] BEGIN WMNewTab: 20 +[16:06.25.841] END WMNewTab: 20 + + +[16:06.27.253] BEGIN WMNewTab: 20 +[16:06.27.253] END WMNewTab: 20 + + +[16:06.28.665] BEGIN WMNewTab: 20 +[16:06.28.665] END WMNewTab: 20 +[16:06.28.680] BEGIN WMNewTab: 60 +[16:06.28.690] END WMNewTab: 60 + + +[16:06.30.080] BEGIN WMNewTab: 20 +[16:06.30.080] END WMNewTab: 20 + + +[16:06.31.497] BEGIN WMNewTab: 20 +[16:06.31.497] END WMNewTab: 20 + +[16:06.32.057] BEGIN WMNewTab: 0 +[16:06.32.057] WMNewTab: FormClick +[16:06.32.057] WMNewTab: LooseFocus +[16:06.32.057] END WMNewTab: 0 +[16:06.32.057] BEGIN WMNewTab: 31 +[16:06.32.057] END WMNewTab: 31 + +[16:06.32.910] BEGIN WMNewTab: 20 +[16:06.32.910] END WMNewTab: 20 + + +[16:06.34.333] BEGIN WMNewTab: 20 +[16:06.34.333] END WMNewTab: 20 + + +[16:06.35.753] BEGIN WMNewTab: 20 +[16:06.35.753] END WMNewTab: 20 + + +[16:06.37.169] BEGIN WMNewTab: 20 +[16:06.37.169] END WMNewTab: 20 + + +[16:06.38.588] BEGIN WMNewTab: 20 +[16:06.38.588] END WMNewTab: 20 + + +[16:06.39.998] BEGIN WMNewTab: 20 +[16:06.39.998] END WMNewTab: 20 + + +[16:06.41.412] BEGIN WMNewTab: 20 +[16:06.41.412] END WMNewTab: 20 + + +[16:06.42.830] BEGIN WMNewTab: 20 +[16:06.42.830] END WMNewTab: 20 + + +[16:06.44.241] BEGIN WMNewTab: 20 +[16:06.44.241] END WMNewTab: 20 + + +[16:06.45.653] BEGIN WMNewTab: 20 +[16:06.45.653] END WMNewTab: 20 + + +[16:06.47.066] BEGIN WMNewTab: 20 +[16:06.47.066] END WMNewTab: 20 + + +[16:06.48.483] BEGIN WMNewTab: 20 +[16:06.48.483] END WMNewTab: 20 + + +[16:06.49.893] BEGIN WMNewTab: 20 +[16:06.49.893] END WMNewTab: 20 + +[16:06.50.535] BEGIN WMNewTab: 0 +[16:06.50.535] WMNewTab: FormClick +[16:06.50.535] WMNewTab: LooseFocus +[16:06.50.535] END WMNewTab: 0 +[16:06.50.535] BEGIN WMNewTab: 31 +[16:06.50.535] END WMNewTab: 31 + +[16:06.51.310] BEGIN WMNewTab: 20 +[16:06.51.310] END WMNewTab: 20 + + +[16:06.52.725] BEGIN WMNewTab: 20 +[16:06.52.725] END WMNewTab: 20 + + +[16:06.54.141] BEGIN WMNewTab: 20 +[16:06.54.141] END WMNewTab: 20 + + +[16:06.55.558] BEGIN WMNewTab: 20 +[16:06.55.558] END WMNewTab: 20 + +[16:06.56.575] BEGIN WMNewTab: 0 +[16:06.56.575] WMNewTab: FormClick +[16:06.56.575] WMNewTab: LooseFocus +[16:06.56.575] END WMNewTab: 0 +[16:06.56.575] BEGIN WMNewTab: 31 +[16:06.56.575] END WMNewTab: 31 + +[16:06.56.968] BEGIN WMNewTab: 20 +[16:06.56.968] END WMNewTab: 20 + + +[16:06.58.385] BEGIN WMNewTab: 20 +[16:06.58.385] END WMNewTab: 20 + + +[16:06.59.800] BEGIN WMNewTab: 20 +[16:06.59.800] END WMNewTab: 20 + + +[16:07.01.222] BEGIN WMNewTab: 20 +[16:07.01.222] END WMNewTab: 20 + + +[16:07.02.643] BEGIN WMNewTab: 20 +[16:07.02.643] END WMNewTab: 20 + + +[16:07.04.061] BEGIN WMNewTab: 20 +[16:07.04.061] END WMNewTab: 20 + +[16:07.05.198] Cts1MouseDown: FormClick +[16:07.05.203] Cts1ActiveTabChanged: New index = 1 +[16:07.05.203] BEGIN DisplayCurrentTab +[16:07.05.203] DisplayCurrentTab: FormClick +[16:07.05.203] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:07.05.203] (SSH-Browser) BEGIN ActiverPanel14 +[16:07.05.203] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:07.05.206] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:07.05.206] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:07.05.206] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:07.05.206] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:07.05.230] (SSH-Browser) END ActiverPanel14; +[16:07.05.250] BEGIN TFormXterm.FormResize +[16:07.05.250] TFormXterm.FormResize: CenterBtnReattachTab +[16:07.05.250] TFormXterm.FormResize: SplitModeResize +[16:07.05.250] TFormXterm.FormResize: BtnSplitNo.Down +[16:07.05.252] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:07.05.252] BEGIN ResizeTerminal +[16:07.05.254] END ResizeTerminal +[16:07.05.254] TFormXterm.FormResize: AdaptSidebarArrows; +[16:07.05.254] BEGIN AdaptSidebarArrows +[16:07.05.254] END AdaptSidebarArrows +[16:07.05.254] TFormXterm.FormResize: AdaptTV2; +[16:07.05.254] END TFormXterm.FormResize +[16:07.05.254] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:07.05.254] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:07.05.255] BEGIN WMNewTab: 62 +[16:07.05.255] END WMNewTab: 62 +[16:07.05.271] ShellExecuteS: ShellExecuteEx 成功. +[16:07.05.271] ShellExecuteS: WaitForInputIdle 失败. +[16:07.05.271] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:07.05.271] DisplayCurrentTab: Cts1.BeginUpdate; +[16:07.05.271] DisplayCurrentTab: Cts1.EndUpdates +[16:07.05.285] DisplayCurrentTab: 显示所选标签页 +[16:07.05.287] DisplayCurrentTab: 隐藏其他标签页 +[16:07.05.291] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:07.05.299] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:07.05.299] DisplayCurrentTab: DistribuerLeFocus +[16:07.05.299] END DisplayCurrentTab +[16:07.05.328] [MobaSCP2] Launching remote monitoring in normal mode +[16:07.05.328] [MobaSCP2] Multiplex=1 +[16:07.05.328] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:07.05.329] [MobaSCP2] USERNAME: root +[16:07.05.367] [MobaSCP2] Using SCP1 +[16:07.05.368] [MobaSCP2] Connected to 192.168.127.10 +[16:07.05.472] BEGIN WMNewTab: 20 +[16:07.05.472] END WMNewTab: 20 + +[16:07.06.232] BEGIN WMNewTab: 0 +[16:07.06.232] WMNewTab: FormClick +[16:07.06.232] WMNewTab: LooseFocus +[16:07.06.232] END WMNewTab: 0 +[16:07.06.327] BEGIN WMNewTab: 0 +[16:07.06.327] WMNewTab: FormClick +[16:07.06.327] WMNewTab: LooseFocus +[16:07.06.329] END WMNewTab: 0 +[16:07.06.482] BEGIN TFormXterm.FormResize +[16:07.06.482] TFormXterm.FormResize: CenterBtnReattachTab +[16:07.06.482] TFormXterm.FormResize: SplitModeResize +[16:07.06.482] TFormXterm.FormResize: BtnSplitNo.Down +[16:07.06.482] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:07.06.482] BEGIN ResizeTerminal +[16:07.06.482] END ResizeTerminal +[16:07.06.482] TFormXterm.FormResize: AdaptSidebarArrows; +[16:07.06.483] BEGIN AdaptSidebarArrows +[16:07.06.483] END AdaptSidebarArrows +[16:07.06.483] TFormXterm.FormResize: AdaptTV2; +[16:07.06.483] END TFormXterm.FormResize + +[16:07.06.884] BEGIN WMNewTab: 20 +[16:07.06.884] END WMNewTab: 20 + + +[16:07.08.299] BEGIN WMNewTab: 20 +[16:07.08.299] END WMNewTab: 20 +[16:07.08.606] BEGIN WMNewTab: 0 +[16:07.08.606] WMNewTab: FormClick +[16:07.08.606] WMNewTab: LooseFocus +[16:07.08.608] END WMNewTab: 0 +[16:07.08.735] BEGIN WMNewTab: 0 +[16:07.08.735] WMNewTab: FormClick +[16:07.08.735] WMNewTab: LooseFocus +[16:07.08.736] END WMNewTab: 0 + +[16:07.09.715] BEGIN WMNewTab: 20 +[16:07.09.715] END WMNewTab: 20 + + +[16:07.11.136] BEGIN WMNewTab: 20 +[16:07.11.136] END WMNewTab: 20 + + +[16:07.12.554] BEGIN WMNewTab: 20 +[16:07.12.554] END WMNewTab: 20 + +[16:07.13.013] BEGIN CWD +[16:07.13.073] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:07.13.073] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:07.13.073] (SSH-Browser) END VerifySFTPConnection(1) +[16:07.13.073] END CWD +[16:07.13.086] BEGIN CWD +[16:07.13.147] END CWD + +[16:07.14.088] BEGIN WMNewTab: 20 +[16:07.14.088] END WMNewTab: 20 +[16:07.14.287] BEGIN CWD +[16:07.14.347] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:07.14.347] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:07.14.347] (SSH-Browser) END VerifySFTPConnection(1) +[16:07.14.347] END CWD +[16:07.14.362] BEGIN CWD +[16:07.14.422] END CWD + +[16:07.15.367] BEGIN WMNewTab: 20 +[16:07.15.367] END WMNewTab: 20 +[16:07.15.623] Cts1MouseDown: FormClick +[16:07.15.627] Cts1ActiveTabChanged: New index = 2 +[16:07.15.627] BEGIN DisplayCurrentTab +[16:07.15.627] DisplayCurrentTab: FormClick +[16:07.15.627] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:07.15.627] (SSH-Browser) BEGIN ActiverPanel14 +[16:07.15.627] (SSH-Browser) BEGIN DesactiverPanel14 +[16:07.15.640] (SSH-Browser) END DesactiverPanel14 +[16:07.15.640] (SSH-Browser) END ActiverPanel14; +[16:07.15.745] BEGIN TFormXterm.FormResize +[16:07.15.745] TFormXterm.FormResize: CenterBtnReattachTab +[16:07.15.750] TFormXterm.FormResize: SplitModeResize +[16:07.15.750] TFormXterm.FormResize: BtnSplitNo.Down +[16:07.15.751] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:07.15.751] BEGIN ResizeTerminal +[16:07.15.754] END ResizeTerminal +[16:07.15.754] TFormXterm.FormResize: AdaptSidebarArrows; +[16:07.15.754] BEGIN AdaptSidebarArrows +[16:07.15.754] END AdaptSidebarArrows +[16:07.15.754] TFormXterm.FormResize: AdaptTV2; +[16:07.15.754] END TFormXterm.FormResize +[16:07.15.754] DisplayCurrentTab: Cts1.BeginUpdate; +[16:07.15.754] DisplayCurrentTab: Cts1.EndUpdates +[16:07.15.768] DisplayCurrentTab: 显示所选标签页 +[16:07.15.770] DisplayCurrentTab: 隐藏其他标签页 +[16:07.15.780] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:07.15.783] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:07.15.783] DisplayCurrentTab: DistribuerLeFocus +[16:07.15.783] END DisplayCurrentTab + +[16:07.16.783] BEGIN WMNewTab: 20 +[16:07.16.783] END WMNewTab: 20 + + +[16:07.18.200] BEGIN WMNewTab: 20 +[16:07.18.200] END WMNewTab: 20 + + +[16:07.19.616] BEGIN WMNewTab: 20 +[16:07.19.616] END WMNewTab: 20 + + +[16:07.21.029] BEGIN WMNewTab: 20 +[16:07.21.029] END WMNewTab: 20 + + +[16:07.22.443] BEGIN WMNewTab: 20 +[16:07.22.443] END WMNewTab: 20 + + +[16:07.23.857] BEGIN WMNewTab: 20 +[16:07.23.857] END WMNewTab: 20 + + +[16:07.25.269] BEGIN WMNewTab: 20 +[16:07.25.269] END WMNewTab: 20 + + +[16:07.26.680] BEGIN WMNewTab: 20 +[16:07.26.680] END WMNewTab: 20 + + +[16:07.28.092] BEGIN WMNewTab: 20 +[16:07.28.092] END WMNewTab: 20 + + +[16:07.29.507] BEGIN WMNewTab: 20 +[16:07.29.507] END WMNewTab: 20 + + +[16:07.30.919] BEGIN WMNewTab: 20 +[16:07.30.919] END WMNewTab: 20 + + +[16:07.32.337] BEGIN WMNewTab: 20 +[16:07.32.337] END WMNewTab: 20 + +[16:07.33.383] Cts1MouseDown: FormClick +[16:07.33.388] Cts1ActiveTabChanged: New index = 1 +[16:07.33.388] BEGIN DisplayCurrentTab +[16:07.33.388] DisplayCurrentTab: FormClick +[16:07.33.388] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:07.33.388] (SSH-Browser) BEGIN ActiverPanel14 +[16:07.33.388] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:07.33.392] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:07.33.392] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:07.33.392] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:07.33.393] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:07.33.420] (SSH-Browser) END ActiverPanel14; +[16:07.33.440] BEGIN TFormXterm.FormResize +[16:07.33.440] TFormXterm.FormResize: CenterBtnReattachTab +[16:07.33.441] TFormXterm.FormResize: SplitModeResize +[16:07.33.441] TFormXterm.FormResize: BtnSplitNo.Down +[16:07.33.441] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:07.33.441] BEGIN ResizeTerminal +[16:07.33.446] END ResizeTerminal +[16:07.33.446] TFormXterm.FormResize: AdaptSidebarArrows; +[16:07.33.446] BEGIN AdaptSidebarArrows +[16:07.33.446] END AdaptSidebarArrows +[16:07.33.446] TFormXterm.FormResize: AdaptTV2; +[16:07.33.446] END TFormXterm.FormResize +[16:07.33.446] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:07.33.446] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:07.33.457] ShellExecuteS: ShellExecuteEx 成功. +[16:07.33.457] ShellExecuteS: WaitForInputIdle 失败. +[16:07.33.457] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:07.33.457] DisplayCurrentTab: Cts1.BeginUpdate; +[16:07.33.457] DisplayCurrentTab: Cts1.EndUpdates +[16:07.33.475] DisplayCurrentTab: 显示所选标签页 +[16:07.33.477] DisplayCurrentTab: 隐藏其他标签页 +[16:07.33.497] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:07.33.501] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:07.33.501] DisplayCurrentTab: DistribuerLeFocus +[16:07.33.501] END DisplayCurrentTab +[16:07.33.517] [MobaSCP2] Launching remote monitoring in normal mode +[16:07.33.518] [MobaSCP2] Multiplex=1 +[16:07.33.518] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:07.33.521] [MobaSCP2] USERNAME: root +[16:07.33.563] [MobaSCP2] Using SCP1 +[16:07.33.564] [MobaSCP2] Connected to 192.168.127.10 +[16:07.33.744] BEGIN WMNewTab: 20 +[16:07.33.744] END WMNewTab: 20 +[16:07.33.848] BEGIN WMNewTab: 0 +[16:07.33.848] WMNewTab: FormClick +[16:07.33.848] WMNewTab: LooseFocus +[16:07.33.848] END WMNewTab: 0 +[16:07.33.951] BEGIN WMNewTab: 0 +[16:07.33.952] WMNewTab: FormClick +[16:07.33.952] WMNewTab: LooseFocus +[16:07.33.952] END WMNewTab: 0 + +[16:07.34.678] BEGIN TFormXterm.FormResize +[16:07.34.678] TFormXterm.FormResize: CenterBtnReattachTab +[16:07.34.678] TFormXterm.FormResize: SplitModeResize +[16:07.34.678] TFormXterm.FormResize: BtnSplitNo.Down +[16:07.34.678] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:07.34.678] BEGIN ResizeTerminal +[16:07.34.679] END ResizeTerminal +[16:07.34.679] TFormXterm.FormResize: AdaptSidebarArrows; +[16:07.34.679] BEGIN AdaptSidebarArrows +[16:07.34.679] END AdaptSidebarArrows +[16:07.34.679] TFormXterm.FormResize: AdaptTV2; +[16:07.34.679] END TFormXterm.FormResize + +[16:07.35.156] BEGIN WMNewTab: 20 +[16:07.35.156] END WMNewTab: 20 + +[16:07.36.069] BEGIN CWD +[16:07.36.130] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:07.36.130] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:07.36.130] (SSH-Browser) END VerifySFTPConnection(1) +[16:07.36.130] END CWD +[16:07.36.144] BEGIN CWD +[16:07.36.206] END CWD + +[16:07.36.675] BEGIN WMNewTab: 20 +[16:07.36.675] END WMNewTab: 20 + + +[16:07.38.093] BEGIN WMNewTab: 20 +[16:07.38.093] END WMNewTab: 20 + +[16:07.38.720] BEGIN WMNewTab: 0 +[16:07.38.720] WMNewTab: FormClick +[16:07.38.720] WMNewTab: LooseFocus +[16:07.38.720] END WMNewTab: 0 +[16:07.38.720] BEGIN WMNewTab: 31 +[16:07.38.720] END WMNewTab: 31 +[16:07.38.832] BEGIN WMNewTab: 0 +[16:07.38.832] WMNewTab: FormClick +[16:07.38.832] WMNewTab: LooseFocus +[16:07.38.833] END WMNewTab: 0 + +[16:07.39.508] BEGIN WMNewTab: 20 +[16:07.39.508] END WMNewTab: 20 +[16:07.39.590] BEGIN CWD +[16:07.39.651] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:07.39.651] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:07.39.651] (SSH-Browser) END VerifySFTPConnection(1) +[16:07.39.651] END CWD +[16:07.39.658] BEGIN CWD +[16:07.39.725] END CWD + + +[16:07.41.137] BEGIN WMNewTab: 20 +[16:07.41.137] END WMNewTab: 20 + + +[16:07.42.557] BEGIN WMNewTab: 20 +[16:07.42.557] END WMNewTab: 20 + + +[16:07.43.974] BEGIN WMNewTab: 20 +[16:07.43.974] END WMNewTab: 20 + + +[16:07.45.388] BEGIN WMNewTab: 20 +[16:07.45.388] END WMNewTab: 20 + +[16:07.46.221] BEGIN CWD +[16:07.46.282] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:07.46.282] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:07.46.282] (SSH-Browser) END VerifySFTPConnection(1) +[16:07.46.282] END CWD +[16:07.46.357] BEGIN CWD +[16:07.46.418] END CWD + +[16:07.46.892] BEGIN WMNewTab: 20 +[16:07.46.892] END WMNewTab: 20 + + +[16:07.48.309] BEGIN WMNewTab: 20 +[16:07.48.309] END WMNewTab: 20 +[16:07.48.504] BEGIN CWD +[16:07.48.564] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:07.48.564] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:07.48.564] (SSH-Browser) END VerifySFTPConnection(1) +[16:07.48.564] END CWD +[16:07.48.571] BEGIN CWD +[16:07.48.631] END CWD + +[16:07.49.575] BEGIN WMNewTab: 20 +[16:07.49.575] END WMNewTab: 20 + + +[16:07.50.995] BEGIN WMNewTab: 20 +[16:07.50.995] END WMNewTab: 20 + + +[16:07.52.412] BEGIN WMNewTab: 20 +[16:07.52.412] END WMNewTab: 20 + + +[16:07.53.828] BEGIN WMNewTab: 20 +[16:07.53.828] END WMNewTab: 20 + + +[16:07.55.246] BEGIN WMNewTab: 20 +[16:07.55.246] END WMNewTab: 20 + +[16:07.55.664] BEGIN WMNewTab: 0 +[16:07.55.664] WMNewTab: FormClick +[16:07.55.664] WMNewTab: LooseFocus +[16:07.55.664] END WMNewTab: 0 +[16:07.55.792] BEGIN WMNewTab: 0 +[16:07.55.792] WMNewTab: FormClick +[16:07.55.792] WMNewTab: LooseFocus +[16:07.55.793] END WMNewTab: 0 + +[16:07.56.660] BEGIN WMNewTab: 20 +[16:07.56.660] END WMNewTab: 20 + + +[16:07.57.876] BEGIN CWD +[16:07.57.936] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:07.57.936] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:07.57.936] (SSH-Browser) END VerifySFTPConnection(1) +[16:07.57.936] END CWD +[16:07.57.937] BEGIN WMNewTab: 20 +[16:07.57.937] END WMNewTab: 20 +[16:07.57.954] BEGIN CWD +[16:07.58.015] END CWD + + +[16:07.59.431] BEGIN WMNewTab: 20 +[16:07.59.431] END WMNewTab: 20 + + +[16:08.00.848] BEGIN WMNewTab: 20 +[16:08.00.848] END WMNewTab: 20 + + +[16:08.02.261] BEGIN WMNewTab: 20 +[16:08.02.261] END WMNewTab: 20 + + +[16:08.03.679] BEGIN WMNewTab: 20 +[16:08.03.679] END WMNewTab: 20 +[16:08.03.854] BEGIN WMNewTab: 60 +[16:08.03.867] END WMNewTab: 60 + +[16:08.04.858] BEGIN WMNewTab: 60 +[16:08.04.859] END WMNewTab: 60 +[16:08.05.090] BEGIN WMNewTab: 20 +[16:08.05.090] END WMNewTab: 20 + + +[16:08.06.500] BEGIN WMNewTab: 20 +[16:08.06.500] END WMNewTab: 20 + + +[16:08.07.912] BEGIN WMNewTab: 20 +[16:08.07.912] END WMNewTab: 20 + + +[16:08.09.352] BEGIN WMNewTab: 20 +[16:08.09.352] END WMNewTab: 20 + + +[16:08.10.750] BEGIN WMNewTab: 20 +[16:08.10.750] END WMNewTab: 20 + + +[16:08.12.158] BEGIN WMNewTab: 20 +[16:08.12.158] END WMNewTab: 20 + + +[16:08.13.568] BEGIN WMNewTab: 20 +[16:08.13.568] END WMNewTab: 20 + + +[16:08.14.989] BEGIN WMNewTab: 20 +[16:08.14.989] END WMNewTab: 20 + + +[16:08.16.404] BEGIN WMNewTab: 20 +[16:08.16.404] END WMNewTab: 20 + + +[16:08.17.816] BEGIN WMNewTab: 20 +[16:08.17.816] END WMNewTab: 20 + + +[16:08.19.230] BEGIN WMNewTab: 20 +[16:08.19.230] END WMNewTab: 20 + + +[16:08.20.645] BEGIN WMNewTab: 20 +[16:08.20.645] END WMNewTab: 20 + + +[16:08.22.059] BEGIN WMNewTab: 20 +[16:08.22.059] END WMNewTab: 20 + + +[16:08.23.472] BEGIN WMNewTab: 20 +[16:08.23.472] END WMNewTab: 20 + + +[16:08.24.886] BEGIN WMNewTab: 20 +[16:08.24.886] END WMNewTab: 20 + + +[16:08.26.301] BEGIN WMNewTab: 20 +[16:08.26.301] END WMNewTab: 20 + + +[16:08.27.740] BEGIN WMNewTab: 20 +[16:08.27.740] END WMNewTab: 20 + + +[16:08.29.142] BEGIN WMNewTab: 20 +[16:08.29.142] END WMNewTab: 20 + + +[16:08.30.556] BEGIN WMNewTab: 20 +[16:08.30.556] END WMNewTab: 20 + + +[16:08.31.972] BEGIN WMNewTab: 20 +[16:08.31.972] END WMNewTab: 20 + + +[16:08.33.388] BEGIN WMNewTab: 20 +[16:08.33.388] END WMNewTab: 20 + + +[16:08.34.800] BEGIN WMNewTab: 20 +[16:08.34.800] END WMNewTab: 20 + +[16:08.35.933] Cts1MouseDown: FormClick +[16:08.35.938] Cts1ActiveTabChanged: New index = 2 +[16:08.35.938] BEGIN DisplayCurrentTab +[16:08.35.938] DisplayCurrentTab: FormClick +[16:08.35.938] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:08.35.938] (SSH-Browser) BEGIN ActiverPanel14 +[16:08.35.938] (SSH-Browser) BEGIN DesactiverPanel14 +[16:08.35.952] (SSH-Browser) END DesactiverPanel14 +[16:08.35.952] (SSH-Browser) END ActiverPanel14; +[16:08.36.058] BEGIN TFormXterm.FormResize +[16:08.36.058] TFormXterm.FormResize: CenterBtnReattachTab +[16:08.36.059] TFormXterm.FormResize: SplitModeResize +[16:08.36.059] TFormXterm.FormResize: BtnSplitNo.Down +[16:08.36.059] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:08.36.059] BEGIN ResizeTerminal +[16:08.36.063] END ResizeTerminal +[16:08.36.063] TFormXterm.FormResize: AdaptSidebarArrows; +[16:08.36.063] BEGIN AdaptSidebarArrows +[16:08.36.063] END AdaptSidebarArrows +[16:08.36.063] TFormXterm.FormResize: AdaptTV2; +[16:08.36.063] END TFormXterm.FormResize +[16:08.36.063] DisplayCurrentTab: Cts1.BeginUpdate; +[16:08.36.063] DisplayCurrentTab: Cts1.EndUpdates +[16:08.36.080] DisplayCurrentTab: 显示所选标签页 +[16:08.36.082] DisplayCurrentTab: 隐藏其他标签页 +[16:08.36.093] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:08.36.096] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:08.36.096] DisplayCurrentTab: DistribuerLeFocus +[16:08.36.096] END DisplayCurrentTab +[16:08.36.108] BEGIN WMNewTab: 62 +[16:08.36.108] END WMNewTab: 62 +[16:08.36.219] BEGIN WMNewTab: 20 +[16:08.36.219] END WMNewTab: 20 +[16:08.36.505] BEGIN WMNewTab: 0 +[16:08.36.505] WMNewTab: FormClick +[16:08.36.505] WMNewTab: LooseFocus +[16:08.36.505] END WMNewTab: 0 +[16:08.36.645] BEGIN WMNewTab: 0 +[16:08.36.645] WMNewTab: FormClick +[16:08.36.645] WMNewTab: LooseFocus +[16:08.36.645] END WMNewTab: 0 + +[16:08.37.633] BEGIN WMNewTab: 20 +[16:08.37.633] END WMNewTab: 20 + + +[16:08.38.837] BEGIN WMNewTab: 31 +[16:08.38.837] END WMNewTab: 31 +[16:08.38.837] BEGIN WMNewTab: 0 +[16:08.38.837] WMNewTab: FormClick +[16:08.38.837] WMNewTab: LooseFocus +[16:08.38.838] END WMNewTab: 0 +[16:08.39.047] BEGIN WMNewTab: 20 +[16:08.39.047] END WMNewTab: 20 + + +[16:08.40.464] BEGIN WMNewTab: 20 +[16:08.40.464] END WMNewTab: 20 + + +[16:08.41.877] BEGIN WMNewTab: 20 +[16:08.41.877] END WMNewTab: 20 + + +[16:08.43.290] BEGIN WMNewTab: 20 +[16:08.43.290] END WMNewTab: 20 + + +[16:08.44.708] BEGIN WMNewTab: 20 +[16:08.44.708] END WMNewTab: 20 + + +[16:08.46.120] BEGIN WMNewTab: 20 +[16:08.46.120] END WMNewTab: 20 + + +[16:08.47.536] BEGIN WMNewTab: 20 +[16:08.47.536] END WMNewTab: 20 + + +[16:08.48.950] BEGIN WMNewTab: 20 +[16:08.48.950] END WMNewTab: 20 + + +[16:08.50.372] BEGIN WMNewTab: 20 +[16:08.50.372] END WMNewTab: 20 + + +[16:08.51.790] BEGIN WMNewTab: 20 +[16:08.51.790] END WMNewTab: 20 + + +[16:08.53.204] BEGIN WMNewTab: 20 +[16:08.53.204] END WMNewTab: 20 + +[16:08.53.621] BEGIN WMNewTab: 0 +[16:08.53.621] WMNewTab: FormClick +[16:08.53.621] WMNewTab: LooseFocus +[16:08.53.621] END WMNewTab: 0 +[16:08.53.621] BEGIN WMNewTab: 31 +[16:08.53.621] END WMNewTab: 31 + +[16:08.54.618] BEGIN WMNewTab: 20 +[16:08.54.618] END WMNewTab: 20 + + +[16:08.56.030] BEGIN WMNewTab: 20 +[16:08.56.030] END WMNewTab: 20 + + +[16:08.57.443] BEGIN WMNewTab: 20 +[16:08.57.443] END WMNewTab: 20 + + +[16:08.58.864] BEGIN WMNewTab: 20 +[16:08.58.864] END WMNewTab: 20 + + +[16:09.00.281] BEGIN WMNewTab: 20 +[16:09.00.281] END WMNewTab: 20 + + +[16:09.01.693] BEGIN WMNewTab: 20 +[16:09.01.693] END WMNewTab: 20 + + +[16:09.03.109] BEGIN WMNewTab: 20 +[16:09.03.109] END WMNewTab: 20 + + +[16:09.04.529] BEGIN WMNewTab: 20 +[16:09.04.529] END WMNewTab: 20 + + +[16:09.05.944] BEGIN WMNewTab: 20 +[16:09.05.944] END WMNewTab: 20 + + +[16:09.07.360] BEGIN WMNewTab: 20 +[16:09.07.360] END WMNewTab: 20 + + +[16:09.08.774] BEGIN WMNewTab: 20 +[16:09.08.774] END WMNewTab: 20 + + +[16:09.10.188] BEGIN WMNewTab: 20 +[16:09.10.188] END WMNewTab: 20 + + +[16:09.11.601] BEGIN WMNewTab: 20 +[16:09.11.601] END WMNewTab: 20 + +[16:09.12.407] BEGIN WMNewTab: 0 +[16:09.12.407] WMNewTab: FormClick +[16:09.12.407] WMNewTab: LooseFocus +[16:09.12.407] END WMNewTab: 0 +[16:09.12.525] BEGIN WMNewTab: 0 +[16:09.12.525] WMNewTab: FormClick +[16:09.12.525] WMNewTab: LooseFocus +[16:09.12.525] END WMNewTab: 0 + +[16:09.13.015] BEGIN WMNewTab: 20 +[16:09.13.015] END WMNewTab: 20 + + +[16:09.14.429] BEGIN WMNewTab: 20 +[16:09.14.429] END WMNewTab: 20 + + +[16:09.15.845] BEGIN WMNewTab: 20 +[16:09.15.845] END WMNewTab: 20 + +[16:09.16.430] BEGIN WMNewTab: 0 +[16:09.16.430] WMNewTab: FormClick +[16:09.16.430] WMNewTab: LooseFocus +[16:09.16.430] END WMNewTab: 0 +[16:09.16.430] BEGIN WMNewTab: 31 +[16:09.16.430] END WMNewTab: 31 +[16:09.16.549] BEGIN WMNewTab: 0 +[16:09.16.549] WMNewTab: FormClick +[16:09.16.549] WMNewTab: LooseFocus +[16:09.16.550] END WMNewTab: 0 + +[16:09.17.261] BEGIN WMNewTab: 20 +[16:09.17.261] END WMNewTab: 20 + + +[16:09.18.679] BEGIN WMNewTab: 20 +[16:09.18.679] END WMNewTab: 20 + + +[16:09.20.098] BEGIN WMNewTab: 20 +[16:09.20.098] END WMNewTab: 20 + + +[16:09.21.517] BEGIN WMNewTab: 20 +[16:09.21.517] END WMNewTab: 20 + + +[16:09.22.926] BEGIN WMNewTab: 20 +[16:09.22.926] END WMNewTab: 20 + + +[16:09.24.342] BEGIN WMNewTab: 20 +[16:09.24.342] END WMNewTab: 20 + + +[16:09.25.757] BEGIN WMNewTab: 20 +[16:09.25.757] END WMNewTab: 20 + + +[16:09.27.168] BEGIN WMNewTab: 20 +[16:09.27.168] END WMNewTab: 20 + + +[16:09.28.581] BEGIN WMNewTab: 20 +[16:09.28.581] END WMNewTab: 20 + + +[16:09.29.995] BEGIN WMNewTab: 20 +[16:09.29.995] END WMNewTab: 20 + + +[16:09.31.410] BEGIN WMNewTab: 20 +[16:09.31.410] END WMNewTab: 20 + + +[16:09.32.829] BEGIN WMNewTab: 20 +[16:09.32.829] END WMNewTab: 20 +[16:09.33.030] BEGIN WMNewTab: 0 +[16:09.33.030] WMNewTab: FormClick +[16:09.33.030] WMNewTab: LooseFocus +[16:09.33.030] END WMNewTab: 0 +[16:09.33.030] BEGIN WMNewTab: 31 +[16:09.33.030] END WMNewTab: 31 + + +[16:09.34.243] BEGIN WMNewTab: 20 +[16:09.34.243] END WMNewTab: 20 + + +[16:09.35.657] BEGIN WMNewTab: 20 +[16:09.35.657] END WMNewTab: 20 + + +[16:09.37.077] BEGIN WMNewTab: 20 +[16:09.37.078] END WMNewTab: 20 + + +[16:09.38.493] BEGIN WMNewTab: 20 +[16:09.38.493] END WMNewTab: 20 + + +[16:09.39.912] BEGIN WMNewTab: 20 +[16:09.39.912] END WMNewTab: 20 + + +[16:09.41.327] BEGIN WMNewTab: 20 +[16:09.41.327] END WMNewTab: 20 + +[16:09.42.454] BEGIN WMNewTab: 0 +[16:09.42.454] WMNewTab: FormClick +[16:09.42.454] WMNewTab: LooseFocus +[16:09.42.454] END WMNewTab: 0 +[16:09.42.518] BEGIN WMNewTab: 0 +[16:09.42.518] WMNewTab: FormClick +[16:09.42.518] WMNewTab: LooseFocus +[16:09.42.519] END WMNewTab: 0 +[16:09.42.738] BEGIN WMNewTab: 20 +[16:09.42.738] END WMNewTab: 20 + + +[16:09.44.155] BEGIN WMNewTab: 20 +[16:09.44.155] END WMNewTab: 20 + +[16:09.45.280] BEGIN WMNewTab: 31 +[16:09.45.280] END WMNewTab: 31 +[16:09.45.280] BEGIN WMNewTab: 0 +[16:09.45.280] WMNewTab: FormClick +[16:09.45.280] WMNewTab: LooseFocus +[16:09.45.280] END WMNewTab: 0 +[16:09.45.570] BEGIN WMNewTab: 20 +[16:09.45.570] END WMNewTab: 20 + + +[16:09.46.985] BEGIN WMNewTab: 20 +[16:09.46.985] END WMNewTab: 20 + + +[16:09.48.403] BEGIN WMNewTab: 20 +[16:09.48.403] END WMNewTab: 20 + + +[16:09.49.815] BEGIN WMNewTab: 20 +[16:09.49.815] END WMNewTab: 20 + + +[16:09.51.032] Cts1MouseDown: FormClick +[16:09.51.036] Cts1ActiveTabChanged: New index = 1 +[16:09.51.036] BEGIN DisplayCurrentTab +[16:09.51.036] DisplayCurrentTab: FormClick +[16:09.51.037] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:09.51.037] (SSH-Browser) BEGIN ActiverPanel14 +[16:09.51.037] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:09.51.041] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:09.51.041] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:09.51.041] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:09.51.041] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:09.51.072] (SSH-Browser) END ActiverPanel14; +[16:09.51.096] BEGIN TFormXterm.FormResize +[16:09.51.096] TFormXterm.FormResize: CenterBtnReattachTab +[16:09.51.097] TFormXterm.FormResize: SplitModeResize +[16:09.51.097] TFormXterm.FormResize: BtnSplitNo.Down +[16:09.51.098] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:09.51.098] BEGIN ResizeTerminal +[16:09.51.102] END ResizeTerminal +[16:09.51.102] TFormXterm.FormResize: AdaptSidebarArrows; +[16:09.51.102] BEGIN AdaptSidebarArrows +[16:09.51.102] END AdaptSidebarArrows +[16:09.51.102] TFormXterm.FormResize: AdaptTV2; +[16:09.51.102] END TFormXterm.FormResize +[16:09.51.102] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:09.51.102] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:09.51.115] ShellExecuteS: ShellExecuteEx 成功. +[16:09.51.115] ShellExecuteS: WaitForInputIdle 失败. +[16:09.51.115] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:09.51.115] DisplayCurrentTab: Cts1.BeginUpdate; +[16:09.51.115] DisplayCurrentTab: Cts1.EndUpdates +[16:09.51.131] DisplayCurrentTab: 显示所选标签页 +[16:09.51.133] DisplayCurrentTab: 隐藏其他标签页 +[16:09.51.148] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:09.51.154] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:09.51.154] DisplayCurrentTab: DistribuerLeFocus +[16:09.51.155] END DisplayCurrentTab +[16:09.51.172] [MobaSCP2] Launching remote monitoring in normal mode +[16:09.51.174] [MobaSCP2] Multiplex=1 +[16:09.51.175] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:09.51.175] [MobaSCP2] USERNAME: root +[16:09.51.223] [MobaSCP2] Using SCP1 +[16:09.51.223] [MobaSCP2] Connected to 192.168.127.10 +[16:09.51.230] BEGIN WMNewTab: 20 +[16:09.51.230] END WMNewTab: 20 + +[16:09.52.338] BEGIN TFormXterm.FormResize +[16:09.52.338] TFormXterm.FormResize: CenterBtnReattachTab +[16:09.52.338] TFormXterm.FormResize: SplitModeResize +[16:09.52.338] TFormXterm.FormResize: BtnSplitNo.Down +[16:09.52.338] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:09.52.338] BEGIN ResizeTerminal +[16:09.52.338] END ResizeTerminal +[16:09.52.338] TFormXterm.FormResize: AdaptSidebarArrows; +[16:09.52.338] BEGIN AdaptSidebarArrows +[16:09.52.338] END AdaptSidebarArrows +[16:09.52.338] TFormXterm.FormResize: AdaptTV2; +[16:09.52.338] END TFormXterm.FormResize +[16:09.52.649] BEGIN WMNewTab: 20 +[16:09.52.649] END WMNewTab: 20 + + +[16:09.54.066] BEGIN WMNewTab: 20 +[16:09.54.066] END WMNewTab: 20 +[16:09.54.081] BEGIN CWD +[16:09.54.142] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:09.54.142] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:09.54.142] (SSH-Browser) END VerifySFTPConnection(1) +[16:09.54.142] END CWD +[16:09.54.158] BEGIN CWD +[16:09.54.219] END CWD + + +[16:09.55.631] BEGIN WMNewTab: 20 +[16:09.55.631] END WMNewTab: 20 + + +[16:09.57.046] BEGIN WMNewTab: 20 +[16:09.57.046] END WMNewTab: 20 +[16:09.57.229] BEGIN CWD +[16:09.57.290] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:09.57.290] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:09.57.290] (SSH-Browser) END VerifySFTPConnection(1) +[16:09.57.290] END CWD +[16:09.57.304] BEGIN CWD +[16:09.57.384] END CWD + +[16:09.58.326] BEGIN WMNewTab: 20 +[16:09.58.327] END WMNewTab: 20 + + +[16:09.59.739] BEGIN WMNewTab: 20 +[16:09.59.739] END WMNewTab: 20 + + +[16:10.01.157] BEGIN WMNewTab: 20 +[16:10.01.157] END WMNewTab: 20 + + +[16:10.02.572] BEGIN WMNewTab: 20 +[16:10.02.572] END WMNewTab: 20 + + +[16:10.03.989] BEGIN WMNewTab: 20 +[16:10.03.989] END WMNewTab: 20 + + +[16:10.05.404] BEGIN WMNewTab: 20 +[16:10.05.404] END WMNewTab: 20 +[16:10.05.423] Cts1MouseDown: FormClick +[16:10.05.428] Cts1ActiveTabChanged: New index = 2 +[16:10.05.428] BEGIN DisplayCurrentTab +[16:10.05.428] DisplayCurrentTab: FormClick +[16:10.05.428] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:10.05.428] (SSH-Browser) BEGIN ActiverPanel14 +[16:10.05.428] (SSH-Browser) BEGIN DesactiverPanel14 +[16:10.05.440] (SSH-Browser) END DesactiverPanel14 +[16:10.05.440] (SSH-Browser) END ActiverPanel14; +[16:10.05.545] BEGIN TFormXterm.FormResize +[16:10.05.545] TFormXterm.FormResize: CenterBtnReattachTab +[16:10.05.546] TFormXterm.FormResize: SplitModeResize +[16:10.05.546] TFormXterm.FormResize: BtnSplitNo.Down +[16:10.05.547] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:10.05.547] BEGIN ResizeTerminal +[16:10.05.549] END ResizeTerminal +[16:10.05.549] TFormXterm.FormResize: AdaptSidebarArrows; +[16:10.05.549] BEGIN AdaptSidebarArrows +[16:10.05.549] END AdaptSidebarArrows +[16:10.05.549] TFormXterm.FormResize: AdaptTV2; +[16:10.05.549] END TFormXterm.FormResize +[16:10.05.549] DisplayCurrentTab: Cts1.BeginUpdate; +[16:10.05.549] DisplayCurrentTab: Cts1.EndUpdates +[16:10.05.563] DisplayCurrentTab: 显示所选标签页 +[16:10.05.565] DisplayCurrentTab: 隐藏其他标签页 +[16:10.05.578] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:10.05.581] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:10.05.581] DisplayCurrentTab: DistribuerLeFocus +[16:10.05.581] END DisplayCurrentTab + + +[16:10.06.822] BEGIN WMNewTab: 20 +[16:10.06.822] END WMNewTab: 20 + + +[16:10.08.235] BEGIN WMNewTab: 20 +[16:10.08.235] END WMNewTab: 20 + + +[16:10.09.649] BEGIN WMNewTab: 20 +[16:10.09.649] END WMNewTab: 20 + + +[16:10.11.065] BEGIN WMNewTab: 20 +[16:10.11.065] END WMNewTab: 20 + + +[16:10.12.479] BEGIN WMNewTab: 20 +[16:10.12.479] END WMNewTab: 20 + +[16:10.13.392] BEGIN WMNewTab: 0 +[16:10.13.392] WMNewTab: FormClick +[16:10.13.392] WMNewTab: LooseFocus +[16:10.13.394] END WMNewTab: 0 + +[16:10.13.870] BEGIN WMNewTab: 0 +[16:10.13.870] WMNewTab: FormClick +[16:10.13.870] WMNewTab: LooseFocus +[16:10.13.871] END WMNewTab: 0 +[16:10.13.892] BEGIN WMNewTab: 20 +[16:10.13.892] END WMNewTab: 20 + +[16:10.14.305] BEGIN WMNewTab: 0 +[16:10.14.305] WMNewTab: FormClick +[16:10.14.305] WMNewTab: LooseFocus +[16:10.14.305] END WMNewTab: 0 +[16:10.14.383] BEGIN WMNewTab: 0 +[16:10.14.383] WMNewTab: FormClick +[16:10.14.383] WMNewTab: LooseFocus +[16:10.14.384] END WMNewTab: 0 + +[16:10.14.936] BEGIN WMNewTab: 0 +[16:10.14.936] WMNewTab: FormClick +[16:10.14.936] WMNewTab: LooseFocus +[16:10.14.936] END WMNewTab: 0 + +[16:10.15.306] BEGIN WMNewTab: 20 +[16:10.15.306] END WMNewTab: 20 + +[16:10.15.774] BEGIN WMNewTab: 0 +[16:10.15.774] WMNewTab: FormClick +[16:10.15.774] WMNewTab: LooseFocus +[16:10.15.777] END WMNewTab: 0 + +[16:10.16.448] BEGIN WMNewTab: 0 +[16:10.16.448] WMNewTab: FormClick +[16:10.16.448] WMNewTab: LooseFocus +[16:10.16.455] END WMNewTab: 0 +[16:10.16.543] BEGIN WMNewTab: 0 +[16:10.16.543] WMNewTab: FormClick +[16:10.16.543] WMNewTab: LooseFocus +[16:10.16.544] END WMNewTab: 0 +[16:10.16.717] BEGIN WMNewTab: 20 +[16:10.16.717] END WMNewTab: 20 +[16:10.17.049] BEGIN WMNewTab: 0 +[16:10.17.049] WMNewTab: FormClick +[16:10.17.049] WMNewTab: LooseFocus +[16:10.17.049] END WMNewTab: 0 + +[16:10.17.959] BEGIN WMNewTab: 0 +[16:10.17.959] WMNewTab: FormClick +[16:10.17.959] WMNewTab: LooseFocus +[16:10.17.962] END WMNewTab: 0 +[16:10.18.128] BEGIN WMNewTab: 20 +[16:10.18.128] END WMNewTab: 20 + + +[16:10.19.537] BEGIN WMNewTab: 20 +[16:10.19.537] END WMNewTab: 20 + + +[16:10.20.951] BEGIN WMNewTab: 20 +[16:10.20.951] END WMNewTab: 20 + + +[16:10.22.363] BEGIN WMNewTab: 20 +[16:10.22.363] END WMNewTab: 20 + + +[16:10.23.778] BEGIN WMNewTab: 20 +[16:10.23.778] END WMNewTab: 20 + + +[16:10.25.188] BEGIN WMNewTab: 20 +[16:10.25.188] END WMNewTab: 20 + + +[16:10.26.601] BEGIN WMNewTab: 20 +[16:10.26.601] END WMNewTab: 20 + + +[16:10.28.016] BEGIN WMNewTab: 20 +[16:10.28.016] END WMNewTab: 20 + + +[16:10.29.430] BEGIN WMNewTab: 20 +[16:10.29.430] END WMNewTab: 20 + + +[16:10.30.843] BEGIN WMNewTab: 20 +[16:10.30.843] END WMNewTab: 20 + + +[16:10.32.252] BEGIN WMNewTab: 20 +[16:10.32.252] END WMNewTab: 20 + + +[16:10.33.662] BEGIN WMNewTab: 20 +[16:10.33.662] END WMNewTab: 20 + + +[16:10.35.070] BEGIN WMNewTab: 20 +[16:10.35.070] END WMNewTab: 20 + + +[16:10.36.485] BEGIN WMNewTab: 20 +[16:10.36.485] END WMNewTab: 20 + + +[16:10.37.900] BEGIN WMNewTab: 20 +[16:10.37.900] END WMNewTab: 20 + + +[16:10.39.310] BEGIN WMNewTab: 20 +[16:10.39.310] END WMNewTab: 20 +[16:10.39.569] BEGIN WMNewTab: 0 +[16:10.39.569] WMNewTab: FormClick +[16:10.39.569] WMNewTab: LooseFocus +[16:10.39.569] END WMNewTab: 0 +[16:10.39.688] BEGIN WMNewTab: 0 +[16:10.39.688] WMNewTab: FormClick +[16:10.39.688] WMNewTab: LooseFocus +[16:10.39.689] END WMNewTab: 0 + +[16:10.40.725] BEGIN WMNewTab: 20 +[16:10.40.725] END WMNewTab: 20 + + +[16:10.42.138] BEGIN WMNewTab: 20 +[16:10.42.138] END WMNewTab: 20 + + +[16:10.43.513] BEGIN WMNewTab: 0 +[16:10.43.513] WMNewTab: FormClick +[16:10.43.513] WMNewTab: LooseFocus +[16:10.43.514] END WMNewTab: 0 +[16:10.43.553] BEGIN WMNewTab: 20 +[16:10.43.553] END WMNewTab: 20 + + +[16:10.44.961] BEGIN WMNewTab: 20 +[16:10.44.961] END WMNewTab: 20 + +[16:10.46.032] BEGIN WMNewTab: 0 +[16:10.46.032] WMNewTab: FormClick +[16:10.46.032] WMNewTab: LooseFocus +[16:10.46.034] END WMNewTab: 0 +[16:10.46.375] BEGIN WMNewTab: 20 +[16:10.46.375] END WMNewTab: 20 + + +[16:10.47.797] BEGIN WMNewTab: 20 +[16:10.47.797] END WMNewTab: 20 + + +[16:10.49.214] BEGIN WMNewTab: 20 +[16:10.49.214] END WMNewTab: 20 +[16:10.49.313] BEGIN WMNewTab: 0 +[16:10.49.313] WMNewTab: FormClick +[16:10.49.313] WMNewTab: LooseFocus +[16:10.49.313] END WMNewTab: 0 + + +[16:10.50.625] BEGIN WMNewTab: 20 +[16:10.50.625] END WMNewTab: 20 + +[16:10.51.441] BEGIN WMNewTab: 0 +[16:10.51.441] WMNewTab: FormClick +[16:10.51.441] WMNewTab: LooseFocus +[16:10.51.441] END WMNewTab: 0 + +[16:10.52.043] BEGIN WMNewTab: 20 +[16:10.52.043] END WMNewTab: 20 + + +[16:10.53.463] BEGIN WMNewTab: 20 +[16:10.53.463] END WMNewTab: 20 + +[16:10.54.465] BEGIN WMNewTab: 0 +[16:10.54.465] WMNewTab: FormClick +[16:10.54.465] WMNewTab: LooseFocus +[16:10.54.465] END WMNewTab: 0 +[16:10.54.560] BEGIN WMNewTab: 0 +[16:10.54.560] WMNewTab: FormClick +[16:10.54.560] WMNewTab: LooseFocus +[16:10.54.561] END WMNewTab: 0 +[16:10.54.871] BEGIN WMNewTab: 20 +[16:10.54.871] END WMNewTab: 20 + + +[16:10.56.113] BEGIN WMNewTab: 0 +[16:10.56.113] WMNewTab: FormClick +[16:10.56.113] WMNewTab: LooseFocus +[16:10.56.113] END WMNewTab: 0 +[16:10.56.284] BEGIN WMNewTab: 20 +[16:10.56.284] END WMNewTab: 20 + + +[16:10.57.696] BEGIN WMNewTab: 20 +[16:10.57.696] END WMNewTab: 20 + + +[16:10.59.110] BEGIN WMNewTab: 20 +[16:10.59.110] END WMNewTab: 20 + +[16:10.59.976] BEGIN WMNewTab: 0 +[16:10.59.976] WMNewTab: FormClick +[16:10.59.977] WMNewTab: LooseFocus +[16:10.59.979] END WMNewTab: 0 + +[16:11.00.528] BEGIN WMNewTab: 20 +[16:11.00.528] END WMNewTab: 20 + + +[16:11.01.938] BEGIN WMNewTab: 20 +[16:11.01.938] END WMNewTab: 20 + + +[16:11.03.354] BEGIN WMNewTab: 20 +[16:11.03.354] END WMNewTab: 20 + + +[16:11.04.768] BEGIN WMNewTab: 20 +[16:11.04.768] END WMNewTab: 20 + + +[16:11.06.184] BEGIN WMNewTab: 20 +[16:11.06.184] END WMNewTab: 20 + + +[16:11.07.600] BEGIN WMNewTab: 20 +[16:11.07.600] END WMNewTab: 20 + + +[16:11.09.014] BEGIN WMNewTab: 20 +[16:11.09.014] END WMNewTab: 20 + + +[16:11.10.426] BEGIN WMNewTab: 20 +[16:11.10.426] END WMNewTab: 20 + + +[16:11.11.837] BEGIN WMNewTab: 20 +[16:11.11.837] END WMNewTab: 20 + + +[16:11.13.252] BEGIN WMNewTab: 20 +[16:11.13.252] END WMNewTab: 20 + + +[16:11.14.665] BEGIN WMNewTab: 20 +[16:11.14.665] END WMNewTab: 20 + + +[16:11.16.078] BEGIN WMNewTab: 20 +[16:11.16.078] END WMNewTab: 20 + + +[16:11.17.487] BEGIN WMNewTab: 20 +[16:11.17.487] END WMNewTab: 20 + + +[16:11.18.896] BEGIN WMNewTab: 20 +[16:11.18.896] END WMNewTab: 20 + +[16:11.19.353] BEGIN WMNewTab: 0 +[16:11.19.353] WMNewTab: FormClick +[16:11.19.353] WMNewTab: LooseFocus +[16:11.19.353] END WMNewTab: 0 +[16:11.19.449] BEGIN WMNewTab: 0 +[16:11.19.449] WMNewTab: FormClick +[16:11.19.449] WMNewTab: LooseFocus +[16:11.19.450] END WMNewTab: 0 + +[16:11.20.311] BEGIN WMNewTab: 20 +[16:11.20.311] END WMNewTab: 20 + + +[16:11.21.726] BEGIN WMNewTab: 20 +[16:11.21.726] END WMNewTab: 20 + + +[16:11.23.135] BEGIN WMNewTab: 20 +[16:11.23.135] END WMNewTab: 20 + + +[16:11.24.550] BEGIN WMNewTab: 20 +[16:11.24.550] END WMNewTab: 20 + + +[16:11.25.963] BEGIN WMNewTab: 20 +[16:11.25.963] END WMNewTab: 20 + + +[16:11.27.378] BEGIN WMNewTab: 20 +[16:11.27.378] END WMNewTab: 20 + + +[16:11.28.794] BEGIN WMNewTab: 20 +[16:11.28.794] END WMNewTab: 20 + + +[16:11.30.212] BEGIN WMNewTab: 20 +[16:11.30.212] END WMNewTab: 20 + + +[16:11.31.628] BEGIN WMNewTab: 20 +[16:11.31.628] END WMNewTab: 20 + + +[16:11.33.039] BEGIN WMNewTab: 20 +[16:11.33.039] END WMNewTab: 20 + + +[16:11.34.456] BEGIN WMNewTab: 20 +[16:11.34.456] END WMNewTab: 20 + + +[16:11.35.871] BEGIN WMNewTab: 20 +[16:11.35.871] END WMNewTab: 20 + + +[16:11.37.286] BEGIN WMNewTab: 20 +[16:11.37.286] END WMNewTab: 20 + + +[16:11.38.707] BEGIN WMNewTab: 20 +[16:11.38.707] END WMNewTab: 20 + + +[16:11.40.120] BEGIN WMNewTab: 20 +[16:11.40.120] END WMNewTab: 20 + + +[16:11.41.539] BEGIN WMNewTab: 20 +[16:11.41.539] END WMNewTab: 20 + + +[16:11.42.952] BEGIN WMNewTab: 20 +[16:11.42.952] END WMNewTab: 20 + + +[16:11.44.364] BEGIN WMNewTab: 20 +[16:11.44.364] END WMNewTab: 20 + + +[16:11.45.776] BEGIN WMNewTab: 20 +[16:11.45.776] END WMNewTab: 20 + + +[16:11.47.196] BEGIN WMNewTab: 20 +[16:11.47.196] END WMNewTab: 20 + + +[16:11.48.616] BEGIN WMNewTab: 20 +[16:11.48.616] END WMNewTab: 20 + + +[16:11.50.030] BEGIN WMNewTab: 20 +[16:11.50.030] END WMNewTab: 20 + +[16:11.50.746] Cts1MouseDown: FormClick +[16:11.50.752] Cts1ActiveTabChanged: New index = 1 +[16:11.50.752] BEGIN DisplayCurrentTab +[16:11.50.752] DisplayCurrentTab: FormClick +[16:11.50.752] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:11.50.752] (SSH-Browser) BEGIN ActiverPanel14 +[16:11.50.752] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:11.50.756] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:11.50.756] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:11.50.756] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:11.50.756] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:11.50.785] (SSH-Browser) END ActiverPanel14; +[16:11.50.806] BEGIN TFormXterm.FormResize +[16:11.50.806] TFormXterm.FormResize: CenterBtnReattachTab +[16:11.50.807] TFormXterm.FormResize: SplitModeResize +[16:11.50.807] TFormXterm.FormResize: BtnSplitNo.Down +[16:11.50.807] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:11.50.807] BEGIN ResizeTerminal +[16:11.50.812] END ResizeTerminal +[16:11.50.813] TFormXterm.FormResize: AdaptSidebarArrows; +[16:11.50.813] BEGIN AdaptSidebarArrows +[16:11.50.813] END AdaptSidebarArrows +[16:11.50.813] TFormXterm.FormResize: AdaptTV2; +[16:11.50.813] END TFormXterm.FormResize +[16:11.50.813] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:11.50.813] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:11.50.823] ShellExecuteS: ShellExecuteEx 成功. +[16:11.50.823] ShellExecuteS: WaitForInputIdle 失败. +[16:11.50.823] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:11.50.823] DisplayCurrentTab: Cts1.BeginUpdate; +[16:11.50.823] DisplayCurrentTab: Cts1.EndUpdates +[16:11.50.841] DisplayCurrentTab: 显示所选标签页 +[16:11.50.842] DisplayCurrentTab: 隐藏其他标签页 +[16:11.50.862] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:11.50.866] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:11.50.866] DisplayCurrentTab: DistribuerLeFocus +[16:11.50.866] END DisplayCurrentTab +[16:11.50.883] [MobaSCP2] Launching remote monitoring in normal mode +[16:11.50.886] [MobaSCP2] Multiplex=1 +[16:11.50.886] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:11.50.886] [MobaSCP2] USERNAME: root +[16:11.50.929] [MobaSCP2] Using SCP1 +[16:11.50.929] [MobaSCP2] Connected to 192.168.127.10 +[16:11.51.207] BEGIN WMNewTab: 0 +[16:11.51.207] WMNewTab: FormClick +[16:11.51.207] WMNewTab: LooseFocus +[16:11.51.207] END WMNewTab: 0 +[16:11.51.318] BEGIN WMNewTab: 0 +[16:11.51.318] WMNewTab: FormClick +[16:11.51.318] WMNewTab: LooseFocus +[16:11.51.318] END WMNewTab: 0 +[16:11.51.448] BEGIN WMNewTab: 20 +[16:11.51.448] END WMNewTab: 20 + +[16:11.52.034] BEGIN TFormXterm.FormResize +[16:11.52.034] TFormXterm.FormResize: CenterBtnReattachTab +[16:11.52.034] TFormXterm.FormResize: SplitModeResize +[16:11.52.034] TFormXterm.FormResize: BtnSplitNo.Down +[16:11.52.034] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:11.52.034] BEGIN ResizeTerminal +[16:11.52.035] END ResizeTerminal +[16:11.52.035] TFormXterm.FormResize: AdaptSidebarArrows; +[16:11.52.035] BEGIN AdaptSidebarArrows +[16:11.52.035] END AdaptSidebarArrows +[16:11.52.035] TFormXterm.FormResize: AdaptTV2; +[16:11.52.035] END TFormXterm.FormResize + +[16:11.52.860] BEGIN WMNewTab: 20 +[16:11.52.860] END WMNewTab: 20 + + +[16:11.54.273] BEGIN WMNewTab: 20 +[16:11.54.273] END WMNewTab: 20 + +[16:11.55.292] BEGIN CWD +[16:11.55.352] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:11.55.352] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:11.55.352] (SSH-Browser) END VerifySFTPConnection(1) +[16:11.55.352] END CWD +[16:11.55.368] BEGIN CWD +[16:11.55.429] END CWD + +[16:11.55.901] BEGIN WMNewTab: 20 +[16:11.55.901] END WMNewTab: 20 + + +[16:11.57.314] BEGIN WMNewTab: 20 +[16:11.57.314] END WMNewTab: 20 + + +[16:11.58.533] BEGIN CWD +[16:11.58.593] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:11.58.593] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:11.58.593] (SSH-Browser) END VerifySFTPConnection(1) +[16:11.58.593] END CWD +[16:11.58.595] BEGIN WMNewTab: 20 +[16:11.58.595] END WMNewTab: 20 +[16:11.58.608] BEGIN CWD +[16:11.58.669] END CWD + + +[16:12.00.082] BEGIN WMNewTab: 20 +[16:12.00.082] END WMNewTab: 20 + + +[16:12.01.499] BEGIN WMNewTab: 20 +[16:12.01.499] END WMNewTab: 20 + + +[16:12.02.909] BEGIN WMNewTab: 20 +[16:12.02.909] END WMNewTab: 20 + + +[16:12.04.318] BEGIN WMNewTab: 20 +[16:12.04.318] END WMNewTab: 20 + + +[16:12.05.731] BEGIN WMNewTab: 20 +[16:12.05.731] END WMNewTab: 20 + + +[16:12.07.138] BEGIN WMNewTab: 20 +[16:12.07.138] END WMNewTab: 20 + + +[16:12.08.553] BEGIN WMNewTab: 20 +[16:12.08.553] END WMNewTab: 20 + + +[16:12.09.966] BEGIN WMNewTab: 20 +[16:12.09.966] END WMNewTab: 20 + + +[16:12.11.386] BEGIN WMNewTab: 20 +[16:12.11.386] END WMNewTab: 20 + + +[16:12.12.800] BEGIN WMNewTab: 20 +[16:12.12.800] END WMNewTab: 20 + + +[16:12.14.211] BEGIN WMNewTab: 20 +[16:12.14.211] END WMNewTab: 20 + + +[16:12.15.627] BEGIN WMNewTab: 20 +[16:12.15.627] END WMNewTab: 20 + + +[16:12.17.036] BEGIN WMNewTab: 20 +[16:12.17.036] END WMNewTab: 20 + + +[16:12.18.452] BEGIN WMNewTab: 20 +[16:12.18.452] END WMNewTab: 20 + + +[16:12.19.868] BEGIN WMNewTab: 20 +[16:12.19.868] END WMNewTab: 20 + +[16:12.21.022] BEGIN WMNewTab: 60 +[16:12.21.034] END WMNewTab: 60 +[16:12.21.288] BEGIN WMNewTab: 20 +[16:12.21.288] END WMNewTab: 20 + + +[16:12.22.704] BEGIN WMNewTab: 20 +[16:12.22.704] END WMNewTab: 20 + + +[16:12.24.119] BEGIN WMNewTab: 20 +[16:12.24.119] END WMNewTab: 20 + + +[16:12.25.531] BEGIN WMNewTab: 20 +[16:12.25.531] END WMNewTab: 20 + +[16:12.26.439] BEGIN WMNewTab: 0 +[16:12.26.439] WMNewTab: FormClick +[16:12.26.439] WMNewTab: LooseFocus +[16:12.26.439] END WMNewTab: 0 + +[16:12.26.943] BEGIN WMNewTab: 20 +[16:12.26.943] END WMNewTab: 20 + +[16:12.27.982] BEGIN WMNewTab: 0 +[16:12.27.982] WMNewTab: FormClick +[16:12.27.982] WMNewTab: LooseFocus +[16:12.27.982] END WMNewTab: 0 + +[16:12.28.350] BEGIN WMNewTab: 20 +[16:12.28.350] END WMNewTab: 20 + + +[16:12.29.767] BEGIN WMNewTab: 20 +[16:12.29.767] END WMNewTab: 20 + + +[16:12.31.183] BEGIN WMNewTab: 20 +[16:12.31.183] END WMNewTab: 20 + + +[16:12.32.592] BEGIN WMNewTab: 20 +[16:12.32.592] END WMNewTab: 20 + + +[16:12.34.008] BEGIN WMNewTab: 20 +[16:12.34.008] END WMNewTab: 20 + + +[16:12.35.424] BEGIN WMNewTab: 20 +[16:12.35.424] END WMNewTab: 20 + + +[16:12.36.834] BEGIN WMNewTab: 20 +[16:12.36.834] END WMNewTab: 20 + + +[16:12.38.253] BEGIN WMNewTab: 20 +[16:12.38.253] END WMNewTab: 20 + + +[16:12.39.665] BEGIN WMNewTab: 20 +[16:12.39.665] END WMNewTab: 20 + + +[16:12.41.081] BEGIN WMNewTab: 20 +[16:12.41.081] END WMNewTab: 20 + + +[16:12.42.491] BEGIN WMNewTab: 20 +[16:12.42.491] END WMNewTab: 20 + + +[16:12.43.903] BEGIN WMNewTab: 20 +[16:12.43.903] END WMNewTab: 20 + + +[16:12.45.313] BEGIN WMNewTab: 20 +[16:12.45.313] END WMNewTab: 20 + + +[16:12.46.727] BEGIN WMNewTab: 20 +[16:12.46.727] END WMNewTab: 20 + + +[16:12.48.146] BEGIN WMNewTab: 20 +[16:12.48.146] END WMNewTab: 20 + + +[16:12.49.560] BEGIN WMNewTab: 20 +[16:12.49.560] END WMNewTab: 20 + + +[16:12.50.973] BEGIN WMNewTab: 20 +[16:12.50.973] END WMNewTab: 20 +[16:12.51.050] BEGIN WMNewTab: 60 +[16:12.51.050] END WMNewTab: 60 + + +[16:12.52.390] BEGIN WMNewTab: 20 +[16:12.52.390] END WMNewTab: 20 + + +[16:12.53.803] BEGIN WMNewTab: 20 +[16:12.53.803] END WMNewTab: 20 + + +[16:12.55.209] BEGIN WMNewTab: 20 +[16:12.55.209] END WMNewTab: 20 + + +[16:12.56.618] BEGIN WMNewTab: 20 +[16:12.56.618] END WMNewTab: 20 + + +[16:12.58.033] BEGIN WMNewTab: 20 +[16:12.58.033] END WMNewTab: 20 + + +[16:12.59.443] BEGIN WMNewTab: 20 +[16:12.59.443] END WMNewTab: 20 + + +[16:13.00.862] BEGIN WMNewTab: 20 +[16:13.00.862] END WMNewTab: 20 + + +[16:13.02.278] BEGIN WMNewTab: 20 +[16:13.02.278] END WMNewTab: 20 + + +[16:13.03.691] BEGIN WMNewTab: 20 +[16:13.03.691] END WMNewTab: 20 + + +[16:13.05.107] BEGIN WMNewTab: 20 +[16:13.05.107] END WMNewTab: 20 + + +[16:13.06.521] BEGIN WMNewTab: 20 +[16:13.06.521] END WMNewTab: 20 + + +[16:13.07.931] BEGIN WMNewTab: 20 +[16:13.07.931] END WMNewTab: 20 + + +[16:13.09.347] BEGIN WMNewTab: 20 +[16:13.09.347] END WMNewTab: 20 + + +[16:13.10.762] BEGIN WMNewTab: 20 +[16:13.10.762] END WMNewTab: 20 + + +[16:13.12.170] BEGIN WMNewTab: 20 +[16:13.12.170] END WMNewTab: 20 + + +[16:13.13.579] BEGIN WMNewTab: 20 +[16:13.13.579] END WMNewTab: 20 + + +[16:13.14.992] BEGIN WMNewTab: 20 +[16:13.14.992] END WMNewTab: 20 + + +[16:13.16.409] BEGIN WMNewTab: 20 +[16:13.16.409] END WMNewTab: 20 + + +[16:13.17.825] BEGIN WMNewTab: 20 +[16:13.17.825] END WMNewTab: 20 + + +[16:13.19.242] BEGIN WMNewTab: 20 +[16:13.19.242] END WMNewTab: 20 + + +[16:13.20.656] BEGIN WMNewTab: 20 +[16:13.20.656] END WMNewTab: 20 + +[16:13.21.082] BEGIN WMNewTab: 60 +[16:13.21.083] END WMNewTab: 60 + +[16:13.22.069] BEGIN WMNewTab: 20 +[16:13.22.069] END WMNewTab: 20 + + +[16:13.23.490] BEGIN WMNewTab: 20 +[16:13.23.490] END WMNewTab: 20 + + +[16:13.24.905] BEGIN WMNewTab: 20 +[16:13.24.905] END WMNewTab: 20 + + +[16:13.26.313] BEGIN WMNewTab: 20 +[16:13.26.313] END WMNewTab: 20 + + +[16:13.27.727] BEGIN WMNewTab: 20 +[16:13.27.727] END WMNewTab: 20 + + +[16:13.29.142] BEGIN WMNewTab: 20 +[16:13.29.142] END WMNewTab: 20 + + +[16:13.30.555] BEGIN WMNewTab: 20 +[16:13.30.555] END WMNewTab: 20 + + +[16:13.31.963] BEGIN WMNewTab: 20 +[16:13.31.963] END WMNewTab: 20 + + +[16:13.33.376] BEGIN WMNewTab: 20 +[16:13.33.376] END WMNewTab: 20 + + +[16:13.34.790] BEGIN WMNewTab: 20 +[16:13.34.790] END WMNewTab: 20 + + +[16:13.36.206] BEGIN WMNewTab: 20 +[16:13.36.206] END WMNewTab: 20 + + +[16:13.37.617] BEGIN WMNewTab: 20 +[16:13.37.617] END WMNewTab: 20 + + +[16:13.39.033] BEGIN WMNewTab: 20 +[16:13.39.033] END WMNewTab: 20 + + +[16:13.40.451] BEGIN WMNewTab: 20 +[16:13.40.451] END WMNewTab: 20 + + +[16:13.41.860] BEGIN WMNewTab: 20 +[16:13.41.860] END WMNewTab: 20 + + +[16:13.43.275] BEGIN WMNewTab: 20 +[16:13.43.275] END WMNewTab: 20 + + +[16:13.44.685] BEGIN WMNewTab: 20 +[16:13.44.685] END WMNewTab: 20 + + +[16:13.46.103] BEGIN WMNewTab: 20 +[16:13.46.103] END WMNewTab: 20 + + +[16:13.47.521] BEGIN WMNewTab: 20 +[16:13.47.521] END WMNewTab: 20 + + +[16:13.48.929] BEGIN WMNewTab: 20 +[16:13.48.929] END WMNewTab: 20 + + +[16:13.50.343] BEGIN WMNewTab: 20 +[16:13.50.343] END WMNewTab: 20 + +[16:13.51.114] BEGIN WMNewTab: 60 +[16:13.51.114] END WMNewTab: 60 + +[16:13.51.760] BEGIN WMNewTab: 20 +[16:13.51.760] END WMNewTab: 20 + + +[16:13.53.176] BEGIN WMNewTab: 20 +[16:13.53.176] END WMNewTab: 20 + + +[16:13.54.590] BEGIN WMNewTab: 20 +[16:13.54.590] END WMNewTab: 20 + + +[16:13.56.001] BEGIN WMNewTab: 20 +[16:13.56.001] END WMNewTab: 20 + + +[16:13.57.415] BEGIN WMNewTab: 20 +[16:13.57.415] END WMNewTab: 20 + + +[16:13.58.831] BEGIN WMNewTab: 20 +[16:13.58.831] END WMNewTab: 20 + + +[16:14.00.248] BEGIN WMNewTab: 20 +[16:14.00.248] END WMNewTab: 20 + + +[16:14.01.659] BEGIN WMNewTab: 20 +[16:14.01.659] END WMNewTab: 20 + + +[16:14.03.075] BEGIN WMNewTab: 20 +[16:14.03.075] END WMNewTab: 20 + + +[16:14.04.494] BEGIN WMNewTab: 20 +[16:14.04.494] END WMNewTab: 20 + + +[16:14.05.911] BEGIN WMNewTab: 20 +[16:14.05.911] END WMNewTab: 20 + + +[16:14.07.330] BEGIN WMNewTab: 20 +[16:14.07.330] END WMNewTab: 20 + + +[16:14.08.756] BEGIN WMNewTab: 20 +[16:14.08.756] END WMNewTab: 20 + + +[16:14.10.155] BEGIN WMNewTab: 20 +[16:14.10.155] END WMNewTab: 20 + + +[16:14.11.569] BEGIN WMNewTab: 20 +[16:14.11.569] END WMNewTab: 20 + + +[16:14.12.984] BEGIN WMNewTab: 20 +[16:14.12.984] END WMNewTab: 20 + + +[16:14.14.398] BEGIN WMNewTab: 20 +[16:14.14.398] END WMNewTab: 20 + + +[16:14.15.813] BEGIN WMNewTab: 20 +[16:14.15.813] END WMNewTab: 20 + + +[16:14.17.230] BEGIN WMNewTab: 20 +[16:14.17.230] END WMNewTab: 20 + + +[16:14.18.646] BEGIN WMNewTab: 20 +[16:14.18.646] END WMNewTab: 20 + + +[16:14.20.067] BEGIN WMNewTab: 20 +[16:14.20.067] END WMNewTab: 20 + +[16:14.21.143] BEGIN WMNewTab: 60 +[16:14.21.143] END WMNewTab: 60 +[16:14.21.480] BEGIN WMNewTab: 20 +[16:14.21.480] END WMNewTab: 20 + + +[16:14.22.890] BEGIN WMNewTab: 20 +[16:14.22.890] END WMNewTab: 20 + + +[16:14.24.310] BEGIN WMNewTab: 20 +[16:14.24.310] END WMNewTab: 20 + + +[16:14.25.722] BEGIN WMNewTab: 20 +[16:14.25.722] END WMNewTab: 20 + + +[16:14.27.142] BEGIN WMNewTab: 20 +[16:14.27.142] END WMNewTab: 20 + + +[16:14.28.551] BEGIN WMNewTab: 20 +[16:14.28.551] END WMNewTab: 20 + + +[16:14.29.967] BEGIN WMNewTab: 20 +[16:14.29.967] END WMNewTab: 20 + + +[16:14.31.382] BEGIN WMNewTab: 20 +[16:14.31.382] END WMNewTab: 20 + + +[16:14.32.796] BEGIN WMNewTab: 20 +[16:14.32.796] END WMNewTab: 20 + + +[16:14.34.213] BEGIN WMNewTab: 20 +[16:14.34.213] END WMNewTab: 20 + + +[16:14.35.625] BEGIN WMNewTab: 20 +[16:14.35.625] END WMNewTab: 20 + + +[16:14.36.971] BEGIN WMNewTab: 0 +[16:14.36.971] WMNewTab: FormClick +[16:14.36.971] WMNewTab: LooseFocus +[16:14.36.971] END WMNewTab: 0 +[16:14.36.971] BEGIN WMNewTab: 31 +[16:14.36.971] END WMNewTab: 31 +[16:14.37.041] BEGIN WMNewTab: 20 +[16:14.37.041] END WMNewTab: 20 + + +[16:14.38.273] BEGIN CWD +[16:14.38.364] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:14.38.364] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:14.38.364] (SSH-Browser) END VerifySFTPConnection(1) +[16:14.38.365] END CWD +[16:14.38.456] BEGIN WMNewTab: 20 +[16:14.38.456] END WMNewTab: 20 +[16:14.38.486] BEGIN CWD +[16:14.38.547] END CWD + + +[16:14.39.958] BEGIN WMNewTab: 20 +[16:14.39.958] END WMNewTab: 20 + + +[16:14.41.375] BEGIN WMNewTab: 20 +[16:14.41.375] END WMNewTab: 20 + + +[16:14.42.788] BEGIN WMNewTab: 20 +[16:14.42.788] END WMNewTab: 20 + + +[16:14.44.200] BEGIN WMNewTab: 20 +[16:14.44.200] END WMNewTab: 20 + + +[16:14.45.613] BEGIN WMNewTab: 20 +[16:14.45.613] END WMNewTab: 20 + + +[16:14.47.033] BEGIN WMNewTab: 20 +[16:14.47.033] END WMNewTab: 20 + +[16:14.47.651] BEGIN WMNewTab: 31 +[16:14.47.651] END WMNewTab: 31 +[16:14.47.651] BEGIN WMNewTab: 0 +[16:14.47.651] WMNewTab: FormClick +[16:14.47.651] WMNewTab: LooseFocus +[16:14.47.652] END WMNewTab: 0 + +[16:14.48.448] BEGIN WMNewTab: 20 +[16:14.48.448] END WMNewTab: 20 + +[16:14.49.531] BEGIN CWD +[16:14.49.606] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:14.49.606] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:14.49.606] (SSH-Browser) END VerifySFTPConnection(1) +[16:14.49.606] END CWD +[16:14.49.623] BEGIN CWD +[16:14.49.683] END CWD +[16:14.49.683] BEGIN WMNewTab: 20 +[16:14.49.683] END WMNewTab: 20 + + +[16:14.51.097] BEGIN WMNewTab: 20 +[16:14.51.097] END WMNewTab: 20 +[16:14.51.173] BEGIN WMNewTab: 60 +[16:14.51.173] END WMNewTab: 60 + + +[16:14.52.510] BEGIN WMNewTab: 20 +[16:14.52.510] END WMNewTab: 20 + + +[16:14.53.924] BEGIN WMNewTab: 20 +[16:14.53.924] END WMNewTab: 20 + + +[16:14.55.339] BEGIN WMNewTab: 20 +[16:14.55.339] END WMNewTab: 20 + + +[16:14.56.753] BEGIN WMNewTab: 20 +[16:14.56.753] END WMNewTab: 20 + + +[16:14.58.169] BEGIN WMNewTab: 20 +[16:14.58.169] END WMNewTab: 20 + + +[16:14.59.584] BEGIN WMNewTab: 20 +[16:14.59.584] END WMNewTab: 20 + + +[16:15.00.997] BEGIN WMNewTab: 20 +[16:15.00.997] END WMNewTab: 20 + + +[16:15.02.288] BEGIN WMNewTab: 0 +[16:15.02.288] WMNewTab: FormClick +[16:15.02.288] WMNewTab: LooseFocus +[16:15.02.288] END WMNewTab: 0 +[16:15.02.407] BEGIN WMNewTab: 0 +[16:15.02.407] WMNewTab: FormClick +[16:15.02.407] WMNewTab: LooseFocus +[16:15.02.408] END WMNewTab: 0 +[16:15.02.414] BEGIN WMNewTab: 20 +[16:15.02.414] END WMNewTab: 20 + + +[16:15.03.833] BEGIN WMNewTab: 20 +[16:15.03.833] END WMNewTab: 20 + + +[16:15.05.248] BEGIN WMNewTab: 20 +[16:15.05.248] END WMNewTab: 20 + + +[16:15.06.663] BEGIN WMNewTab: 20 +[16:15.06.663] END WMNewTab: 20 + +[16:15.07.731] BEGIN CWD +[16:15.07.792] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:15.07.792] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:15.07.792] (SSH-Browser) END VerifySFTPConnection(1) +[16:15.07.792] END CWD +[16:15.07.806] BEGIN CWD +[16:15.07.867] END CWD +[16:15.07.867] BEGIN WMNewTab: 20 +[16:15.07.867] END WMNewTab: 20 + + +[16:15.09.284] BEGIN WMNewTab: 20 +[16:15.09.284] END WMNewTab: 20 + + +[16:15.10.702] BEGIN WMNewTab: 20 +[16:15.10.702] END WMNewTab: 20 + + +[16:15.12.120] BEGIN WMNewTab: 20 +[16:15.12.120] END WMNewTab: 20 + + +[16:15.13.540] BEGIN WMNewTab: 20 +[16:15.13.540] END WMNewTab: 20 + +[16:15.14.008] BEGIN CWD +[16:15.14.083] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:15.14.083] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:15.14.083] (SSH-Browser) END VerifySFTPConnection(1) +[16:15.14.084] END CWD +[16:15.14.090] BEGIN CWD +[16:15.14.151] END CWD + +[16:15.15.119] BEGIN WMNewTab: 20 +[16:15.15.119] END WMNewTab: 20 + + +[16:15.16.321] BEGIN WMNewTab: 0 +[16:15.16.321] WMNewTab: FormClick +[16:15.16.321] WMNewTab: LooseFocus +[16:15.16.321] END WMNewTab: 0 +[16:15.16.520] BEGIN WMNewTab: 20 +[16:15.16.520] END WMNewTab: 20 + + +[16:15.17.931] BEGIN WMNewTab: 20 +[16:15.17.931] END WMNewTab: 20 +[16:15.17.974] BEGIN WMNewTab: 0 +[16:15.17.974] WMNewTab: FormClick +[16:15.17.974] WMNewTab: LooseFocus +[16:15.17.975] END WMNewTab: 0 + + +[16:15.19.346] BEGIN WMNewTab: 20 +[16:15.19.346] END WMNewTab: 20 + + +[16:15.20.764] BEGIN WMNewTab: 20 +[16:15.20.764] END WMNewTab: 20 + +[16:15.21.205] BEGIN WMNewTab: 60 +[16:15.21.205] END WMNewTab: 60 + +[16:15.22.181] BEGIN WMNewTab: 20 +[16:15.22.181] END WMNewTab: 20 + + +[16:15.23.602] BEGIN WMNewTab: 20 +[16:15.23.602] END WMNewTab: 20 + + +[16:15.25.017] BEGIN WMNewTab: 20 +[16:15.25.017] END WMNewTab: 20 + + +[16:15.26.432] BEGIN WMNewTab: 20 +[16:15.26.432] END WMNewTab: 20 + + +[16:15.27.839] BEGIN WMNewTab: 20 +[16:15.27.839] END WMNewTab: 20 + + +[16:15.29.253] BEGIN WMNewTab: 20 +[16:15.29.253] END WMNewTab: 20 + + +[16:15.30.672] BEGIN WMNewTab: 20 +[16:15.30.672] END WMNewTab: 20 + + +[16:15.32.084] BEGIN WMNewTab: 20 +[16:15.32.084] END WMNewTab: 20 + + +[16:15.33.517] BEGIN WMNewTab: 20 +[16:15.33.517] END WMNewTab: 20 + + +[16:15.34.925] BEGIN WMNewTab: 20 +[16:15.34.925] END WMNewTab: 20 + +[16:15.35.488] BEGIN WMNewTab: 0 +[16:15.35.489] WMNewTab: FormClick +[16:15.35.489] WMNewTab: LooseFocus +[16:15.35.489] END WMNewTab: 0 +[16:15.35.489] BEGIN WMNewTab: 31 +[16:15.35.489] END WMNewTab: 31 + +[16:15.36.338] BEGIN WMNewTab: 20 +[16:15.36.338] END WMNewTab: 20 + + +[16:15.37.739] BEGIN CWD +[16:15.37.754] BEGIN WMNewTab: 20 +[16:15.37.754] END WMNewTab: 20 +[16:15.37.800] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:15.37.800] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:15.37.800] (SSH-Browser) END VerifySFTPConnection(1) +[16:15.37.800] END CWD +[16:15.37.814] BEGIN CWD +[16:15.37.874] END CWD + + +[16:15.39.283] BEGIN WMNewTab: 20 +[16:15.39.283] END WMNewTab: 20 + + +[16:15.40.701] BEGIN WMNewTab: 20 +[16:15.40.701] END WMNewTab: 20 + + +[16:15.42.116] BEGIN WMNewTab: 20 +[16:15.42.116] END WMNewTab: 20 +[16:15.42.216] BEGIN WMNewTab: 31 +[16:15.42.216] END WMNewTab: 31 +[16:15.42.216] BEGIN WMNewTab: 0 +[16:15.42.216] WMNewTab: FormClick +[16:15.42.216] WMNewTab: LooseFocus +[16:15.42.217] END WMNewTab: 0 + +[16:15.43.330] BEGIN CWD +[16:15.43.391] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:15.43.391] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:15.43.391] (SSH-Browser) END VerifySFTPConnection(1) +[16:15.43.391] END CWD +[16:15.43.392] BEGIN WMNewTab: 20 +[16:15.43.392] END WMNewTab: 20 +[16:15.43.406] BEGIN CWD +[16:15.43.466] END CWD + + +[16:15.44.882] BEGIN WMNewTab: 20 +[16:15.44.882] END WMNewTab: 20 + + +[16:15.46.298] BEGIN WMNewTab: 20 +[16:15.46.298] END WMNewTab: 20 + + +[16:15.47.712] BEGIN WMNewTab: 20 +[16:15.47.712] END WMNewTab: 20 + + +[16:15.49.125] BEGIN WMNewTab: 20 +[16:15.49.125] END WMNewTab: 20 + + +[16:15.50.538] BEGIN WMNewTab: 20 +[16:15.50.538] END WMNewTab: 20 + +[16:15.51.236] BEGIN WMNewTab: 60 +[16:15.51.236] END WMNewTab: 60 +[16:15.51.552] BEGIN WMNewTab: 0 +[16:15.51.552] WMNewTab: FormClick +[16:15.51.552] WMNewTab: LooseFocus +[16:15.51.552] END WMNewTab: 0 + +[16:15.51.952] BEGIN WMNewTab: 20 +[16:15.51.952] END WMNewTab: 20 + +[16:15.53.050] BEGIN WMNewTab: 0 +[16:15.53.050] WMNewTab: FormClick +[16:15.53.050] WMNewTab: LooseFocus +[16:15.53.053] END WMNewTab: 0 +[16:15.53.366] BEGIN WMNewTab: 20 +[16:15.53.366] END WMNewTab: 20 + + +[16:15.54.782] BEGIN WMNewTab: 20 +[16:15.54.782] END WMNewTab: 20 + + +[16:15.56.200] BEGIN WMNewTab: 20 +[16:15.56.200] END WMNewTab: 20 + + +[16:15.57.617] BEGIN WMNewTab: 20 +[16:15.57.617] END WMNewTab: 20 + + +[16:15.59.029] BEGIN WMNewTab: 20 +[16:15.59.029] END WMNewTab: 20 + + +[16:16.00.442] BEGIN WMNewTab: 20 +[16:16.00.442] END WMNewTab: 20 + + +[16:16.01.853] BEGIN WMNewTab: 20 +[16:16.01.853] END WMNewTab: 20 + + +[16:16.03.262] BEGIN WMNewTab: 20 +[16:16.03.262] END WMNewTab: 20 + + +[16:16.04.675] BEGIN WMNewTab: 20 +[16:16.04.675] END WMNewTab: 20 + + +[16:16.06.087] BEGIN WMNewTab: 20 +[16:16.06.087] END WMNewTab: 20 + + +[16:16.07.496] BEGIN WMNewTab: 20 +[16:16.07.496] END WMNewTab: 20 + + +[16:16.08.908] BEGIN WMNewTab: 20 +[16:16.08.908] END WMNewTab: 20 + + +[16:16.10.320] BEGIN WMNewTab: 20 +[16:16.10.320] END WMNewTab: 20 + + +[16:16.11.732] BEGIN WMNewTab: 20 +[16:16.11.732] END WMNewTab: 20 + + +[16:16.13.141] BEGIN WMNewTab: 20 +[16:16.13.141] END WMNewTab: 20 + + +[16:16.14.554] BEGIN WMNewTab: 20 +[16:16.14.554] END WMNewTab: 20 + + +[16:16.15.968] BEGIN WMNewTab: 20 +[16:16.15.968] END WMNewTab: 20 + + +[16:16.17.384] BEGIN WMNewTab: 20 +[16:16.17.384] END WMNewTab: 20 + + +[16:16.18.799] BEGIN WMNewTab: 20 +[16:16.18.799] END WMNewTab: 20 + + +[16:16.20.057] BEGIN WMNewTab: 0 +[16:16.20.057] WMNewTab: FormClick +[16:16.20.058] WMNewTab: LooseFocus +[16:16.20.058] END WMNewTab: 0 +[16:16.20.058] BEGIN WMNewTab: 31 +[16:16.20.058] END WMNewTab: 31 +[16:16.20.215] BEGIN WMNewTab: 20 +[16:16.20.215] END WMNewTab: 20 + +[16:16.21.267] BEGIN WMNewTab: 60 +[16:16.21.267] END WMNewTab: 60 + +[16:16.21.633] BEGIN WMNewTab: 20 +[16:16.21.633] END WMNewTab: 20 + +[16:16.22.286] BEGIN CWD +[16:16.22.347] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:16.22.347] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:16.22.347] (SSH-Browser) END VerifySFTPConnection(1) +[16:16.22.347] END CWD +[16:16.22.361] BEGIN CWD +[16:16.22.422] END CWD + +[16:16.22.896] BEGIN WMNewTab: 20 +[16:16.22.896] END WMNewTab: 20 + + +[16:16.24.310] BEGIN WMNewTab: 20 +[16:16.24.310] END WMNewTab: 20 + + +[16:16.25.721] BEGIN WMNewTab: 20 +[16:16.25.721] END WMNewTab: 20 + + +[16:16.27.135] BEGIN WMNewTab: 20 +[16:16.27.135] END WMNewTab: 20 + + +[16:16.28.549] BEGIN WMNewTab: 20 +[16:16.28.549] END WMNewTab: 20 + + +[16:16.29.968] BEGIN WMNewTab: 20 +[16:16.29.968] END WMNewTab: 20 + + +[16:16.31.381] BEGIN WMNewTab: 20 +[16:16.31.381] END WMNewTab: 20 + + +[16:16.32.802] BEGIN WMNewTab: 20 +[16:16.32.802] END WMNewTab: 20 + + +[16:16.34.215] BEGIN WMNewTab: 20 +[16:16.34.215] END WMNewTab: 20 + + +[16:16.35.635] BEGIN WMNewTab: 20 +[16:16.35.635] END WMNewTab: 20 + + +[16:16.37.047] BEGIN WMNewTab: 20 +[16:16.37.047] END WMNewTab: 20 + +[16:16.37.842] BEGIN WMNewTab: 0 +[16:16.37.842] WMNewTab: FormClick +[16:16.37.842] WMNewTab: LooseFocus +[16:16.37.842] END WMNewTab: 0 + +[16:16.38.462] BEGIN WMNewTab: 20 +[16:16.38.462] END WMNewTab: 20 +[16:16.38.762] BEGIN WMNewTab: 0 +[16:16.38.762] WMNewTab: FormClick +[16:16.38.762] WMNewTab: LooseFocus +[16:16.38.765] END WMNewTab: 0 + +[16:16.39.874] BEGIN WMNewTab: 20 +[16:16.39.874] END WMNewTab: 20 + + +[16:16.41.288] BEGIN WMNewTab: 20 +[16:16.41.288] END WMNewTab: 20 + + +[16:16.42.706] BEGIN WMNewTab: 20 +[16:16.42.706] END WMNewTab: 20 + + +[16:16.44.122] BEGIN WMNewTab: 20 +[16:16.44.122] END WMNewTab: 20 + + +[16:16.45.533] BEGIN WMNewTab: 20 +[16:16.45.533] END WMNewTab: 20 + + +[16:16.46.957] BEGIN WMNewTab: 20 +[16:16.46.957] END WMNewTab: 20 + + +[16:16.48.364] BEGIN WMNewTab: 20 +[16:16.48.364] END WMNewTab: 20 + + +[16:16.49.779] BEGIN WMNewTab: 20 +[16:16.49.779] END WMNewTab: 20 + + +[16:16.51.195] BEGIN WMNewTab: 20 +[16:16.51.195] END WMNewTab: 20 +[16:16.51.279] BEGIN WMNewTab: 60 +[16:16.51.279] END WMNewTab: 60 + + +[16:16.52.612] BEGIN WMNewTab: 20 +[16:16.52.612] END WMNewTab: 20 +[16:16.52.707] BEGIN WMNewTab: 0 +[16:16.52.707] WMNewTab: FormClick +[16:16.52.707] WMNewTab: LooseFocus +[16:16.52.707] END WMNewTab: 0 +[16:16.52.850] BEGIN WMNewTab: 0 +[16:16.52.850] WMNewTab: FormClick +[16:16.52.850] WMNewTab: LooseFocus +[16:16.52.852] END WMNewTab: 0 + +[16:16.53.562] BEGIN WMNewTab: 0 +[16:16.53.562] WMNewTab: FormClick +[16:16.53.562] WMNewTab: LooseFocus +[16:16.53.562] END WMNewTab: 0 +[16:16.53.562] BEGIN WMNewTab: 31 +[16:16.53.562] END WMNewTab: 31 + +[16:16.54.027] BEGIN WMNewTab: 20 +[16:16.54.027] END WMNewTab: 20 + + +[16:16.55.434] BEGIN WMNewTab: 20 +[16:16.55.434] END WMNewTab: 20 + + +[16:16.56.772] BEGIN CWD +[16:16.56.832] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:16.56.832] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:16.56.832] (SSH-Browser) END VerifySFTPConnection(1) +[16:16.56.832] END CWD +[16:16.56.849] BEGIN WMNewTab: 20 +[16:16.56.849] END WMNewTab: 20 +[16:16.56.879] BEGIN CWD +[16:16.56.939] END CWD + + +[16:16.58.355] BEGIN WMNewTab: 20 +[16:16.58.355] END WMNewTab: 20 + + +[16:16.59.768] BEGIN WMNewTab: 20 +[16:16.59.768] END WMNewTab: 20 + + +[16:17.01.185] BEGIN WMNewTab: 20 +[16:17.01.185] END WMNewTab: 20 + + +[16:17.02.605] BEGIN WMNewTab: 20 +[16:17.02.605] END WMNewTab: 20 + + +[16:17.04.019] BEGIN WMNewTab: 20 +[16:17.04.019] END WMNewTab: 20 + + +[16:17.05.431] BEGIN WMNewTab: 20 +[16:17.05.431] END WMNewTab: 20 + + +[16:17.06.851] BEGIN WMNewTab: 20 +[16:17.06.851] END WMNewTab: 20 + + +[16:17.08.264] BEGIN WMNewTab: 20 +[16:17.08.264] END WMNewTab: 20 + + +[16:17.09.674] BEGIN WMNewTab: 20 +[16:17.09.674] END WMNewTab: 20 + + +[16:17.11.087] BEGIN WMNewTab: 20 +[16:17.11.087] END WMNewTab: 20 + + +[16:17.12.504] BEGIN WMNewTab: 20 +[16:17.12.504] END WMNewTab: 20 + + +[16:17.13.917] BEGIN WMNewTab: 20 +[16:17.13.917] END WMNewTab: 20 + + +[16:17.15.340] BEGIN WMNewTab: 20 +[16:17.15.340] END WMNewTab: 20 + + +[16:17.16.749] BEGIN WMNewTab: 20 +[16:17.16.749] END WMNewTab: 20 + + +[16:17.18.161] BEGIN WMNewTab: 20 +[16:17.18.161] END WMNewTab: 20 + + +[16:17.19.580] BEGIN WMNewTab: 20 +[16:17.19.580] END WMNewTab: 20 + + +[16:17.20.995] BEGIN WMNewTab: 20 +[16:17.20.995] END WMNewTab: 20 +[16:17.21.310] BEGIN WMNewTab: 60 +[16:17.21.310] END WMNewTab: 60 + +[16:17.22.406] BEGIN WMNewTab: 20 +[16:17.22.406] END WMNewTab: 20 + + +[16:17.23.740] BEGIN WMNewTab: 0 +[16:17.23.740] WMNewTab: FormClick +[16:17.23.740] WMNewTab: LooseFocus +[16:17.23.740] END WMNewTab: 0 +[16:17.23.820] BEGIN WMNewTab: 20 +[16:17.23.820] END WMNewTab: 20 +[16:17.24.139] BEGIN WMNewTab: 0 +[16:17.24.139] WMNewTab: FormClick +[16:17.24.139] WMNewTab: LooseFocus +[16:17.24.139] END WMNewTab: 0 +[16:17.24.467] BEGIN WMNewTab: 0 +[16:17.24.467] WMNewTab: FormClick +[16:17.24.467] WMNewTab: LooseFocus +[16:17.24.467] END WMNewTab: 0 +[16:17.24.564] BEGIN WMNewTab: 0 +[16:17.24.564] WMNewTab: FormClick +[16:17.24.564] WMNewTab: LooseFocus +[16:17.24.565] END WMNewTab: 0 + +[16:17.25.235] BEGIN WMNewTab: 20 +[16:17.25.235] END WMNewTab: 20 + + +[16:17.26.650] BEGIN WMNewTab: 20 +[16:17.26.650] END WMNewTab: 20 + + +[16:17.28.068] BEGIN WMNewTab: 20 +[16:17.28.068] END WMNewTab: 20 + + +[16:17.29.479] BEGIN WMNewTab: 20 +[16:17.29.479] END WMNewTab: 20 +[16:17.29.788] BEGIN WMNewTab: 0 +[16:17.29.788] WMNewTab: FormClick +[16:17.29.788] WMNewTab: LooseFocus +[16:17.29.788] END WMNewTab: 0 + +[16:17.30.891] BEGIN WMNewTab: 20 +[16:17.30.891] END WMNewTab: 20 +[16:17.31.175] BEGIN WMNewTab: 0 +[16:17.31.175] WMNewTab: FormClick +[16:17.31.175] WMNewTab: LooseFocus +[16:17.31.178] END WMNewTab: 0 +[16:17.31.404] BEGIN WMNewTab: 0 +[16:17.31.404] WMNewTab: FormClick +[16:17.31.404] WMNewTab: LooseFocus +[16:17.31.405] END WMNewTab: 0 +[16:17.31.515] BEGIN WMNewTab: 0 +[16:17.31.515] WMNewTab: FormClick +[16:17.31.515] WMNewTab: LooseFocus +[16:17.31.515] END WMNewTab: 0 + +[16:17.32.308] BEGIN WMNewTab: 20 +[16:17.32.308] END WMNewTab: 20 + + +[16:17.33.726] BEGIN WMNewTab: 20 +[16:17.33.726] END WMNewTab: 20 + +[16:17.34.872] BEGIN WMNewTab: 0 +[16:17.34.872] WMNewTab: FormClick +[16:17.34.872] WMNewTab: LooseFocus +[16:17.34.872] END WMNewTab: 0 +[16:17.35.147] BEGIN WMNewTab: 20 +[16:17.35.147] END WMNewTab: 20 + + +[16:17.36.387] BEGIN WMNewTab: 0 +[16:17.36.387] WMNewTab: FormClick +[16:17.36.387] WMNewTab: LooseFocus +[16:17.36.389] END WMNewTab: 0 +[16:17.36.567] BEGIN WMNewTab: 20 +[16:17.36.567] END WMNewTab: 20 +[16:17.36.900] BEGIN WMNewTab: 0 +[16:17.36.900] WMNewTab: FormClick +[16:17.36.900] WMNewTab: LooseFocus +[16:17.36.900] END WMNewTab: 0 +[16:17.37.019] BEGIN WMNewTab: 0 +[16:17.37.019] WMNewTab: FormClick +[16:17.37.019] WMNewTab: LooseFocus +[16:17.37.020] END WMNewTab: 0 + +[16:17.37.981] BEGIN WMNewTab: 20 +[16:17.37.981] END WMNewTab: 20 + + +[16:17.39.399] BEGIN WMNewTab: 20 +[16:17.39.399] END WMNewTab: 20 + + +[16:17.40.810] BEGIN WMNewTab: 20 +[16:17.40.810] END WMNewTab: 20 + + +[16:17.42.226] BEGIN WMNewTab: 20 +[16:17.42.226] END WMNewTab: 20 + + +[16:17.43.645] BEGIN WMNewTab: 20 +[16:17.43.645] END WMNewTab: 20 + + +[16:17.45.058] BEGIN WMNewTab: 20 +[16:17.45.058] END WMNewTab: 20 + + +[16:17.46.476] BEGIN WMNewTab: 20 +[16:17.46.476] END WMNewTab: 20 + + +[16:17.47.889] BEGIN WMNewTab: 20 +[16:17.47.889] END WMNewTab: 20 + + +[16:17.49.301] BEGIN WMNewTab: 20 +[16:17.49.301] END WMNewTab: 20 + + +[16:17.50.718] BEGIN WMNewTab: 20 +[16:17.50.718] END WMNewTab: 20 + +[16:17.51.342] BEGIN WMNewTab: 60 +[16:17.51.342] END WMNewTab: 60 + +[16:17.52.133] BEGIN WMNewTab: 20 +[16:17.52.133] END WMNewTab: 20 + + +[16:17.53.551] BEGIN WMNewTab: 20 +[16:17.53.551] END WMNewTab: 20 + + +[16:17.54.964] BEGIN WMNewTab: 20 +[16:17.54.964] END WMNewTab: 20 + + +[16:17.56.381] BEGIN WMNewTab: 20 +[16:17.56.381] END WMNewTab: 20 + + +[16:17.57.800] BEGIN WMNewTab: 20 +[16:17.57.800] END WMNewTab: 20 + + +[16:17.59.217] BEGIN WMNewTab: 20 +[16:17.59.217] END WMNewTab: 20 + + +[16:18.00.635] BEGIN WMNewTab: 20 +[16:18.00.635] END WMNewTab: 20 + + +[16:18.02.049] BEGIN WMNewTab: 20 +[16:18.02.049] END WMNewTab: 20 + + +[16:18.03.337] BEGIN WMNewTab: 0 +[16:18.03.337] WMNewTab: FormClick +[16:18.03.337] WMNewTab: LooseFocus +[16:18.03.337] END WMNewTab: 0 +[16:18.03.460] BEGIN WMNewTab: 20 +[16:18.03.460] END WMNewTab: 20 + +[16:18.03.856] BEGIN WMNewTab: 0 +[16:18.03.856] WMNewTab: FormClick +[16:18.03.856] WMNewTab: LooseFocus +[16:18.03.858] END WMNewTab: 0 +[16:18.03.928] BEGIN WMNewTab: 0 +[16:18.03.928] WMNewTab: FormClick +[16:18.03.928] WMNewTab: LooseFocus +[16:18.03.929] END WMNewTab: 0 +[16:18.04.151] BEGIN WMNewTab: 0 +[16:18.04.151] WMNewTab: FormClick +[16:18.04.151] WMNewTab: LooseFocus +[16:18.04.152] END WMNewTab: 0 + +[16:18.04.874] BEGIN WMNewTab: 20 +[16:18.04.874] END WMNewTab: 20 +[16:18.04.950] BEGIN WMNewTab: 0 +[16:18.04.950] WMNewTab: FormClick +[16:18.04.950] WMNewTab: LooseFocus +[16:18.04.950] END WMNewTab: 0 + +[16:18.06.032] BEGIN WMNewTab: 0 +[16:18.06.032] WMNewTab: FormClick +[16:18.06.032] WMNewTab: LooseFocus +[16:18.06.034] END WMNewTab: 0 +[16:18.06.290] BEGIN WMNewTab: 20 +[16:18.06.290] END WMNewTab: 20 + + +[16:18.07.707] BEGIN WMNewTab: 20 +[16:18.07.707] END WMNewTab: 20 + + +[16:18.09.124] BEGIN WMNewTab: 20 +[16:18.09.124] END WMNewTab: 20 + + +[16:18.10.538] BEGIN WMNewTab: 20 +[16:18.10.538] END WMNewTab: 20 + + +[16:18.11.953] BEGIN WMNewTab: 20 +[16:18.11.953] END WMNewTab: 20 + + +[16:18.13.367] BEGIN WMNewTab: 20 +[16:18.13.367] END WMNewTab: 20 + + +[16:18.14.780] BEGIN WMNewTab: 20 +[16:18.14.780] END WMNewTab: 20 + + +[16:18.16.201] BEGIN WMNewTab: 20 +[16:18.16.201] END WMNewTab: 20 + + +[16:18.17.611] BEGIN WMNewTab: 20 +[16:18.17.611] END WMNewTab: 20 + + +[16:18.19.035] BEGIN WMNewTab: 20 +[16:18.19.035] END WMNewTab: 20 + +[16:18.19.755] BEGIN WMNewTab: 0 +[16:18.19.755] WMNewTab: FormClick +[16:18.19.755] WMNewTab: LooseFocus +[16:18.19.755] END WMNewTab: 0 +[16:18.19.755] BEGIN WMNewTab: 31 +[16:18.19.755] END WMNewTab: 31 + +[16:18.20.449] BEGIN WMNewTab: 20 +[16:18.20.449] END WMNewTab: 20 + +[16:18.21.373] BEGIN WMNewTab: 60 +[16:18.21.373] END WMNewTab: 60 + +[16:18.21.863] BEGIN WMNewTab: 20 +[16:18.21.863] END WMNewTab: 20 + +[16:18.22.363] BEGIN CWD +[16:18.22.424] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:18.22.424] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:18.22.424] (SSH-Browser) END VerifySFTPConnection(1) +[16:18.22.424] END CWD +[16:18.22.439] BEGIN CWD +[16:18.22.502] END CWD + +[16:18.23.451] BEGIN WMNewTab: 20 +[16:18.23.451] END WMNewTab: 20 + + +[16:18.24.866] BEGIN WMNewTab: 20 +[16:18.24.866] END WMNewTab: 20 + + +[16:18.26.281] BEGIN WMNewTab: 20 +[16:18.26.281] END WMNewTab: 20 + + +[16:18.27.693] BEGIN WMNewTab: 20 +[16:18.27.693] END WMNewTab: 20 + + +[16:18.28.969] BEGIN WMNewTab: 0 +[16:18.28.969] WMNewTab: FormClick +[16:18.28.969] WMNewTab: LooseFocus +[16:18.28.969] END WMNewTab: 0 +[16:18.29.103] BEGIN WMNewTab: 20 +[16:18.29.103] END WMNewTab: 20 + +[16:18.29.489] BEGIN WMNewTab: 0 +[16:18.29.489] WMNewTab: FormClick +[16:18.29.489] WMNewTab: LooseFocus +[16:18.29.491] END WMNewTab: 0 +[16:18.29.650] BEGIN WMNewTab: 0 +[16:18.29.650] WMNewTab: FormClick +[16:18.29.650] WMNewTab: LooseFocus +[16:18.29.650] END WMNewTab: 0 +[16:18.29.736] BEGIN WMNewTab: 0 +[16:18.29.736] WMNewTab: FormClick +[16:18.29.736] WMNewTab: LooseFocus +[16:18.29.738] END WMNewTab: 0 +[16:18.29.989] BEGIN WMNewTab: 0 +[16:18.29.989] WMNewTab: FormClick +[16:18.29.989] WMNewTab: LooseFocus +[16:18.29.990] END WMNewTab: 0 + +[16:18.30.518] BEGIN WMNewTab: 20 +[16:18.30.518] END WMNewTab: 20 +[16:18.30.529] BEGIN WMNewTab: 0 +[16:18.30.529] WMNewTab: FormClick +[16:18.30.529] WMNewTab: LooseFocus +[16:18.30.532] END WMNewTab: 0 + +[16:18.31.265] BEGIN WMNewTab: 0 +[16:18.31.265] WMNewTab: FormClick +[16:18.31.265] WMNewTab: LooseFocus +[16:18.31.265] END WMNewTab: 0 + +[16:18.31.930] BEGIN WMNewTab: 20 +[16:18.31.930] END WMNewTab: 20 +[16:18.32.250] BEGIN WMNewTab: 0 +[16:18.32.250] WMNewTab: FormClick +[16:18.32.250] WMNewTab: LooseFocus +[16:18.32.253] END WMNewTab: 0 + +[16:18.33.347] BEGIN WMNewTab: 20 +[16:18.33.347] END WMNewTab: 20 + + +[16:18.34.763] BEGIN WMNewTab: 20 +[16:18.34.763] END WMNewTab: 20 + + +[16:18.36.177] BEGIN WMNewTab: 20 +[16:18.36.177] END WMNewTab: 20 + + +[16:18.37.592] BEGIN WMNewTab: 20 +[16:18.37.592] END WMNewTab: 20 + + +[16:18.39.006] BEGIN WMNewTab: 20 +[16:18.39.006] END WMNewTab: 20 + + +[16:18.40.425] BEGIN WMNewTab: 20 +[16:18.40.425] END WMNewTab: 20 + + +[16:18.41.843] BEGIN WMNewTab: 20 +[16:18.41.843] END WMNewTab: 20 + +[16:18.42.673] BEGIN WMNewTab: 0 +[16:18.42.673] WMNewTab: FormClick +[16:18.42.673] WMNewTab: LooseFocus +[16:18.42.673] END WMNewTab: 0 +[16:18.42.673] BEGIN WMNewTab: 31 +[16:18.42.673] END WMNewTab: 31 +[16:18.42.761] BEGIN WMNewTab: 0 +[16:18.42.761] WMNewTab: FormClick +[16:18.42.761] WMNewTab: LooseFocus +[16:18.42.761] END WMNewTab: 0 + +[16:18.43.254] BEGIN WMNewTab: 20 +[16:18.43.254] END WMNewTab: 20 +[16:18.43.496] BEGIN CWD +[16:18.43.557] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:18.43.557] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:18.43.557] (SSH-Browser) END VerifySFTPConnection(1) +[16:18.43.557] END CWD +[16:18.43.572] BEGIN CWD +[16:18.43.632] END CWD + +[16:18.44.575] BEGIN WMNewTab: 20 +[16:18.44.575] END WMNewTab: 20 + + +[16:18.45.986] BEGIN WMNewTab: 20 +[16:18.45.986] END WMNewTab: 20 + + +[16:18.47.404] BEGIN WMNewTab: 20 +[16:18.47.404] END WMNewTab: 20 + + +[16:18.48.822] BEGIN WMNewTab: 20 +[16:18.48.822] END WMNewTab: 20 + + +[16:18.50.242] BEGIN WMNewTab: 20 +[16:18.50.242] END WMNewTab: 20 + +[16:18.51.405] BEGIN WMNewTab: 60 +[16:18.51.405] END WMNewTab: 60 +[16:18.51.658] BEGIN WMNewTab: 20 +[16:18.51.658] END WMNewTab: 20 + + +[16:18.53.072] BEGIN WMNewTab: 20 +[16:18.53.072] END WMNewTab: 20 + + +[16:18.54.490] BEGIN WMNewTab: 20 +[16:18.54.490] END WMNewTab: 20 + + +[16:18.55.904] BEGIN WMNewTab: 20 +[16:18.55.904] END WMNewTab: 20 + + +[16:18.57.320] BEGIN WMNewTab: 20 +[16:18.57.320] END WMNewTab: 20 + + +[16:18.58.736] BEGIN WMNewTab: 20 +[16:18.58.736] END WMNewTab: 20 + + +[16:19.00.152] BEGIN WMNewTab: 20 +[16:19.00.152] END WMNewTab: 20 + + +[16:19.01.570] BEGIN WMNewTab: 20 +[16:19.01.570] END WMNewTab: 20 + + +[16:19.02.989] BEGIN WMNewTab: 20 +[16:19.02.989] END WMNewTab: 20 + + +[16:19.04.410] BEGIN WMNewTab: 20 +[16:19.04.410] END WMNewTab: 20 + + +[16:19.05.830] BEGIN WMNewTab: 20 +[16:19.05.830] END WMNewTab: 20 + + +[16:19.07.246] BEGIN WMNewTab: 20 +[16:19.07.246] END WMNewTab: 20 + + +[16:19.08.665] BEGIN WMNewTab: 20 +[16:19.08.665] END WMNewTab: 20 + + +[16:19.10.085] BEGIN WMNewTab: 20 +[16:19.10.085] END WMNewTab: 20 + + +[16:19.11.504] BEGIN WMNewTab: 20 +[16:19.11.504] END WMNewTab: 20 + + +[16:19.12.921] BEGIN WMNewTab: 20 +[16:19.12.921] END WMNewTab: 20 + + +[16:19.14.343] BEGIN WMNewTab: 20 +[16:19.14.343] END WMNewTab: 20 + + +[16:19.15.765] BEGIN WMNewTab: 20 +[16:19.15.765] END WMNewTab: 20 + + +[16:19.17.179] BEGIN WMNewTab: 20 +[16:19.17.179] END WMNewTab: 20 + + +[16:19.18.599] BEGIN WMNewTab: 20 +[16:19.18.599] END WMNewTab: 20 + + +[16:19.20.029] BEGIN WMNewTab: 20 +[16:19.20.029] END WMNewTab: 20 + + +[16:19.21.430] BEGIN WMNewTab: 20 +[16:19.21.430] END WMNewTab: 20 +[16:19.21.437] BEGIN WMNewTab: 60 +[16:19.21.437] END WMNewTab: 60 + + +[16:19.22.844] BEGIN WMNewTab: 20 +[16:19.22.844] END WMNewTab: 20 + + +[16:19.24.259] BEGIN WMNewTab: 20 +[16:19.24.259] END WMNewTab: 20 + + +[16:19.25.678] BEGIN WMNewTab: 20 +[16:19.25.678] END WMNewTab: 20 +[16:19.25.764] BEGIN WMNewTab: 0 +[16:19.25.764] WMNewTab: FormClick +[16:19.25.764] WMNewTab: LooseFocus +[16:19.25.764] END WMNewTab: 0 +[16:19.25.889] BEGIN WMNewTab: 0 +[16:19.25.889] WMNewTab: FormClick +[16:19.25.890] WMNewTab: LooseFocus +[16:19.25.890] END WMNewTab: 0 + + +[16:19.27.095] BEGIN WMNewTab: 20 +[16:19.27.095] END WMNewTab: 20 + + +[16:19.28.508] BEGIN WMNewTab: 20 +[16:19.28.508] END WMNewTab: 20 + + +[16:19.29.932] BEGIN WMNewTab: 20 +[16:19.29.932] END WMNewTab: 20 + + +[16:19.31.354] BEGIN WMNewTab: 20 +[16:19.31.354] END WMNewTab: 20 + + +[16:19.32.772] BEGIN WMNewTab: 20 +[16:19.32.772] END WMNewTab: 20 + + +[16:19.34.192] BEGIN WMNewTab: 20 +[16:19.34.192] END WMNewTab: 20 + + +[16:19.35.612] BEGIN WMNewTab: 20 +[16:19.35.612] END WMNewTab: 20 + + +[16:19.37.028] BEGIN WMNewTab: 20 +[16:19.37.028] END WMNewTab: 20 + + +[16:19.38.439] BEGIN WMNewTab: 20 +[16:19.38.439] END WMNewTab: 20 + + +[16:19.39.858] BEGIN WMNewTab: 20 +[16:19.39.858] END WMNewTab: 20 + + +[16:19.41.270] BEGIN WMNewTab: 20 +[16:19.41.270] END WMNewTab: 20 + + +[16:19.42.690] BEGIN WMNewTab: 20 +[16:19.42.690] END WMNewTab: 20 + + +[16:19.44.113] BEGIN WMNewTab: 20 +[16:19.44.113] END WMNewTab: 20 + + +[16:19.45.540] BEGIN WMNewTab: 20 +[16:19.45.540] END WMNewTab: 20 + + +[16:19.46.948] BEGIN WMNewTab: 20 +[16:19.46.948] END WMNewTab: 20 + + +[16:19.48.364] BEGIN WMNewTab: 20 +[16:19.48.364] END WMNewTab: 20 + + +[16:19.49.784] BEGIN WMNewTab: 20 +[16:19.49.784] END WMNewTab: 20 + + +[16:19.51.201] BEGIN WMNewTab: 20 +[16:19.51.201] END WMNewTab: 20 +[16:19.51.469] BEGIN WMNewTab: 60 +[16:19.51.469] END WMNewTab: 60 + +[16:19.52.623] BEGIN WMNewTab: 20 +[16:19.52.623] END WMNewTab: 20 + + +[16:19.54.038] BEGIN WMNewTab: 20 +[16:19.54.038] END WMNewTab: 20 + + +[16:19.55.456] BEGIN WMNewTab: 20 +[16:19.55.456] END WMNewTab: 20 + + +[16:19.56.876] BEGIN WMNewTab: 20 +[16:19.56.876] END WMNewTab: 20 + + +[16:19.58.293] BEGIN WMNewTab: 20 +[16:19.58.293] END WMNewTab: 20 + + +[16:19.59.713] BEGIN WMNewTab: 20 +[16:19.59.713] END WMNewTab: 20 + + +[16:20.01.132] BEGIN WMNewTab: 20 +[16:20.01.132] END WMNewTab: 20 + + +[16:20.02.549] BEGIN WMNewTab: 20 +[16:20.02.549] END WMNewTab: 20 + + +[16:20.03.967] BEGIN WMNewTab: 20 +[16:20.03.967] END WMNewTab: 20 + + +[16:20.05.389] BEGIN WMNewTab: 20 +[16:20.05.389] END WMNewTab: 20 + + +[16:20.06.803] BEGIN WMNewTab: 20 +[16:20.06.803] END WMNewTab: 20 + + +[16:20.08.225] BEGIN WMNewTab: 20 +[16:20.08.225] END WMNewTab: 20 + + +[16:20.09.643] BEGIN WMNewTab: 20 +[16:20.09.643] END WMNewTab: 20 + + +[16:20.11.061] BEGIN WMNewTab: 20 +[16:20.11.061] END WMNewTab: 20 + + +[16:20.12.475] BEGIN WMNewTab: 20 +[16:20.12.475] END WMNewTab: 20 + + +[16:20.13.892] BEGIN WMNewTab: 20 +[16:20.13.892] END WMNewTab: 20 + + +[16:20.15.306] BEGIN WMNewTab: 20 +[16:20.15.306] END WMNewTab: 20 + + +[16:20.16.726] BEGIN WMNewTab: 20 +[16:20.16.726] END WMNewTab: 20 + + +[16:20.18.142] BEGIN WMNewTab: 20 +[16:20.18.142] END WMNewTab: 20 + + +[16:20.19.562] BEGIN WMNewTab: 20 +[16:20.19.562] END WMNewTab: 20 + + +[16:20.20.983] BEGIN WMNewTab: 20 +[16:20.20.983] END WMNewTab: 20 + +[16:20.21.501] BEGIN WMNewTab: 60 +[16:20.21.501] END WMNewTab: 60 + +[16:20.22.405] BEGIN WMNewTab: 20 +[16:20.22.405] END WMNewTab: 20 + + +[16:20.23.823] BEGIN WMNewTab: 20 +[16:20.23.823] END WMNewTab: 20 + + +[16:20.25.238] BEGIN WMNewTab: 20 +[16:20.25.238] END WMNewTab: 20 + + +[16:20.26.654] BEGIN WMNewTab: 20 +[16:20.26.654] END WMNewTab: 20 + + +[16:20.28.070] BEGIN WMNewTab: 20 +[16:20.28.070] END WMNewTab: 20 + + +[16:20.29.487] BEGIN WMNewTab: 20 +[16:20.29.487] END WMNewTab: 20 + + +[16:20.30.907] BEGIN WMNewTab: 20 +[16:20.30.907] END WMNewTab: 20 + + +[16:20.32.324] BEGIN WMNewTab: 20 +[16:20.32.324] END WMNewTab: 20 + + +[16:20.33.741] BEGIN WMNewTab: 20 +[16:20.33.741] END WMNewTab: 20 + + +[16:20.35.161] BEGIN WMNewTab: 20 +[16:20.35.161] END WMNewTab: 20 + + +[16:20.36.582] BEGIN WMNewTab: 20 +[16:20.36.582] END WMNewTab: 20 + + +[16:20.37.993] BEGIN WMNewTab: 20 +[16:20.37.993] END WMNewTab: 20 + + +[16:20.39.408] BEGIN WMNewTab: 20 +[16:20.39.408] END WMNewTab: 20 + + +[16:20.40.826] BEGIN WMNewTab: 20 +[16:20.40.826] END WMNewTab: 20 + + +[16:20.42.245] BEGIN WMNewTab: 20 +[16:20.42.245] END WMNewTab: 20 + + +[16:20.43.661] BEGIN WMNewTab: 20 +[16:20.43.661] END WMNewTab: 20 + + +[16:20.45.081] BEGIN WMNewTab: 20 +[16:20.45.081] END WMNewTab: 20 + + +[16:20.46.494] BEGIN WMNewTab: 20 +[16:20.46.494] END WMNewTab: 20 + + +[16:20.47.914] BEGIN WMNewTab: 20 +[16:20.47.914] END WMNewTab: 20 + + +[16:20.49.330] BEGIN WMNewTab: 20 +[16:20.49.330] END WMNewTab: 20 + + +[16:20.50.749] BEGIN WMNewTab: 20 +[16:20.50.749] END WMNewTab: 20 + +[16:20.51.532] BEGIN WMNewTab: 60 +[16:20.51.533] END WMNewTab: 60 + +[16:20.52.167] BEGIN WMNewTab: 20 +[16:20.52.167] END WMNewTab: 20 + + +[16:20.53.586] BEGIN WMNewTab: 20 +[16:20.53.586] END WMNewTab: 20 + + +[16:20.55.002] BEGIN WMNewTab: 20 +[16:20.55.002] END WMNewTab: 20 + + +[16:20.56.421] BEGIN WMNewTab: 20 +[16:20.56.421] END WMNewTab: 20 + + +[16:20.57.832] BEGIN WMNewTab: 20 +[16:20.57.832] END WMNewTab: 20 + + +[16:20.59.251] BEGIN WMNewTab: 20 +[16:20.59.251] END WMNewTab: 20 + + +[16:21.00.663] BEGIN WMNewTab: 20 +[16:21.00.663] END WMNewTab: 20 + + +[16:21.02.088] BEGIN WMNewTab: 20 +[16:21.02.088] END WMNewTab: 20 + + +[16:21.03.505] BEGIN WMNewTab: 20 +[16:21.03.505] END WMNewTab: 20 + + +[16:21.04.927] BEGIN WMNewTab: 20 +[16:21.04.927] END WMNewTab: 20 + + +[16:21.06.344] BEGIN WMNewTab: 20 +[16:21.06.344] END WMNewTab: 20 + + +[16:21.07.760] BEGIN WMNewTab: 20 +[16:21.07.760] END WMNewTab: 20 + + +[16:21.09.176] BEGIN WMNewTab: 20 +[16:21.09.176] END WMNewTab: 20 + + +[16:21.10.590] BEGIN WMNewTab: 20 +[16:21.10.590] END WMNewTab: 20 + + +[16:21.12.011] BEGIN WMNewTab: 20 +[16:21.12.011] END WMNewTab: 20 + + +[16:21.13.428] BEGIN WMNewTab: 20 +[16:21.13.428] END WMNewTab: 20 + + +[16:21.14.848] BEGIN WMNewTab: 20 +[16:21.14.848] END WMNewTab: 20 + + +[16:21.16.261] BEGIN WMNewTab: 20 +[16:21.16.261] END WMNewTab: 20 + + +[16:21.17.678] BEGIN WMNewTab: 20 +[16:21.17.678] END WMNewTab: 20 + + +[16:21.19.096] BEGIN WMNewTab: 20 +[16:21.19.096] END WMNewTab: 20 + + +[16:21.20.517] BEGIN WMNewTab: 20 +[16:21.20.517] END WMNewTab: 20 + +[16:21.21.565] BEGIN WMNewTab: 60 +[16:21.21.565] END WMNewTab: 60 + +[16:21.21.946] BEGIN WMNewTab: 20 +[16:21.21.946] END WMNewTab: 20 + + +[16:21.23.351] BEGIN WMNewTab: 20 +[16:21.23.351] END WMNewTab: 20 + + +[16:21.24.768] BEGIN WMNewTab: 20 +[16:21.24.768] END WMNewTab: 20 + + +[16:21.26.188] BEGIN WMNewTab: 20 +[16:21.26.188] END WMNewTab: 20 + + +[16:21.27.614] BEGIN WMNewTab: 20 +[16:21.27.614] END WMNewTab: 20 + + +[16:21.29.026] BEGIN WMNewTab: 20 +[16:21.29.026] END WMNewTab: 20 + + +[16:21.30.447] BEGIN WMNewTab: 20 +[16:21.30.447] END WMNewTab: 20 + + +[16:21.31.863] BEGIN WMNewTab: 20 +[16:21.31.863] END WMNewTab: 20 + + +[16:21.33.279] BEGIN WMNewTab: 20 +[16:21.33.279] END WMNewTab: 20 + + +[16:21.34.701] BEGIN WMNewTab: 20 +[16:21.34.701] END WMNewTab: 20 + + +[16:21.36.118] BEGIN WMNewTab: 20 +[16:21.36.118] END WMNewTab: 20 + + +[16:21.37.541] BEGIN WMNewTab: 20 +[16:21.37.541] END WMNewTab: 20 + + +[16:21.38.962] BEGIN WMNewTab: 20 +[16:21.38.962] END WMNewTab: 20 + + +[16:21.40.381] BEGIN WMNewTab: 20 +[16:21.40.381] END WMNewTab: 20 + + +[16:21.41.803] BEGIN WMNewTab: 20 +[16:21.41.803] END WMNewTab: 20 + + +[16:21.43.220] BEGIN WMNewTab: 20 +[16:21.43.220] END WMNewTab: 20 + + +[16:21.44.640] BEGIN WMNewTab: 20 +[16:21.44.640] END WMNewTab: 20 + + +[16:21.46.057] BEGIN WMNewTab: 20 +[16:21.46.057] END WMNewTab: 20 + + +[16:21.47.472] BEGIN WMNewTab: 20 +[16:21.47.472] END WMNewTab: 20 + + +[16:21.48.890] BEGIN WMNewTab: 20 +[16:21.48.890] END WMNewTab: 20 + + +[16:21.50.308] BEGIN WMNewTab: 20 +[16:21.50.308] END WMNewTab: 20 + + +[16:21.51.596] BEGIN WMNewTab: 60 +[16:21.51.596] END WMNewTab: 60 +[16:21.51.727] BEGIN WMNewTab: 20 +[16:21.51.727] END WMNewTab: 20 + + +[16:21.53.141] BEGIN WMNewTab: 20 +[16:21.53.141] END WMNewTab: 20 + + +[16:21.54.550] BEGIN WMNewTab: 20 +[16:21.54.550] END WMNewTab: 20 + + +[16:21.55.961] BEGIN WMNewTab: 20 +[16:21.55.961] END WMNewTab: 20 + + +[16:21.57.378] BEGIN WMNewTab: 20 +[16:21.57.378] END WMNewTab: 20 + + +[16:21.58.798] BEGIN WMNewTab: 20 +[16:21.58.798] END WMNewTab: 20 + + +[16:22.00.212] BEGIN WMNewTab: 20 +[16:22.00.212] END WMNewTab: 20 + + +[16:22.01.628] BEGIN WMNewTab: 20 +[16:22.01.628] END WMNewTab: 20 + + +[16:22.03.043] BEGIN WMNewTab: 20 +[16:22.03.043] END WMNewTab: 20 + + +[16:22.04.457] BEGIN WMNewTab: 20 +[16:22.04.457] END WMNewTab: 20 + + +[16:22.05.870] BEGIN WMNewTab: 20 +[16:22.05.870] END WMNewTab: 20 + + +[16:22.07.277] BEGIN WMNewTab: 20 +[16:22.07.277] END WMNewTab: 20 + + +[16:22.08.687] BEGIN WMNewTab: 20 +[16:22.08.687] END WMNewTab: 20 + + +[16:22.10.100] BEGIN WMNewTab: 20 +[16:22.10.100] END WMNewTab: 20 + + +[16:22.11.515] BEGIN WMNewTab: 20 +[16:22.11.515] END WMNewTab: 20 + + +[16:22.12.937] BEGIN WMNewTab: 20 +[16:22.12.937] END WMNewTab: 20 + + +[16:22.14.352] BEGIN WMNewTab: 20 +[16:22.14.352] END WMNewTab: 20 + + +[16:22.15.766] BEGIN WMNewTab: 20 +[16:22.15.766] END WMNewTab: 20 + + +[16:22.17.180] BEGIN WMNewTab: 20 +[16:22.17.180] END WMNewTab: 20 + + +[16:22.18.597] BEGIN WMNewTab: 20 +[16:22.18.597] END WMNewTab: 20 + + +[16:22.20.012] BEGIN WMNewTab: 20 +[16:22.20.012] END WMNewTab: 20 + + +[16:22.21.428] BEGIN WMNewTab: 20 +[16:22.21.428] END WMNewTab: 20 +[16:22.21.627] BEGIN WMNewTab: 60 +[16:22.21.627] END WMNewTab: 60 + + +[16:22.22.842] BEGIN WMNewTab: 20 +[16:22.22.842] END WMNewTab: 20 + + +[16:22.24.253] BEGIN WMNewTab: 20 +[16:22.24.253] END WMNewTab: 20 + + +[16:22.25.666] BEGIN WMNewTab: 20 +[16:22.25.666] END WMNewTab: 20 + + +[16:22.27.081] BEGIN WMNewTab: 20 +[16:22.27.081] END WMNewTab: 20 + + +[16:22.28.497] BEGIN WMNewTab: 20 +[16:22.28.497] END WMNewTab: 20 + + +[16:22.29.911] BEGIN WMNewTab: 20 +[16:22.29.911] END WMNewTab: 20 + + +[16:22.31.322] BEGIN WMNewTab: 20 +[16:22.31.322] END WMNewTab: 20 + + +[16:22.32.716] BEGIN WMNewTab: 0 +[16:22.32.716] WMNewTab: FormClick +[16:22.32.716] WMNewTab: LooseFocus +[16:22.32.716] END WMNewTab: 0 +[16:22.32.716] BEGIN WMNewTab: 31 +[16:22.32.716] END WMNewTab: 31 +[16:22.32.734] BEGIN WMNewTab: 20 +[16:22.32.734] END WMNewTab: 20 + + +[16:22.34.120] BEGIN CWD +[16:22.34.150] BEGIN WMNewTab: 20 +[16:22.34.150] END WMNewTab: 20 +[16:22.34.181] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:22.34.181] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:22.34.181] (SSH-Browser) END VerifySFTPConnection(1) +[16:22.34.181] END CWD +[16:22.34.196] BEGIN CWD +[16:22.34.258] END CWD + + +[16:22.35.671] BEGIN WMNewTab: 20 +[16:22.35.671] END WMNewTab: 20 + + +[16:22.37.080] BEGIN WMNewTab: 20 +[16:22.37.080] END WMNewTab: 20 + + +[16:22.38.495] BEGIN WMNewTab: 20 +[16:22.38.495] END WMNewTab: 20 + + +[16:22.39.907] BEGIN WMNewTab: 20 +[16:22.39.907] END WMNewTab: 20 + + +[16:22.41.319] BEGIN WMNewTab: 20 +[16:22.41.319] END WMNewTab: 20 + + +[16:22.42.733] BEGIN WMNewTab: 20 +[16:22.42.733] END WMNewTab: 20 + + +[16:22.44.165] BEGIN WMNewTab: 20 +[16:22.44.165] END WMNewTab: 20 + + +[16:22.45.580] BEGIN WMNewTab: 20 +[16:22.45.580] END WMNewTab: 20 + + +[16:22.46.998] BEGIN WMNewTab: 20 +[16:22.46.998] END WMNewTab: 20 + +[16:22.47.396] BEGIN WMNewTab: 0 +[16:22.47.396] WMNewTab: FormClick +[16:22.47.396] WMNewTab: LooseFocus +[16:22.47.396] END WMNewTab: 0 +[16:22.47.396] BEGIN WMNewTab: 31 +[16:22.47.396] END WMNewTab: 31 + +[16:22.48.413] BEGIN WMNewTab: 20 +[16:22.48.413] END WMNewTab: 20 +[16:22.48.428] BEGIN CWD +[16:22.48.488] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:22.48.488] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:22.48.488] (SSH-Browser) END VerifySFTPConnection(1) +[16:22.48.488] END CWD +[16:22.48.503] BEGIN CWD +[16:22.48.563] END CWD + + +[16:22.49.979] BEGIN WMNewTab: 20 +[16:22.49.979] END WMNewTab: 20 + +[16:22.50.461] BEGIN WMNewTab: 0 +[16:22.50.461] WMNewTab: FormClick +[16:22.50.461] WMNewTab: LooseFocus +[16:22.50.461] END WMNewTab: 0 + +[16:22.51.395] BEGIN WMNewTab: 20 +[16:22.51.395] END WMNewTab: 20 +[16:22.51.659] BEGIN WMNewTab: 60 +[16:22.51.659] END WMNewTab: 60 +[16:22.51.964] BEGIN WMNewTab: 0 +[16:22.51.964] WMNewTab: FormClick +[16:22.51.964] WMNewTab: LooseFocus +[16:22.51.965] END WMNewTab: 0 + +[16:22.52.812] BEGIN WMNewTab: 20 +[16:22.52.812] END WMNewTab: 20 + + +[16:22.54.228] BEGIN WMNewTab: 20 +[16:22.54.228] END WMNewTab: 20 + + +[16:22.55.645] BEGIN WMNewTab: 20 +[16:22.55.645] END WMNewTab: 20 + + +[16:22.57.059] BEGIN WMNewTab: 20 +[16:22.57.059] END WMNewTab: 20 + + +[16:22.58.475] BEGIN WMNewTab: 20 +[16:22.58.475] END WMNewTab: 20 + + +[16:22.59.888] BEGIN WMNewTab: 20 +[16:22.59.888] END WMNewTab: 20 + + +[16:23.01.308] BEGIN WMNewTab: 20 +[16:23.01.308] END WMNewTab: 20 + + +[16:23.02.730] BEGIN WMNewTab: 20 +[16:23.02.730] END WMNewTab: 20 + + +[16:23.04.138] BEGIN WMNewTab: 20 +[16:23.04.138] END WMNewTab: 20 + + +[16:23.05.556] BEGIN WMNewTab: 20 +[16:23.05.556] END WMNewTab: 20 + + +[16:23.06.972] BEGIN WMNewTab: 20 +[16:23.06.972] END WMNewTab: 20 + + +[16:23.08.385] BEGIN WMNewTab: 20 +[16:23.08.385] END WMNewTab: 20 + + +[16:23.09.799] BEGIN WMNewTab: 20 +[16:23.09.799] END WMNewTab: 20 + + +[16:23.11.208] BEGIN WMNewTab: 20 +[16:23.11.208] END WMNewTab: 20 + + +[16:23.12.627] BEGIN WMNewTab: 20 +[16:23.12.627] END WMNewTab: 20 + + +[16:23.14.044] BEGIN WMNewTab: 20 +[16:23.14.044] END WMNewTab: 20 + +[16:23.14.581] BEGIN WMNewTab: 0 +[16:23.14.581] WMNewTab: FormClick +[16:23.14.581] WMNewTab: LooseFocus +[16:23.14.581] END WMNewTab: 0 +[16:23.14.581] BEGIN WMNewTab: 31 +[16:23.14.581] END WMNewTab: 31 + +[16:23.15.460] BEGIN WMNewTab: 20 +[16:23.15.460] END WMNewTab: 20 + +[16:23.16.472] BEGIN CWD +[16:23.16.533] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:23.16.533] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:23.16.533] (SSH-Browser) END VerifySFTPConnection(1) +[16:23.16.533] END CWD +[16:23.16.547] BEGIN CWD +[16:23.16.609] END CWD + +[16:23.17.078] BEGIN WMNewTab: 20 +[16:23.17.078] END WMNewTab: 20 + + +[16:23.18.491] BEGIN WMNewTab: 20 +[16:23.18.491] END WMNewTab: 20 + + +[16:23.19.909] BEGIN WMNewTab: 20 +[16:23.19.909] END WMNewTab: 20 + + +[16:23.21.321] BEGIN WMNewTab: 20 +[16:23.21.321] END WMNewTab: 20 + +[16:23.21.691] BEGIN WMNewTab: 60 +[16:23.21.691] END WMNewTab: 60 + +[16:23.22.733] BEGIN WMNewTab: 20 +[16:23.22.733] END WMNewTab: 20 + +[16:23.23.690] BEGIN CWD +[16:23.23.750] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:23.23.750] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:23.23.750] (SSH-Browser) END VerifySFTPConnection(1) +[16:23.23.750] END CWD +[16:23.23.756] BEGIN CWD +[16:23.23.816] END CWD + +[16:23.24.291] BEGIN WMNewTab: 20 +[16:23.24.291] END WMNewTab: 20 + + +[16:23.25.705] BEGIN WMNewTab: 20 +[16:23.25.705] END WMNewTab: 20 + + +[16:23.27.118] BEGIN WMNewTab: 20 +[16:23.27.118] END WMNewTab: 20 + + +[16:23.28.532] BEGIN WMNewTab: 20 +[16:23.28.532] END WMNewTab: 20 + +[16:23.29.453] BEGIN WMNewTab: 0 +[16:23.29.453] WMNewTab: FormClick +[16:23.29.453] WMNewTab: LooseFocus +[16:23.29.453] END WMNewTab: 0 +[16:23.29.605] BEGIN WMNewTab: 0 +[16:23.29.605] WMNewTab: FormClick +[16:23.29.605] WMNewTab: LooseFocus +[16:23.29.606] END WMNewTab: 0 +[16:23.29.953] BEGIN WMNewTab: 20 +[16:23.29.953] END WMNewTab: 20 + +[16:23.31.111] BEGIN WMNewTab: 0 +[16:23.31.111] WMNewTab: FormClick +[16:23.31.111] WMNewTab: LooseFocus +[16:23.31.111] END WMNewTab: 0 +[16:23.31.111] BEGIN WMNewTab: 31 +[16:23.31.111] END WMNewTab: 31 +[16:23.31.360] BEGIN WMNewTab: 20 +[16:23.31.360] END WMNewTab: 20 + + +[16:23.32.768] BEGIN WMNewTab: 20 +[16:23.32.768] END WMNewTab: 20 + + +[16:23.34.179] BEGIN WMNewTab: 20 +[16:23.34.179] END WMNewTab: 20 +[16:23.34.314] BEGIN CWD +[16:23.34.374] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:23.34.374] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:23.34.374] (SSH-Browser) END VerifySFTPConnection(1) +[16:23.34.374] END CWD +[16:23.34.390] BEGIN CWD +[16:23.34.451] END CWD + +[16:23.35.391] BEGIN WMNewTab: 20 +[16:23.35.391] END WMNewTab: 20 + + +[16:23.36.798] BEGIN WMNewTab: 20 +[16:23.36.798] END WMNewTab: 20 + +[16:23.37.196] BEGIN WMNewTab: 0 +[16:23.37.196] WMNewTab: FormClick +[16:23.37.196] WMNewTab: LooseFocus +[16:23.37.198] END WMNewTab: 0 +[16:23.37.341] BEGIN WMNewTab: 0 +[16:23.37.341] WMNewTab: FormClick +[16:23.37.341] WMNewTab: LooseFocus +[16:23.37.342] END WMNewTab: 0 + +[16:23.38.209] BEGIN WMNewTab: 20 +[16:23.38.209] END WMNewTab: 20 + + +[16:23.39.627] BEGIN WMNewTab: 20 +[16:23.39.627] END WMNewTab: 20 + +[16:23.40.694] BEGIN WMNewTab: 0 +[16:23.40.694] WMNewTab: FormClick +[16:23.40.694] WMNewTab: LooseFocus +[16:23.40.694] END WMNewTab: 0 +[16:23.40.742] BEGIN WMNewTab: 0 +[16:23.40.742] WMNewTab: FormClick +[16:23.40.742] WMNewTab: LooseFocus +[16:23.40.742] END WMNewTab: 0 +[16:23.41.043] BEGIN WMNewTab: 20 +[16:23.41.043] END WMNewTab: 20 + + +[16:23.42.458] BEGIN WMNewTab: 20 +[16:23.42.458] END WMNewTab: 20 + + +[16:23.43.876] BEGIN WMNewTab: 20 +[16:23.43.876] END WMNewTab: 20 + + +[16:23.45.288] BEGIN WMNewTab: 20 +[16:23.45.288] END WMNewTab: 20 + + +[16:23.46.697] BEGIN WMNewTab: 20 +[16:23.46.697] END WMNewTab: 20 + + +[16:23.48.104] BEGIN WMNewTab: 20 +[16:23.48.104] END WMNewTab: 20 + + +[16:23.49.528] BEGIN WMNewTab: 20 +[16:23.49.528] END WMNewTab: 20 + + +[16:23.50.932] BEGIN WMNewTab: 20 +[16:23.50.932] END WMNewTab: 20 + +[16:23.51.719] BEGIN WMNewTab: 60 +[16:23.51.719] END WMNewTab: 60 + +[16:23.52.344] BEGIN WMNewTab: 20 +[16:23.52.344] END WMNewTab: 20 + + +[16:23.53.752] BEGIN WMNewTab: 20 +[16:23.53.752] END WMNewTab: 20 + +[16:23.54.758] BEGIN WMNewTab: 0 +[16:23.54.758] WMNewTab: FormClick +[16:23.54.758] WMNewTab: LooseFocus +[16:23.54.759] END WMNewTab: 0 + +[16:23.55.159] BEGIN WMNewTab: 20 +[16:23.55.159] END WMNewTab: 20 + + +[16:23.56.574] BEGIN WMNewTab: 20 +[16:23.56.574] END WMNewTab: 20 + + +[16:23.57.993] BEGIN WMNewTab: 20 +[16:23.57.993] END WMNewTab: 20 +[16:23.58.162] BEGIN WMNewTab: 0 +[16:23.58.162] WMNewTab: FormClick +[16:23.58.162] WMNewTab: LooseFocus +[16:23.58.164] END WMNewTab: 0 + + +[16:23.59.409] BEGIN WMNewTab: 20 +[16:23.59.409] END WMNewTab: 20 + + +[16:24.00.822] BEGIN WMNewTab: 20 +[16:24.00.822] END WMNewTab: 20 + + +[16:24.02.237] BEGIN WMNewTab: 20 +[16:24.02.237] END WMNewTab: 20 + + +[16:24.03.652] BEGIN WMNewTab: 20 +[16:24.03.652] END WMNewTab: 20 + + +[16:24.05.066] BEGIN WMNewTab: 20 +[16:24.05.066] END WMNewTab: 20 + + +[16:24.06.479] BEGIN WMNewTab: 20 +[16:24.06.479] END WMNewTab: 20 + + +[16:24.07.890] BEGIN WMNewTab: 20 +[16:24.07.890] END WMNewTab: 20 + + +[16:24.09.302] BEGIN WMNewTab: 20 +[16:24.09.302] END WMNewTab: 20 + + +[16:24.10.716] BEGIN WMNewTab: 20 +[16:24.10.716] END WMNewTab: 20 + + +[16:24.12.125] BEGIN WMNewTab: 20 +[16:24.12.125] END WMNewTab: 20 + + +[16:24.13.537] BEGIN WMNewTab: 20 +[16:24.13.537] END WMNewTab: 20 + + +[16:24.14.951] BEGIN WMNewTab: 20 +[16:24.14.951] END WMNewTab: 20 + + +[16:24.16.368] BEGIN WMNewTab: 20 +[16:24.16.368] END WMNewTab: 20 + + +[16:24.17.781] BEGIN WMNewTab: 20 +[16:24.17.781] END WMNewTab: 20 + + +[16:24.19.202] BEGIN WMNewTab: 20 +[16:24.19.202] END WMNewTab: 20 + + +[16:24.20.613] BEGIN WMNewTab: 20 +[16:24.20.613] END WMNewTab: 20 + +[16:24.21.745] BEGIN WMNewTab: 60 +[16:24.21.745] END WMNewTab: 60 +[16:24.22.025] BEGIN WMNewTab: 20 +[16:24.22.025] END WMNewTab: 20 + + +[16:24.23.437] BEGIN WMNewTab: 20 +[16:24.23.437] END WMNewTab: 20 + + +[16:24.24.847] BEGIN WMNewTab: 20 +[16:24.24.847] END WMNewTab: 20 + + +[16:24.26.275] BEGIN WMNewTab: 20 +[16:24.26.275] END WMNewTab: 20 + + +[16:24.27.678] BEGIN WMNewTab: 20 +[16:24.27.678] END WMNewTab: 20 + + +[16:24.29.096] BEGIN WMNewTab: 20 +[16:24.29.096] END WMNewTab: 20 + + +[16:24.30.513] BEGIN WMNewTab: 20 +[16:24.30.513] END WMNewTab: 20 + + +[16:24.31.929] BEGIN WMNewTab: 20 +[16:24.31.929] END WMNewTab: 20 + + +[16:24.33.344] BEGIN WMNewTab: 20 +[16:24.33.344] END WMNewTab: 20 + + +[16:24.34.759] BEGIN WMNewTab: 20 +[16:24.34.759] END WMNewTab: 20 + + +[16:24.36.172] BEGIN WMNewTab: 20 +[16:24.36.172] END WMNewTab: 20 + + +[16:24.37.584] BEGIN WMNewTab: 20 +[16:24.37.584] END WMNewTab: 20 + + +[16:24.38.995] BEGIN WMNewTab: 20 +[16:24.38.995] END WMNewTab: 20 + + +[16:24.40.411] BEGIN WMNewTab: 20 +[16:24.40.411] END WMNewTab: 20 + + +[16:24.41.824] BEGIN WMNewTab: 20 +[16:24.41.824] END WMNewTab: 20 + + +[16:24.43.238] BEGIN WMNewTab: 20 +[16:24.43.238] END WMNewTab: 20 + + +[16:24.44.655] BEGIN WMNewTab: 20 +[16:24.44.655] END WMNewTab: 20 + + +[16:24.46.070] BEGIN WMNewTab: 20 +[16:24.46.070] END WMNewTab: 20 + + +[16:24.47.486] BEGIN WMNewTab: 20 +[16:24.47.486] END WMNewTab: 20 + + +[16:24.48.903] BEGIN WMNewTab: 20 +[16:24.48.903] END WMNewTab: 20 + + +[16:24.50.316] BEGIN WMNewTab: 20 +[16:24.50.316] END WMNewTab: 20 + + +[16:24.51.727] BEGIN WMNewTab: 20 +[16:24.51.727] END WMNewTab: 20 +[16:24.51.771] BEGIN WMNewTab: 60 +[16:24.51.771] END WMNewTab: 60 + +[16:24.52.586] +[16:24.52.586] +[16:24.52.586] BEGIN TForm1.MobaInputDialog +[16:24.52.586] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[16:24.52.586] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=0; +[16:24.52.586] TForm1.MobaInputDialog: FormInputDialog.ShowModal + +[16:24.53.146] BEGIN WMNewTab: 20 +[16:24.53.146] END WMNewTab: 20 + + +[16:24.54.560] BEGIN WMNewTab: 20 +[16:24.54.560] END WMNewTab: 20 + +[16:24.55.069] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[16:24.55.069] END TForm1.MobaInputDialog +[16:24.55.069] +[16:24.55.069] +[16:24.55.069] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:24.55.069] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:24.55.069] (SSH-Browser) END VerifySFTPConnection(1) +[16:24.55.069] (SSH-Browser) NewFile1Click: SFTP.CreateFile(/root/fix_ppp_route.sh) +[16:24.55.077] (SSH-Browser) ElSFTP1OpenFile(1) +[16:24.55.077] (SSH-Browser) ElSFTP1OpenFile(1): CloseCurrentHandle +[16:24.55.077] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:24.55.077] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:24.55.077] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:24.55.077] (SSH-Browser) END VerifySFTPConnection(1) +[16:24.55.077] (SSH-Browser) END CloseCurrentHandle(1) +[16:24.55.077] (SSH-Browser) BEGIN OpenDir(1) +[16:24.55.077] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:24.55.077] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:24.55.077] (SSH-Browser) END VerifySFTPConnection(1) +[16:24.55.077] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:24.55.083] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/); +[16:24.55.083] (SSH-Browser) END OpenDir(1) +[16:24.55.108] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:24.55.108] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:24.55.139] (SSH-Browser) ElSFTP1OpenFile(1) +[16:24.55.139] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:24.55.199] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:24.55.199] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:24.55.199] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:24.55.199] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:24.55.199] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:24.55.199] (SSH-Browser) END VerifySFTPConnection(1) +[16:24.55.199] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:24.55.199] (SSH-Browser) END CloseCurrentHandle(1) +[16:24.55.199] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:24.55.199] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=17 +[16:24.55.199] (SSH-Browser) 对项目进行排序 +[16:24.55.199] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:24.55.203] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:24.55.229] (SSH-Browser) ElSFTP1Success(1) + +[16:24.56.173] BEGIN WMNewTab: 20 +[16:24.56.173] END WMNewTab: 20 + + +[16:24.57.452] BEGIN WMNewTab: 0 +[16:24.57.452] WMNewTab: FormClick +[16:24.57.452] WMNewTab: LooseFocus +[16:24.57.455] END WMNewTab: 0 +[16:24.57.554] BEGIN WMNewTab: 0 +[16:24.57.554] WMNewTab: FormClick +[16:24.57.554] WMNewTab: LooseFocus +[16:24.57.554] END WMNewTab: 0 +[16:24.57.587] BEGIN WMNewTab: 20 +[16:24.57.587] END WMNewTab: 20 + + +[16:24.59.005] BEGIN WMNewTab: 20 +[16:24.59.005] END WMNewTab: 20 + + +[16:25.00.423] BEGIN WMNewTab: 20 +[16:25.00.423] END WMNewTab: 20 + + +[16:25.01.845] BEGIN WMNewTab: 20 +[16:25.01.845] END WMNewTab: 20 + + +[16:25.03.268] BEGIN WMNewTab: 20 +[16:25.03.268] END WMNewTab: 20 + + +[16:25.04.548] BEGIN CWD +[16:25.04.608] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:25.04.608] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:25.04.608] (SSH-Browser) END VerifySFTPConnection(1) +[16:25.04.608] END CWD +[16:25.04.686] BEGIN WMNewTab: 20 +[16:25.04.686] END WMNewTab: 20 +[16:25.04.717] BEGIN CWD +[16:25.04.778] END CWD + + +[16:25.06.196] BEGIN WMNewTab: 20 +[16:25.06.196] END WMNewTab: 20 + + +[16:25.07.612] BEGIN WMNewTab: 20 +[16:25.07.612] END WMNewTab: 20 + + +[16:25.09.024] BEGIN WMNewTab: 20 +[16:25.09.024] END WMNewTab: 20 + +[16:25.10.152] BEGIN WMNewTab: 0 +[16:25.10.152] WMNewTab: FormClick +[16:25.10.152] WMNewTab: LooseFocus +[16:25.10.152] END WMNewTab: 0 +[16:25.10.152] BEGIN WMNewTab: 31 +[16:25.10.152] END WMNewTab: 31 +[16:25.10.438] BEGIN WMNewTab: 20 +[16:25.10.438] END WMNewTab: 20 + + +[16:25.11.854] BEGIN WMNewTab: 20 +[16:25.11.854] END WMNewTab: 20 + + +[16:25.13.270] BEGIN WMNewTab: 20 +[16:25.13.270] END WMNewTab: 20 + +[16:25.14.415] BEGIN CWD +[16:25.14.476] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:25.14.476] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:25.14.476] (SSH-Browser) END VerifySFTPConnection(1) +[16:25.14.476] END CWD +[16:25.14.478] BEGIN WMNewTab: 20 +[16:25.14.478] END WMNewTab: 20 +[16:25.14.490] BEGIN CWD +[16:25.14.551] END CWD + + +[16:25.15.968] BEGIN WMNewTab: 20 +[16:25.15.968] END WMNewTab: 20 + + +[16:25.17.383] BEGIN WMNewTab: 20 +[16:25.17.383] END WMNewTab: 20 + + +[16:25.18.798] BEGIN WMNewTab: 20 +[16:25.18.798] END WMNewTab: 20 + + +[16:25.20.219] BEGIN WMNewTab: 20 +[16:25.20.219] END WMNewTab: 20 + + +[16:25.21.635] BEGIN WMNewTab: 20 +[16:25.21.635] END WMNewTab: 20 +[16:25.21.798] BEGIN WMNewTab: 60 +[16:25.21.798] END WMNewTab: 60 + + +[16:25.23.059] BEGIN WMNewTab: 20 +[16:25.23.059] END WMNewTab: 20 + + +[16:25.24.473] BEGIN WMNewTab: 20 +[16:25.24.473] END WMNewTab: 20 + + +[16:25.25.897] BEGIN WMNewTab: 20 +[16:25.25.897] END WMNewTab: 20 + + +[16:25.27.317] BEGIN WMNewTab: 20 +[16:25.27.317] END WMNewTab: 20 + + +[16:25.28.730] BEGIN WMNewTab: 20 +[16:25.28.730] END WMNewTab: 20 + + +[16:25.30.147] BEGIN WMNewTab: 20 +[16:25.30.147] END WMNewTab: 20 + + +[16:25.31.588] BEGIN WMNewTab: 20 +[16:25.31.588] END WMNewTab: 20 + +[16:25.32.046] BEGIN WMNewTab: 0 +[16:25.32.046] WMNewTab: FormClick +[16:25.32.046] WMNewTab: LooseFocus +[16:25.32.046] END WMNewTab: 0 +[16:25.32.046] BEGIN WMNewTab: 31 +[16:25.32.046] END WMNewTab: 31 +[16:25.32.132] BEGIN WMNewTab: 0 +[16:25.32.132] WMNewTab: FormClick +[16:25.32.132] WMNewTab: LooseFocus +[16:25.32.133] END WMNewTab: 0 + +[16:25.33.005] BEGIN WMNewTab: 20 +[16:25.33.005] END WMNewTab: 20 + + +[16:25.34.422] BEGIN WMNewTab: 20 +[16:25.34.422] END WMNewTab: 20 + +[16:25.35.004] BEGIN CWD +[16:25.35.064] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:25.35.064] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:25.35.064] (SSH-Browser) END VerifySFTPConnection(1) +[16:25.35.064] END CWD +[16:25.35.081] BEGIN CWD +[16:25.35.141] END CWD + +[16:25.36.090] BEGIN WMNewTab: 20 +[16:25.36.090] END WMNewTab: 20 + +[16:25.37.118] BEGIN WMNewTab: 0 +[16:25.37.118] WMNewTab: FormClick +[16:25.37.118] WMNewTab: LooseFocus +[16:25.37.118] END WMNewTab: 0 +[16:25.37.246] BEGIN WMNewTab: 0 +[16:25.37.246] WMNewTab: FormClick +[16:25.37.246] WMNewTab: LooseFocus +[16:25.37.246] END WMNewTab: 0 +[16:25.37.510] BEGIN WMNewTab: 20 +[16:25.37.510] END WMNewTab: 20 + + +[16:25.38.930] BEGIN WMNewTab: 20 +[16:25.38.930] END WMNewTab: 20 + + +[16:25.40.341] BEGIN WMNewTab: 20 +[16:25.40.341] END WMNewTab: 20 +[16:25.40.401] BEGIN CWD +[16:25.40.462] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:25.40.462] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:25.40.462] (SSH-Browser) END VerifySFTPConnection(1) +[16:25.40.462] END CWD +[16:25.40.476] BEGIN CWD +[16:25.40.537] END CWD + + +[16:25.41.960] BEGIN WMNewTab: 20 +[16:25.41.960] END WMNewTab: 20 + + +[16:25.43.382] BEGIN WMNewTab: 20 +[16:25.43.382] END WMNewTab: 20 + + +[16:25.44.801] BEGIN WMNewTab: 20 +[16:25.44.801] END WMNewTab: 20 +[16:25.44.932] sListView1Click: FormClick +[16:25.44.999] +[16:25.44.999] BEGIN LIVE-CREATING TFormDownloadBloquant +[16:25.45.053] END LIVE-CREATING TFormDownloadBloquant +[16:25.45.053] +[16:25.45.053] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:25.45.053] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:25.45.053] (SSH-Browser) END VerifySFTPConnection(1) +[16:25.45.055] (SSH-Browser) sListView1DblClick: SFTP.OpenFile(/root/fix_ppp_route.sh); +[16:25.45.055] (SSH-Browser) sListView1DblClick: MODE = DOWNLOAD (FILE EDITION) +[16:25.45.055] (SSH-Browser) sListView1DblClick: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:25.45.055] (SSH-Browser) sListView1DblClick: PipelineLength = 32 +[16:25.45.055] (SSH-Browser) sListView1DblClick: DownloadBlockSize = 32768 +[16:25.45.055] (SSH-Browser) sListView1DblClick: UploadBlockSize = 65536 +[16:25.45.055] (SSH-Browser) sListView1DblClick: SftpBufferSize = 131072 +[16:25.45.055] (SSH-Browser) sListView1DblClick: DefaultWindowSize = 2097152 +[16:25.45.055] (SSH-Browser) sListView1DblClick: MinWindowSize = 2048 +[16:25.45.055] (SSH-Browser) sListView1DblClick: MaxSSHPacketSize = 262144 +[16:25.45.055] (SSH-Browser) sListView1DblClick: AutoAdjustTransferBlock = FALSE +[16:25.45.055] (SSH-Browser) sListView1DblClick: Ascii mode = false +[16:25.45.153] (SSH-Browser) ElSFTP1OpenFile(1) +[16:25.45.175] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.Read +[16:25.45.471] (SSH-Browser) ElSFTP1Data(1) +[16:25.45.471] (SSH-Browser) ElSFTP1Error(1): #1 - +[16:25.45.472] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle2 +[16:25.45.472] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:25.45.472] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:25.45.472] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:25.45.472] (SSH-Browser) END VerifySFTPConnection(1) +[16:25.45.472] (SSH-Browser) END CloseCurrentHandle(1) +[16:25.45.490] +[16:25.45.490] BEGIN Form4.FormActivate +[16:25.45.490] END Form4.FormActivate +[16:25.45.490] +[16:25.45.491] (SSH-Browser) ReallyOpenFile +[16:25.45.492] 请求提取文件: /bin/MobaRTE.exe +[16:25.45.851] 文件 MobaRTE.exe 已提取, 来自 mobase. + + +[16:25.47.861] BEGIN WMNewTab: 20 +[16:25.47.861] END WMNewTab: 20 +[16:25.47.942] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:25.48.233] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:25.49.271] BEGIN WMNewTab: 20 +[16:25.49.271] END WMNewTab: 20 + +[16:25.49.850] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:25.50.690] BEGIN WMNewTab: 20 +[16:25.50.690] END WMNewTab: 20 + +[16:25.51.465] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:25.51.825] BEGIN WMNewTab: 60 +[16:25.51.825] END WMNewTab: 60 +[16:25.52.104] BEGIN WMNewTab: 20 +[16:25.52.104] END WMNewTab: 20 + +[16:25.53.066] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:25.53.523] BEGIN WMNewTab: 20 +[16:25.53.523] END WMNewTab: 20 + +[16:25.54.679] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:25.54.804] 收到消息: 文本编辑器已关闭: SurchargerFichierIni(EditorWindowPos_3200_2000_192|MobaTextEditor|MobaTextEditorAddedShortcuts|MobaTextEditorRemovedShortcuts) +[16:25.54.804] +[16:25.54.804] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:25.54.804] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:25.54.827] +[16:25.54.827] +[16:25.54.827] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:25.54.827] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:25.54.828] +[16:25.54.828] +[16:25.54.828] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:25.54.828] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:25.54.829] +[16:25.54.829] +[16:25.54.829] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:25.54.829] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:25.54.829] +[16:25.54.941] BEGIN WMNewTab: 20 +[16:25.54.941] END WMNewTab: 20 + + +[16:25.56.283] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:25.56.359] BEGIN WMNewTab: 20 +[16:25.56.359] END WMNewTab: 20 + + +[16:25.57.599] BEGIN WMNewTab: 0 +[16:25.57.599] WMNewTab: FormClick +[16:25.57.599] WMNewTab: LooseFocus +[16:25.57.603] END WMNewTab: 0 +[16:25.57.780] BEGIN WMNewTab: 20 +[16:25.57.780] END WMNewTab: 20 +[16:25.57.888] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:25.59.197] BEGIN WMNewTab: 20 +[16:25.59.197] END WMNewTab: 20 +[16:25.59.247] BEGIN WMNewTab: 0 +[16:25.59.247] WMNewTab: FormClick +[16:25.59.247] WMNewTab: LooseFocus +[16:25.59.249] END WMNewTab: 0 +[16:25.59.500] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.00.615] BEGIN WMNewTab: 20 +[16:26.00.615] END WMNewTab: 20 + +[16:26.01.112] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.02.031] BEGIN WMNewTab: 20 +[16:26.02.031] END WMNewTab: 20 + +[16:26.02.730] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.03.479] BEGIN WMNewTab: 20 +[16:26.03.479] END WMNewTab: 20 + +[16:26.04.328] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.04.889] BEGIN WMNewTab: 20 +[16:26.04.889] END WMNewTab: 20 + +[16:26.05.942] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.06.304] BEGIN WMNewTab: 20 +[16:26.06.304] END WMNewTab: 20 + + +[16:26.07.556] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:26.07.724] BEGIN WMNewTab: 20 +[16:26.07.724] END WMNewTab: 20 + + +[16:26.09.139] BEGIN WMNewTab: 20 +[16:26.09.139] END WMNewTab: 20 +[16:26.09.154] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:26.10.557] BEGIN WMNewTab: 20 +[16:26.10.557] END WMNewTab: 20 +[16:26.10.768] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:26.11.970] BEGIN WMNewTab: 20 +[16:26.11.970] END WMNewTab: 20 + +[16:26.12.431] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.13.388] BEGIN WMNewTab: 20 +[16:26.13.388] END WMNewTab: 20 + +[16:26.13.985] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.14.809] BEGIN WMNewTab: 20 +[16:26.14.809] END WMNewTab: 20 + +[16:26.15.603] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.16.228] BEGIN WMNewTab: 20 +[16:26.16.228] END WMNewTab: 20 + +[16:26.16.813] BEGIN WMNewTab: 0 +[16:26.16.813] WMNewTab: FormClick +[16:26.16.813] WMNewTab: LooseFocus +[16:26.16.813] END WMNewTab: 0 +[16:26.16.949] BEGIN WMNewTab: 0 +[16:26.16.949] WMNewTab: FormClick +[16:26.16.949] WMNewTab: LooseFocus +[16:26.16.950] END WMNewTab: 0 +[16:26.17.199] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.17.646] BEGIN WMNewTab: 20 +[16:26.17.646] END WMNewTab: 20 + +[16:26.18.818] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:26.19.063] BEGIN WMNewTab: 20 +[16:26.19.063] END WMNewTab: 20 + +[16:26.19.703] BEGIN WMSysCommand (minimize/restore) +[16:26.19.734] BEGIN WMSize +[16:26.19.734] END WMSize +[16:26.19.779] END WMSysCommand + +[16:26.20.423] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:26.20.503] BEGIN WMNewTab: 20 +[16:26.20.503] END WMNewTab: 20 +[16:26.20.503] BEGIN WMSysCommand (minimize/restore) +[16:26.20.504] BEGIN WMNewTab: 0 +[16:26.20.504] WMNewTab: FormClick +[16:26.20.504] WMNewTab: LooseFocus +[16:26.20.504] END WMNewTab: 0 +[16:26.20.627] BEGIN WMSize +[16:26.20.627] BEGIN TFormXterm.FormResize +[16:26.20.627] TFormXterm.FormResize: CenterBtnReattachTab +[16:26.20.627] TFormXterm.FormResize: SplitModeResize +[16:26.20.627] TFormXterm.FormResize: BtnSplitNo.Down +[16:26.20.627] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:26.20.627] BEGIN ResizeTerminal +[16:26.20.628] END ResizeTerminal +[16:26.20.628] TFormXterm.FormResize: AdaptSidebarArrows; +[16:26.20.628] BEGIN AdaptSidebarArrows +[16:26.20.628] END AdaptSidebarArrows +[16:26.20.628] TFormXterm.FormResize: AdaptTV2; +[16:26.20.628] END TFormXterm.FormResize +[16:26.20.628] END WMSize +[16:26.20.635] END WMSysCommand + +[16:26.21.446] BEGIN WMSysCommand (minimize/restore) +[16:26.21.477] BEGIN WMSize +[16:26.21.477] END WMSize +[16:26.21.515] END WMSysCommand +[16:26.21.852] BEGIN WMNewTab: 60 +[16:26.21.852] END WMNewTab: 60 +[16:26.21.911] BEGIN WMNewTab: 20 +[16:26.21.911] END WMNewTab: 20 +[16:26.22.031] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:26.23.331] BEGIN WMNewTab: 20 +[16:26.23.331] END WMNewTab: 20 +[16:26.23.638] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.24.754] BEGIN WMNewTab: 20 +[16:26.24.754] END WMNewTab: 20 + +[16:26.25.260] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.26.176] BEGIN WMNewTab: 20 +[16:26.26.176] END WMNewTab: 20 + +[16:26.26.864] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.27.595] BEGIN WMNewTab: 20 +[16:26.27.595] END WMNewTab: 20 + +[16:26.28.467] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.29.043] BEGIN WMNewTab: 20 +[16:26.29.043] END WMNewTab: 20 + +[16:26.30.079] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.30.461] BEGIN WMNewTab: 20 +[16:26.30.461] END WMNewTab: 20 + + +[16:26.31.697] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:26.31.881] BEGIN WMNewTab: 20 +[16:26.31.881] END WMNewTab: 20 + + +[16:26.33.298] BEGIN WMNewTab: 20 +[16:26.33.298] END WMNewTab: 20 +[16:26.33.298] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:26.34.711] BEGIN WMNewTab: 20 +[16:26.34.711] END WMNewTab: 20 +[16:26.34.907] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:26.36.131] BEGIN WMNewTab: 20 +[16:26.36.131] END WMNewTab: 20 + +[16:26.36.516] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.37.552] BEGIN WMNewTab: 20 +[16:26.37.552] END WMNewTab: 20 + +[16:26.38.126] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.38.963] BEGIN WMNewTab: 20 +[16:26.38.963] END WMNewTab: 20 + +[16:26.39.741] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.40.384] BEGIN WMNewTab: 20 +[16:26.40.384] END WMNewTab: 20 + +[16:26.41.347] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.41.802] BEGIN WMNewTab: 20 +[16:26.41.802] END WMNewTab: 20 + +[16:26.42.963] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:26.43.223] BEGIN WMNewTab: 20 +[16:26.43.223] END WMNewTab: 20 + + +[16:26.44.568] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:26.44.644] BEGIN WMNewTab: 20 +[16:26.44.644] END WMNewTab: 20 + + +[16:26.46.082] BEGIN WMNewTab: 20 +[16:26.46.082] END WMNewTab: 20 +[16:26.46.177] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:26.47.500] BEGIN WMNewTab: 20 +[16:26.47.500] END WMNewTab: 20 +[16:26.47.792] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.48.918] BEGIN WMNewTab: 20 +[16:26.48.918] END WMNewTab: 20 + +[16:26.49.390] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.50.333] BEGIN WMNewTab: 20 +[16:26.50.333] END WMNewTab: 20 + +[16:26.51.004] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.51.752] BEGIN WMNewTab: 20 +[16:26.51.752] END WMNewTab: 20 +[16:26.51.880] BEGIN WMNewTab: 60 +[16:26.51.880] END WMNewTab: 60 + +[16:26.52.606] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:26.53.171] BEGIN WMNewTab: 20 +[16:26.53.171] END WMNewTab: 20 + +[16:26.54.263] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:26.54.590] BEGIN WMNewTab: 20 +[16:26.54.590] END WMNewTab: 20 + + +[16:26.55.828] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:26.56.009] BEGIN WMNewTab: 20 +[16:26.56.009] END WMNewTab: 20 + + +[16:26.57.429] BEGIN WMNewTab: 20 +[16:26.57.429] END WMNewTab: 20 +[16:26.57.445] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:26.58.847] BEGIN WMNewTab: 20 +[16:26.58.847] END WMNewTab: 20 +[16:26.59.048] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:27.00.273] BEGIN WMNewTab: 20 +[16:27.00.273] END WMNewTab: 20 + +[16:27.00.652] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.01.692] BEGIN WMNewTab: 20 +[16:27.01.692] END WMNewTab: 20 + +[16:27.02.270] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.03.108] BEGIN WMNewTab: 20 +[16:27.03.108] END WMNewTab: 20 + +[16:27.03.872] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.04.529] BEGIN WMNewTab: 20 +[16:27.04.529] END WMNewTab: 20 + +[16:27.05.500] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.05.949] BEGIN WMNewTab: 20 +[16:27.05.949] END WMNewTab: 20 + +[16:27.07.093] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.07.369] BEGIN WMNewTab: 20 +[16:27.07.369] END WMNewTab: 20 + + +[16:27.08.711] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.08.788] BEGIN WMNewTab: 20 +[16:27.08.788] END WMNewTab: 20 + + +[16:27.10.202] BEGIN WMNewTab: 20 +[16:27.10.202] END WMNewTab: 20 +[16:27.10.309] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:27.11.650] BEGIN WMNewTab: 20 +[16:27.11.650] END WMNewTab: 20 +[16:27.11.927] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.13.056] BEGIN WMNewTab: 20 +[16:27.13.056] END WMNewTab: 20 + +[16:27.13.528] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.14.475] BEGIN WMNewTab: 20 +[16:27.14.475] END WMNewTab: 20 + +[16:27.15.145] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.15.892] BEGIN WMNewTab: 20 +[16:27.15.892] END WMNewTab: 20 + +[16:27.16.750] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.17.314] BEGIN WMNewTab: 20 +[16:27.17.314] END WMNewTab: 20 + +[16:27.18.364] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.18.730] BEGIN WMNewTab: 20 +[16:27.18.730] END WMNewTab: 20 + + +[16:27.19.968] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.20.150] BEGIN WMNewTab: 20 +[16:27.20.150] END WMNewTab: 20 + + +[16:27.21.564] BEGIN WMNewTab: 20 +[16:27.21.564] END WMNewTab: 20 +[16:27.21.578] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.21.907] BEGIN WMNewTab: 60 +[16:27.21.907] END WMNewTab: 60 + +[16:27.22.972] BEGIN WMNewTab: 20 +[16:27.22.972] END WMNewTab: 20 +[16:27.23.186] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:27.24.393] BEGIN WMNewTab: 20 +[16:27.24.393] END WMNewTab: 20 + +[16:27.24.807] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.25.814] BEGIN WMNewTab: 20 +[16:27.25.814] END WMNewTab: 20 + +[16:27.26.410] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.27.231] BEGIN WMNewTab: 20 +[16:27.27.231] END WMNewTab: 20 + +[16:27.28.024] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.28.646] BEGIN WMNewTab: 20 +[16:27.28.646] END WMNewTab: 20 + +[16:27.29.622] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.30.108] BEGIN WMNewTab: 20 +[16:27.30.108] END WMNewTab: 20 + +[16:27.31.236] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.31.525] BEGIN WMNewTab: 20 +[16:27.31.525] END WMNewTab: 20 + + +[16:27.32.854] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.32.948] BEGIN WMNewTab: 20 +[16:27.32.948] END WMNewTab: 20 + + +[16:27.34.362] BEGIN WMNewTab: 20 +[16:27.34.362] END WMNewTab: 20 +[16:27.34.454] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:27.35.778] BEGIN WMNewTab: 20 +[16:27.35.778] END WMNewTab: 20 +[16:27.36.067] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.37.195] BEGIN WMNewTab: 20 +[16:27.37.195] END WMNewTab: 20 + +[16:27.37.683] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.38.614] BEGIN WMNewTab: 20 +[16:27.38.614] END WMNewTab: 20 + +[16:27.39.288] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.40.038] BEGIN WMNewTab: 20 +[16:27.40.038] END WMNewTab: 20 + +[16:27.40.892] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.41.456] BEGIN WMNewTab: 20 +[16:27.41.456] END WMNewTab: 20 + +[16:27.42.508] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.42.873] BEGIN WMNewTab: 20 +[16:27.42.873] END WMNewTab: 20 + + +[16:27.44.109] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.44.310] BEGIN WMNewTab: 20 +[16:27.44.310] END WMNewTab: 20 + + +[16:27.45.716] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.45.731] BEGIN WMNewTab: 20 +[16:27.45.731] END WMNewTab: 20 + + +[16:27.47.150] BEGIN WMNewTab: 20 +[16:27.47.150] END WMNewTab: 20 +[16:27.47.381] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.48.573] BEGIN WMNewTab: 20 +[16:27.48.573] END WMNewTab: 20 + +[16:27.48.940] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.49.993] BEGIN WMNewTab: 20 +[16:27.49.993] END WMNewTab: 20 + +[16:27.50.556] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.51.410] BEGIN WMNewTab: 20 +[16:27.51.410] END WMNewTab: 20 + +[16:27.51.935] BEGIN WMNewTab: 60 +[16:27.51.935] END WMNewTab: 60 +[16:27.52.154] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.52.825] BEGIN WMNewTab: 20 +[16:27.52.825] END WMNewTab: 20 + +[16:27.53.768] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:27.54.241] BEGIN WMNewTab: 20 +[16:27.54.241] END WMNewTab: 20 + +[16:27.55.386] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.55.676] BEGIN WMNewTab: 20 +[16:27.55.676] END WMNewTab: 20 + + +[16:27.56.989] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:27.57.095] BEGIN WMNewTab: 20 +[16:27.57.095] END WMNewTab: 20 + + +[16:27.58.511] BEGIN WMNewTab: 20 +[16:27.58.511] END WMNewTab: 20 +[16:27.58.593] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:27.59.929] BEGIN WMNewTab: 20 +[16:27.59.929] END WMNewTab: 20 +[16:28.00.201] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.01.349] BEGIN WMNewTab: 20 +[16:28.01.349] END WMNewTab: 20 + +[16:28.01.820] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.02.762] BEGIN WMNewTab: 20 +[16:28.02.762] END WMNewTab: 20 + +[16:28.03.433] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.04.185] BEGIN WMNewTab: 20 +[16:28.04.185] END WMNewTab: 20 + +[16:28.05.035] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.05.595] BEGIN WMNewTab: 20 +[16:28.05.595] END WMNewTab: 20 + +[16:28.06.647] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.07.013] BEGIN WMNewTab: 20 +[16:28.07.013] END WMNewTab: 20 + + +[16:28.08.260] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.08.427] BEGIN WMNewTab: 20 +[16:28.08.427] END WMNewTab: 20 + + +[16:28.09.844] BEGIN WMNewTab: 20 +[16:28.09.844] END WMNewTab: 20 +[16:28.09.858] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:28.11.266] BEGIN WMNewTab: 20 +[16:28.11.266] END WMNewTab: 20 +[16:28.11.475] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:28.12.681] BEGIN WMNewTab: 20 +[16:28.12.681] END WMNewTab: 20 + +[16:28.13.078] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.14.100] BEGIN WMNewTab: 20 +[16:28.14.100] END WMNewTab: 20 + +[16:28.14.694] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.15.520] BEGIN WMNewTab: 20 +[16:28.15.520] END WMNewTab: 20 + +[16:28.16.297] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.16.960] BEGIN WMNewTab: 20 +[16:28.16.960] END WMNewTab: 20 + +[16:28.17.916] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.18.372] BEGIN WMNewTab: 20 +[16:28.18.372] END WMNewTab: 20 + +[16:28.19.517] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.19.791] BEGIN WMNewTab: 20 +[16:28.19.791] END WMNewTab: 20 + + +[16:28.21.133] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.21.209] BEGIN WMNewTab: 20 +[16:28.21.209] END WMNewTab: 20 + +[16:28.21.962] BEGIN WMNewTab: 60 +[16:28.21.962] END WMNewTab: 60 + +[16:28.22.624] BEGIN WMNewTab: 20 +[16:28.22.624] END WMNewTab: 20 +[16:28.22.731] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:28.24.037] BEGIN WMNewTab: 20 +[16:28.24.037] END WMNewTab: 20 +[16:28.24.341] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.25.454] BEGIN WMNewTab: 20 +[16:28.25.454] END WMNewTab: 20 + +[16:28.25.960] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.26.870] BEGIN WMNewTab: 20 +[16:28.26.870] END WMNewTab: 20 + +[16:28.27.569] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.28.287] BEGIN WMNewTab: 20 +[16:28.28.287] END WMNewTab: 20 + +[16:28.29.171] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.29.704] BEGIN WMNewTab: 20 +[16:28.29.704] END WMNewTab: 20 + +[16:28.30.785] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.31.119] BEGIN WMNewTab: 20 +[16:28.31.119] END WMNewTab: 20 + +[16:28.31.728] BEGIN WMSysCommand (minimize/restore) +[16:28.31.729] BEGIN WMNewTab: 0 +[16:28.31.729] WMNewTab: FormClick +[16:28.31.729] WMNewTab: LooseFocus +[16:28.31.730] END WMNewTab: 0 +[16:28.31.935] BEGIN WMSize +[16:28.31.935] BEGIN TFormXterm.FormResize +[16:28.31.935] TFormXterm.FormResize: CenterBtnReattachTab +[16:28.31.935] TFormXterm.FormResize: SplitModeResize +[16:28.31.935] TFormXterm.FormResize: BtnSplitNo.Down +[16:28.31.935] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:28.31.935] BEGIN ResizeTerminal +[16:28.31.937] END ResizeTerminal +[16:28.31.937] TFormXterm.FormResize: AdaptSidebarArrows; +[16:28.31.937] BEGIN AdaptSidebarArrows +[16:28.31.937] END AdaptSidebarArrows +[16:28.31.937] TFormXterm.FormResize: AdaptTV2; +[16:28.31.937] END TFormXterm.FormResize +[16:28.31.937] END WMSize +[16:28.31.942] END WMSysCommand + +[16:28.32.407] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.32.540] BEGIN WMNewTab: 20 +[16:28.32.540] END WMNewTab: 20 +[16:28.32.762] sListView1Click: FormClick + +[16:28.33.958] BEGIN WMNewTab: 20 +[16:28.33.958] END WMNewTab: 20 +[16:28.34.003] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.34.245] +[16:28.34.245] +[16:28.34.245] BEGIN TForm1.MobaInputDialog +[16:28.34.246] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[16:28.34.246] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=Form4.Handle; +[16:28.34.248] TForm1.MobaInputDialog: FormInputDialog.ShowModal + +[16:28.35.376] BEGIN WMNewTab: 20 +[16:28.35.376] END WMNewTab: 20 +[16:28.35.618] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.35.807] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[16:28.35.807] END TForm1.MobaInputDialog +[16:28.35.807] +[16:28.35.807] +[16:28.35.807] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:28.35.807] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:28.35.807] (SSH-Browser) END VerifySFTPConnection(1) +[16:28.35.807] (SSH-Browser) NewFile1Click: SFTP.CreateFile(/root/auto_ppp_connect.sh) +[16:28.35.876] (SSH-Browser) ElSFTP1OpenFile(1) +[16:28.35.876] (SSH-Browser) ElSFTP1OpenFile(1): CloseCurrentHandle +[16:28.35.876] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:28.35.876] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:28.35.876] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:28.35.876] (SSH-Browser) END VerifySFTPConnection(1) +[16:28.35.876] (SSH-Browser) END CloseCurrentHandle(1) +[16:28.35.876] (SSH-Browser) BEGIN OpenDir(1) +[16:28.35.876] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:28.35.876] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:28.35.876] (SSH-Browser) END VerifySFTPConnection(1) +[16:28.35.876] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:28.35.879] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/); +[16:28.35.879] (SSH-Browser) END OpenDir(1) +[16:28.35.907] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:28.35.907] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:28.35.937] (SSH-Browser) ElSFTP1OpenFile(1) +[16:28.35.938] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:28.35.998] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:28.35.998] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:28.35.999] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:28.35.999] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:28.35.999] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:28.35.999] (SSH-Browser) END VerifySFTPConnection(1) +[16:28.35.999] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:28.35.999] (SSH-Browser) END CloseCurrentHandle(1) +[16:28.35.999] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:28.35.999] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=18 +[16:28.35.999] (SSH-Browser) 对项目进行排序 +[16:28.35.999] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:28.36.010] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:28.36.044] (SSH-Browser) ElSFTP1Success(1) + +[16:28.36.985] BEGIN WMNewTab: 20 +[16:28.36.985] END WMNewTab: 20 +[16:28.37.150] sListView1Click: FormClick +[16:28.37.231] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.38.410] BEGIN WMNewTab: 20 +[16:28.38.410] END WMNewTab: 20 +[16:28.38.478] BEGIN WMNewTab: 0 +[16:28.38.478] WMNewTab: FormClick +[16:28.38.478] WMNewTab: LooseFocus +[16:28.38.486] END WMNewTab: 0 +[16:28.38.565] BEGIN WMNewTab: 0 +[16:28.38.567] WMNewTab: FormClick +[16:28.38.567] WMNewTab: LooseFocus +[16:28.38.567] END WMNewTab: 0 +[16:28.38.845] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.39.818] BEGIN WMNewTab: 20 +[16:28.39.818] END WMNewTab: 20 + +[16:28.40.466] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.41.234] BEGIN WMNewTab: 20 +[16:28.41.234] END WMNewTab: 20 + +[16:28.42.071] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.42.654] BEGIN WMNewTab: 20 +[16:28.42.654] END WMNewTab: 20 + +[16:28.43.675] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.44.072] BEGIN WMNewTab: 20 +[16:28.44.072] END WMNewTab: 20 + +[16:28.44.558] BEGIN CWD +[16:28.44.619] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:28.44.619] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:28.44.619] (SSH-Browser) END VerifySFTPConnection(1) +[16:28.44.619] END CWD +[16:28.44.633] BEGIN CWD +[16:28.44.695] END CWD + +[16:28.45.289] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.45.642] BEGIN WMNewTab: 20 +[16:28.45.642] END WMNewTab: 20 + + +[16:28.46.893] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.47.061] BEGIN WMNewTab: 20 +[16:28.47.061] END WMNewTab: 20 + + +[16:28.48.474] BEGIN WMNewTab: 20 +[16:28.48.474] END WMNewTab: 20 +[16:28.48.504] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.49.574] BEGIN WMNewTab: 0 +[16:28.49.574] WMNewTab: FormClick +[16:28.49.574] WMNewTab: LooseFocus +[16:28.49.574] END WMNewTab: 0 +[16:28.49.574] BEGIN WMNewTab: 31 +[16:28.49.574] END WMNewTab: 31 +[16:28.49.890] BEGIN WMNewTab: 20 +[16:28.49.890] END WMNewTab: 20 +[16:28.50.119] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.51.304] BEGIN WMNewTab: 20 +[16:28.51.304] END WMNewTab: 20 + +[16:28.51.752] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.51.991] BEGIN WMNewTab: 60 +[16:28.51.991] END WMNewTab: 60 + +[16:28.52.722] BEGIN WMNewTab: 20 +[16:28.52.722] END WMNewTab: 20 + +[16:28.53.331] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:28.54.137] BEGIN WMNewTab: 20 +[16:28.54.137] END WMNewTab: 20 + +[16:28.54.945] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.55.299] BEGIN CWD +[16:28.55.359] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:28.55.359] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:28.55.359] (SSH-Browser) END VerifySFTPConnection(1) +[16:28.55.359] END CWD +[16:28.55.362] BEGIN WMNewTab: 20 +[16:28.55.362] END WMNewTab: 20 +[16:28.55.376] BEGIN CWD +[16:28.55.437] END CWD + +[16:28.56.550] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.56.854] BEGIN WMNewTab: 20 +[16:28.56.854] END WMNewTab: 20 + + +[16:28.58.071] BEGIN WMNewTab: 0 +[16:28.58.071] WMNewTab: FormClick +[16:28.58.071] WMNewTab: LooseFocus +[16:28.58.071] END WMNewTab: 0 +[16:28.58.168] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:28.58.181] BEGIN WMNewTab: 0 +[16:28.58.181] WMNewTab: FormClick +[16:28.58.181] WMNewTab: LooseFocus +[16:28.58.181] END WMNewTab: 0 +[16:28.58.274] BEGIN WMNewTab: 20 +[16:28.58.274] END WMNewTab: 20 + + +[16:28.59.693] BEGIN WMNewTab: 20 +[16:28.59.693] END WMNewTab: 20 +[16:28.59.769] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:29.01.108] BEGIN WMNewTab: 20 +[16:29.01.108] END WMNewTab: 20 +[16:29.01.382] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.02.525] BEGIN WMNewTab: 20 +[16:29.02.525] END WMNewTab: 20 + +[16:29.02.982] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.03.941] BEGIN WMNewTab: 20 +[16:29.03.941] END WMNewTab: 20 + +[16:29.04.602] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.05.088] BEGIN CWD +[16:29.05.149] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:29.05.149] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:29.05.149] (SSH-Browser) END VerifySFTPConnection(1) +[16:29.05.149] END CWD +[16:29.05.152] BEGIN WMNewTab: 20 +[16:29.05.152] END WMNewTab: 20 +[16:29.05.165] BEGIN CWD +[16:29.05.227] END CWD + +[16:29.06.200] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.06.645] BEGIN WMNewTab: 20 +[16:29.06.645] END WMNewTab: 20 + +[16:29.07.818] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.08.061] BEGIN WMNewTab: 20 +[16:29.08.061] END WMNewTab: 20 + +[16:29.08.990] BEGIN CWD +[16:29.09.050] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:29.09.050] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:29.09.050] (SSH-Browser) END VerifySFTPConnection(1) +[16:29.09.050] END CWD +[16:29.09.067] BEGIN CWD +[16:29.09.130] END CWD +[16:29.09.419] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.09.602] BEGIN WMNewTab: 20 +[16:29.09.602] END WMNewTab: 20 + + +[16:29.11.025] BEGIN WMNewTab: 20 +[16:29.11.025] END WMNewTab: 20 +[16:29.11.082] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:29.12.444] BEGIN WMNewTab: 20 +[16:29.12.444] END WMNewTab: 20 +[16:29.12.644] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:29.13.862] BEGIN WMNewTab: 20 +[16:29.13.862] END WMNewTab: 20 + +[16:29.14.257] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.15.283] BEGIN WMNewTab: 20 +[16:29.15.283] END WMNewTab: 20 + +[16:29.15.864] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.16.705] BEGIN WMNewTab: 20 +[16:29.16.705] END WMNewTab: 20 + +[16:29.17.469] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.18.126] BEGIN WMNewTab: 20 +[16:29.18.126] END WMNewTab: 20 + +[16:29.19.082] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.19.540] BEGIN WMNewTab: 20 +[16:29.19.540] END WMNewTab: 20 + +[16:29.20.684] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.20.958] BEGIN WMNewTab: 20 +[16:29.20.958] END WMNewTab: 20 + +[16:29.22.018] BEGIN WMNewTab: 60 +[16:29.22.018] END WMNewTab: 60 +[16:29.22.309] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.22.377] BEGIN WMNewTab: 20 +[16:29.22.377] END WMNewTab: 20 + + +[16:29.23.800] BEGIN WMNewTab: 20 +[16:29.23.800] END WMNewTab: 20 +[16:29.23.907] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:29.25.220] BEGIN WMNewTab: 20 +[16:29.25.220] END WMNewTab: 20 +[16:29.25.523] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.26.639] BEGIN WMNewTab: 20 +[16:29.26.639] END WMNewTab: 20 + +[16:29.27.125] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.28.058] BEGIN WMNewTab: 20 +[16:29.28.058] END WMNewTab: 20 + +[16:29.28.745] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.29.478] BEGIN WMNewTab: 20 +[16:29.29.478] END WMNewTab: 20 + +[16:29.30.349] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.30.899] BEGIN WMNewTab: 20 +[16:29.30.899] END WMNewTab: 20 + +[16:29.31.964] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.32.316] BEGIN WMNewTab: 20 +[16:29.32.316] END WMNewTab: 20 + + +[16:29.33.567] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.33.734] BEGIN WMNewTab: 20 +[16:29.33.734] END WMNewTab: 20 + + +[16:29.35.157] BEGIN WMNewTab: 20 +[16:29.35.157] END WMNewTab: 20 +[16:29.35.171] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:29.36.600] BEGIN WMNewTab: 20 +[16:29.36.600] END WMNewTab: 20 +[16:29.36.778] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:29.38.015] BEGIN WMNewTab: 20 +[16:29.38.015] END WMNewTab: 20 + +[16:29.38.399] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.39.438] BEGIN WMNewTab: 20 +[16:29.39.438] END WMNewTab: 20 + +[16:29.40.003] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.40.858] BEGIN WMNewTab: 20 +[16:29.40.858] END WMNewTab: 20 + +[16:29.41.607] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.42.281] BEGIN WMNewTab: 20 +[16:29.42.281] END WMNewTab: 20 + +[16:29.43.229] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.43.742] BEGIN WMNewTab: 20 +[16:29.43.742] END WMNewTab: 20 + +[16:29.44.837] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.45.159] BEGIN WMNewTab: 20 +[16:29.45.159] END WMNewTab: 20 + + +[16:29.46.440] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.46.579] BEGIN WMNewTab: 20 +[16:29.46.579] END WMNewTab: 20 + + +[16:29.48.000] BEGIN WMNewTab: 20 +[16:29.48.000] END WMNewTab: 20 +[16:29.48.046] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:29.49.421] BEGIN WMNewTab: 20 +[16:29.49.421] END WMNewTab: 20 +[16:29.49.653] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.50.845] BEGIN WMNewTab: 20 +[16:29.50.845] END WMNewTab: 20 + +[16:29.51.273] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.52.039] BEGIN WMNewTab: 60 +[16:29.52.039] END WMNewTab: 60 +[16:29.52.264] BEGIN WMNewTab: 20 +[16:29.52.264] END WMNewTab: 20 + +[16:29.52.876] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.53.686] BEGIN WMNewTab: 20 +[16:29.53.686] END WMNewTab: 20 + +[16:29.54.481] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.55.107] BEGIN WMNewTab: 20 +[16:29.55.107] END WMNewTab: 20 + +[16:29.56.097] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:29.56.523] BEGIN WMNewTab: 20 +[16:29.56.523] END WMNewTab: 20 + +[16:29.57.712] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.57.942] BEGIN WMNewTab: 20 +[16:29.57.942] END WMNewTab: 20 + + +[16:29.59.314] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:29.59.361] BEGIN WMNewTab: 20 +[16:29.59.361] END WMNewTab: 20 + + +[16:30.00.783] BEGIN WMNewTab: 20 +[16:30.00.783] END WMNewTab: 20 +[16:30.00.920] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.02.198] BEGIN WMNewTab: 20 +[16:30.02.198] END WMNewTab: 20 +[16:30.02.531] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.03.616] BEGIN WMNewTab: 20 +[16:30.03.616] END WMNewTab: 20 + +[16:30.04.158] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.05.038] BEGIN WMNewTab: 20 +[16:30.05.038] END WMNewTab: 20 + +[16:30.05.754] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.06.455] BEGIN WMNewTab: 20 +[16:30.06.455] END WMNewTab: 20 + +[16:30.07.368] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.07.875] BEGIN WMNewTab: 20 +[16:30.07.875] END WMNewTab: 20 + +[16:30.08.973] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:30.09.296] BEGIN WMNewTab: 20 +[16:30.09.296] END WMNewTab: 20 + + +[16:30.10.578] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:30.10.713] BEGIN WMNewTab: 20 +[16:30.10.713] END WMNewTab: 20 + + +[16:30.12.135] BEGIN WMNewTab: 20 +[16:30.12.135] END WMNewTab: 20 +[16:30.12.197] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.13.558] BEGIN WMNewTab: 20 +[16:30.13.558] END WMNewTab: 20 +[16:30.13.802] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.14.979] BEGIN WMNewTab: 20 +[16:30.14.979] END WMNewTab: 20 + +[16:30.15.406] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.16.397] BEGIN WMNewTab: 20 +[16:30.16.397] END WMNewTab: 20 + +[16:30.17.024] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.17.819] BEGIN WMNewTab: 20 +[16:30.17.819] END WMNewTab: 20 + +[16:30.18.626] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.19.235] BEGIN WMNewTab: 20 +[16:30.19.235] END WMNewTab: 20 + +[16:30.20.239] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.20.649] BEGIN WMNewTab: 20 +[16:30.20.649] END WMNewTab: 20 + +[16:30.21.844] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:30.22.059] BEGIN WMNewTab: 60 +[16:30.22.059] END WMNewTab: 60 +[16:30.22.072] BEGIN WMNewTab: 20 +[16:30.22.072] END WMNewTab: 20 + + +[16:30.23.457] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:30.23.471] BEGIN WMNewTab: 0 +[16:30.23.471] WMNewTab: FormClick +[16:30.23.471] WMNewTab: LooseFocus +[16:30.23.471] END WMNewTab: 0 +[16:30.23.488] BEGIN WMNewTab: 20 +[16:30.23.488] END WMNewTab: 20 +[16:30.23.608] BEGIN WMNewTab: 0 +[16:30.23.608] WMNewTab: FormClick +[16:30.23.608] WMNewTab: LooseFocus +[16:30.23.609] END WMNewTab: 0 + + +[16:30.24.902] BEGIN WMNewTab: 20 +[16:30.24.902] END WMNewTab: 20 +[16:30.25.069] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.26.326] BEGIN WMNewTab: 20 +[16:30.26.326] END WMNewTab: 20 +[16:30.26.673] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:30.26.676] BEGIN WMNewTab: 48 +[16:30.26.676] 收到消息: SSH 会话部分关闭 (2) +[16:30.26.746] BEGIN TFormXterm.FormResize +[16:30.26.746] TFormXterm.FormResize: CenterBtnReattachTab +[16:30.26.747] TFormXterm.FormResize: SplitModeResize +[16:30.26.747] TFormXterm.FormResize: BtnSplitNo.Down +[16:30.26.748] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:30.26.748] BEGIN ResizeTerminal +[16:30.26.797] END ResizeTerminal +[16:30.26.797] TFormXterm.FormResize: AdaptSidebarArrows; +[16:30.26.797] BEGIN AdaptSidebarArrows +[16:30.26.797] END AdaptSidebarArrows +[16:30.26.797] TFormXterm.FormResize: AdaptTV2; +[16:30.26.797] END TFormXterm.FormResize +[16:30.26.797] BEGIN DisconnectSSH(1) +[16:30.26.797] (SSH-Browser) DisconnectSSH(1): (Socket.Active) and (SocketState<>SOCKET_STATE_CONNECTING) +[16:30.26.823] SetTitle(1, ); +[16:30.26.825] (SSH-Browser) ElSFTP1CloseConnection(1) +[16:30.26.825] (SSH-Browser) ElSFTP1Error(1): #103 - 连接被低层协议关闭 +[16:30.26.825] SFTPErr #103 附带说明 "连接被低层协议关闭" +[16:30.26.825] (SSH-Browser) ElSFTP1CloseConnection(1) +[16:30.26.826] BEGIN ElSSH1CloseConnection(1) +[16:30.26.826] END ElSSH1CloseConnection(1) +[16:30.26.826] (SSH-Browser) DisconnectSSH(1): Socket.Close; +[16:30.26.826] (SSH-Browser) BEGIN DesactiverPanel14 +[16:30.26.848] (SSH-Browser) END DesactiverPanel14 +[16:30.26.848] END DisconnectSSH(1) +[16:30.26.864] END WMNewTab: 48 + + +[16:30.28.283] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.29.899] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.31.505] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.33.117] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.34.724] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.36.325] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.37.942] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.39.543] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.41.165] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.42.763] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.44.380] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.45.997] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.47.600] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.49.202] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.50.824] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.51.597] BEGIN WMNewTab: 60 +[16:30.51.597] END WMNewTab: 60 + +[16:30.52.219] BEGIN WMNewTab: 60 +[16:30.52.219] END WMNewTab: 60 +[16:30.52.428] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:30.52.830] BEGIN WMNewTab: 60 +[16:30.52.830] END WMNewTab: 60 + +[16:30.53.800] BEGIN WMNewTab: 60 +[16:30.53.801] END WMNewTab: 60 +[16:30.53.933] Cts1MouseDown: FormClick +[16:30.53.943] Cts1ActiveTabChanged: New index = 2 +[16:30.53.943] BEGIN DisplayCurrentTab +[16:30.53.943] DisplayCurrentTab: FormClick +[16:30.53.943] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:30.53.943] (SSH-Browser) BEGIN ActiverPanel14 +[16:30.53.943] (SSH-Browser) BEGIN DesactiverPanel14 +[16:30.53.944] (SSH-Browser) END DesactiverPanel14 +[16:30.53.944] (SSH-Browser) END ActiverPanel14; +[16:30.53.971] DisplayCurrentTab: Cts1.BeginUpdate; +[16:30.53.971] DisplayCurrentTab: Cts1.EndUpdates +[16:30.53.998] DisplayCurrentTab: 显示所选标签页 +[16:30.54.005] DisplayCurrentTab: 隐藏其他标签页 +[16:30.54.007] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:30.54.011] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:30.54.011] DisplayCurrentTab: DistribuerLeFocus +[16:30.54.011] END DisplayCurrentTab +[16:30.54.031] BEGIN WMNewTab: 62 +[16:30.54.031] END WMNewTab: 62 +[16:30.54.033] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.55.649] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.57.248] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:30.58.861] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.00.478] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.02.077] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.03.698] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.05.297] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.06.906] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.08.517] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.10.133] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.11.744] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.13.340] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.14.949] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.16.566] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.17.381] BEGIN WMNewTab: 0 +[16:31.17.381] WMNewTab: FormClick +[16:31.17.381] WMNewTab: LooseFocus +[16:31.17.383] END WMNewTab: 0 +[16:31.17.461] BEGIN WMNewTab: 0 +[16:31.17.461] WMNewTab: FormClick +[16:31.17.461] WMNewTab: LooseFocus +[16:31.17.462] END WMNewTab: 0 + +[16:31.18.168] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.19.786] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.21.397] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.22.966] Cts1MouseDown: FormClick +[16:31.22.974] Cts1ActiveTabChanged: New index = 1 +[16:31.22.974] BEGIN DisplayCurrentTab +[16:31.22.974] DisplayCurrentTab: FormClick +[16:31.22.974] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:31.22.974] (SSH-Browser) BEGIN ActiverPanel14 +[16:31.22.974] (SSH-Browser) BEGIN DesactiverPanel14 +[16:31.22.974] (SSH-Browser) END DesactiverPanel14 +[16:31.22.974] (SSH-Browser) END ActiverPanel14; +[16:31.23.002] DisplayCurrentTab: Cts1.BeginUpdate; +[16:31.23.002] DisplayCurrentTab: Cts1.EndUpdates +[16:31.23.025] DisplayCurrentTab: 显示所选标签页 +[16:31.23.028] DisplayCurrentTab: 隐藏其他标签页 +[16:31.23.029] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:31.23.033] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:31.23.033] DisplayCurrentTab: DistribuerLeFocus +[16:31.23.034] END DisplayCurrentTab +[16:31.23.057] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.23.870] BEGIN WMNewTab: 62 +[16:31.23.870] END WMNewTab: 62 +[16:31.24.016] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:31.24.016] 主机密钥与缓存中的密钥是一致的 +[16:31.24.032] BEGIN GetPassword +[16:31.24.033] BEGIN GetnSaveCredPassword +[16:31.24.033] END GetnSaveCredPassword +[16:31.24.033] END GetPassword +[16:31.24.037] SetTitle(1, 192.168.127.10 (root)); + +[16:31.24.620] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.25.822] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:31.25.822] BEGIN SauvegarderMotDePasseSSH +[16:31.25.822] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:31.25.827] SetTitle(1, root@192.168.127.10); +[16:31.25.827] +[16:31.25.827] (SSH-Browser) BEGIN ConnectSSH(1,192.168.127.10,root,) +[16:31.25.827] (SSH-Browser) ConnectSSH(1): 初始化 TabSFTP +[16:31.25.830] (SSH-Browser) ConnectSSH(1): 未使用代理 +[16:31.25.830] (SSH-Browser) ConnectSSH(1): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:31.25.832] (SSH-Browser) ConnectSSH(1): 已成功连接到 192.168.127.10. +[16:31.25.832] (SSH-Browser) ConnectSSH(1): SSH.Open +[16:31.25.832] (SSH-Browser) END ConnectSSH(1) +[16:31.25.832] BEGIN DisplayCurrentTab +[16:31.25.832] DisplayCurrentTab: FormClick +[16:31.25.832] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:31.25.832] (SSH-Browser) BEGIN ActiverPanel14 +[16:31.25.832] (SSH-Browser) BEGIN DesactiverPanel14 +[16:31.25.832] (SSH-Browser) END DesactiverPanel14 +[16:31.25.832] (SSH-Browser) END ActiverPanel14; +[16:31.25.856] DisplayCurrentTab: Cts1.BeginUpdate; +[16:31.25.856] DisplayCurrentTab: Cts1.EndUpdates +[16:31.25.876] DisplayCurrentTab: 显示所选标签页 +[16:31.25.878] DisplayCurrentTab: 隐藏其他标签页 +[16:31.25.878] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:31.25.878] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:31.25.878] DisplayCurrentTab: DistribuerLeFocus +[16:31.25.878] END DisplayCurrentTab +[16:31.25.878] BEGIN SavePassword +[16:31.25.879] END SavePassword +[16:31.25.879] END SauvegarderMotDePasseSSH +[16:31.25.879] BEGIN WMNewTab: 80 +[16:31.25.879] 收到消息: 正在启动远程监控 终端 #2 +[16:31.25.912] BEGIN TFormXterm.FormResize +[16:31.25.912] TFormXterm.FormResize: CenterBtnReattachTab +[16:31.25.913] TFormXterm.FormResize: SplitModeResize +[16:31.25.913] TFormXterm.FormResize: BtnSplitNo.Down +[16:31.25.914] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:31.25.914] BEGIN ResizeTerminal +[16:31.25.939] END ResizeTerminal +[16:31.25.939] TFormXterm.FormResize: AdaptSidebarArrows; +[16:31.25.939] BEGIN AdaptSidebarArrows +[16:31.25.939] END AdaptSidebarArrows +[16:31.25.939] TFormXterm.FormResize: AdaptTV2; +[16:31.25.939] END TFormXterm.FormResize +[16:31.25.944] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:31.25.944] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:31.25.970] ShellExecuteS: ShellExecuteEx 成功. +[16:31.25.970] ShellExecuteS: WaitForInputIdle 失败. +[16:31.25.970] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:31.25.971] END WMNewTab: 80 +[16:31.26.044] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:31.26.045] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:31.26.045] (SSH-Browser) 主机密钥指纹信息 (Sha256): 2b:ca:32:12:87:5d:69:9e:24:78:db:b7:f5:ec:40:a8:c2:4b:0c:47:27:72:0a:10:19:c4:4f:43:cf:7c:05:be +[16:31.26.045] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[16:31.26.045] (SSH-Browser) END GetSftpOnValidateStatus +[16:31.26.070] [MobaSCP2] Launching remote monitoring in normal mode +[16:31.26.070] [MobaSCP2] Multiplex=1 +[16:31.26.071] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:31.26.071] [MobaSCP2] USERNAME: root +[16:31.26.119] +[16:31.26.119] (SSH-Browser) ElSSH1AuthenticationStart(1, 134) +[16:31.26.119] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:31.26.119] (SSH-Browser) 服务器支持以下认证方式: +[16:31.26.119] (SSH-Browser) . PUBLICKEYAGENT +[16:31.26.119] (SSH-Browser) . PUBLICKEY +[16:31.26.119] (SSH-Browser) . PASSWORD +[16:31.26.119] (SSH-Browser) 客户端支持以下认证方式: +[16:31.26.119] (SSH-Browser) . PUBLICKEYAGENT +[16:31.26.119] (SSH-Browser) . PUBLICKEY +[16:31.26.119] (SSH-Browser) . RHOSTS +[16:31.26.119] (SSH-Browser) . HOSTBASED +[16:31.26.119] (SSH-Browser) . PASSWORD +[16:31.26.119] (SSH-Browser) . KEYBOARD +[16:31.26.119] +[16:31.26.119] +[16:31.26.119] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEY) +[16:31.26.119] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEYAGENT) +[16:31.26.119] (SSH-Browser) ElSSH1AuthenticationAttempt(1, PASSWORD) +[16:31.26.131] [MobaSCP2] Using SCP1 +[16:31.26.132] [MobaSCP2] Connected to 192.168.127.10 +[16:31.26.225] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:31.26.499] (SSH-Browser) ElSSH1AuthenticationSuccess(1) +[16:31.26.499] (SSH-Browser) ElSSH1OpenConnection(1) +[16:31.26.499] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:31.26.499] +[16:31.26.851] (SSH-Browser) BEGIN ElSFTP1OpenConnection(1) +[16:31.26.851] (SSH-Browser) ElSFTP1OpenConnection(1): SFTP 已正确连接 +[16:31.26.851] (SSH-Browser) ElSFTP1OpenConnection(1): ActiverPanel14 +[16:31.26.851] (SSH-Browser) BEGIN ActiverPanel14 +[16:31.26.851] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:31.26.859] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:31.26.859] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:31.26.859] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:31.26.860] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:31.26.914] (SSH-Browser) END ActiverPanel14; +[16:31.27.002] (SSH-Browser) ElSFTP1OpenConnection(1): 已成功打开连接 --> 正在退出 +[16:31.27.002] (SSH-Browser) END ElSFTP1OpenConnection(1) +[16:31.27.308] BEGIN TFormXterm.FormResize +[16:31.27.308] TFormXterm.FormResize: CenterBtnReattachTab +[16:31.27.308] TFormXterm.FormResize: SplitModeResize +[16:31.27.308] TFormXterm.FormResize: BtnSplitNo.Down +[16:31.27.308] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:31.27.308] BEGIN ResizeTerminal +[16:31.27.309] END ResizeTerminal +[16:31.27.309] TFormXterm.FormResize: AdaptSidebarArrows; +[16:31.27.309] BEGIN AdaptSidebarArrows +[16:31.27.309] END AdaptSidebarArrows +[16:31.27.309] TFormXterm.FormResize: AdaptTV2; +[16:31.27.309] END TFormXterm.FormResize +[16:31.27.464] BEGIN WMNewTab: 20 +[16:31.27.464] END WMNewTab: 20 + +[16:31.27.830] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.28.880] BEGIN WMNewTab: 20 +[16:31.28.880] END WMNewTab: 20 + +[16:31.29.439] +[16:31.29.439] +[16:31.29.439] BEGIN TForm1.MobaInputDialog +[16:31.29.439] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[16:31.29.439] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=0; +[16:31.29.441] TForm1.MobaInputDialog: FormInputDialog.ShowModal +[16:31.29.511] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.30.293] BEGIN WMNewTab: 20 +[16:31.30.293] END WMNewTab: 20 + +[16:31.31.059] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.31.713] BEGIN WMNewTab: 20 +[16:31.31.713] END WMNewTab: 20 + +[16:31.32.661] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.33.135] BEGIN WMNewTab: 20 +[16:31.33.135] END WMNewTab: 20 + +[16:31.34.266] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:31.34.558] BEGIN WMNewTab: 20 +[16:31.34.558] END WMNewTab: 20 + +[16:31.35.307] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[16:31.35.307] END TForm1.MobaInputDialog +[16:31.35.307] +[16:31.35.307] +[16:31.35.307] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:31.35.307] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:31.35.307] (SSH-Browser) END VerifySFTPConnection(1) +[16:31.35.307] (SSH-Browser) MakeDirectory1Click: SFTP.MakeDirectory(/root/tsxt) +[16:31.35.375] (SSH-Browser) ElSFTP1Success(1) +[16:31.35.375] (SSH-Browser) BEGIN OpenDir(1) +[16:31.35.375] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:31.35.375] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:31.35.375] (SSH-Browser) END VerifySFTPConnection(1) +[16:31.35.375] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:31.35.376] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/); +[16:31.35.376] (SSH-Browser) END OpenDir(1) +[16:31.35.403] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:31.35.403] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:31.35.432] (SSH-Browser) ElSFTP1OpenFile(1) +[16:31.35.432] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:31.35.494] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:31.35.494] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:31.35.494] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:31.35.494] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:31.35.494] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:31.35.494] (SSH-Browser) END VerifySFTPConnection(1) +[16:31.35.494] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:31.35.494] (SSH-Browser) END CloseCurrentHandle(1) +[16:31.35.494] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:31.35.494] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=19 +[16:31.35.494] (SSH-Browser) 对项目进行排序 +[16:31.35.494] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:31.35.499] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:31.35.542] (SSH-Browser) ElSFTP1Success(1) +[16:31.35.877] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:31.36.014] BEGIN WMNewTab: 20 +[16:31.36.014] END WMNewTab: 20 + + +[16:31.37.432] BEGIN WMNewTab: 20 +[16:31.37.432] END WMNewTab: 20 +[16:31.37.494] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.38.877] BEGIN WMNewTab: 20 +[16:31.38.877] END WMNewTab: 20 +[16:31.39.096] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.40.284] BEGIN WMNewTab: 20 +[16:31.40.284] END WMNewTab: 20 + +[16:31.40.755] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.41.479] +[16:31.41.479] +[16:31.41.479] BEGIN TForm1.MobaInputDialog +[16:31.41.481] TForm1.MobaInputDialog: FormInputDialog.Visible=false +[16:31.41.481] TForm1.MobaInputDialog: FormInputDialog.ParentWindow:=Form4.Handle; +[16:31.41.482] TForm1.MobaInputDialog: FormInputDialog.ShowModal +[16:31.41.700] BEGIN WMNewTab: 20 +[16:31.41.700] END WMNewTab: 20 + +[16:31.42.311] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.43.114] BEGIN WMNewTab: 20 +[16:31.43.114] END WMNewTab: 20 + +[16:31.43.920] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.44.534] BEGIN WMNewTab: 20 +[16:31.44.534] END WMNewTab: 20 + +[16:31.45.552] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.45.951] BEGIN WMNewTab: 20 +[16:31.45.951] END WMNewTab: 20 + +[16:31.46.859] TForm1.MobaInputDialog: FormInputDialog.ShowModal --> OK +[16:31.46.859] END TForm1.MobaInputDialog +[16:31.46.859] +[16:31.46.859] +[16:31.46.859] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:31.46.859] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:31.46.859] (SSH-Browser) END VerifySFTPConnection(1) +[16:31.46.859] (SSH-Browser) Rename1Click: SFTP.RenameFile(/root/tsxt/) +[16:31.46.929] (SSH-Browser) ElSFTP1Success(1) +[16:31.46.929] (SSH-Browser) BEGIN OpenDir(1) +[16:31.46.929] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:31.46.929] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:31.46.929] (SSH-Browser) END VerifySFTPConnection(1) +[16:31.46.929] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:31.46.930] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/); +[16:31.46.930] (SSH-Browser) END OpenDir(1) +[16:31.46.958] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:31.46.958] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:31.46.989] (SSH-Browser) ElSFTP1OpenFile(1) +[16:31.46.990] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:31.47.050] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:31.47.050] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:31.47.050] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:31.47.050] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:31.47.050] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:31.47.050] (SSH-Browser) END VerifySFTPConnection(1) +[16:31.47.050] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:31.47.050] (SSH-Browser) END CloseCurrentHandle(1) +[16:31.47.050] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:31.47.050] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=19 +[16:31.47.050] (SSH-Browser) 对项目进行排序 +[16:31.47.050] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:31.47.056] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:31.47.095] (SSH-Browser) ElSFTP1Success(1) +[16:31.47.140] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.47.577] BEGIN WMNewTab: 20 +[16:31.47.577] END WMNewTab: 20 + +[16:31.48.408] sListView1Click: FormClick +[16:31.48.487] (SSH-Browser) BEGIN OpenDir(1) +[16:31.48.487] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:31.48.487] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:31.48.487] (SSH-Browser) END VerifySFTPConnection(1) +[16:31.48.487] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:31.48.490] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/test/); +[16:31.48.491] (SSH-Browser) END OpenDir(1) +[16:31.48.543] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:31.48.543] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root/test) +[16:31.48.604] (SSH-Browser) ElSFTP1OpenFile(1) +[16:31.48.604] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:31.48.666] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:31.48.666] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:31.48.666] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:31.48.666] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:31.48.666] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:31.48.666] (SSH-Browser) END VerifySFTPConnection(1) +[16:31.48.666] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:31.48.666] (SSH-Browser) END CloseCurrentHandle(1) +[16:31.48.666] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:31.48.666] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=2 +[16:31.48.666] (SSH-Browser) 对项目进行排序 +[16:31.48.667] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:31.48.678] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:31.48.697] (SSH-Browser) ElSFTP1Success(1) +[16:31.48.752] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.49.170] BEGIN WMNewTab: 20 +[16:31.49.170] END WMNewTab: 20 + +[16:31.50.359] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:31.50.651] BEGIN WMNewTab: 20 +[16:31.50.651] END WMNewTab: 20 + + +[16:31.51.966] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:31.52.063] BEGIN WMNewTab: 20 +[16:31.52.063] END WMNewTab: 20 + + +[16:31.53.478] BEGIN WMNewTab: 20 +[16:31.53.478] END WMNewTab: 20 +[16:31.53.584] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:31.54.897] BEGIN WMNewTab: 20 +[16:31.54.897] END WMNewTab: 20 +[16:31.55.185] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31.56.310] BEGIN WMNewTab: 20 +[16:31.56.310] END WMNewTab: 20 + +[16:31.56.890] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31:57] BEGIN WMNewTab: 20 +[16:31:57] END WMNewTab: 20 + +[16:31:58] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:31:59] BEGIN WMNewTab: 20 +[16:31:59] END WMNewTab: 20 + +[16:32:00] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:00] BEGIN WMNewTab: 20 +[16:32:00] END WMNewTab: 20 + +[16:32:01] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32:01] BEGIN WMNewTab: 20 +[16:32:01] END WMNewTab: 20 + + +[16:32:03] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32:03] BEGIN WMNewTab: 20 +[16:32:03] END WMNewTab: 20 + + +[16:32:04] BEGIN WMNewTab: 20 +[16:32:04] END WMNewTab: 20 +[16:32:04] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:32:06] BEGIN WMNewTab: 20 +[16:32:06] END WMNewTab: 20 +[16:32:06] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:07] BEGIN WMNewTab: 20 +[16:32:07] END WMNewTab: 20 + +[16:32:08] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:09] BEGIN WMNewTab: 20 +[16:32:09] END WMNewTab: 20 + +[16:32:09] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:10] BEGIN WMNewTab: 20 +[16:32:10] END WMNewTab: 20 + +[16:32:11] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:11] BEGIN WMNewTab: 20 +[16:32:11] END WMNewTab: 20 + +[16:32:12] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:13] BEGIN WMNewTab: 20 +[16:32:13] END WMNewTab: 20 + + +[16:32:14] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32:14] BEGIN WMNewTab: 20 +[16:32:14] END WMNewTab: 20 + + +[16:32:16] BEGIN WMNewTab: 20 +[16:32:16] END WMNewTab: 20 +[16:32:16] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:32:17] BEGIN WMNewTab: 20 +[16:32:17] END WMNewTab: 20 +[16:32:17] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:32:18] BEGIN WMNewTab: 20 +[16:32:18] END WMNewTab: 20 +[16:32:19] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:20] BEGIN WMNewTab: 20 +[16:32:20] END WMNewTab: 20 + +[16:32:20] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:21] BEGIN WMNewTab: 20 +[16:32:21] END WMNewTab: 20 + +[16:32:22] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:23] BEGIN WMNewTab: 20 +[16:32:23] END WMNewTab: 20 + +[16:32:24] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32:24] BEGIN WMNewTab: 20 +[16:32:24] END WMNewTab: 20 +[16:32:25] (SSH-Browser) TDownUpForm.Timer1Timer +[16:32:25] (SSH-Browser) InitializeSFTP +[16:32:25] (SSH-Browser) InitializeSFTP: Socketcli.Open; +[16:32:25] (SSH-Browser) InitializeSFTP: Connected to 192.168.127.10. +[16:32:25] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. + +[16:32:25] (SSH-Browser) BEGIN SSHcliOpenConnection +[16:32:25] (SSH-Browser) SSHcliOpenConnection: OpenSSH = TRUE +[16:32:25] (SSH-Browser) SSHcliOpenConnection: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:32:25] (SSH-Browser) SSHcliOpenConnection: PipelineLength = 32 +[16:32:25] (SSH-Browser) SSHcliOpenConnection: DownloadBlockSize = 32768 +[16:32:25] (SSH-Browser) SSHcliOpenConnection: UploadBlockSize = 65536 +[16:32:25] (SSH-Browser) SSHcliOpenConnection: SftpBufferSize = 262144 +[16:32:25] (SSH-Browser) SSHcliOpenConnection: DefaultWindowSize = 2097152 +[16:32:25] (SSH-Browser) SSHcliOpenConnection: MinWindowSize = 2048 +[16:32:25] (SSH-Browser) SSHcliOpenConnection: MaxSSHPacketSize = 262144 +[16:32:25] (SSH-Browser) SSHcliOpenConnection: AutoAdjustTransferBlock = FALSE +[16:32:25] (SSH-Browser) END SSHcliOpenConnection +[16:32:25] (SSH-Browser) TDownUpForm.Timer1Timer +[16:32:25] (SSH-Browser) InitializeSFTP +[16:32:25] (SSH-Browser) InitializeSFTP: result:=true; +[16:32:25] (SSH-Browser) SFTPcliOpenConnection +[16:32:25] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:32:25] (SSH-Browser) 上传下载文件: 正在上传 start_camera_stream.sh +[16:32:25] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:32:25] (SSH-Browser) DownUpFile: SFTPcli.CreateFile(/root/test/start_camera_stream.sh) +[16:32:25] (SSH-Browser) DownUpFile: MODE = UPLOAD +[16:32:25] (SSH-Browser) DownUpFile: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:32:25] (SSH-Browser) DownUpFile: PipelineLength = 32 +[16:32:25] (SSH-Browser) DownUpFile: DownloadBlockSize = 32768 +[16:32:25] (SSH-Browser) DownUpFile: UploadBlockSize = 65536 +[16:32:25] (SSH-Browser) DownUpFile: SftpBufferSize = 262144 +[16:32:25] (SSH-Browser) DownUpFile: DefaultWindowSize = 2097152 +[16:32:25] (SSH-Browser) DownUpFile: MinWindowSize = 2048 +[16:32:25] (SSH-Browser) DownUpFile: MaxSSHPacketSize = 262144 +[16:32:25] (SSH-Browser) DownUpFile: AutoAdjustTransferBlock = FALSE +[16:32:25] (SSH-Browser) DownUpFile: AsciiMode = FALSE +[16:32:25] (SSH-Browser) SFTPcliOpenFile +[16:32:25] (SSH-Browser) Uploading file +[16:32:25] (SSH-Browser) CloseCurrentHandle +[16:32:25] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:32:25] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:32:25] (SSH-Browser) TDownUpForm.Timer1Timer2 +[16:32:25] (SSH-Browser) BEGIN OpenDir(1) +[16:32:25] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:32:25] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:32:25] (SSH-Browser) END VerifySFTPConnection(1) +[16:32:25] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:32:25] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/test/); +[16:32:25] (SSH-Browser) END OpenDir(1) +[16:32:25] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:32:25] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root/test) +[16:32:25] (SSH-Browser) ElSFTP1OpenFile(1) +[16:32:25] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:32:26] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:32:26] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:32:26] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:32:26] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:32:26] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:32:26] (SSH-Browser) END VerifySFTPConnection(1) +[16:32:26] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:32:26] (SSH-Browser) END CloseCurrentHandle(1) +[16:32:26] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:32:26] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[16:32:26] (SSH-Browser) 对项目进行排序 +[16:32:26] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:32.26.051] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:32.26.064] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32.26.079] (SSH-Browser) ElSFTP1Success(1) +[16:32.26.079] BEGIN WMNewTab: 20 +[16:32.26.079] END WMNewTab: 20 + + +[16:32.27.493] BEGIN WMNewTab: 20 +[16:32.27.493] END WMNewTab: 20 +[16:32.27.676] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:32.28.913] BEGIN WMNewTab: 20 +[16:32.28.913] END WMNewTab: 20 + +[16:32.29.281] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.30.334] BEGIN WMNewTab: 20 +[16:32.30.334] END WMNewTab: 20 + +[16:32.30.887] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.31.752] BEGIN WMNewTab: 20 +[16:32.31.752] END WMNewTab: 20 + +[16:32.32.499] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.33.171] BEGIN WMNewTab: 20 +[16:32.33.171] END WMNewTab: 20 + +[16:32.34.112] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.34.585] BEGIN WMNewTab: 20 +[16:32.34.585] END WMNewTab: 20 + +[16:32.35.726] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32.36.002] BEGIN WMNewTab: 20 +[16:32.36.002] END WMNewTab: 20 + + +[16:32.37.330] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32.37.421] BEGIN WMNewTab: 20 +[16:32.37.421] END WMNewTab: 20 + + +[16:32.38.839] BEGIN WMNewTab: 20 +[16:32.38.839] END WMNewTab: 20 +[16:32.38.935] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:32.40.256] BEGIN WMNewTab: 20 +[16:32.40.256] END WMNewTab: 20 +[16:32.40.545] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.41.088] BEGIN WMNewTab: 0 +[16:32.41.088] WMNewTab: FormClick +[16:32.41.088] WMNewTab: LooseFocus +[16:32.41.093] END WMNewTab: 0 +[16:32.41.201] BEGIN WMNewTab: 0 +[16:32.41.201] WMNewTab: FormClick +[16:32.41.201] WMNewTab: LooseFocus +[16:32.41.201] END WMNewTab: 0 + +[16:32.41.672] BEGIN WMNewTab: 20 +[16:32.41.672] END WMNewTab: 20 + +[16:32.42.159] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.43.092] BEGIN WMNewTab: 20 +[16:32.43.092] END WMNewTab: 20 + +[16:32.43.773] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.44.507] BEGIN WMNewTab: 20 +[16:32.44.507] END WMNewTab: 20 + +[16:32.45.375] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.45.921] BEGIN WMNewTab: 20 +[16:32.45.921] END WMNewTab: 20 + +[16:32.46.986] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32.47.337] BEGIN WMNewTab: 20 +[16:32.47.337] END WMNewTab: 20 + + +[16:32.48.600] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32.48.790] BEGIN WMNewTab: 20 +[16:32.48.790] END WMNewTab: 20 + + +[16:32.50.201] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:32.50.209] BEGIN WMNewTab: 20 +[16:32.50.209] END WMNewTab: 20 + +[16:32.50.688] BEGIN WMNewTab: 0 +[16:32.50.688] WMNewTab: FormClick +[16:32.50.688] WMNewTab: LooseFocus +[16:32.50.688] END WMNewTab: 0 +[16:32.50.688] BEGIN WMNewTab: 31 +[16:32.50.688] END WMNewTab: 31 +[16:32.50.836] BEGIN WMNewTab: 0 +[16:32.50.836] WMNewTab: FormClick +[16:32.50.836] WMNewTab: LooseFocus +[16:32.50.836] END WMNewTab: 0 + +[16:32.51.631] BEGIN WMNewTab: 20 +[16:32.51.631] END WMNewTab: 20 +[16:32.51.856] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.53.054] BEGIN WMNewTab: 20 +[16:32.53.054] END WMNewTab: 20 + +[16:32.53.422] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.54.476] BEGIN WMNewTab: 20 +[16:32.54.476] END WMNewTab: 20 + +[16:32.55.039] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.55.934] BEGIN WMNewTab: 20 +[16:32.55.934] END WMNewTab: 20 + +[16:32.56.644] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.57.344] BEGIN WMNewTab: 20 +[16:32.57.344] END WMNewTab: 20 + +[16:32.57.873] BEGIN WMNewTab: 0 +[16:32.57.873] WMNewTab: FormClick +[16:32.57.873] WMNewTab: LooseFocus +[16:32.57.877] END WMNewTab: 0 +[16:32.58.000] BEGIN WMNewTab: 0 +[16:32.58.000] WMNewTab: FormClick +[16:32.58.000] WMNewTab: LooseFocus +[16:32.58.000] END WMNewTab: 0 +[16:32.58.258] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:32.58.762] BEGIN WMNewTab: 20 +[16:32.58.762] END WMNewTab: 20 +[16:32.58.913] BEGIN WMNewTab: 0 +[16:32.58.913] WMNewTab: FormClick +[16:32.58.913] WMNewTab: LooseFocus +[16:32.58.914] END WMNewTab: 0 +[16:32.58.914] BEGIN WMNewTab: 31 +[16:32.58.914] END WMNewTab: 31 +[16:32.59.016] BEGIN WMNewTab: 0 +[16:32.59.016] WMNewTab: FormClick +[16:32.59.016] WMNewTab: LooseFocus +[16:32.59.017] END WMNewTab: 0 + +[16:32.59.866] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.00.186] BEGIN WMNewTab: 20 +[16:33.00.186] END WMNewTab: 20 + + +[16:33.01.475] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.01.596] BEGIN WMNewTab: 20 +[16:33.01.596] END WMNewTab: 20 + + +[16:33.03.013] BEGIN WMNewTab: 20 +[16:33.03.013] END WMNewTab: 20 +[16:33.03.089] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:33.04.435] BEGIN WMNewTab: 20 +[16:33.04.435] END WMNewTab: 20 +[16:33.04.695] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.04.864] BEGIN CWD +[16:33.04.864] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:33.04.864] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:33.04.864] (SSH-Browser) END VerifySFTPConnection(1) +[16:33.04.864] END CWD +[16:33.05.002] (SSH-Browser) ElCommandSSHTunnel1Open +[16:33.05.034] (SSH-Browser) ExecuteCommandData +[16:33.05.063] (SSH-Browser) ExecuteCommandData +[16:33.05.141] (SSH-Browser) ExecuteCommandData +[16:33.05.170] (SSH-Browser) ExecuteCommandData +[16:33.05.201] (SSH-Browser) ExecuteCommandData +[16:33.05.231] (SSH-Browser) ExecuteCommandData +[16:33.05.322] (SSH-Browser) ExecuteCommandClose +[16:33.05.322] BEGIN CWD +[16:33.05.330] (CWD) TenterDeTrouverLeCWD: Minute=1 / Seconde=39 +[16:33.05.392] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:33.05.392] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:33.05.392] (SSH-Browser) END VerifySFTPConnection(1) +[16:33.05.392] END CWD +[16:33.05.413] BEGIN CWD +[16:33.05.475] (CWD) OpenDir(/root); +[16:33.05.475] (SSH-Browser) BEGIN OpenDir(1) +[16:33.05.475] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:33.05.475] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:33.05.475] (SSH-Browser) END VerifySFTPConnection(1) +[16:33.05.475] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:33.05.476] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root); +[16:33.05.476] (SSH-Browser) END OpenDir(1) +[16:33.05.476] END CWD +[16:33.05.505] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:33.05.505] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:33.05.535] (SSH-Browser) ElSFTP1OpenFile(1) +[16:33.05.535] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:33.05.597] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:33.05.597] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:33.05.597] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:33.05.597] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:33.05.597] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:33.05.597] (SSH-Browser) END VerifySFTPConnection(1) +[16:33.05.597] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:33.05.597] (SSH-Browser) END CloseCurrentHandle(1) +[16:33.05.597] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:33.05.597] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=19 +[16:33.05.597] (SSH-Browser) 对项目进行排序 +[16:33.05.597] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:33.05.602] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:33.05.644] (SSH-Browser) ElSFTP1Success(1) +[16:33.05.644] BEGIN WMNewTab: 20 +[16:33.05.644] END WMNewTab: 20 + +[16:33.06.297] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.07.060] BEGIN WMNewTab: 20 +[16:33.07.060] END WMNewTab: 20 + +[16:33.07.912] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.08.475] BEGIN WMNewTab: 20 +[16:33.08.475] END WMNewTab: 20 + +[16:33.09.515] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.09.898] BEGIN WMNewTab: 20 +[16:33.09.898] END WMNewTab: 20 + +[16:33.10.512] BEGIN WMNewTab: 0 +[16:33.10.512] WMNewTab: FormClick +[16:33.10.512] WMNewTab: LooseFocus +[16:33.10.514] END WMNewTab: 0 +[16:33.10.514] BEGIN WMNewTab: 31 +[16:33.10.514] END WMNewTab: 31 +[16:33.10.681] BEGIN WMNewTab: 0 +[16:33.10.681] WMNewTab: FormClick +[16:33.10.681] WMNewTab: LooseFocus +[16:33.10.681] END WMNewTab: 0 + +[16:33.11.136] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.11.319] BEGIN WMNewTab: 20 +[16:33.11.319] END WMNewTab: 20 + + +[16:33.12.742] BEGIN WMNewTab: 20 +[16:33.12.742] END WMNewTab: 20 +[16:33.12.742] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:33.14.157] BEGIN WMNewTab: 20 +[16:33.14.157] END WMNewTab: 20 +[16:33.14.353] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:33.15.575] BEGIN WMNewTab: 20 +[16:33.15.575] END WMNewTab: 20 + +[16:33.15.956] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.16.993] BEGIN WMNewTab: 20 +[16:33.16.993] END WMNewTab: 20 + +[16:33.17.559] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.18.405] BEGIN WMNewTab: 20 +[16:33.18.405] END WMNewTab: 20 + +[16:33.19.170] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.19.825] BEGIN WMNewTab: 20 +[16:33.19.825] END WMNewTab: 20 + +[16:33.20.786] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.21.245] BEGIN WMNewTab: 20 +[16:33.21.245] END WMNewTab: 20 + +[16:33.22.401] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.22.658] BEGIN WMNewTab: 20 +[16:33.22.658] END WMNewTab: 20 + + +[16:33.23.999] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.24.075] BEGIN WMNewTab: 20 +[16:33.24.075] END WMNewTab: 20 + + +[16:33.25.491] BEGIN WMNewTab: 20 +[16:33.25.491] END WMNewTab: 20 +[16:33.25.614] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.26.637] BEGIN WMNewTab: 0 +[16:33.26.637] WMNewTab: FormClick +[16:33.26.637] WMNewTab: LooseFocus +[16:33.26.638] END WMNewTab: 0 +[16:33.26.907] BEGIN WMNewTab: 20 +[16:33.26.907] END WMNewTab: 20 +[16:33.27.228] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.28.327] BEGIN WMNewTab: 20 +[16:33.28.327] END WMNewTab: 20 +[16:33.28.342] BEGIN WMNewTab: 0 +[16:33.28.342] WMNewTab: FormClick +[16:33.28.342] WMNewTab: LooseFocus +[16:33.28.343] END WMNewTab: 0 +[16:33.28.629] BEGIN WMNewTab: 0 +[16:33.28.629] WMNewTab: FormClick +[16:33.28.629] WMNewTab: LooseFocus +[16:33.28.629] END WMNewTab: 0 +[16:33.28.629] BEGIN WMNewTab: 31 +[16:33.28.629] END WMNewTab: 31 +[16:33.28.721] BEGIN WMNewTab: 0 +[16:33.28.721] WMNewTab: FormClick +[16:33.28.721] WMNewTab: LooseFocus +[16:33.28.722] END WMNewTab: 0 +[16:33.28.833] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.29.506] BEGIN CWD +[16:33.29.568] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:33.29.568] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:33.29.568] (SSH-Browser) END VerifySFTPConnection(1) +[16:33.29.568] END CWD +[16:33.29.569] BEGIN WMNewTab: 20 +[16:33.29.569] END WMNewTab: 20 +[16:33.29.581] BEGIN CWD +[16:33.29.642] END CWD + +[16:33.30.436] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.31.061] BEGIN WMNewTab: 20 +[16:33.31.061] END WMNewTab: 20 + +[16:33.32.053] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.32.480] BEGIN WMNewTab: 20 +[16:33.32.480] END WMNewTab: 20 + +[16:33.33.409] BEGIN WMNewTab: 0 +[16:33.33.409] WMNewTab: FormClick +[16:33.33.411] WMNewTab: LooseFocus +[16:33.33.411] END WMNewTab: 0 +[16:33.33.522] BEGIN WMNewTab: 0 +[16:33.33.522] WMNewTab: FormClick +[16:33.33.522] WMNewTab: LooseFocus +[16:33.33.522] END WMNewTab: 0 +[16:33.33.655] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.33.903] BEGIN WMNewTab: 20 +[16:33.33.903] END WMNewTab: 20 + + +[16:33.35.276] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.35.322] BEGIN WMNewTab: 20 +[16:33.35.322] END WMNewTab: 20 + +[16:33.36.338] sListView1Click: FormClick +[16:33.36.390] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:33.36.390] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:33.36.390] (SSH-Browser) END VerifySFTPConnection(1) +[16:33.36.391] (SSH-Browser) sListView1DblClick: SFTP.OpenFile(/root/.bashrc); +[16:33.36.391] (SSH-Browser) sListView1DblClick: MODE = DOWNLOAD (FILE EDITION) +[16:33.36.391] (SSH-Browser) sListView1DblClick: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:33.36.391] (SSH-Browser) sListView1DblClick: PipelineLength = 32 +[16:33.36.391] (SSH-Browser) sListView1DblClick: DownloadBlockSize = 32768 +[16:33.36.391] (SSH-Browser) sListView1DblClick: UploadBlockSize = 65536 +[16:33.36.391] (SSH-Browser) sListView1DblClick: SftpBufferSize = 131072 +[16:33.36.391] (SSH-Browser) sListView1DblClick: DefaultWindowSize = 2097152 +[16:33.36.391] (SSH-Browser) sListView1DblClick: MinWindowSize = 2048 +[16:33.36.391] (SSH-Browser) sListView1DblClick: MaxSSHPacketSize = 262144 +[16:33.36.391] (SSH-Browser) sListView1DblClick: AutoAdjustTransferBlock = FALSE +[16:33.36.391] (SSH-Browser) sListView1DblClick: Ascii mode = false +[16:33.36.520] (SSH-Browser) ElSFTP1OpenFile(1) +[16:33.36.536] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.Read +[16:33.36.542] BEGIN WMNewTab: 20 +[16:33.36.542] END WMNewTab: 20 +[16:33.36.572] (SSH-Browser) ElSFTP1Data(1) +[16:33.36.573] (SSH-Browser) ElSFTP1Error(1): #1 - +[16:33.36.573] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle2 +[16:33.36.573] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:33.36.573] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:33.36.573] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:33.36.573] (SSH-Browser) END VerifySFTPConnection(1) +[16:33.36.573] (SSH-Browser) END CloseCurrentHandle(1) +[16:33.36.587] +[16:33.36.587] BEGIN Form4.FormActivate +[16:33.36.587] END Form4.FormActivate +[16:33.36.587] +[16:33.36.589] (SSH-Browser) ReallyOpenFile + + +[16:33.38.195] BEGIN WMNewTab: 20 +[16:33.38.195] END WMNewTab: 20 +[16:33.38.299] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.38.508] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.39.609] BEGIN WMNewTab: 20 +[16:33.39.609] END WMNewTab: 20 + +[16:33.40.113] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.41.029] BEGIN WMNewTab: 20 +[16:33.41.029] END WMNewTab: 20 + +[16:33.41.716] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.42.449] BEGIN WMNewTab: 20 +[16:33.42.449] END WMNewTab: 20 + +[16:33.43.337] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.43.869] BEGIN WMNewTab: 20 +[16:33.43.869] END WMNewTab: 20 + +[16:33.44.987] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.45.285] BEGIN WMNewTab: 20 +[16:33.45.285] END WMNewTab: 20 + + +[16:33.46.550] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.46.702] BEGIN WMNewTab: 20 +[16:33.46.703] END WMNewTab: 20 + + +[16:33.48.115] BEGIN WMNewTab: 20 +[16:33.48.115] END WMNewTab: 20 +[16:33.48.160] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:33.49.528] BEGIN WMNewTab: 20 +[16:33.49.528] END WMNewTab: 20 +[16:33.49.771] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.50.944] BEGIN WMNewTab: 20 +[16:33.50.944] END WMNewTab: 20 + +[16:33.51.371] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.52.368] BEGIN WMNewTab: 20 +[16:33.52.368] END WMNewTab: 20 + +[16:33.52.993] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.53.784] BEGIN WMNewTab: 20 +[16:33.53.784] END WMNewTab: 20 + +[16:33.54.592] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.55.203] BEGIN WMNewTab: 20 +[16:33.55.203] END WMNewTab: 20 + +[16:33.56.212] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:33.56.627] BEGIN WMNewTab: 20 +[16:33.56.627] END WMNewTab: 20 + +[16:33.57.815] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.58.043] BEGIN WMNewTab: 20 +[16:33.58.043] END WMNewTab: 20 + + +[16:33.59.432] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:33.59.461] BEGIN WMNewTab: 20 +[16:33.59.461] END WMNewTab: 20 + + +[16:34.00.883] BEGIN WMNewTab: 20 +[16:34.00.883] END WMNewTab: 20 +[16:34.01.035] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:34.02.330] BEGIN WMNewTab: 20 +[16:34.02.330] END WMNewTab: 20 +[16:34.02.644] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.03.736] BEGIN WMNewTab: 20 +[16:34.03.736] END WMNewTab: 20 + +[16:34.04.256] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.05.153] BEGIN WMNewTab: 20 +[16:34.05.153] END WMNewTab: 20 + +[16:34.05.866] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.06.572] BEGIN WMNewTab: 20 +[16:34.06.572] END WMNewTab: 20 + +[16:34.07.467] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.07.983] BEGIN WMNewTab: 20 +[16:34.07.983] END WMNewTab: 20 + +[16:34.09.081] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.09.400] BEGIN WMNewTab: 20 +[16:34.09.400] END WMNewTab: 20 + + +[16:34.10.685] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.10.814] BEGIN WMNewTab: 20 +[16:34.10.814] END WMNewTab: 20 + + +[16:34.12.232] BEGIN WMNewTab: 20 +[16:34.12.232] END WMNewTab: 20 +[16:34.12.302] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.12.423] +[16:34.12.423] BEGIN LIVE-CREATING TFormRemoteSave +[16:34.12.450] END LIVE-CREATING TFormRemoteSave +[16:34.12.450] +[16:34.12.808] 收到消息: 文本编辑器已关闭: SurchargerFichierIni(EditorWindowPos_3200_2000_192|MobaTextEditor|MobaTextEditorAddedShortcuts|MobaTextEditorRemovedShortcuts) +[16:34.12.808] +[16:34.12.808] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:34.12.808] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:34.12.841] +[16:34.12.841] +[16:34.12.841] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:34.12.841] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:34.12.843] +[16:34.12.843] +[16:34.12.843] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:34.12.843] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:34.12.843] +[16:34.12.843] +[16:34.12.843] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:34.12.843] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:34.12.844] + +[16:34.13.648] BEGIN WMNewTab: 20 +[16:34.13.648] END WMNewTab: 20 +[16:34.13.906] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.14.149] (SSH-Browser) TDownUpForm.Timer1Timer +[16:34.14.210] (SSH-Browser) InitializeSFTP +[16:34.14.210] (SSH-Browser) SFTPcliError +[16:34.14.210] (SSH-Browser) TDownUpForm.SFTPcliError #103 (/root/test/start_camera_stream.sh): 连接被低层协议关闭 +[16:34.14.358] BEGIN WMNewTab: 0 +[16:34.14.358] WMNewTab: FormClick +[16:34.14.358] WMNewTab: LooseFocus +[16:34.14.363] END WMNewTab: 0 +[16:34.14.423] BEGIN WMNewTab: 0 +[16:34.14.423] WMNewTab: FormClick +[16:34.14.423] WMNewTab: LooseFocus +[16:34.14.425] END WMNewTab: 0 +[16:34.14.746] (SSH-Browser) TDownUpForm.Timer1Timer +[16:34.14.746] (SSH-Browser) InitializeSFTP +[16:34.14.746] (SSH-Browser) InitializeSFTP: Socketcli.Open; +[16:34.14.748] (SSH-Browser) InitializeSFTP: Connected to 192.168.127.10. +[16:34.14.903] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:34.15.064] BEGIN WMNewTab: 20 +[16:34.15.064] END WMNewTab: 20 +[16:34.15.269] (SSH-Browser) BEGIN SSHcliOpenConnection +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: OpenSSH = TRUE +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: PipelineLength = 32 +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: DownloadBlockSize = 32768 +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: UploadBlockSize = 65536 +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: SftpBufferSize = 262144 +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: DefaultWindowSize = 2097152 +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: MinWindowSize = 2048 +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: MaxSSHPacketSize = 262144 +[16:34.15.269] (SSH-Browser) SSHcliOpenConnection: AutoAdjustTransferBlock = FALSE +[16:34.15.269] (SSH-Browser) END SSHcliOpenConnection +[16:34.15.367] (SSH-Browser) TDownUpForm.Timer1Timer +[16:34.15.367] (SSH-Browser) InitializeSFTP +[16:34.15.367] (SSH-Browser) InitializeSFTP: result:=true; +[16:34.15.520] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.15.527] (SSH-Browser) SFTPcliOpenConnection +[16:34.15.527] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:34.15.527] (SSH-Browser) 上传下载文件: 正在上传 .bashrc +[16:34.15.559] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:34.15.559] (SSH-Browser) DownUpFile: SFTPcli.CreateFile(/root/.bashrc) +[16:34.15.559] (SSH-Browser) DownUpFile: MODE = UPLOAD +[16:34.15.559] (SSH-Browser) DownUpFile: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:34.15.559] (SSH-Browser) DownUpFile: PipelineLength = 32 +[16:34.15.559] (SSH-Browser) DownUpFile: DownloadBlockSize = 32768 +[16:34.15.559] (SSH-Browser) DownUpFile: UploadBlockSize = 65536 +[16:34.15.559] (SSH-Browser) DownUpFile: SftpBufferSize = 262144 +[16:34.15.559] (SSH-Browser) DownUpFile: DefaultWindowSize = 2097152 +[16:34.15.559] (SSH-Browser) DownUpFile: MinWindowSize = 2048 +[16:34.15.559] (SSH-Browser) DownUpFile: MaxSSHPacketSize = 262144 +[16:34.15.559] (SSH-Browser) DownUpFile: AutoAdjustTransferBlock = FALSE +[16:34.15.559] (SSH-Browser) DownUpFile: AsciiMode = FALSE +[16:34.15.607] (SSH-Browser) SFTPcliOpenFile +[16:34.15.607] (SSH-Browser) Uploading file +[16:34.15.617] (SSH-Browser) CloseCurrentHandle +[16:34.15.617] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:34.15.619] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:34.15.619] (SSH-Browser) TDownUpForm.Timer1Timer2 +[16:34.15.682] (SSH-Browser) BEGIN OpenDir(1) +[16:34.15.682] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:34.15.682] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:34.15.682] (SSH-Browser) END VerifySFTPConnection(1) +[16:34.15.682] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:34.15.682] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/); +[16:34.15.682] (SSH-Browser) END OpenDir(1) +[16:34.15.689] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:34.15.689] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:34.15.719] (SSH-Browser) ElSFTP1OpenFile(1) +[16:34.15.719] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:34.15.780] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:34.15.780] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:34.15.780] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:34.15.780] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:34.15.780] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:34.15.780] (SSH-Browser) END VerifySFTPConnection(1) +[16:34.15.780] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:34.15.780] (SSH-Browser) END CloseCurrentHandle(1) +[16:34.15.780] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:34.15.780] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=19 +[16:34.15.780] (SSH-Browser) 对项目进行排序 +[16:34.15.780] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:34.15.784] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:34.15.826] (SSH-Browser) ElSFTP1Success(1) + +[16:34.16.299] BEGIN WMNewTab: 20 +[16:34.16.299] END WMNewTab: 20 + +[16:34.17.122] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.17.718] BEGIN WMNewTab: 20 +[16:34.17.718] END WMNewTab: 20 + +[16:34.18.740] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.19.136] BEGIN WMNewTab: 20 +[16:34.19.136] END WMNewTab: 20 + + +[16:34.20.342] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.20.554] BEGIN WMNewTab: 20 +[16:34.20.554] END WMNewTab: 20 + + +[16:34.21.960] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.21.975] BEGIN WMNewTab: 20 +[16:34.21.975] END WMNewTab: 20 + +[16:34.22.530] BEGIN CWD +[16:34.22.590] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:34.22.590] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:34.22.590] (SSH-Browser) END VerifySFTPConnection(1) +[16:34.22.590] END CWD +[16:34.22.598] BEGIN CWD +[16:34.22.659] END CWD + +[16:34.23.561] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.23.607] BEGIN WMNewTab: 20 +[16:34.23.609] END WMNewTab: 20 + + +[16:34.25.021] BEGIN WMNewTab: 20 +[16:34.25.021] END WMNewTab: 20 +[16:34.25.172] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:34.26.442] BEGIN WMNewTab: 20 +[16:34.26.442] END WMNewTab: 20 +[16:34.26.784] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.27.877] BEGIN WMNewTab: 20 +[16:34.27.877] END WMNewTab: 20 + +[16:34.28.390] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.29.286] BEGIN WMNewTab: 20 +[16:34.29.286] END WMNewTab: 20 + +[16:34.30.004] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.30.707] BEGIN WMNewTab: 20 +[16:34.30.707] END WMNewTab: 20 + +[16:34.31.607] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.32.126] BEGIN WMNewTab: 20 +[16:34.32.126] END WMNewTab: 20 + +[16:34.33.224] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.33.548] BEGIN WMNewTab: 20 +[16:34.33.548] END WMNewTab: 20 + + +[16:34.34.829] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.34.967] BEGIN WMNewTab: 20 +[16:34.34.967] END WMNewTab: 20 + + +[16:34.36.388] BEGIN WMNewTab: 20 +[16:34.36.388] END WMNewTab: 20 +[16:34.36.434] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:34.37.803] BEGIN WMNewTab: 20 +[16:34.37.803] END WMNewTab: 20 +[16:34.38.046] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.39.223] BEGIN WMNewTab: 20 +[16:34.39.223] END WMNewTab: 20 + +[16:34.39.664] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.40.637] BEGIN WMNewTab: 20 +[16:34.40.638] END WMNewTab: 20 + +[16:34.41.267] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.42.055] BEGIN WMNewTab: 20 +[16:34.42.055] END WMNewTab: 20 + +[16:34.42.875] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.43.471] BEGIN WMNewTab: 20 +[16:34.43.471] END WMNewTab: 20 + +[16:34.44.488] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.44.887] BEGIN WMNewTab: 20 +[16:34.44.887] END WMNewTab: 20 + + +[16:34.46.102] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.46.301] BEGIN WMNewTab: 20 +[16:34.46.302] END WMNewTab: 20 + + +[16:34.47.699] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.47.714] BEGIN WMNewTab: 20 +[16:34.47.714] END WMNewTab: 20 + + +[16:34.49.135] BEGIN WMNewTab: 20 +[16:34.49.135] END WMNewTab: 20 +[16:34.49.348] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:34.50.550] BEGIN WMNewTab: 20 +[16:34.50.550] END WMNewTab: 20 + +[16:34.50.928] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.51.441] BEGIN WMNewTab: 0 +[16:34.51.441] WMNewTab: FormClick +[16:34.51.441] WMNewTab: LooseFocus +[16:34.51.442] END WMNewTab: 0 +[16:34.51.471] BEGIN WMNewTab: 0 +[16:34.51.471] WMNewTab: FormClick +[16:34.51.471] WMNewTab: LooseFocus +[16:34.51.471] END WMNewTab: 0 + +[16:34.51.963] BEGIN WMNewTab: 20 +[16:34.51.963] END WMNewTab: 20 + +[16:34.52.543] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.53.259] BEGIN CWD +[16:34.53.320] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:34.53.320] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:34.53.320] (SSH-Browser) END VerifySFTPConnection(1) +[16:34.53.320] END CWD +[16:34.53.400] BEGIN WMNewTab: 20 +[16:34.53.400] END WMNewTab: 20 +[16:34.53.426] BEGIN CWD +[16:34.53.486] END CWD + +[16:34.54.145] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.54.903] BEGIN WMNewTab: 20 +[16:34.54.903] END WMNewTab: 20 + +[16:34.55.761] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.56.327] BEGIN WMNewTab: 20 +[16:34.56.327] END WMNewTab: 20 + +[16:34.57.367] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:34.57.745] BEGIN WMNewTab: 20 +[16:34.57.745] END WMNewTab: 20 + + +[16:34.58.979] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:34.59.160] BEGIN WMNewTab: 20 +[16:34.59.160] END WMNewTab: 20 + + +[16:35.00.580] BEGIN WMNewTab: 20 +[16:35.00.580] END WMNewTab: 20 +[16:35.00.580] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:35.01.998] BEGIN WMNewTab: 20 +[16:35.01.998] END WMNewTab: 20 +[16:35.02.184] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.02.916] BEGIN WMNewTab: 0 +[16:35.02.916] WMNewTab: FormClick +[16:35.02.916] WMNewTab: LooseFocus +[16:35.02.916] END WMNewTab: 0 +[16:35.03.023] BEGIN WMNewTab: 0 +[16:35.03.023] WMNewTab: FormClick +[16:35.03.023] WMNewTab: LooseFocus +[16:35.03.024] END WMNewTab: 0 + +[16:35.03.415] BEGIN WMNewTab: 20 +[16:35.03.415] END WMNewTab: 20 + +[16:35.03.794] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.04.352] BEGIN WMNewTab: 0 +[16:35.04.352] WMNewTab: FormClick +[16:35.04.352] WMNewTab: LooseFocus +[16:35.04.352] END WMNewTab: 0 +[16:35.04.504] BEGIN WMNewTab: 0 +[16:35.04.504] WMNewTab: FormClick +[16:35.04.504] WMNewTab: LooseFocus +[16:35.04.506] END WMNewTab: 0 +[16:35.04.840] BEGIN WMNewTab: 20 +[16:35.04.840] END WMNewTab: 20 + +[16:35.05.418] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.06.259] BEGIN WMNewTab: 20 +[16:35.06.259] END WMNewTab: 20 + +[16:35.07.018] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.07.694] BEGIN WMNewTab: 20 +[16:35.07.694] END WMNewTab: 20 + +[16:35.08.625] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.09.113] BEGIN WMNewTab: 20 +[16:35.09.113] END WMNewTab: 20 + +[16:35.10.240] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:35.10.530] BEGIN WMNewTab: 20 +[16:35.10.530] END WMNewTab: 20 + + +[16:35.11.843] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:35.11.950] BEGIN WMNewTab: 20 +[16:35.11.950] END WMNewTab: 20 + +[16:35.12.401] BEGIN WMNewTab: 0 +[16:35.12.401] WMNewTab: FormClick +[16:35.12.401] WMNewTab: LooseFocus +[16:35.12.402] END WMNewTab: 0 +[16:35.12.402] BEGIN WMNewTab: 31 +[16:35.12.402] END WMNewTab: 31 +[16:35.12.552] BEGIN WMNewTab: 0 +[16:35.12.552] WMNewTab: FormClick +[16:35.12.552] WMNewTab: LooseFocus +[16:35.12.552] END WMNewTab: 0 + +[16:35.13.370] BEGIN WMNewTab: 20 +[16:35.13.370] END WMNewTab: 20 +[16:35.13.461] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.14.248] BEGIN WMNewTab: 0 +[16:35.14.248] WMNewTab: FormClick +[16:35.14.248] WMNewTab: LooseFocus +[16:35.14.249] END WMNewTab: 0 +[16:35.14.249] BEGIN WMNewTab: 31 +[16:35.14.249] END WMNewTab: 31 +[16:35.14.416] BEGIN WMNewTab: 0 +[16:35.14.416] WMNewTab: FormClick +[16:35.14.416] WMNewTab: LooseFocus +[16:35.14.417] END WMNewTab: 0 + +[16:35.14.787] BEGIN WMNewTab: 20 +[16:35.14.787] END WMNewTab: 20 +[16:35.15.062] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.16.203] BEGIN WMNewTab: 20 +[16:35.16.203] END WMNewTab: 20 + +[16:35.16.673] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.17.619] BEGIN WMNewTab: 20 +[16:35.17.619] END WMNewTab: 20 +[16:35.17.623] BEGIN CWD +[16:35.17.684] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:35.17.684] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:35.17.684] (SSH-Browser) END VerifySFTPConnection(1) +[16:35.17.684] END CWD +[16:35.17.694] BEGIN CWD +[16:35.17.756] END CWD + +[16:35.18.290] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.19.171] BEGIN WMNewTab: 20 +[16:35.19.171] END WMNewTab: 20 + +[16:35.19.889] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.20.586] BEGIN WMNewTab: 20 +[16:35.20.586] END WMNewTab: 20 + +[16:35.21.500] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.22.022] BEGIN WMNewTab: 20 +[16:35.22.022] END WMNewTab: 20 + +[16:35.23.118] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:35.23.437] BEGIN WMNewTab: 20 +[16:35.23.437] END WMNewTab: 20 + + +[16:35.24.729] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:35.24.851] BEGIN WMNewTab: 20 +[16:35.24.851] END WMNewTab: 20 + + +[16:35.26.270] BEGIN WMNewTab: 20 +[16:35.26.270] END WMNewTab: 20 +[16:35.26.328] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:35.27.686] BEGIN WMNewTab: 20 +[16:35.27.686] END WMNewTab: 20 +[16:35.27.944] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.28.521] BEGIN WMNCLButtonDown +[16:35.28.656] BEGIN WMSysCommand (minimize/restore) +[16:35.28.691] BEGIN WMSize +[16:35.28.691] END WMSize +[16:35.28.731] END WMSysCommand +[16:35.28.731] END WMNCLButtonDown + +[16:35.29.106] BEGIN WMNewTab: 20 +[16:35.29.106] END WMNewTab: 20 + +[16:35.29.549] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.30.522] BEGIN WMNewTab: 20 +[16:35.30.522] END WMNewTab: 20 + +[16:35.31.190] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:35.31.521] BEGIN WMSysCommand (minimize/restore) +[16:35.31.521] BEGIN WMNewTab: 0 +[16:35.31.521] WMNewTab: FormClick +[16:35.31.521] WMNewTab: LooseFocus +[16:35.31.522] END WMNewTab: 0 +[16:35.31.694] BEGIN WMSize +[16:35.31.694] BEGIN TFormXterm.FormResize +[16:35.31.694] TFormXterm.FormResize: CenterBtnReattachTab +[16:35.31.694] TFormXterm.FormResize: SplitModeResize +[16:35.31.694] TFormXterm.FormResize: BtnSplitNo.Down +[16:35.31.694] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:35.31.694] BEGIN ResizeTerminal +[16:35.31.696] END ResizeTerminal +[16:35.31.696] TFormXterm.FormResize: AdaptSidebarArrows; +[16:35.31.696] BEGIN AdaptSidebarArrows +[16:35.31.696] END AdaptSidebarArrows +[16:35.31.696] TFormXterm.FormResize: AdaptTV2; +[16:35.31.696] END TFormXterm.FormResize +[16:35.31.696] END WMSize +[16:35.31.707] END WMSysCommand +[16:35.31.940] BEGIN WMNewTab: 20 +[16:35.31.940] END WMNewTab: 20 +[16:35.31.968] BEGIN WMNewTab: 0 +[16:35.31.968] WMNewTab: FormClick +[16:35.31.968] WMNewTab: LooseFocus +[16:35.31.968] END WMNewTab: 0 +[16:35.32.096] BEGIN WMNewTab: 0 +[16:35.32.096] WMNewTab: FormClick +[16:35.32.096] WMNewTab: LooseFocus +[16:35.32.098] END WMNewTab: 0 + +[16:35.32.768] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.33.363] BEGIN WMNewTab: 20 +[16:35.33.363] END WMNewTab: 20 + +[16:35.34.386] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.34.752] BEGIN CWD +[16:35.34.781] BEGIN WMNewTab: 20 +[16:35.34.781] END WMNewTab: 20 +[16:35.34.812] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:35.34.812] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:35.34.812] (SSH-Browser) END VerifySFTPConnection(1) +[16:35.34.812] END CWD +[16:35.34.827] BEGIN CWD +[16:35.34.887] END CWD + +[16:35.35.983] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:35.36.303] BEGIN WMNewTab: 20 +[16:35.36.303] END WMNewTab: 20 + + +[16:35.37.597] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:35.37.717] BEGIN WMNewTab: 20 +[16:35.37.717] END WMNewTab: 20 + + +[16:35.39.138] BEGIN WMNewTab: 20 +[16:35.39.138] END WMNewTab: 20 +[16:35.39.213] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.40.241] BEGIN WMNewTab: 0 +[16:35.40.241] WMNewTab: FormClick +[16:35.40.241] WMNewTab: LooseFocus +[16:35.40.242] END WMNewTab: 0 +[16:35.40.553] BEGIN WMNewTab: 20 +[16:35.40.553] END WMNewTab: 20 +[16:35.40.811] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.41.809] BEGIN WMNewTab: 0 +[16:35.41.809] WMNewTab: FormClick +[16:35.41.809] WMNewTab: LooseFocus +[16:35.41.811] END WMNewTab: 0 +[16:35.41.972] BEGIN WMNewTab: 20 +[16:35.41.972] END WMNewTab: 20 + +[16:35.42.432] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.43.391] BEGIN WMNewTab: 20 +[16:35.43.391] END WMNewTab: 20 + +[16:35.44.030] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.44.809] BEGIN WMNewTab: 20 +[16:35.44.809] END WMNewTab: 20 + +[16:35.45.648] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.46.229] BEGIN WMNewTab: 20 +[16:35.46.229] END WMNewTab: 20 + +[16:35.47.249] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.47.647] BEGIN WMNewTab: 20 +[16:35.47.647] END WMNewTab: 20 + + +[16:35.48.864] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:35.49.062] BEGIN WMNewTab: 20 +[16:35.49.062] END WMNewTab: 20 + + +[16:35.50.477] BEGIN WMNewTab: 20 +[16:35.50.477] END WMNewTab: 20 +[16:35.50.477] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:35.51.890] BEGIN WMNewTab: 20 +[16:35.51.890] END WMNewTab: 20 +[16:35.52.087] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:35.53.306] BEGIN WMNewTab: 20 +[16:35.53.306] END WMNewTab: 20 + +[16:35.53.685] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.54.724] BEGIN WMNewTab: 20 +[16:35.54.724] END WMNewTab: 20 + +[16:35.55.304] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.56.144] BEGIN WMNewTab: 20 +[16:35.56.144] END WMNewTab: 20 + +[16:35.56.907] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.57.562] BEGIN WMNewTab: 20 +[16:35.57.562] END WMNewTab: 20 + +[16:35.58.522] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:35.58.982] BEGIN WMNewTab: 20 +[16:35.58.982] END WMNewTab: 20 + +[16:36.00.123] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.00.397] BEGIN WMNewTab: 20 +[16:36.00.397] END WMNewTab: 20 + + +[16:36.01.742] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.01.834] BEGIN WMNewTab: 20 +[16:36.01.834] END WMNewTab: 20 + + +[16:36.03.252] BEGIN WMNewTab: 20 +[16:36.03.252] END WMNewTab: 20 +[16:36.03.344] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:36.04.666] BEGIN WMNewTab: 20 +[16:36.04.666] END WMNewTab: 20 +[16:36.04.954] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.06.084] BEGIN WMNewTab: 20 +[16:36.06.084] END WMNewTab: 20 + +[16:36.06.559] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.07.506] BEGIN WMNewTab: 20 +[16:36.07.506] END WMNewTab: 20 + +[16:36.08.179] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.08.925] BEGIN WMNewTab: 20 +[16:36.08.925] END WMNewTab: 20 + +[16:36.09.789] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.10.338] BEGIN WMNewTab: 20 +[16:36.10.338] END WMNewTab: 20 + +[16:36.11.392] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.11.757] BEGIN WMNewTab: 20 +[16:36.11.757] END WMNewTab: 20 + + +[16:36.13.006] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.13.174] BEGIN WMNewTab: 20 +[16:36.13.174] END WMNewTab: 20 + + +[16:36.14.592] BEGIN WMNewTab: 20 +[16:36.14.592] END WMNewTab: 20 +[16:36.14.608] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:36.16.016] BEGIN WMNewTab: 20 +[16:36.16.016] END WMNewTab: 20 +[16:36.16.227] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:36.17.428] BEGIN WMNewTab: 20 +[16:36.17.428] END WMNewTab: 20 + +[16:36.17.838] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.18.847] BEGIN WMNewTab: 20 +[16:36.18.847] END WMNewTab: 20 + +[16:36.19.437] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.20.260] BEGIN WMNewTab: 20 +[16:36.20.260] END WMNewTab: 20 + +[16:36.21.051] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.21.678] BEGIN WMNewTab: 20 +[16:36.21.678] END WMNewTab: 20 + +[16:36.22.653] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.23.094] BEGIN WMNewTab: 20 +[16:36.23.094] END WMNewTab: 20 + + +[16:36.24.318] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.24.513] BEGIN WMNewTab: 20 +[16:36.24.513] END WMNewTab: 20 + + +[16:36.25.884] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.25.931] BEGIN WMNewTab: 20 +[16:36.25.931] END WMNewTab: 20 + + +[16:36.27.366] BEGIN WMNewTab: 20 +[16:36.27.366] END WMNewTab: 20 +[16:36.27.486] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:36.28.783] BEGIN WMNewTab: 20 +[16:36.28.783] END WMNewTab: 20 +[16:36.29.103] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.30.205] BEGIN WMNewTab: 20 +[16:36.30.205] END WMNewTab: 20 + +[16:36.30.708] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.31.626] BEGIN WMNewTab: 20 +[16:36.31.626] END WMNewTab: 20 + +[16:36.32.312] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.33.043] BEGIN WMNewTab: 20 +[16:36.33.043] END WMNewTab: 20 + +[16:36.33.930] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.34.466] BEGIN WMNewTab: 20 +[16:36.34.466] END WMNewTab: 20 + +[16:36.35.538] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.35.886] BEGIN WMNewTab: 20 +[16:36.35.886] END WMNewTab: 20 + + +[16:36.37.137] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.37.307] BEGIN WMNewTab: 20 +[16:36.37.307] END WMNewTab: 20 + + +[16:36.38.721] BEGIN WMNewTab: 20 +[16:36.38.721] END WMNewTab: 20 +[16:36.38.753] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:36.40.141] BEGIN WMNewTab: 20 +[16:36.40.141] END WMNewTab: 20 +[16:36.40.356] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:36.41.562] BEGIN WMNewTab: 20 +[16:36.41.562] END WMNewTab: 20 + +[16:36.41.972] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.42.978] BEGIN WMNewTab: 20 +[16:36.42.978] END WMNewTab: 20 + +[16:36.43.574] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.44.401] BEGIN WMNewTab: 20 +[16:36.44.401] END WMNewTab: 20 + +[16:36.45.196] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.45.826] BEGIN WMNewTab: 20 +[16:36.45.826] END WMNewTab: 20 + +[16:36.46.801] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.47.243] BEGIN WMNewTab: 20 +[16:36.47.243] END WMNewTab: 20 + +[16:36.48.405] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.48.663] BEGIN WMNewTab: 20 +[16:36.48.663] END WMNewTab: 20 + + +[16:36.50.024] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:36.50.083] BEGIN WMNewTab: 20 +[16:36.50.083] END WMNewTab: 20 + + +[16:36.51.505] BEGIN WMNewTab: 20 +[16:36.51.505] END WMNewTab: 20 +[16:36.51.626] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:36.52.921] BEGIN WMNewTab: 20 +[16:36.52.921] END WMNewTab: 20 +[16:36.53.239] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.54.340] BEGIN WMNewTab: 20 +[16:36.54.340] END WMNewTab: 20 + +[16:36.54.846] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.55.759] BEGIN WMNewTab: 20 +[16:36.55.759] END WMNewTab: 20 + +[16:36.56.460] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.57.179] BEGIN WMNewTab: 20 +[16:36.57.179] END WMNewTab: 20 + +[16:36.58.061] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:36.58.597] BEGIN WMNewTab: 20 +[16:36.58.597] END WMNewTab: 20 + +[16:36.59.681] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.00.015] BEGIN WMNewTab: 20 +[16:37.00.015] END WMNewTab: 20 + + +[16:37.01.284] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.01.437] BEGIN WMNewTab: 20 +[16:37.01.437] END WMNewTab: 20 + + +[16:37.02.853] BEGIN WMNewTab: 20 +[16:37.02.853] END WMNewTab: 20 +[16:37.02.899] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:37.04.273] BEGIN WMNewTab: 20 +[16:37.04.273] END WMNewTab: 20 +[16:37.04.503] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.05.692] BEGIN WMNewTab: 20 +[16:37.05.692] END WMNewTab: 20 + +[16:37.06.119] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.07.110] BEGIN WMNewTab: 20 +[16:37.07.110] END WMNewTab: 20 + +[16:37.07.724] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.08.530] BEGIN WMNewTab: 20 +[16:37.08.530] END WMNewTab: 20 + +[16:37.09.335] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.09.946] BEGIN WMNewTab: 20 +[16:37.09.946] END WMNewTab: 20 + +[16:37.10.949] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.11.364] BEGIN WMNewTab: 20 +[16:37.11.364] END WMNewTab: 20 + +[16:37.12.556] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.12.785] BEGIN WMNewTab: 20 +[16:37.12.785] END WMNewTab: 20 + + +[16:37.14.156] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.14.203] BEGIN WMNewTab: 20 +[16:37.14.203] END WMNewTab: 20 + + +[16:37.15.623] BEGIN WMNewTab: 20 +[16:37.15.623] END WMNewTab: 20 +[16:37.15.776] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:37.17.041] BEGIN WMNewTab: 20 +[16:37.17.041] END WMNewTab: 20 + +[16:37.17.409] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.18.456] BEGIN WMNewTab: 20 +[16:37.18.456] END WMNewTab: 20 + +[16:37.18.994] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.19.883] BEGIN WMNewTab: 20 +[16:37.19.883] END WMNewTab: 20 + +[16:37.20.603] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.21.300] BEGIN WMNewTab: 20 +[16:37.21.300] END WMNewTab: 20 + +[16:37.22.214] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.22.719] BEGIN WMNewTab: 20 +[16:37.22.719] END WMNewTab: 20 + +[16:37.23.812] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.24.129] BEGIN WMNewTab: 20 +[16:37.24.129] END WMNewTab: 20 + + +[16:37.25.430] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.25.591] BEGIN WMNewTab: 20 +[16:37.25.591] END WMNewTab: 20 + + +[16:37.27.003] BEGIN WMNewTab: 20 +[16:37.27.003] END WMNewTab: 20 +[16:37.27.034] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:37.28.420] BEGIN WMNewTab: 20 +[16:37.28.420] END WMNewTab: 20 +[16:37.28.670] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.29.840] BEGIN WMNewTab: 20 +[16:37.29.840] END WMNewTab: 20 + +[16:37.30.254] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.31.265] BEGIN WMNewTab: 20 +[16:37.31.265] END WMNewTab: 20 + +[16:37.31.860] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.32.685] BEGIN WMNewTab: 20 +[16:37.32.685] END WMNewTab: 20 + +[16:37.33.477] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.34.104] BEGIN WMNewTab: 20 +[16:37.34.104] END WMNewTab: 20 + +[16:37.35.079] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.35.521] BEGIN WMNewTab: 20 +[16:37.35.521] END WMNewTab: 20 + +[16:37.36.699] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.36.942] BEGIN WMNewTab: 20 +[16:37.36.942] END WMNewTab: 20 + + +[16:37.38.295] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.38.356] BEGIN WMNewTab: 20 +[16:37.38.356] END WMNewTab: 20 + + +[16:37.39.773] BEGIN WMNewTab: 20 +[16:37.39.773] END WMNewTab: 20 +[16:37.39.921] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:37.41.194] BEGIN WMNewTab: 20 +[16:37.41.194] END WMNewTab: 20 +[16:37.41.517] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.42.624] BEGIN WMNewTab: 20 +[16:37.42.624] END WMNewTab: 20 + +[16:37.43.124] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.44.045] BEGIN WMNewTab: 20 +[16:37.44.045] END WMNewTab: 20 + +[16:37.44.743] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.45.463] BEGIN WMNewTab: 20 +[16:37.45.463] END WMNewTab: 20 + +[16:37.46.350] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.46.882] BEGIN WMNewTab: 20 +[16:37.46.882] END WMNewTab: 20 + +[16:37.47.949] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.48.300] BEGIN WMNewTab: 20 +[16:37.48.300] END WMNewTab: 20 + + +[16:37.49.566] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:37.49.720] BEGIN WMNewTab: 20 +[16:37.49.720] END WMNewTab: 20 + + +[16:37.51.148] BEGIN WMNewTab: 20 +[16:37.51.148] END WMNewTab: 20 +[16:37.51.170] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:37.52.558] BEGIN WMNewTab: 20 +[16:37.52.558] END WMNewTab: 20 +[16:37.52.787] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.53.973] BEGIN WMNewTab: 20 +[16:37.53.973] END WMNewTab: 20 + +[16:37.54.398] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.55.389] BEGIN WMNewTab: 20 +[16:37.55.389] END WMNewTab: 20 + +[16:37.55.997] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.56.803] BEGIN WMNewTab: 20 +[16:37.56.803] END WMNewTab: 20 + +[16:37.57.607] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.58.218] BEGIN WMNewTab: 20 +[16:37.58.218] END WMNewTab: 20 + +[16:37.59.230] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:37.59.642] BEGIN WMNewTab: 20 +[16:37.59.642] END WMNewTab: 20 + +[16:38.00.834] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.01.064] BEGIN WMNewTab: 20 +[16:38.01.064] END WMNewTab: 20 + + +[16:38.02.439] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.02.485] BEGIN WMNewTab: 20 +[16:38.02.485] END WMNewTab: 20 + + +[16:38.03.905] BEGIN WMNewTab: 20 +[16:38.03.905] END WMNewTab: 20 +[16:38.04.056] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:38.05.316] BEGIN WMNewTab: 20 +[16:38.05.316] END WMNewTab: 20 +[16:38.05.655] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.06.747] BEGIN WMNewTab: 20 +[16:38.06.747] END WMNewTab: 20 +[16:38.07.074] sListView1Click: FormClick +[16:38.07.270] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.07.289] sListView1Click: FormClick +[16:38.07.625] (SSH-Browser) BEGIN OpenDir(1) +[16:38.07.625] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.07.625] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.07.625] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.07.625] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:38.07.627] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/test/); +[16:38.07.627] (SSH-Browser) END OpenDir(1) +[16:38.07.712] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:38.07.712] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root/test) +[16:38.07.743] (SSH-Browser) ElSFTP1OpenFile(1) +[16:38.07.743] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:38.07.803] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:38.07.803] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:38.07.803] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:38.07.803] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.07.803] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.07.803] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.07.803] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:38.07.803] (SSH-Browser) END CloseCurrentHandle(1) +[16:38.07.804] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:38.07.804] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[16:38.07.804] (SSH-Browser) 对项目进行排序 +[16:38.07.804] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:38.07.807] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:38.07.833] (SSH-Browser) ElSFTP1Success(1) +[16:38.07.937] sListView1Click: FormClick + +[16:38.08.308] BEGIN WMNewTab: 20 +[16:38.08.308] END WMNewTab: 20 +[16:38.08.495] sListView1Click: FormClick +[16:38.08.538] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.08.538] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.08.538] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.08.543] (SSH-Browser) sListView1DblClick: SFTP.OpenFile(/root/test/start_camera_stream.sh); +[16:38.08.543] (SSH-Browser) sListView1DblClick: MODE = DOWNLOAD (FILE EDITION) +[16:38.08.543] (SSH-Browser) sListView1DblClick: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:38.08.543] (SSH-Browser) sListView1DblClick: PipelineLength = 32 +[16:38.08.543] (SSH-Browser) sListView1DblClick: DownloadBlockSize = 32768 +[16:38.08.543] (SSH-Browser) sListView1DblClick: UploadBlockSize = 65536 +[16:38.08.543] (SSH-Browser) sListView1DblClick: SftpBufferSize = 131072 +[16:38.08.543] (SSH-Browser) sListView1DblClick: DefaultWindowSize = 2097152 +[16:38.08.543] (SSH-Browser) sListView1DblClick: MinWindowSize = 2048 +[16:38.08.543] (SSH-Browser) sListView1DblClick: MaxSSHPacketSize = 262144 +[16:38.08.543] (SSH-Browser) sListView1DblClick: AutoAdjustTransferBlock = FALSE +[16:38.08.543] (SSH-Browser) sListView1DblClick: Ascii mode = false +[16:38.08.674] (SSH-Browser) ElSFTP1OpenFile(1) +[16:38.08.688] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.Read +[16:38.08.872] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.08.962] (SSH-Browser) ElSFTP1Data(1) +[16:38.08.962] (SSH-Browser) ElSFTP1Error(1): #1 - +[16:38.08.962] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle2 +[16:38.08.963] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:38.08.963] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.08.963] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.08.963] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.08.963] (SSH-Browser) END CloseCurrentHandle(1) +[16:38.08.974] +[16:38.08.974] BEGIN Form4.FormActivate +[16:38.08.974] END Form4.FormActivate +[16:38.08.974] +[16:38.08.977] (SSH-Browser) ReallyOpenFile + +[16:38.10.156] BEGIN WMNewTab: 20 +[16:38.10.156] END WMNewTab: 20 +[16:38.10.482] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.11.565] BEGIN WMNewTab: 20 +[16:38.11.565] END WMNewTab: 20 + +[16:38.12.098] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.12.981] BEGIN WMNewTab: 20 +[16:38.12.981] END WMNewTab: 20 + +[16:38.13.715] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.14.403] BEGIN WMNewTab: 20 +[16:38.14.403] END WMNewTab: 20 + +[16:38.15.322] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.15.824] BEGIN WMNewTab: 20 +[16:38.15.824] END WMNewTab: 20 + +[16:38.16.923] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.17.243] BEGIN WMNewTab: 20 +[16:38.17.243] END WMNewTab: 20 + + +[16:38.18.540] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.18.718] BEGIN WMNewTab: 20 +[16:38.18.718] END WMNewTab: 20 + + +[16:38.20.138] BEGIN WMNewTab: 20 +[16:38.20.138] END WMNewTab: 20 +[16:38.20.138] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:38.21.554] BEGIN WMNewTab: 20 +[16:38.21.554] END WMNewTab: 20 +[16:38.21.779] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.22.975] BEGIN WMNewTab: 20 +[16:38.22.976] END WMNewTab: 20 + +[16:38.23.356] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.24.395] BEGIN WMNewTab: 20 +[16:38.24.395] END WMNewTab: 20 + +[16:38.24.970] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.25.907] BEGIN WMNewTab: 20 +[16:38.25.907] END WMNewTab: 20 + +[16:38.26.590] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.27.320] BEGIN WMNewTab: 20 +[16:38.27.320] END WMNewTab: 20 + +[16:38.28.188] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.28.741] BEGIN WMNewTab: 20 +[16:38.28.741] END WMNewTab: 20 + +[16:38.29.797] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.30.161] BEGIN WMNewTab: 20 +[16:38.30.161] END WMNewTab: 20 + + +[16:38.31.410] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.31.579] BEGIN WMNewTab: 20 +[16:38.31.579] END WMNewTab: 20 + + +[16:38.33.003] BEGIN WMNewTab: 20 +[16:38.33.003] END WMNewTab: 20 +[16:38.33.028] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:38.34.415] BEGIN WMNewTab: 20 +[16:38.34.415] END WMNewTab: 20 +[16:38.34.629] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:38.35.832] BEGIN WMNewTab: 20 +[16:38.35.832] END WMNewTab: 20 + +[16:38.36.242] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.37.251] BEGIN WMNewTab: 20 +[16:38.37.251] END WMNewTab: 20 + +[16:38.37.846] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.38.673] BEGIN WMNewTab: 20 +[16:38.38.673] END WMNewTab: 20 + +[16:38.39.451] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.40.091] BEGIN WMNewTab: 20 +[16:38.40.091] END WMNewTab: 20 + +[16:38.41.066] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.41.509] BEGIN WMNewTab: 20 +[16:38.41.509] END WMNewTab: 20 + +[16:38.42.682] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.42.925] BEGIN WMNewTab: 20 +[16:38.42.925] END WMNewTab: 20 + + +[16:38.44.285] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.44.346] BEGIN WMNewTab: 20 +[16:38.44.346] END WMNewTab: 20 + + +[16:38.45.760] BEGIN WMNewTab: 20 +[16:38.45.760] END WMNewTab: 20 +[16:38.45.899] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.45.959] (SSH-Browser) TDownUpForm.Timer1Timer +[16:38.46.002] (SSH-Browser) InitializeSFTP +[16:38.46.002] (SSH-Browser) SFTPcliError +[16:38.46.002] (SSH-Browser) TDownUpForm.SFTPcliError #103 (/root/.bashrc): 连接被低层协议关闭 + +[16:38.46.524] 收到消息: 文本编辑器已关闭: SurchargerFichierIni(EditorWindowPos_3200_2000_192|MobaTextEditor|MobaTextEditorAddedShortcuts|MobaTextEditorRemovedShortcuts) +[16:38.46.524] +[16:38.46.524] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:38.46.524] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:38.46.575] +[16:38.46.575] +[16:38.46.575] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:38.46.575] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:38.46.577] +[16:38.46.577] +[16:38.46.577] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:38.46.577] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:38.46.578] +[16:38.46.578] +[16:38.46.578] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:38.46.578] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:38.46.578] +[16:38.46.578] (SSH-Browser) TDownUpForm.Timer1Timer +[16:38.46.579] (SSH-Browser) InitializeSFTP +[16:38.46.579] (SSH-Browser) InitializeSFTP: Socketcli.Open; +[16:38.46.580] (SSH-Browser) InitializeSFTP: Connected to 192.168.127.10. +[16:38.46.742] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. + +[16:38.47.110] (SSH-Browser) BEGIN SSHcliOpenConnection +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: OpenSSH = TRUE +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: PipelineLength = 32 +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: DownloadBlockSize = 32768 +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: UploadBlockSize = 65536 +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: SftpBufferSize = 262144 +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: DefaultWindowSize = 2097152 +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: MinWindowSize = 2048 +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: MaxSSHPacketSize = 262144 +[16:38.47.110] (SSH-Browser) SSHcliOpenConnection: AutoAdjustTransferBlock = FALSE +[16:38.47.110] (SSH-Browser) END SSHcliOpenConnection +[16:38.47.174] (SSH-Browser) TDownUpForm.Timer1Timer +[16:38.47.174] (SSH-Browser) InitializeSFTP +[16:38.47.175] (SSH-Browser) InitializeSFTP: result:=true; +[16:38.47.182] BEGIN WMNewTab: 20 +[16:38.47.182] END WMNewTab: 20 +[16:38.47.340] (SSH-Browser) SFTPcliOpenConnection +[16:38.47.340] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:38.47.340] (SSH-Browser) 上传下载文件: 正在上传 start_camera_stream.sh +[16:38.47.367] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:38.47.367] (SSH-Browser) DownUpFile: SFTPcli.CreateFile(/root/test/start_camera_stream.sh) +[16:38.47.367] (SSH-Browser) DownUpFile: MODE = UPLOAD +[16:38.47.367] (SSH-Browser) DownUpFile: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:38.47.367] (SSH-Browser) DownUpFile: PipelineLength = 32 +[16:38.47.367] (SSH-Browser) DownUpFile: DownloadBlockSize = 32768 +[16:38.47.367] (SSH-Browser) DownUpFile: UploadBlockSize = 65536 +[16:38.47.367] (SSH-Browser) DownUpFile: SftpBufferSize = 262144 +[16:38.47.367] (SSH-Browser) DownUpFile: DefaultWindowSize = 2097152 +[16:38.47.367] (SSH-Browser) DownUpFile: MinWindowSize = 2048 +[16:38.47.367] (SSH-Browser) DownUpFile: MaxSSHPacketSize = 262144 +[16:38.47.367] (SSH-Browser) DownUpFile: AutoAdjustTransferBlock = FALSE +[16:38.47.367] (SSH-Browser) DownUpFile: AsciiMode = FALSE +[16:38.47.370] (SSH-Browser) SFTPcliOpenFile +[16:38.47.370] (SSH-Browser) Uploading file +[16:38.47.373] (SSH-Browser) CloseCurrentHandle +[16:38.47.373] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:38.47.375] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:38.47.375] (SSH-Browser) TDownUpForm.Timer1Timer2 +[16:38.47.421] (SSH-Browser) BEGIN OpenDir(1) +[16:38.47.421] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.47.421] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.47.421] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.47.421] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:38.47.422] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/test/); +[16:38.47.422] (SSH-Browser) END OpenDir(1) +[16:38.47.443] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:38.47.443] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root/test) +[16:38.47.473] (SSH-Browser) ElSFTP1OpenFile(1) +[16:38.47.473] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:38.47.503] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.47.533] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:38.47.533] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:38.47.533] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:38.47.533] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.47.533] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.47.533] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.47.533] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:38.47.533] (SSH-Browser) END CloseCurrentHandle(1) +[16:38.47.533] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:38.47.533] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[16:38.47.534] (SSH-Browser) 对项目进行排序 +[16:38.47.534] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:38.47.542] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:38.47.563] (SSH-Browser) ElSFTP1Success(1) + +[16:38.48.426] BEGIN WMNewTab: 0 +[16:38.48.426] WMNewTab: FormClick +[16:38.48.426] WMNewTab: LooseFocus +[16:38.48.429] END WMNewTab: 0 +[16:38.48.508] BEGIN WMNewTab: 20 +[16:38.48.508] END WMNewTab: 20 +[16:38.48.554] BEGIN WMNewTab: 0 +[16:38.48.554] WMNewTab: FormClick +[16:38.48.555] WMNewTab: LooseFocus +[16:38.48.555] END WMNewTab: 0 + +[16:38.49.120] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.49.688] BEGIN CWD +[16:38.49.748] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.49.748] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.49.748] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.49.748] END CWD +[16:38.49.750] BEGIN WMNewTab: 20 +[16:38.49.750] END WMNewTab: 20 +[16:38.49.764] BEGIN CWD +[16:38.49.826] (CWD) OpenDir(/root); +[16:38.49.826] (SSH-Browser) BEGIN OpenDir(1) +[16:38.49.826] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.49.826] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.49.826] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.49.827] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:38.49.828] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root); +[16:38.49.828] (SSH-Browser) END OpenDir(1) +[16:38.49.828] END CWD +[16:38.49.855] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:38.49.855] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:38.49.887] (SSH-Browser) ElSFTP1OpenFile(1) +[16:38.49.887] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:38.49.948] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:38.49.948] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:38.49.948] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:38.49.948] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:38.49.948] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:38.49.948] (SSH-Browser) END VerifySFTPConnection(1) +[16:38.49.948] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:38.49.948] (SSH-Browser) END CloseCurrentHandle(1) +[16:38.49.948] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:38.49.948] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=19 +[16:38.49.948] (SSH-Browser) 对项目进行排序 +[16:38.49.948] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:38.49.952] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:38.49.978] (SSH-Browser) ElSFTP1Success(1) + +[16:38.50.715] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.51.401] BEGIN WMNewTab: 20 +[16:38.51.401] END WMNewTab: 20 + +[16:38.52.330] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.52.822] BEGIN WMNewTab: 20 +[16:38.52.822] END WMNewTab: 20 + +[16:38.53.936] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.54.241] BEGIN WMNewTab: 20 +[16:38.54.241] END WMNewTab: 20 + + +[16:38.55.551] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:38.55.660] BEGIN WMNewTab: 20 +[16:38.55.660] END WMNewTab: 20 + + +[16:38.57.077] BEGIN WMNewTab: 20 +[16:38.57.077] END WMNewTab: 20 +[16:38.57.153] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:38.58.515] BEGIN WMNewTab: 20 +[16:38.58.515] END WMNewTab: 20 +[16:38.58.766] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:38.59.929] BEGIN WMNewTab: 20 +[16:38.59.929] END WMNewTab: 20 + +[16:39.00.384] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.01.348] BEGIN WMNewTab: 20 +[16:39.01.348] END WMNewTab: 20 + +[16:39.01.986] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.02.763] BEGIN WMNewTab: 20 +[16:39.02.763] END WMNewTab: 20 + +[16:39.03.635] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.04.181] BEGIN WMNewTab: 20 +[16:39.04.181] END WMNewTab: 20 + +[16:39.05.202] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.05.596] BEGIN WMNewTab: 20 +[16:39.05.596] END WMNewTab: 20 +[16:39.05.706] sListView1Click: FormClick +[16:39.05.772] (SSH-Browser) BEGIN OpenDir(1) +[16:39.05.772] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.05.772] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.05.772] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.05.772] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:39.05.774] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/test/); +[16:39.05.774] (SSH-Browser) END OpenDir(1) +[16:39.05.779] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:39.05.779] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root/test) +[16:39.05.810] (SSH-Browser) ElSFTP1OpenFile(1) +[16:39.05.810] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:39.05.871] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:39.05.871] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:39.05.871] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:39.05.871] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.05.871] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.05.871] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.05.871] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:39.05.871] (SSH-Browser) END CloseCurrentHandle(1) +[16:39.05.871] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:39.05.871] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[16:39.05.871] (SSH-Browser) 对项目进行排序 +[16:39.05.871] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:39.05.876] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:39.05.903] (SSH-Browser) ElSFTP1Success(1) + +[16:39.06.428] sListView1Click: FormClick +[16:39.06.499] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.06.499] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.06.499] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.06.501] (SSH-Browser) sListView1DblClick: SFTP.OpenFile(/root/test/start_camera_stream.sh); +[16:39.06.501] (SSH-Browser) sListView1DblClick: MODE = DOWNLOAD (FILE EDITION) +[16:39.06.501] (SSH-Browser) sListView1DblClick: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:39.06.501] (SSH-Browser) sListView1DblClick: PipelineLength = 32 +[16:39.06.501] (SSH-Browser) sListView1DblClick: DownloadBlockSize = 32768 +[16:39.06.501] (SSH-Browser) sListView1DblClick: UploadBlockSize = 65536 +[16:39.06.501] (SSH-Browser) sListView1DblClick: SftpBufferSize = 131072 +[16:39.06.501] (SSH-Browser) sListView1DblClick: DefaultWindowSize = 2097152 +[16:39.06.501] (SSH-Browser) sListView1DblClick: MinWindowSize = 2048 +[16:39.06.501] (SSH-Browser) sListView1DblClick: MaxSSHPacketSize = 262144 +[16:39.06.501] (SSH-Browser) sListView1DblClick: AutoAdjustTransferBlock = FALSE +[16:39.06.501] (SSH-Browser) sListView1DblClick: Ascii mode = false +[16:39.06.599] (SSH-Browser) ElSFTP1OpenFile(1) +[16:39.06.619] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.Read +[16:39.06.812] BEGIN WMNewTab: 20 +[16:39.06.812] END WMNewTab: 20 +[16:39.06.814] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.06.816] (SSH-Browser) ElSFTP1Data(1) +[16:39.06.816] (SSH-Browser) ElSFTP1Error(1): #1 - +[16:39.06.816] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle2 +[16:39.06.816] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:39.06.816] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.06.816] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.06.816] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.06.816] (SSH-Browser) END CloseCurrentHandle(1) +[16:39.06.828] +[16:39.06.828] BEGIN Form4.FormActivate +[16:39.06.828] END Form4.FormActivate +[16:39.06.828] +[16:39.06.830] (SSH-Browser) ReallyOpenFile + + +[16:39.08.272] BEGIN WMNewTab: 20 +[16:39.08.272] END WMNewTab: 20 +[16:39.08.427] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:39.09.673] BEGIN WMNewTab: 20 +[16:39.09.673] END WMNewTab: 20 + +[16:39.10.039] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.11.090] BEGIN WMNewTab: 20 +[16:39.11.090] END WMNewTab: 20 + +[16:39.11.641] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.12.509] BEGIN WMNewTab: 20 +[16:39.12.509] END WMNewTab: 20 + +[16:39.13.251] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.13.922] BEGIN WMNewTab: 20 +[16:39.13.922] END WMNewTab: 20 + +[16:39.14.865] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.15.339] BEGIN WMNewTab: 20 +[16:39.15.339] END WMNewTab: 20 + +[16:39.16.470] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.16.758] BEGIN WMNewTab: 20 +[16:39.16.758] END WMNewTab: 20 + + +[16:39.18.079] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.18.172] BEGIN WMNewTab: 20 +[16:39.18.172] END WMNewTab: 20 + + +[16:39.19.591] BEGIN WMNewTab: 20 +[16:39.19.591] END WMNewTab: 20 +[16:39.19.698] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.20.038] 收到消息: 文本编辑器已关闭: SurchargerFichierIni(EditorWindowPos_3200_2000_192|MobaTextEditor|MobaTextEditorAddedShortcuts|MobaTextEditorRemovedShortcuts) +[16:39.20.038] +[16:39.20.038] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:39.20.038] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:39.20.062] +[16:39.20.062] +[16:39.20.062] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:39.20.062] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:39.20.063] +[16:39.20.064] +[16:39.20.064] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:39.20.064] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:39.20.064] +[16:39.20.064] +[16:39.20.064] [Customization] 使用以下文件补充 INI 文件: D:\MobaXterm_25.2_CN\MobaXterm.ini +[16:39.20.064] [Customization] 读取自定义 INI 文件 "D:\MobaXterm_25.2_CN\MobaXterm.ini" +[16:39.20.064] +[16:39.20.080] (SSH-Browser) TDownUpForm.Timer1Timer +[16:39.20.135] (SSH-Browser) InitializeSFTP +[16:39.20.136] (SSH-Browser) SFTPcliError +[16:39.20.136] (SSH-Browser) TDownUpForm.SFTPcliError #103 (/root/test/start_camera_stream.sh): 连接被低层协议关闭 + +[16:39.20.509] BEGIN WMNewTab: 0 +[16:39.20.509] WMNewTab: FormClick +[16:39.20.509] WMNewTab: LooseFocus +[16:39.20.512] END WMNewTab: 0 +[16:39.20.611] BEGIN WMNewTab: 0 +[16:39.20.611] WMNewTab: FormClick +[16:39.20.611] WMNewTab: LooseFocus +[16:39.20.611] END WMNewTab: 0 +[16:39.20.690] (SSH-Browser) TDownUpForm.Timer1Timer +[16:39.20.690] (SSH-Browser) InitializeSFTP +[16:39.20.690] (SSH-Browser) InitializeSFTP: Socketcli.Open; +[16:39.20.692] (SSH-Browser) InitializeSFTP: Connected to 192.168.127.10. +[16:39.20.849] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:39.21.010] BEGIN WMNewTab: 20 +[16:39.21.010] END WMNewTab: 20 +[16:39.21.216] (SSH-Browser) BEGIN SSHcliOpenConnection +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: OpenSSH = TRUE +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: PipelineLength = 32 +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: DownloadBlockSize = 32768 +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: UploadBlockSize = 65536 +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: SftpBufferSize = 262144 +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: DefaultWindowSize = 2097152 +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: MinWindowSize = 2048 +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: MaxSSHPacketSize = 262144 +[16:39.21.216] (SSH-Browser) SSHcliOpenConnection: AutoAdjustTransferBlock = FALSE +[16:39.21.216] (SSH-Browser) END SSHcliOpenConnection +[16:39.21.299] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.21.300] (SSH-Browser) TDownUpForm.Timer1Timer +[16:39.21.300] (SSH-Browser) InitializeSFTP +[16:39.21.300] (SSH-Browser) InitializeSFTP: result:=true; +[16:39.21.459] (SSH-Browser) SFTPcliOpenConnection +[16:39.21.459] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:39.21.459] (SSH-Browser) 上传下载文件: 正在上传 start_camera_stream.sh +[16:39.21.477] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:39.21.477] (SSH-Browser) DownUpFile: SFTPcli.CreateFile(/root/test/start_camera_stream.sh) +[16:39.21.477] (SSH-Browser) DownUpFile: MODE = UPLOAD +[16:39.21.477] (SSH-Browser) DownUpFile: Server name: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:39.21.477] (SSH-Browser) DownUpFile: PipelineLength = 32 +[16:39.21.477] (SSH-Browser) DownUpFile: DownloadBlockSize = 32768 +[16:39.21.477] (SSH-Browser) DownUpFile: UploadBlockSize = 65536 +[16:39.21.477] (SSH-Browser) DownUpFile: SftpBufferSize = 262144 +[16:39.21.477] (SSH-Browser) DownUpFile: DefaultWindowSize = 2097152 +[16:39.21.477] (SSH-Browser) DownUpFile: MinWindowSize = 2048 +[16:39.21.477] (SSH-Browser) DownUpFile: MaxSSHPacketSize = 262144 +[16:39.21.477] (SSH-Browser) DownUpFile: AutoAdjustTransferBlock = FALSE +[16:39.21.477] (SSH-Browser) DownUpFile: AsciiMode = FALSE +[16:39.21.480] (SSH-Browser) SFTPcliOpenFile +[16:39.21.480] (SSH-Browser) Uploading file +[16:39.21.484] (SSH-Browser) CloseCurrentHandle +[16:39.21.484] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:39.21.486] (SSH-Browser) VerifyAvailabilityOfSFTPcli: result=true +[16:39.21.486] (SSH-Browser) TDownUpForm.Timer1Timer2 +[16:39.21.522] (SSH-Browser) BEGIN OpenDir(1) +[16:39.21.522] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.21.522] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.21.522] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.21.522] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:39.21.522] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/test/); +[16:39.21.522] (SSH-Browser) END OpenDir(1) +[16:39.21.530] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:39.21.530] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root/test) +[16:39.21.561] (SSH-Browser) ElSFTP1OpenFile(1) +[16:39.21.561] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:39.21.623] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:39.21.623] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:39.21.623] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:39.21.623] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.21.623] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.21.623] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.21.623] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:39.21.623] (SSH-Browser) END CloseCurrentHandle(1) +[16:39.21.623] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:39.21.623] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[16:39.21.623] (SSH-Browser) 对项目进行排序 +[16:39.21.623] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:39.21.627] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:39.21.653] (SSH-Browser) ElSFTP1Success(1) + +[16:39.22.598] BEGIN WMNewTab: 20 +[16:39.22.598] END WMNewTab: 20 +[16:39.22.903] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.23.802] BEGIN CWD +[16:39.23.863] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.23.863] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.23.863] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.23.863] END CWD +[16:39.23.865] BEGIN WMNewTab: 20 +[16:39.23.865] END WMNewTab: 20 +[16:39.23.880] BEGIN CWD +[16:39.23.943] (CWD) OpenDir(/root); +[16:39.23.943] (SSH-Browser) BEGIN OpenDir(1) +[16:39.23.943] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.23.943] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.23.943] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.23.943] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:39.23.944] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root); +[16:39.23.944] (SSH-Browser) END OpenDir(1) +[16:39.23.944] END CWD +[16:39.23.973] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:39.23.973] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:39.24.042] (SSH-Browser) ElSFTP1OpenFile(1) +[16:39.24.042] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:39.24.097] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:39.24.097] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:39.24.097] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:39.24.097] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.24.097] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.24.097] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.24.097] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:39.24.098] (SSH-Browser) END CloseCurrentHandle(1) +[16:39.24.098] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:39.24.098] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=19 +[16:39.24.098] (SSH-Browser) 对项目进行排序 +[16:39.24.098] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:39.24.101] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:39.24.126] (SSH-Browser) ElSFTP1Success(1) + +[16:39.24.522] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.25.073] BEGIN WMNewTab: 20 +[16:39.25.073] END WMNewTab: 20 +[16:39.25.149] BEGIN CWD +[16:39.25.210] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:39.25.210] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:39.25.210] (SSH-Browser) END VerifySFTPConnection(1) +[16:39.25.210] END CWD +[16:39.25.226] BEGIN CWD +[16:39.25.288] END CWD + +[16:39.26.126] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.26.704] BEGIN WMNewTab: 20 +[16:39.26.704] END WMNewTab: 20 + +[16:39.27.743] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.28.125] BEGIN WMNewTab: 20 +[16:39.28.125] END WMNewTab: 20 + + +[16:39.29.350] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.29.548] BEGIN WMNewTab: 20 +[16:39.29.548] END WMNewTab: 20 + + +[16:39.30.961] BEGIN WMNewTab: 20 +[16:39.30.961] END WMNewTab: 20 +[16:39.30.961] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:39.32.382] BEGIN WMNewTab: 20 +[16:39.32.382] END WMNewTab: 20 +[16:39.32.563] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:39.33.800] BEGIN WMNewTab: 20 +[16:39.33.800] END WMNewTab: 20 + +[16:39.34.179] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.35.215] BEGIN WMNewTab: 20 +[16:39.35.215] END WMNewTab: 20 + +[16:39.35.777] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.36.632] BEGIN WMNewTab: 20 +[16:39.36.632] END WMNewTab: 20 + +[16:39.37.397] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.38.054] BEGIN WMNewTab: 20 +[16:39.38.054] END WMNewTab: 20 + +[16:39.39.001] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.39.471] BEGIN WMNewTab: 20 +[16:39.39.471] END WMNewTab: 20 + +[16:39.40.620] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.40.898] BEGIN WMNewTab: 20 +[16:39.40.898] END WMNewTab: 20 + + +[16:39.42.222] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.42.313] BEGIN WMNewTab: 20 +[16:39.42.313] END WMNewTab: 20 + + +[16:39.43.730] BEGIN WMNewTab: 20 +[16:39.43.730] END WMNewTab: 20 +[16:39.43.838] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:39.45.161] BEGIN WMNewTab: 20 +[16:39.45.161] END WMNewTab: 20 +[16:39.45.437] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.46.588] BEGIN WMNewTab: 20 +[16:39.46.588] END WMNewTab: 20 + +[16:39.47.047] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.48.005] BEGIN WMNewTab: 20 +[16:39.48.005] END WMNewTab: 20 + +[16:39.48.660] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.49.423] BEGIN WMNewTab: 20 +[16:39.49.423] END WMNewTab: 20 + +[16:39.50.276] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.50.839] BEGIN WMNewTab: 20 +[16:39.50.839] END WMNewTab: 20 + +[16:39.51.874] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.52.256] BEGIN WMNewTab: 20 +[16:39.52.256] END WMNewTab: 20 + + +[16:39.53.492] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:39.53.673] BEGIN WMNewTab: 20 +[16:39.53.673] END WMNewTab: 20 + + +[16:39.55.082] BEGIN WMNewTab: 20 +[16:39.55.082] END WMNewTab: 20 +[16:39.55.097] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:39.56.496] BEGIN WMNewTab: 20 +[16:39.56.496] END WMNewTab: 20 +[16:39.56.710] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.57.911] BEGIN WMNewTab: 20 +[16:39.57.911] END WMNewTab: 20 + +[16:39.58.325] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:39.59.337] BEGIN WMNewTab: 20 +[16:39.59.337] END WMNewTab: 20 + +[16:39.59.938] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.00.754] BEGIN WMNewTab: 20 +[16:40.00.754] END WMNewTab: 20 + +[16:40.01.527] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.02.168] BEGIN WMNewTab: 20 +[16:40.02.168] END WMNewTab: 20 + +[16:40.03.144] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.03.586] BEGIN WMNewTab: 20 +[16:40.03.586] END WMNewTab: 20 + +[16:40.04.759] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:40.05.050] BEGIN WMNewTab: 20 +[16:40.05.050] END WMNewTab: 20 + + +[16:40.06.356] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:40.06.463] BEGIN WMNewTab: 20 +[16:40.06.463] END WMNewTab: 20 + + +[16:40.07.884] BEGIN WMNewTab: 20 +[16:40.07.884] END WMNewTab: 20 +[16:40.07.975] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.09.299] BEGIN WMNewTab: 20 +[16:40.09.299] END WMNewTab: 20 +[16:40.09.589] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.10.719] BEGIN WMNewTab: 20 +[16:40.10.719] END WMNewTab: 20 + +[16:40.11.188] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.12.134] BEGIN WMNewTab: 20 +[16:40.12.134] END WMNewTab: 20 + +[16:40.12.803] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.13.549] BEGIN WMNewTab: 20 +[16:40.13.549] END WMNewTab: 20 + +[16:40.14.405] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.14.968] BEGIN WMNewTab: 20 +[16:40.14.968] END WMNewTab: 20 + +[16:40.16.021] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.16.386] BEGIN WMNewTab: 20 +[16:40.16.386] END WMNewTab: 20 + + +[16:40.17.635] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:40.17.801] BEGIN WMNewTab: 20 +[16:40.17.801] END WMNewTab: 20 + + +[16:40.19.213] BEGIN WMNewTab: 20 +[16:40.19.213] END WMNewTab: 20 +[16:40.19.243] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.20.626] BEGIN WMNewTab: 20 +[16:40.20.626] END WMNewTab: 20 +[16:40.20.740] BEGIN WMNewTab: 0 +[16:40.20.740] WMNewTab: FormClick +[16:40.20.740] WMNewTab: LooseFocus +[16:40.20.740] END WMNewTab: 0 +[16:40.20.823] BEGIN WMNewTab: 0 +[16:40.20.823] WMNewTab: FormClick +[16:40.20.823] WMNewTab: LooseFocus +[16:40.20.823] END WMNewTab: 0 +[16:40.20.841] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.22.043] BEGIN WMNewTab: 20 +[16:40.22.043] END WMNewTab: 20 + +[16:40.22.484] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.23.496] BEGIN WMNewTab: 20 +[16:40.23.496] END WMNewTab: 20 + +[16:40.24.063] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.24.916] BEGIN WMNewTab: 20 +[16:40.24.916] END WMNewTab: 20 + +[16:40.25.678] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.26.337] BEGIN WMNewTab: 20 +[16:40.26.337] END WMNewTab: 20 + +[16:40.27.278] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:40.27.549] BEGIN WMNewTab: 20 +[16:40.27.549] END WMNewTab: 20 +[16:40.27.599] BEGIN WMNewTab: 48 +[16:40.27.599] 收到消息: SSH 会话部分关闭 (2) +[16:40.27.703] BEGIN TFormXterm.FormResize +[16:40.27.703] TFormXterm.FormResize: CenterBtnReattachTab +[16:40.27.706] TFormXterm.FormResize: SplitModeResize +[16:40.27.706] TFormXterm.FormResize: BtnSplitNo.Down +[16:40.27.708] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:40.27.708] BEGIN ResizeTerminal +[16:40.27.772] END ResizeTerminal +[16:40.27.772] TFormXterm.FormResize: AdaptSidebarArrows; +[16:40.27.772] BEGIN AdaptSidebarArrows +[16:40.27.772] END AdaptSidebarArrows +[16:40.27.772] TFormXterm.FormResize: AdaptTV2; +[16:40.27.772] END TFormXterm.FormResize +[16:40.27.772] BEGIN DisconnectSSH(1) +[16:40.27.772] (SSH-Browser) DisconnectSSH(1): (Socket.Active) and (SocketState<>SOCKET_STATE_CONNECTING) +[16:40.27.816] SetTitle(1, ); +[16:40.27.816] (SSH-Browser) ElSFTP1CloseConnection(1) +[16:40.27.816] (SSH-Browser) ElSFTP1Error(1): #103 - 连接被低层协议关闭 +[16:40.27.816] SFTPErr #103 附带说明 "连接被低层协议关闭" +[16:40.27.816] (SSH-Browser) ElSFTP1CloseConnection(1) +[16:40.27.816] BEGIN ElSSH1CloseConnection(1) +[16:40.27.816] END ElSSH1CloseConnection(1) +[16:40.27.816] (SSH-Browser) DisconnectSSH(1): Socket.Close; +[16:40.27.816] (SSH-Browser) BEGIN DesactiverPanel14 +[16:40.27.851] (SSH-Browser) END DesactiverPanel14 +[16:40.27.851] END DisconnectSSH(1) +[16:40.27.875] END WMNewTab: 48 + +[16:40.28.889] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.30.510] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.32.112] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.33.727] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.35.327] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.36.950] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.38.573] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.40.174] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.41.790] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.43.394] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.44.999] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.46.619] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.48.225] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.49.829] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.50.781] BEGIN WMNewTab: 60 +[16:40.50.798] END WMNewTab: 60 + +[16:40.51.387] BEGIN WMNewTab: 60 +[16:40.51.387] END WMNewTab: 60 +[16:40.51.441] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:40.51.999] BEGIN WMNewTab: 60 +[16:40.51.999] END WMNewTab: 60 + +[16:40.52.405] Cts1MouseDown: FormClick +[16:40.52.412] Cts1ActiveTabChanged: New index = 2 +[16:40.52.412] BEGIN DisplayCurrentTab +[16:40.52.412] DisplayCurrentTab: FormClick +[16:40.52.412] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:40.52.412] (SSH-Browser) BEGIN ActiverPanel14 +[16:40.52.412] (SSH-Browser) BEGIN DesactiverPanel14 +[16:40.52.412] (SSH-Browser) END DesactiverPanel14 +[16:40.52.412] (SSH-Browser) END ActiverPanel14; +[16:40.52.440] DisplayCurrentTab: Cts1.BeginUpdate; +[16:40.52.440] DisplayCurrentTab: Cts1.EndUpdates +[16:40.52.462] DisplayCurrentTab: 显示所选标签页 +[16:40.52.464] DisplayCurrentTab: 隐藏其他标签页 +[16:40.52.465] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:40.52.468] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:40.52.468] DisplayCurrentTab: DistribuerLeFocus +[16:40.52.468] END DisplayCurrentTab +[16:40.52.489] BEGIN WMNewTab: 62 +[16:40.52.489] END WMNewTab: 62 + +[16:40.53.054] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.54.664] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.56.276] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.57.874] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:40.59.487] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.01.102] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.02.701] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.04.313] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.05.929] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.07.540] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.09.137] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.10.757] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.12.364] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.13.978] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.15.586] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.17.184] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.18.797] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.20.413] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.22.024] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.23.625] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.25.244] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.26.844] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.28.455] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.30.068] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.31.673] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.33.281] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.34.889] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.36.507] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.38.107] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.39.716] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.41.329] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.42.949] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.44.548] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.46.157] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.47.773] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.49.383] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.50.988] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.52.600] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.54.211] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.55.812] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:41.57.427] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:41.57.843] BEGIN WMNewTab: 0 +[16:41.57.843] WMNewTab: FormClick +[16:41.57.843] WMNewTab: LooseFocus +[16:41.57.844] END WMNewTab: 0 +[16:41.57.987] BEGIN WMNewTab: 0 +[16:41.57.987] WMNewTab: FormClick +[16:41.57.987] WMNewTab: LooseFocus +[16:41.57.988] END WMNewTab: 0 + +[16:41.59.037] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.00.640] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.02.253] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.03.868] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.05.478] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.07.089] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.08.694] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.10.294] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.11.910] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.13.516] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.15.129] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.16.735] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.18.353] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.19.952] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.21.569] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.23.182] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.24.781] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.26.398] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.28.002] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.29.612] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.31.228] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.32.828] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.34.435] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.36.053] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.37.666] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.39.263] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.40.879] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.42.496] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.44.093] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.45.702] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.47.317] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.48.919] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.50.536] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.52.147] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.53.747] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.55.366] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.56.977] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:42.58.577] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.00.198] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.01.796] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.03.404] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.05.014] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.06.631] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.08.233] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.09.851] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.11.463] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.13.069] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.14.673] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.16.287] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.17.890] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.19.500] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:43.20.663] BEGIN WMNewTab: 0 +[16:43.20.663] WMNewTab: FormClick +[16:43.20.663] WMNewTab: LooseFocus +[16:43.20.664] END WMNewTab: 0 +[16:43.20.779] BEGIN WMNewTab: 0 +[16:43.20.779] WMNewTab: FormClick +[16:43.20.779] WMNewTab: LooseFocus +[16:43.20.781] END WMNewTab: 0 +[16:43.21.114] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.22.719] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.24.327] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.25.944] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.27.554] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.29.156] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.30.773] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.32.375] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.33.988] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.35.591] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.37.207] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.38.813] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.40.430] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.42.033] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.43.637] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.45.261] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.46.868] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.48.470] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.50.087] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.51.694] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.53.306] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.54.907] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.56.525] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.58.123] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:43.59.742] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.01.345] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.02.962] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.04.562] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.06.178] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.07.780] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.09.390] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.11.006] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.12.619] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.14.218] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.15.832] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.17.439] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.19.056] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.20.656] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.22.276] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.23.875] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.25.487] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.27.105] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.28.704] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.30.319] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.31.620] BEGIN WMNewTab: 0 +[16:44.31.620] WMNewTab: FormClick +[16:44.31.620] WMNewTab: LooseFocus +[16:44.31.620] END WMNewTab: 0 +[16:44.31.722] BEGIN WMNewTab: 0 +[16:44.31.722] WMNewTab: FormClick +[16:44.31.722] WMNewTab: LooseFocus +[16:44.31.723] END WMNewTab: 0 +[16:44.31.933] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.33.535] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.35.144] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.36.761] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.38.359] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.39.973] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.41.581] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.43.196] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.44.802] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.46.405] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.48.019] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.49.621] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.51.239] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.52.845] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.54.463] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.56.063] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.57.669] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:44.59.291] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.00.894] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.02.502] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.04.116] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.05.723] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.07.326] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.08.935] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.10.550] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.12.164] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.13.762] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.15.376] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.16.983] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.18.601] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.20.211] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.21.809] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.23.431] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.25.031] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.26.648] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.28.250] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.29.866] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.31.470] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.33.088] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.34.698] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.36.305] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.37.905] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.39.526] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.41.125] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.42.739] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.44.342] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.45.959] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.47.570] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.49.173] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.50.790] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.52.397] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.53.998] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.55.616] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.57.222] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:45.58.838] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.00.439] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.02.055] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.03.657] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.05.263] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.06.880] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.08.482] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.10.106] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.11.707] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.13.322] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.14.921] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.16.535] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.18.146] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.19.752] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.21.370] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.22.976] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.24.580] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.26.185] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.27.801] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.29.410] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.31.026] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.32.622] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.34.241] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.35.847] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.37.450] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.39.064] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.40.678] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.42.280] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.43.896] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.45.501] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.47.120] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.48.723] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.50.325] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.51.940] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.53.557] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.55.162] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.56.762] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.58.373] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:46.59.988] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.01.596] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.03.212] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.04.812] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.06.420] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.08.035] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.09.650] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.11.254] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.12.858] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.14.476] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.16.086] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.17.848] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.19.294] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.20.903] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.21.608] BEGIN WMNewTab: 0 +[16:47.21.608] WMNewTab: FormClick +[16:47.21.608] WMNewTab: LooseFocus +[16:47.21.610] END WMNewTab: 0 +[16:47.21.663] BEGIN WMNewTab: 0 +[16:47.21.663] WMNewTab: FormClick +[16:47.21.663] WMNewTab: LooseFocus +[16:47.21.663] END WMNewTab: 0 + +[16:47.22.522] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.23.079] Cts1MouseDown: FormClick +[16:47.23.088] Cts1ActiveTabChanged: New index = 1 +[16:47.23.088] BEGIN DisplayCurrentTab +[16:47.23.088] DisplayCurrentTab: FormClick +[16:47.23.088] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:47.23.088] (SSH-Browser) BEGIN ActiverPanel14 +[16:47.23.088] (SSH-Browser) BEGIN DesactiverPanel14 +[16:47.23.088] (SSH-Browser) END DesactiverPanel14 +[16:47.23.088] (SSH-Browser) END ActiverPanel14; +[16:47.23.106] DisplayCurrentTab: Cts1.BeginUpdate; +[16:47.23.106] DisplayCurrentTab: Cts1.EndUpdates +[16:47.23.127] DisplayCurrentTab: 显示所选标签页 +[16:47.23.129] DisplayCurrentTab: 隐藏其他标签页 +[16:47.23.131] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:47.23.135] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:47.23.135] DisplayCurrentTab: DistribuerLeFocus +[16:47.23.135] END DisplayCurrentTab + +[16:47.24.064] BEGIN WMNewTab: 62 +[16:47.24.064] END WMNewTab: 62 +[16:47.24.135] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.24.181] SetTitle(1, 192.168.127.10 (root)); +[16:47.24.199] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:47.24.199] 主机密钥与缓存中的密钥是不一致的 +[16:47.24.200] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:47.24.200] 主机密钥与缓存中的密钥是不一致的 + + +[16:47.25.739] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.25.774] 收到主机密钥存储请求: ssh-ed25519@22:192.168.127.10|0x4fbdeb0cc708bedaad7244d9ccc03a9b5cb295f23736588e66709ddd9c4b8735,0x5ec1cdf861f8c174c9e669cf4bcd8c288d273792c4b772d85bb963292275a928 +[16:47.25.790] BEGIN GetPassword +[16:47.25.790] BEGIN GetnSaveCredPassword +[16:47.25.790] END GetnSaveCredPassword +[16:47.25.790] END GetPassword +[16:47.26.135] BEGIN WMNewTab: 0 +[16:47.26.135] WMNewTab: FormClick +[16:47.26.135] WMNewTab: LooseFocus +[16:47.26.135] END WMNewTab: 0 +[16:47.26.231] BEGIN WMNewTab: 0 +[16:47.26.231] WMNewTab: FormClick +[16:47.26.231] WMNewTab: LooseFocus +[16:47.26.231] END WMNewTab: 0 + +[16:47.27.350] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.28.950] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.30.565] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.30.776] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:47.30.776] BEGIN SauvegarderMotDePasseSSH +[16:47.30.776] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:47.30.776] SetTitle(1, root@192.168.127.10); +[16:47.30.776] +[16:47.30.776] (SSH-Browser) BEGIN ConnectSSH(1,192.168.127.10,root,) +[16:47.30.776] (SSH-Browser) ConnectSSH(1): 初始化 TabSFTP +[16:47.30.780] (SSH-Browser) ConnectSSH(1): 未使用代理 +[16:47.30.780] (SSH-Browser) ConnectSSH(1): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:47.30.782] (SSH-Browser) ConnectSSH(1): 已成功连接到 192.168.127.10. +[16:47.30.782] (SSH-Browser) ConnectSSH(1): SSH.Open +[16:47.30.782] (SSH-Browser) END ConnectSSH(1) +[16:47.30.782] BEGIN DisplayCurrentTab +[16:47.30.782] DisplayCurrentTab: FormClick +[16:47.30.782] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:47.30.782] (SSH-Browser) BEGIN ActiverPanel14 +[16:47.30.782] (SSH-Browser) BEGIN DesactiverPanel14 +[16:47.30.782] (SSH-Browser) END DesactiverPanel14 +[16:47.30.782] (SSH-Browser) END ActiverPanel14; +[16:47.30.806] DisplayCurrentTab: Cts1.BeginUpdate; +[16:47.30.806] DisplayCurrentTab: Cts1.EndUpdates +[16:47.30.828] DisplayCurrentTab: 显示所选标签页 +[16:47.30.829] DisplayCurrentTab: 隐藏其他标签页 +[16:47.30.829] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:47.30.842] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:47.30.842] DisplayCurrentTab: DistribuerLeFocus +[16:47.30.842] END DisplayCurrentTab +[16:47.30.842] BEGIN SavePassword +[16:47.30.842] END SavePassword +[16:47.30.842] END SauvegarderMotDePasseSSH +[16:47.30.842] BEGIN WMNewTab: 80 +[16:47.30.842] 收到消息: 正在启动远程监控 终端 #2 +[16:47.30.880] BEGIN TFormXterm.FormResize +[16:47.30.880] TFormXterm.FormResize: CenterBtnReattachTab +[16:47.30.881] TFormXterm.FormResize: SplitModeResize +[16:47.30.881] TFormXterm.FormResize: BtnSplitNo.Down +[16:47.30.882] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:47.30.882] BEGIN ResizeTerminal +[16:47.30.906] END ResizeTerminal +[16:47.30.906] TFormXterm.FormResize: AdaptSidebarArrows; +[16:47.30.906] BEGIN AdaptSidebarArrows +[16:47.30.906] END AdaptSidebarArrows +[16:47.30.906] TFormXterm.FormResize: AdaptTV2; +[16:47.30.906] END TFormXterm.FormResize +[16:47.30.907] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:47.30.907] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:47.30.946] ShellExecuteS: ShellExecuteEx 成功. +[16:47.30.946] ShellExecuteS: WaitForInputIdle 失败. +[16:47.30.946] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:47.30.946] END WMNewTab: 80 +[16:47.31.028] [MobaSCP2] Launching remote monitoring in normal mode +[16:47.31.029] [MobaSCP2] Multiplex=1 +[16:47.31.029] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:47.31.029] [MobaSCP2] USERNAME: root + +[16:47.32.182] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.32.335] BEGIN WMNewTab: 20 +[16:47.32.335] END WMNewTab: 20 + +[16:47.33.130] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:47.33.130] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:47.33.130] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[16:47.33.130] (SSH-Browser) 主机密钥数据已存在于 INI 文件中 +[16:47.33.130] (SSH-Browser) END GetSftpOnValidateStatus +[16:47.33.202] +[16:47.33.202] (SSH-Browser) ElSSH1AuthenticationStart(1, 134) +[16:47.33.202] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:47.33.202] (SSH-Browser) 服务器支持以下认证方式: +[16:47.33.202] (SSH-Browser) . PUBLICKEYAGENT +[16:47.33.202] (SSH-Browser) . PUBLICKEY +[16:47.33.202] (SSH-Browser) . PASSWORD +[16:47.33.202] (SSH-Browser) 客户端支持以下认证方式: +[16:47.33.202] (SSH-Browser) . PUBLICKEYAGENT +[16:47.33.202] (SSH-Browser) . PUBLICKEY +[16:47.33.202] (SSH-Browser) . RHOSTS +[16:47.33.202] (SSH-Browser) . HOSTBASED +[16:47.33.202] (SSH-Browser) . PASSWORD +[16:47.33.202] (SSH-Browser) . KEYBOARD +[16:47.33.202] +[16:47.33.202] +[16:47.33.202] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEY) +[16:47.33.202] (SSH-Browser) ElSSH1AuthenticationFailed(1, PUBLICKEYAGENT) +[16:47.33.202] (SSH-Browser) ElSSH1AuthenticationAttempt(1, PASSWORD) +[16:47.33.431] (SSH-Browser) ElSSH1AuthenticationSuccess(1) +[16:47.33.431] (SSH-Browser) ElSSH1OpenConnection(1) +[16:47.33.431] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:47.33.431] +[16:47.33.783] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.33.795] BEGIN WMNewTab: 20 +[16:47.33.795] END WMNewTab: 20 +[16:47.33.875] [MobaSCP2] Using SCP1 +[16:47.33.875] [MobaSCP2] Connected to 192.168.127.10 +[16:47.33.951] (SSH-Browser) BEGIN ElSFTP1OpenConnection(1) +[16:47.33.951] (SSH-Browser) ElSFTP1OpenConnection(1): SFTP 已正确连接 +[16:47.33.951] (SSH-Browser) ElSFTP1OpenConnection(1): ActiverPanel14 +[16:47.33.951] (SSH-Browser) BEGIN ActiverPanel14 +[16:47.33.951] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:47.33.958] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:47.33.958] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:47.33.958] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:47.33.958] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:47.34.029] (SSH-Browser) END ActiverPanel14; +[16:47.34.098] (SSH-Browser) ElSFTP1OpenConnection(1): 已成功打开连接 --> 正在退出 +[16:47.34.098] (SSH-Browser) END ElSFTP1OpenConnection(1) + +[16:47.35.033] BEGIN TFormXterm.FormResize +[16:47.35.033] TFormXterm.FormResize: CenterBtnReattachTab +[16:47.35.033] TFormXterm.FormResize: SplitModeResize +[16:47.35.033] TFormXterm.FormResize: BtnSplitNo.Down +[16:47.35.033] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:47.35.033] BEGIN ResizeTerminal +[16:47.35.033] BEGIN WMNewTab: 20 +[16:47.35.033] END WMNewTab: 20 +[16:47.35.034] END ResizeTerminal +[16:47.35.034] TFormXterm.FormResize: AdaptSidebarArrows; +[16:47.35.034] BEGIN AdaptSidebarArrows +[16:47.35.034] END AdaptSidebarArrows +[16:47.35.034] TFormXterm.FormResize: AdaptTV2; +[16:47.35.034] END TFormXterm.FormResize + +[16:47.35.398] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.36.451] BEGIN WMNewTab: 20 +[16:47.36.451] END WMNewTab: 20 + +[16:47.36.997] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.37.869] BEGIN WMNewTab: 20 +[16:47.37.869] END WMNewTab: 20 + +[16:47.38.617] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.39.287] BEGIN WMNewTab: 20 +[16:47.39.288] END WMNewTab: 20 + +[16:47.40.219] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.40.707] BEGIN WMNewTab: 20 +[16:47.40.707] END WMNewTab: 20 + +[16:47.41.836] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.42.125] BEGIN WMNewTab: 20 +[16:47.42.125] END WMNewTab: 20 + + +[16:47.43.449] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.43.541] BEGIN WMNewTab: 20 +[16:47.43.541] END WMNewTab: 20 + + +[16:47.44.955] BEGIN WMNewTab: 20 +[16:47.44.955] END WMNewTab: 20 +[16:47.45.048] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.46.374] BEGIN WMNewTab: 20 +[16:47.46.374] END WMNewTab: 20 +[16:47.46.664] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.47.796] BEGIN WMNewTab: 20 +[16:47.47.796] END WMNewTab: 20 + +[16:47.48.274] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.48.616] BEGIN WMNewTab: 0 +[16:47.48.616] WMNewTab: FormClick +[16:47.48.616] WMNewTab: LooseFocus +[16:47.48.616] END WMNewTab: 0 +[16:47.48.735] BEGIN WMNewTab: 0 +[16:47.48.735] WMNewTab: FormClick +[16:47.48.735] WMNewTab: LooseFocus +[16:47.48.736] END WMNewTab: 0 + +[16:47.49.213] BEGIN WMNewTab: 20 +[16:47.49.213] END WMNewTab: 20 + +[16:47.49.883] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.50.361] Cts1MouseDown: FormClick +[16:47.50.448] BEGIN TFormXterm.Cts1ButtonCloseTabClick +[16:47.50.450] +[16:47.50.453] BEGIN CloseTab(2) +[16:47.50.453] CloseTab: 标签页是外部应用 +[16:47.50.453] CloseTab: 发送 WM_CLOSE (36) 至外部应用 +[16:47.50.453] Form4.Closing = false +[16:47.50.453] END CloseTab(2) +[16:47.50.453] +[16:47.50.453] END TFormXterm.Cts1ButtonCloseTabClick +[16:47.50.633] BEGIN WMNewTab: 20 +[16:47.50.633] END WMNewTab: 20 + +[16:47.51.274] +[16:47.51.274] Timer1: CloseTab(2); +[16:47.51.274] +[16:47.51.274] BEGIN CloseTab(2) +[16:47.51.274] CloseTab: 标签页是外部应用 +[16:47.51.274] CloseTab: 删除 MobaScript 文件 +[16:47.51.274] CloseTab: 关闭 TFormDetachedTab +[16:47.51.274] CloseTab: 检查会话的网关连接是否已启动, 会话 #2 +[16:47.51.277] CloseTab: Cts1.BeginUpdate; +[16:47.51.277] CloseTab: Cts1.Tabs.Delete(2); +[16:47.51.280] CloseTab: Cts1.Tabs.Delete(2); +[16:47.51.280] (SSH-Browser) TabSFTP[2].Free; +[16:47.51.280] 释放对象 TMobaThread +[16:47.51.281] 释放对象 TElSftpClient +[16:47.51.281] 释放对象 TElSSHClient +[16:47.51.282] 释放对象 TElSocket +[16:47.51.282] 释放对象 TSshBrowserList +[16:47.51.282] 释放对象 TElSSHTunnelList +[16:47.51.282] 释放对象 TElSubsystemSSHTunnel +[16:47.51.282] 释放对象 TList +[16:47.51.282] 释放对象 TTimer +[16:47.51.283] BEGIN DisplayCurrentTab +[16:47.51.283] DisplayCurrentTab: FormClick +[16:47.51.283] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:47.51.283] (SSH-Browser) BEGIN ActiverPanel14 +[16:47.51.283] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:47.51.300] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:47.51.300] (SSH-Browser) ActiverPanel14: 远程目录已列出 +[16:47.51.300] (SSH-Browser) END ActiverPanel14; +[16:47.51.300] DisplayCurrentTab: Cts1.BeginUpdate; +[16:47.51.300] DisplayCurrentTab: Cts1.EndUpdates +[16:47.51.318] DisplayCurrentTab: 显示所选标签页 +[16:47.51.319] DisplayCurrentTab: 隐藏其他标签页 +[16:47.51.319] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:47.51.322] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:47.51.322] DisplayCurrentTab: DistribuerLeFocus +[16:47.51.322] END DisplayCurrentTab +[16:47.51.322] END CloseTab(2) +[16:47.51.322] +[16:47.51.492] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.52.050] BEGIN WMNewTab: 20 +[16:47.52.050] END WMNewTab: 20 + +[16:47.53.098] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:47.53.468] BEGIN WMNewTab: 20 +[16:47.53.468] END WMNewTab: 20 + + +[16:47.54.701] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.54.905] BEGIN WMNewTab: 20 +[16:47.54.905] END WMNewTab: 20 + +[16:47.55.442] (SSH-Browser) BEGIN OpenDir(1) +[16:47.55.442] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:47.55.442] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:47.55.442] (SSH-Browser) END VerifySFTPConnection(1) +[16:47.55.442] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:47.55.443] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/); +[16:47.55.443] (SSH-Browser) END OpenDir(1) +[16:47.55.449] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:47.55.449] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/root) +[16:47.55.479] (SSH-Browser) ElSFTP1OpenFile(1) +[16:47.55.479] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:47.55.539] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:47.55.539] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:47.55.539] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:47.55.539] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:47.55.539] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:47.55.539] (SSH-Browser) END VerifySFTPConnection(1) +[16:47.55.539] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:47.55.539] (SSH-Browser) END CloseCurrentHandle(1) +[16:47.55.539] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:47.55.539] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=18 +[16:47.55.539] (SSH-Browser) 对项目进行排序 +[16:47.55.539] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:47.55.544] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:47.55.626] (SSH-Browser) ElSFTP1Success(1) + +[16:47.56.466] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:47.56.559] BEGIN WMNewTab: 20 +[16:47.56.559] END WMNewTab: 20 + + +[16:47.57.990] BEGIN WMNewTab: 20 +[16:47.57.990] END WMNewTab: 20 +[16:47.57.993] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:47.59.413] BEGIN WMNewTab: 20 +[16:47.59.413] END WMNewTab: 20 +[16:47.59.534] (SSH-Browser) TDownUpForm.JvTimer1Timer + + +[16:48.00.828] BEGIN WMNewTab: 20 +[16:48.00.828] END WMNewTab: 20 +[16:48.01.145] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.02.243] BEGIN WMNewTab: 20 +[16:48.02.243] END WMNewTab: 20 + +[16:48.02.739] BEGIN ExecuteSessionTree +[16:48.02.739] ExecuteSessionTree: FormClick +[16:48.02.746] BEGIN ExecuteSelectedSession +[16:48.02.746] ExecuteSelectedSession: FormClick +[16:48.02.746] ExecuteSelectedSession0 +[16:48.02.746] ExecuteSelectedSession1 +[16:48.02.746] ExecuteSelectedSession2 +[16:48.02.746] ExecuteSelectedSession3 +[16:48.02.747] BEGIN ChargerLaSession +[16:48.02.748] ChargerLaSession1 +[16:48.02.763] ChargerLaSession2 +[16:48.02.763] ChargerLaSession3 +[16:48.02.765] ChargerLaSession4 +[16:48.02.765] ChargerLaSession5 +[16:48.02.765] ChargerLaSession6 +[16:48.02.766] ChargerLaSession7 +[16:48.02.767] ChargerLaSession8 +[16:48.02.767] ChargerLaSession8_ssh_1 +[16:48.02.767] ChargerLaSession8_ssh_2 +[16:48.02.767] ChargerLaSession8_ssh_3 +[16:48.02.767] ChargerLaSession8_ssh_4 +[16:48.02.767] ChargerLaSession9 +[16:48.02.800] ChargerLaSession10 +[16:48.02.800] END ChargerLaSession +[16:48.02.800] ExecuteSelectedSession4 +[16:48.02.800] LaunchSession0 +[16:48.02.832] LaunchSession1 +[16:48.02.832] LaunchSession4 +[16:48.02.832] LaunchSession5 +[16:48.02.832] +[16:48.02.832] BEGIN NEWTAB(ssh "192.168.110.17" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.02.832] NEWTAB: Application.ProcessMessages +[16:48.02.835] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.02.836] NEWTAB: Timer1_Disable +[16:48.02.836] NEWTAB: 检查是否已达到最大标签数... +[16:48.02.836] NEWTAB: 创建 SFTPRecord... +[16:48.02.846] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[16:48.02.846] NEWTAB: 尝试查找旧索引... +[16:48.02.846] NEWTAB: Cts1.BeginUpdate; +[16:48.02.846] NEWTAB: 创建新标签页... +[16:48.02.846] NEWTAB: 标签页索引: 2 +[16:48.02.846] NEWTAB: 终端编号 : 6 +[16:48.02.846] NEWTAB: 标题 : 192.168.110.17 (root) +[16:48.02.846] NEWTAB: 命令 : ssh "192.168.110.17" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[16:48.02.846] Cts1ActiveTabChanged: New index = 2 +[16:48.02.847] NEWTAB: Cts1.EndUpdates +[16:48.02.854] NEWTAB: 更改标签页索引 A = 2 +[16:48.02.854] BEGIN WaitForAllThreads +[16:48.02.856] END WaitForAllThreads +[16:48.02.856] +[16:48.02.856] LaunchTabContent(ssh "192.168.110.17" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.110.17 (root)); +[16:48.02.856] +[16:48.02.856] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.02.857] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.02.857] MOBANOACL=onlyslash +[16:48.02.857] +[16:48.02.857] ShellExecute: motty.exe +[16:48.02.857] +[16:48.02.858] CreerSessionMoTTY(6, ssh "192.168.110.17" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.110.17 (root)) +[16:48.02.870] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.02.871] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.02.871] MOBANOACL=onlyslash +[16:48.02.877] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756666") +[16:48.03.048] ShellExecuteS: ShellExecuteEx 成功. +[16:48.03.159] ShellExecuteS: WaitForInputIdle 成功. +[16:48.03.159] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756666") +[16:48.03.159] +[16:48.03.159] FindWindow(CMoTTY) +[16:48.03.159] 潜在窗口 661370 成功通过第二次验证. +[16:48.03.159] --> 成功 +[16:48.03.161] BEGIN MoTTY.SetParent +[16:48.03.194] END MoTTY.SetParent +[16:48.03.194] NEWTAB: Application.OnMessage:=AppMessage +[16:48.03.210] NEWTAB: 更改标签页索引 C = 2 +[16:48.03.210] NEWTAB: 正在启动 DisplayCurrentTab... +[16:48.03.210] BEGIN DisplayCurrentTab +[16:48.03.210] DisplayCurrentTab: FormClick +[16:48.03.210] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:48.03.210] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.03.210] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.03.222] (SSH-Browser) END DesactiverPanel14 +[16:48.03.222] (SSH-Browser) END ActiverPanel14; +[16:48.03.359] BEGIN TFormXterm.FormResize +[16:48.03.359] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.03.361] TFormXterm.FormResize: SplitModeResize +[16:48.03.361] TFormXterm.FormResize: BtnSplitNo.Down +[16:48.03.361] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:48.03.361] BEGIN ResizeTerminal +[16:48.03.383] END ResizeTerminal +[16:48.03.383] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.03.383] BEGIN AdaptSidebarArrows +[16:48.03.383] END AdaptSidebarArrows +[16:48.03.383] TFormXterm.FormResize: AdaptTV2; +[16:48.03.383] END TFormXterm.FormResize +[16:48.03.383] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.03.383] DisplayCurrentTab: Cts1.EndUpdates +[16:48.03.402] DisplayCurrentTab: 显示所选标签页 +[16:48.03.418] DisplayCurrentTab: 隐藏其他标签页 +[16:48.03.427] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.03.428] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.03.428] DisplayCurrentTab: DistribuerLeFocus +[16:48.03.433] END DisplayCurrentTab +[16:48.03.433] NEWTAB: NewTab_ReEnable_Timer1 +[16:48.03.433] NEWTAB: MajVerticalTabs +[16:48.03.433] NEWTAB: Cts1.Resize; +[16:48.03.457] END NEWTAB(ssh "192.168.110.17" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.03.457] +[16:48.03.457] LaunchSession6 +[16:48.03.457] ExecuteSelectedSession5 +[16:48.03.457] END ExecuteSelectedSession +[16:48.03.457] END ExecuteSessionTree +[16:48.03.479] SetTitle(2, 192.168.110.17 (root)); +[16:48.03.661] BEGIN WMNewTab: 20 +[16:48.03.661] END WMNewTab: 20 + +[16:48.04.362] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.04.416] Cts1MouseDown: FormClick +[16:48.04.529] BEGIN TFormXterm.Cts1ButtonCloseTabClick +[16:48.04.529] +[16:48.04.529] BEGIN CloseTab(2) +[16:48.04.529] CloseTab: 标签页是外部应用 +[16:48.04.529] CloseTab: 发送 WM_CLOSE (36) 至外部应用 +[16:48.04.529] Form4.Closing = false +[16:48.04.529] END CloseTab(2) +[16:48.04.529] +[16:48.04.529] END TFormXterm.Cts1ButtonCloseTabClick + +[16:48.05.081] BEGIN WMNewTab: 20 +[16:48.05.081] END WMNewTab: 20 +[16:48.05.352] +[16:48.05.352] Timer1: CloseTab(2); +[16:48.05.352] +[16:48.05.352] BEGIN CloseTab(2) +[16:48.05.352] CloseTab: 标签页是外部应用 +[16:48.05.352] CloseTab: 删除 MobaScript 文件 +[16:48.05.353] CloseTab: 关闭 TFormDetachedTab +[16:48.05.353] CloseTab: 检查会话的网关连接是否已启动, 会话 #2 +[16:48.05.353] CloseTab: Cts1.BeginUpdate; +[16:48.05.353] CloseTab: Cts1.Tabs.Delete(2); +[16:48.05.353] Cts1ActiveTabChanged: New index = 1 +[16:48.05.353] CloseTab: Cts1.Tabs.Delete(2); +[16:48.05.353] (SSH-Browser) TabSFTP[2].Free; +[16:48.05.353] 释放对象 TMobaThread +[16:48.05.353] 释放对象 TElSftpClient +[16:48.05.353] 释放对象 TElSSHClient +[16:48.05.353] 释放对象 TElSocket +[16:48.05.353] 释放对象 TSshBrowserList +[16:48.05.353] 释放对象 TElSSHTunnelList +[16:48.05.353] 释放对象 TElSubsystemSSHTunnel +[16:48.05.353] 释放对象 TList +[16:48.05.353] 释放对象 TTimer +[16:48.05.355] BEGIN DisplayCurrentTab +[16:48.05.355] DisplayCurrentTab: FormClick +[16:48.05.355] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:48.05.355] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.05.355] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:48.05.361] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:48.05.361] (SSH-Browser) ActiverPanel14: 远程目录已列出 +[16:48.05.361] (SSH-Browser) END ActiverPanel14; +[16:48.05.394] BEGIN TFormXterm.FormResize +[16:48.05.394] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.05.395] TFormXterm.FormResize: SplitModeResize +[16:48.05.395] TFormXterm.FormResize: BtnSplitNo.Down +[16:48.05.396] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:48.05.396] BEGIN ResizeTerminal +[16:48.05.403] END ResizeTerminal +[16:48.05.403] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.05.403] BEGIN AdaptSidebarArrows +[16:48.05.403] END AdaptSidebarArrows +[16:48.05.403] TFormXterm.FormResize: AdaptTV2; +[16:48.05.403] END TFormXterm.FormResize +[16:48.05.403] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:48.05.403] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:48.05.429] ShellExecuteS: ShellExecuteEx 成功. +[16:48.05.429] ShellExecuteS: WaitForInputIdle 失败. +[16:48.05.429] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:48.05.430] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.05.430] DisplayCurrentTab: Cts1.EndUpdates +[16:48.05.448] DisplayCurrentTab: 显示所选标签页 +[16:48.05.449] DisplayCurrentTab: 隐藏其他标签页 +[16:48.05.449] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.05.455] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.05.455] DisplayCurrentTab: DistribuerLeFocus +[16:48.05.455] END DisplayCurrentTab +[16:48.05.455] END CloseTab(2) +[16:48.05.455] +[16:48.05.519] [MobaSCP2] Launching remote monitoring in normal mode +[16:48.05.520] [MobaSCP2] Multiplex=1 +[16:48.05.520] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:48.05.521] [MobaSCP2] USERNAME: root +[16:48.05.572] [MobaSCP2] Using SCP1 +[16:48.05.572] [MobaSCP2] Connected to 192.168.127.10 +[16:48.05.599] BEGIN ExecuteSessionTree +[16:48.05.599] ExecuteSessionTree: FormClick +[16:48.05.605] BEGIN ExecuteSelectedSession +[16:48.05.605] ExecuteSelectedSession: FormClick +[16:48.05.605] ExecuteSelectedSession0 +[16:48.05.605] ExecuteSelectedSession1 +[16:48.05.605] ExecuteSelectedSession2 +[16:48.05.605] ExecuteSelectedSession3 +[16:48.05.605] BEGIN ChargerLaSession +[16:48.05.606] ChargerLaSession1 +[16:48.05.618] ChargerLaSession2 +[16:48.05.618] ChargerLaSession3 +[16:48.05.618] ChargerLaSession4 +[16:48.05.619] ChargerLaSession5 +[16:48.05.619] ChargerLaSession6 +[16:48.05.619] ChargerLaSession7 +[16:48.05.619] ChargerLaSession8 +[16:48.05.619] ChargerLaSession8_ssh_1 +[16:48.05.619] ChargerLaSession8_ssh_2 +[16:48.05.619] ChargerLaSession8_ssh_3 +[16:48.05.619] ChargerLaSession8_ssh_4 +[16:48.05.619] ChargerLaSession9 +[16:48.05.645] ChargerLaSession10 +[16:48.05.645] END ChargerLaSession +[16:48.05.645] ExecuteSelectedSession4 +[16:48.05.645] LaunchSession0 +[16:48.05.649] LaunchSession1 +[16:48.05.649] LaunchSession4 +[16:48.05.649] LaunchSession5 +[16:48.05.649] +[16:48.05.649] BEGIN NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.05.649] NEWTAB: Application.ProcessMessages +[16:48.05.652] NEWTAB: Timer1_Disable +[16:48.05.652] NEWTAB: 检查是否已达到最大标签数... +[16:48.05.653] NEWTAB: 创建 SFTPRecord... +[16:48.05.657] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[16:48.05.657] NEWTAB: 尝试查找旧索引... +[16:48.05.657] NEWTAB: Cts1.BeginUpdate; +[16:48.05.657] NEWTAB: 创建新标签页... +[16:48.05.657] NEWTAB: 标签页索引: 2 +[16:48.05.657] NEWTAB: 终端编号 : 7 +[16:48.05.657] NEWTAB: 标题 : 192.168.127.10 (root) +[16:48.05.657] NEWTAB: 命令 : ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[16:48.05.657] Cts1ActiveTabChanged: New index = 2 +[16:48.05.657] NEWTAB: Cts1.EndUpdates +[16:48.05.661] NEWTAB: 更改标签页索引 A = 2 +[16:48.05.661] BEGIN WaitForAllThreads +[16:48.05.661] END WaitForAllThreads +[16:48.05.661] +[16:48.05.661] LaunchTabContent(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)); +[16:48.05.661] +[16:48.05.661] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.05.662] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.05.662] MOBANOACL=onlyslash +[16:48.05.663] +[16:48.05.663] ShellExecute: motty.exe +[16:48.05.663] +[16:48.05.663] CreerSessionMoTTY(7, ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)) +[16:48.05.678] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.05.679] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.05.679] MOBANOACL=onlyslash +[16:48.05.681] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756667") +[16:48.05.703] ShellExecuteS: ShellExecuteEx 成功. +[16:48.05.792] ShellExecuteS: WaitForInputIdle 成功. +[16:48.05.792] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756667") +[16:48.05.792] +[16:48.05.792] FindWindow(CMoTTY) +[16:48.05.792] 潜在窗口 4392998 成功通过第二次验证. +[16:48.05.792] --> 成功 +[16:48.05.794] BEGIN MoTTY.SetParent +[16:48.05.823] END MoTTY.SetParent +[16:48.05.823] NEWTAB: Application.OnMessage:=AppMessage +[16:48.05.837] NEWTAB: 更改标签页索引 C = 2 +[16:48.05.837] NEWTAB: 正在启动 DisplayCurrentTab... +[16:48.05.837] BEGIN DisplayCurrentTab +[16:48.05.837] DisplayCurrentTab: FormClick +[16:48.05.837] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:48.05.837] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.05.837] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.05.855] (SSH-Browser) END DesactiverPanel14 +[16:48.05.855] (SSH-Browser) END ActiverPanel14; +[16:48.05.957] BEGIN TFormXterm.FormResize +[16:48.05.957] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.05.958] TFormXterm.FormResize: SplitModeResize +[16:48.05.958] TFormXterm.FormResize: BtnSplitNo.Down +[16:48.05.959] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:48.05.959] BEGIN ResizeTerminal +[16:48.05.976] SetTitle(2, 192.168.127.10 (root)); +[16:48.05.987] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.06.006] END ResizeTerminal +[16:48.06.006] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.06.006] BEGIN AdaptSidebarArrows +[16:48.06.006] END AdaptSidebarArrows +[16:48.06.006] TFormXterm.FormResize: AdaptTV2; +[16:48.06.006] END TFormXterm.FormResize +[16:48.06.006] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.06.006] DisplayCurrentTab: Cts1.EndUpdates +[16:48.06.032] DisplayCurrentTab: 显示所选标签页 +[16:48.06.039] BEGIN ExecuteSessionTree +[16:48.06.039] ExecuteSessionTree: FormClick +[16:48.06.045] BEGIN ExecuteSelectedSession +[16:48.06.045] ExecuteSelectedSession: FormClick +[16:48.06.045] ExecuteSelectedSession0 +[16:48.06.045] ExecuteSelectedSession1 +[16:48.06.045] ExecuteSelectedSession2 +[16:48.06.045] ExecuteSelectedSession3 +[16:48.06.045] BEGIN ChargerLaSession +[16:48.06.046] ChargerLaSession1 +[16:48.06.059] ChargerLaSession2 +[16:48.06.059] ChargerLaSession3 +[16:48.06.059] ChargerLaSession4 +[16:48.06.059] ChargerLaSession5 +[16:48.06.059] ChargerLaSession6 +[16:48.06.059] ChargerLaSession7 +[16:48.06.060] ChargerLaSession8 +[16:48.06.060] ChargerLaSession8_ssh_1 +[16:48.06.060] ChargerLaSession8_ssh_2 +[16:48.06.060] ChargerLaSession8_ssh_3 +[16:48.06.060] ChargerLaSession8_ssh_4 +[16:48.06.060] ChargerLaSession9 +[16:48.06.084] ChargerLaSession10 +[16:48.06.084] END ChargerLaSession +[16:48.06.084] ExecuteSelectedSession4 +[16:48.06.084] LaunchSession0 +[16:48.06.087] LaunchSession1 +[16:48.06.087] LaunchSession4 +[16:48.06.087] LaunchSession5 +[16:48.06.087] +[16:48.06.087] BEGIN NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.06.088] NEWTAB: Application.ProcessMessages +[16:48.06.093] NEWTAB: Timer1_Disable +[16:48.06.093] NEWTAB: 检查是否已达到最大标签数... +[16:48.06.093] NEWTAB: 创建 SFTPRecord... +[16:48.06.097] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[16:48.06.097] NEWTAB: 尝试查找旧索引... +[16:48.06.097] NEWTAB: Cts1.BeginUpdate; +[16:48.06.097] NEWTAB: 创建新标签页... +[16:48.06.097] NEWTAB: 标签页索引: 3 +[16:48.06.097] NEWTAB: 终端编号 : 8 +[16:48.06.097] NEWTAB: 标题 : 192.168.127.10 (root) +[16:48.06.097] NEWTAB: 命令 : ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[16:48.06.097] Cts1ActiveTabChanged: New index = 3 +[16:48.06.097] NEWTAB: Cts1.EndUpdates +[16:48.06.103] NEWTAB: 更改标签页索引 A = 3 +[16:48.06.103] BEGIN WaitForAllThreads +[16:48.06.103] END WaitForAllThreads +[16:48.06.103] +[16:48.06.103] LaunchTabContent(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)); +[16:48.06.103] +[16:48.06.103] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.06.106] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.06.106] MOBANOACL=onlyslash +[16:48.06.106] +[16:48.06.106] ShellExecute: motty.exe +[16:48.06.106] +[16:48.06.106] CreerSessionMoTTY(8, ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)) +[16:48.06.121] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.06.122] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.06.123] MOBANOACL=onlyslash +[16:48.06.125] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756668") +[16:48.06.147] ShellExecuteS: ShellExecuteEx 成功. +[16:48.06.231] ShellExecuteS: WaitForInputIdle 成功. +[16:48.06.231] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756668") +[16:48.06.231] +[16:48.06.231] FindWindow(CMoTTY) +[16:48.06.231] 潜在窗口 3870280 成功通过第二次验证. +[16:48.06.231] --> 成功 +[16:48.06.234] BEGIN MoTTY.SetParent +[16:48.06.258] END MoTTY.SetParent +[16:48.06.258] NEWTAB: Application.OnMessage:=AppMessage +[16:48.06.267] NEWTAB: 更改标签页索引 C = 3 +[16:48.06.267] NEWTAB: 正在启动 DisplayCurrentTab... +[16:48.06.267] BEGIN DisplayCurrentTab +[16:48.06.267] DisplayCurrentTab: FormClick +[16:48.06.267] (SSH-Browser) DisplayCurrentTab(3): ActiverPanel14 +[16:48.06.267] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.06.267] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.06.267] (SSH-Browser) END DesactiverPanel14 +[16:48.06.267] (SSH-Browser) END ActiverPanel14; +[16:48.06.287] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.06.287] DisplayCurrentTab: Cts1.EndUpdates +[16:48.06.311] DisplayCurrentTab: 显示所选标签页 +[16:48.06.325] SetTitle(3, 192.168.127.10 (root)); +[16:48.06.330] DisplayCurrentTab: 隐藏其他标签页 +[16:48.06.339] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.06.345] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.06.345] DisplayCurrentTab: DistribuerLeFocus +[16:48.06.345] END DisplayCurrentTab +[16:48.06.345] NEWTAB: NewTab_ReEnable_Timer1 +[16:48.06.345] NEWTAB: MajVerticalTabs +[16:48.06.345] NEWTAB: Cts1.Resize; +[16:48.06.369] END NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.06.369] +[16:48.06.369] LaunchSession6 +[16:48.06.369] ExecuteSelectedSession5 +[16:48.06.369] END ExecuteSelectedSession +[16:48.06.369] END ExecuteSessionTree +[16:48.06.378] DisplayCurrentTab: 隐藏其他标签页 +[16:48.06.380] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.06.380] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.06.380] DisplayCurrentTab: DistribuerLeFocus +[16:48.06.380] END DisplayCurrentTab +[16:48.06.380] NEWTAB: NewTab_ReEnable_Timer1 +[16:48.06.380] NEWTAB: MajVerticalTabs +[16:48.06.380] NEWTAB: Cts1.Resize; +[16:48.06.403] END NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.06.403] +[16:48.06.403] LaunchSession6 +[16:48.06.403] ExecuteSelectedSession5 +[16:48.06.403] END ExecuteSelectedSession +[16:48.06.403] END ExecuteSessionTree +[16:48.06.448] BEGIN ExecuteSessionTree +[16:48.06.448] ExecuteSessionTree: FormClick +[16:48.06.455] BEGIN ExecuteSelectedSession +[16:48.06.455] ExecuteSelectedSession: FormClick +[16:48.06.455] ExecuteSelectedSession0 +[16:48.06.455] ExecuteSelectedSession1 +[16:48.06.455] ExecuteSelectedSession2 +[16:48.06.455] ExecuteSelectedSession3 +[16:48.06.455] BEGIN ChargerLaSession +[16:48.06.456] ChargerLaSession1 +[16:48.06.467] ChargerLaSession2 +[16:48.06.467] ChargerLaSession3 +[16:48.06.467] ChargerLaSession4 +[16:48.06.467] ChargerLaSession5 +[16:48.06.467] ChargerLaSession6 +[16:48.06.467] ChargerLaSession7 +[16:48.06.468] ChargerLaSession8 +[16:48.06.468] ChargerLaSession8_ssh_1 +[16:48.06.468] ChargerLaSession8_ssh_2 +[16:48.06.468] ChargerLaSession8_ssh_3 +[16:48.06.468] ChargerLaSession8_ssh_4 +[16:48.06.468] ChargerLaSession9 +[16:48.06.491] ChargerLaSession10 +[16:48.06.491] END ChargerLaSession +[16:48.06.491] ExecuteSelectedSession4 +[16:48.06.491] LaunchSession0 +[16:48.06.494] LaunchSession1 +[16:48.06.494] LaunchSession4 +[16:48.06.494] LaunchSession5 +[16:48.06.494] +[16:48.06.494] BEGIN NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.06.494] NEWTAB: Application.ProcessMessages +[16:48.06.494] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:48.06.494] 主机密钥与缓存中的密钥是一致的 +[16:48.06.494] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:48.06.494] 主机密钥与缓存中的密钥是一致的 +[16:48.06.495] BEGIN WMNewTab: 20 +[16:48.06.495] END WMNewTab: 20 +[16:48.06.501] NEWTAB: Timer1_Disable +[16:48.06.501] NEWTAB: 检查是否已达到最大标签数... +[16:48.06.501] NEWTAB: 创建 SFTPRecord... +[16:48.06.506] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[16:48.06.506] NEWTAB: 尝试查找旧索引... +[16:48.06.506] NEWTAB: Cts1.BeginUpdate; +[16:48.06.506] NEWTAB: 创建新标签页... +[16:48.06.506] NEWTAB: 标签页索引: 4 +[16:48.06.506] NEWTAB: 终端编号 : 9 +[16:48.06.506] NEWTAB: 标题 : 192.168.127.10 (root) +[16:48.06.506] NEWTAB: 命令 : ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[16:48.06.506] Cts1ActiveTabChanged: New index = 4 +[16:48.06.506] NEWTAB: Cts1.EndUpdates +[16:48.06.513] NEWTAB: 更改标签页索引 A = 4 +[16:48.06.513] BEGIN WaitForAllThreads +[16:48.06.513] END WaitForAllThreads +[16:48.06.513] +[16:48.06.513] LaunchTabContent(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)); +[16:48.06.513] +[16:48.06.513] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.06.514] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.06.514] MOBANOACL=onlyslash +[16:48.06.515] +[16:48.06.515] ShellExecute: motty.exe +[16:48.06.515] +[16:48.06.515] CreerSessionMoTTY(9, ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)) +[16:48.06.530] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.06.531] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.06.531] MOBANOACL=onlyslash +[16:48.06.534] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756669") +[16:48.06.535] BEGIN GetPassword +[16:48.06.535] BEGIN GetnSaveCredPassword +[16:48.06.535] END GetnSaveCredPassword +[16:48.06.535] END GetPassword +[16:48.06.535] BEGIN GetPassword +[16:48.06.535] BEGIN GetnSaveCredPassword +[16:48.06.535] END GetnSaveCredPassword +[16:48.06.535] END GetPassword +[16:48.06.555] ShellExecuteS: ShellExecuteEx 成功. +[16:48.06.636] ShellExecuteS: WaitForInputIdle 成功. +[16:48.06.636] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM131756669") +[16:48.06.636] +[16:48.06.636] FindWindow(CMoTTY) +[16:48.06.636] 潜在窗口 2232464 成功通过第二次验证. +[16:48.06.636] --> 成功 +[16:48.06.638] BEGIN MoTTY.SetParent +[16:48.06.664] END MoTTY.SetParent +[16:48.06.664] NEWTAB: Application.OnMessage:=AppMessage +[16:48.06.673] NEWTAB: 更改标签页索引 C = 4 +[16:48.06.673] NEWTAB: 正在启动 DisplayCurrentTab... +[16:48.06.673] BEGIN DisplayCurrentTab +[16:48.06.673] DisplayCurrentTab: FormClick +[16:48.06.673] (SSH-Browser) DisplayCurrentTab(4): ActiverPanel14 +[16:48.06.673] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.06.673] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.06.673] (SSH-Browser) END DesactiverPanel14 +[16:48.06.673] (SSH-Browser) END ActiverPanel14; +[16:48.06.691] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.06.691] DisplayCurrentTab: Cts1.EndUpdates +[16:48.06.724] DisplayCurrentTab: 显示所选标签页 +[16:48.06.737] SetTitle(4, 192.168.127.10 (root)); +[16:48.06.744] DisplayCurrentTab: 隐藏其他标签页 +[16:48.06.747] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.06.751] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.06.751] DisplayCurrentTab: DistribuerLeFocus +[16:48.06.751] END DisplayCurrentTab +[16:48.06.752] NEWTAB: NewTab_ReEnable_Timer1 +[16:48.06.752] NEWTAB: MajVerticalTabs +[16:48.06.752] NEWTAB: Cts1.Resize; +[16:48.06.782] END NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.06.782] +[16:48.06.782] LaunchSession6 +[16:48.06.782] ExecuteSelectedSession5 +[16:48.06.782] END ExecuteSelectedSession +[16:48.06.782] END ExecuteSessionTree +[16:48.06.850] BEGIN ExecuteSessionTree +[16:48.06.850] ExecuteSessionTree: FormClick +[16:48.06.855] BEGIN ExecuteSelectedSession +[16:48.06.855] ExecuteSelectedSession: FormClick +[16:48.06.855] ExecuteSelectedSession0 +[16:48.06.855] ExecuteSelectedSession1 +[16:48.06.855] ExecuteSelectedSession2 +[16:48.06.855] ExecuteSelectedSession3 +[16:48.06.855] BEGIN ChargerLaSession +[16:48.06.856] ChargerLaSession1 +[16:48.06.866] ChargerLaSession2 +[16:48.06.866] ChargerLaSession3 +[16:48.06.866] ChargerLaSession4 +[16:48.06.867] ChargerLaSession5 +[16:48.06.867] ChargerLaSession6 +[16:48.06.867] ChargerLaSession7 +[16:48.06.867] ChargerLaSession8 +[16:48.06.867] ChargerLaSession8_ssh_1 +[16:48.06.867] ChargerLaSession8_ssh_2 +[16:48.06.867] ChargerLaSession8_ssh_3 +[16:48.06.867] ChargerLaSession8_ssh_4 +[16:48.06.867] ChargerLaSession9 +[16:48.06.889] ChargerLaSession10 +[16:48.06.889] END ChargerLaSession +[16:48.06.889] ExecuteSelectedSession4 +[16:48.06.889] LaunchSession0 +[16:48.06.892] LaunchSession1 +[16:48.06.892] LaunchSession4 +[16:48.06.892] LaunchSession5 +[16:48.06.892] +[16:48.06.892] BEGIN NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.06.892] NEWTAB: Application.ProcessMessages +[16:48.06.892] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:48.06.892] 主机密钥与缓存中的密钥是一致的 +[16:48.06.899] NEWTAB: Timer1_Disable +[16:48.06.899] NEWTAB: 检查是否已达到最大标签数... +[16:48.06.899] NEWTAB: 创建 SFTPRecord... +[16:48.06.904] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[16:48.06.909] NEWTAB: 尝试查找旧索引... +[16:48.06.909] NEWTAB: Cts1.BeginUpdate; +[16:48.06.909] NEWTAB: 创建新标签页... +[16:48.06.909] NEWTAB: 标签页索引: 5 +[16:48.06.909] NEWTAB: 终端编号 : 10 +[16:48.06.909] NEWTAB: 标题 : 192.168.127.10 (root) +[16:48.06.909] NEWTAB: 命令 : ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[16:48.06.909] Cts1ActiveTabChanged: New index = 5 +[16:48.06.909] NEWTAB: Cts1.EndUpdates +[16:48.06.914] NEWTAB: 更改标签页索引 A = 5 +[16:48.06.914] BEGIN WaitForAllThreads +[16:48.06.914] END WaitForAllThreads +[16:48.06.914] +[16:48.06.914] LaunchTabContent(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)); +[16:48.06.914] +[16:48.06.914] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.06.916] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.06.916] MOBANOACL=onlyslash +[16:48.06.916] +[16:48.06.916] ShellExecute: motty.exe +[16:48.06.916] +[16:48.06.916] CreerSessionMoTTY(10, ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)) +[16:48.06.931] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.06.932] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.06.932] MOBANOACL=onlyslash +[16:48.06.936] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM1317566610") +[16:48.06.936] BEGIN GetPassword +[16:48.06.936] BEGIN GetnSaveCredPassword +[16:48.06.936] END GetnSaveCredPassword +[16:48.06.936] END GetPassword +[16:48.06.953] ShellExecuteS: ShellExecuteEx 成功. +[16:48.07.036] ShellExecuteS: WaitForInputIdle 成功. +[16:48.07.036] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM1317566610") +[16:48.07.036] +[16:48.07.036] FindWindow(CMoTTY) +[16:48.07.036] 潜在窗口 6229214 成功通过第二次验证. +[16:48.07.036] --> 成功 +[16:48.07.038] BEGIN MoTTY.SetParent +[16:48.07.064] END MoTTY.SetParent +[16:48.07.064] NEWTAB: Application.OnMessage:=AppMessage +[16:48.07.073] NEWTAB: 更改标签页索引 C = 5 +[16:48.07.073] NEWTAB: 正在启动 DisplayCurrentTab... +[16:48.07.073] BEGIN DisplayCurrentTab +[16:48.07.073] DisplayCurrentTab: FormClick +[16:48.07.073] (SSH-Browser) DisplayCurrentTab(5): ActiverPanel14 +[16:48.07.073] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.07.073] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.07.073] (SSH-Browser) END DesactiverPanel14 +[16:48.07.073] (SSH-Browser) END ActiverPanel14; +[16:48.07.091] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.07.092] DisplayCurrentTab: Cts1.EndUpdates +[16:48.07.135] DisplayCurrentTab: 显示所选标签页 +[16:48.07.141] SetTitle(5, 192.168.127.10 (root)); +[16:48.07.148] DisplayCurrentTab: 隐藏其他标签页 +[16:48.07.150] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.07.150] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.07.150] DisplayCurrentTab: DistribuerLeFocus +[16:48.07.150] END DisplayCurrentTab +[16:48.07.150] NEWTAB: NewTab_ReEnable_Timer1 +[16:48.07.150] NEWTAB: MajVerticalTabs +[16:48.07.150] NEWTAB: Cts1.Resize; +[16:48.07.191] END NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.07.191] +[16:48.07.191] LaunchSession6 +[16:48.07.191] ExecuteSelectedSession5 +[16:48.07.191] END ExecuteSelectedSession +[16:48.07.191] END ExecuteSessionTree +[16:48.07.270] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:48.07.271] 主机密钥与缓存中的密钥是一致的 +[16:48.07.283] BEGIN GetPassword +[16:48.07.283] BEGIN GetnSaveCredPassword +[16:48.07.283] END GetnSaveCredPassword +[16:48.07.283] END GetPassword +[16:48.07.440] BEGIN ExecuteSessionTree +[16:48.07.440] ExecuteSessionTree: FormClick +[16:48.07.446] BEGIN ExecuteSelectedSession +[16:48.07.446] ExecuteSelectedSession: FormClick +[16:48.07.446] ExecuteSelectedSession0 +[16:48.07.446] ExecuteSelectedSession1 +[16:48.07.446] ExecuteSelectedSession2 +[16:48.07.447] ExecuteSelectedSession3 +[16:48.07.447] BEGIN ChargerLaSession +[16:48.07.448] ChargerLaSession1 +[16:48.07.459] ChargerLaSession2 +[16:48.07.459] ChargerLaSession3 +[16:48.07.459] ChargerLaSession4 +[16:48.07.459] ChargerLaSession5 +[16:48.07.459] ChargerLaSession6 +[16:48.07.459] ChargerLaSession7 +[16:48.07.460] ChargerLaSession8 +[16:48.07.460] ChargerLaSession8_ssh_1 +[16:48.07.460] ChargerLaSession8_ssh_2 +[16:48.07.460] ChargerLaSession8_ssh_3 +[16:48.07.461] ChargerLaSession8_ssh_4 +[16:48.07.461] ChargerLaSession9 +[16:48.07.485] ChargerLaSession10 +[16:48.07.485] END ChargerLaSession +[16:48.07.485] ExecuteSelectedSession4 +[16:48.07.485] LaunchSession0 +[16:48.07.490] LaunchSession1 +[16:48.07.490] LaunchSession4 +[16:48.07.490] LaunchSession5 +[16:48.07.491] +[16:48.07.491] BEGIN NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.07.491] NEWTAB: Application.ProcessMessages +[16:48.07.496] NEWTAB: Timer1_Disable +[16:48.07.496] NEWTAB: 检查是否已达到最大标签数... +[16:48.07.496] NEWTAB: 创建 SFTPRecord... +[16:48.07.505] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[16:48.07.505] NEWTAB: 尝试查找旧索引... +[16:48.07.505] NEWTAB: Cts1.BeginUpdate; +[16:48.07.505] NEWTAB: 创建新标签页... +[16:48.07.505] NEWTAB: 标签页索引: 6 +[16:48.07.505] NEWTAB: 终端编号 : 11 +[16:48.07.505] NEWTAB: 标题 : 192.168.127.10 (root) +[16:48.07.506] NEWTAB: 命令 : ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[16:48.07.506] Cts1ActiveTabChanged: New index = 6 +[16:48.07.506] NEWTAB: Cts1.EndUpdates +[16:48.07.512] NEWTAB: 更改标签页索引 A = 6 +[16:48.07.512] BEGIN WaitForAllThreads +[16:48.07.512] END WaitForAllThreads +[16:48.07.512] +[16:48.07.512] LaunchTabContent(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)); +[16:48.07.512] +[16:48.07.512] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.07.513] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.07.513] MOBANOACL=onlyslash +[16:48.07.513] +[16:48.07.513] ShellExecute: motty.exe +[16:48.07.513] +[16:48.07.513] CreerSessionMoTTY(11, ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)) +[16:48.07.525] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.07.526] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.07.526] MOBANOACL=onlyslash +[16:48.07.533] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM1317566611") +[16:48.07.553] ShellExecuteS: ShellExecuteEx 成功. +[16:48.07.594] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.07.647] ShellExecuteS: WaitForInputIdle 成功. +[16:48.07.647] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM1317566611") +[16:48.07.647] +[16:48.07.647] FindWindow(CMoTTY) +[16:48.07.647] 潜在窗口 3281096 成功通过第二次验证. +[16:48.07.647] --> 成功 +[16:48.07.649] BEGIN MoTTY.SetParent +[16:48.07.675] END MoTTY.SetParent +[16:48.07.675] NEWTAB: Application.OnMessage:=AppMessage +[16:48.07.683] NEWTAB: 更改标签页索引 C = 6 +[16:48.07.683] NEWTAB: 正在启动 DisplayCurrentTab... +[16:48.07.683] BEGIN DisplayCurrentTab +[16:48.07.683] DisplayCurrentTab: FormClick +[16:48.07.683] (SSH-Browser) DisplayCurrentTab(6): ActiverPanel14 +[16:48.07.683] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.07.683] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.07.683] (SSH-Browser) END DesactiverPanel14 +[16:48.07.683] (SSH-Browser) END ActiverPanel14; +[16:48.07.702] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.07.702] DisplayCurrentTab: Cts1.EndUpdates +[16:48.07.752] DisplayCurrentTab: 显示所选标签页 +[16:48.07.759] SetTitle(6, 192.168.127.10 (root)); +[16:48.07.766] DisplayCurrentTab: 隐藏其他标签页 +[16:48.07.768] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.07.769] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.07.769] DisplayCurrentTab: DistribuerLeFocus +[16:48.07.769] END DisplayCurrentTab +[16:48.07.769] NEWTAB: NewTab_ReEnable_Timer1 +[16:48.07.769] NEWTAB: MajVerticalTabs +[16:48.07.769] NEWTAB: Cts1.Resize; +[16:48.07.816] END NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.07.816] +[16:48.07.816] LaunchSession6 +[16:48.07.816] ExecuteSelectedSession5 +[16:48.07.816] END ExecuteSelectedSession +[16:48.07.816] END ExecuteSessionTree +[16:48.07.891] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:48.07.891] 主机密钥与缓存中的密钥是一致的 +[16:48.07.904] BEGIN GetPassword +[16:48.07.904] BEGIN GetnSaveCredPassword +[16:48.07.904] END GetnSaveCredPassword +[16:48.07.904] END GetPassword +[16:48.07.913] BEGIN WMNewTab: 20 +[16:48.07.913] END WMNewTab: 20 + + +[16:48.09.193] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.09.330] BEGIN WMNewTab: 20 +[16:48.09.330] END WMNewTab: 20 + + +[16:48.10.746] BEGIN WMNewTab: 20 +[16:48.10.746] END WMNewTab: 20 +[16:48.10.807] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.11.056] BEGIN ExecuteSessionTree +[16:48.11.056] ExecuteSessionTree: FormClick +[16:48.11.062] BEGIN ExecuteSelectedSession +[16:48.11.062] ExecuteSelectedSession: FormClick +[16:48.11.062] ExecuteSelectedSession0 +[16:48.11.062] ExecuteSelectedSession1 +[16:48.11.062] ExecuteSelectedSession2 +[16:48.11.062] ExecuteSelectedSession3 +[16:48.11.062] BEGIN ChargerLaSession +[16:48.11.063] ChargerLaSession1 +[16:48.11.075] ChargerLaSession2 +[16:48.11.075] ChargerLaSession3 +[16:48.11.075] ChargerLaSession4 +[16:48.11.075] ChargerLaSession5 +[16:48.11.076] ChargerLaSession6 +[16:48.11.076] ChargerLaSession7 +[16:48.11.076] ChargerLaSession8 +[16:48.11.076] ChargerLaSession8_ssh_1 +[16:48.11.076] ChargerLaSession8_ssh_2 +[16:48.11.076] ChargerLaSession8_ssh_3 +[16:48.11.076] ChargerLaSession8_ssh_4 +[16:48.11.076] ChargerLaSession9 +[16:48.11.100] ChargerLaSession10 +[16:48.11.100] END ChargerLaSession +[16:48.11.100] ExecuteSelectedSession4 +[16:48.11.100] LaunchSession0 +[16:48.11.104] LaunchSession1 +[16:48.11.104] LaunchSession4 +[16:48.11.104] LaunchSession5 +[16:48.11.104] +[16:48.11.104] BEGIN NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.11.104] NEWTAB: Application.ProcessMessages +[16:48.11.108] NEWTAB: Timer1_Disable +[16:48.11.108] NEWTAB: 检查是否已达到最大标签数... +[16:48.11.108] NEWTAB: 创建 SFTPRecord... +[16:48.11.113] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[16:48.11.113] NEWTAB: 尝试查找旧索引... +[16:48.11.113] NEWTAB: Cts1.BeginUpdate; +[16:48.11.113] NEWTAB: 创建新标签页... +[16:48.11.113] NEWTAB: 标签页索引: 7 +[16:48.11.113] NEWTAB: 终端编号 : 12 +[16:48.11.113] NEWTAB: 标题 : 192.168.127.10 (root) +[16:48.11.113] NEWTAB: 命令 : ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[16:48.11.113] Cts1ActiveTabChanged: New index = 7 +[16:48.11.113] NEWTAB: Cts1.EndUpdates +[16:48.11.120] NEWTAB: 更改标签页索引 A = 7 +[16:48.11.120] BEGIN WaitForAllThreads +[16:48.11.120] END WaitForAllThreads +[16:48.11.120] +[16:48.11.120] LaunchTabContent(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)); +[16:48.11.120] +[16:48.11.120] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.11.122] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.11.122] MOBANOACL=onlyslash +[16:48.11.122] +[16:48.11.122] ShellExecute: motty.exe +[16:48.11.122] +[16:48.11.122] CreerSessionMoTTY(12, ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)) +[16:48.11.138] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.11.139] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.11.139] MOBANOACL=onlyslash +[16:48.11.143] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM1317566612") +[16:48.11.164] ShellExecuteS: ShellExecuteEx 成功. +[16:48.11.258] ShellExecuteS: WaitForInputIdle 成功. +[16:48.11.258] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM1317566612") +[16:48.11.258] +[16:48.11.258] FindWindow(CMoTTY) +[16:48.11.258] 潜在窗口 1114408 成功通过第二次验证. +[16:48.11.258] --> 成功 +[16:48.11.260] BEGIN MoTTY.SetParent +[16:48.11.288] END MoTTY.SetParent +[16:48.11.289] NEWTAB: Application.OnMessage:=AppMessage +[16:48.11.304] NEWTAB: 更改标签页索引 C = 7 +[16:48.11.304] NEWTAB: 正在启动 DisplayCurrentTab... +[16:48.11.304] BEGIN DisplayCurrentTab +[16:48.11.304] DisplayCurrentTab: FormClick +[16:48.11.304] (SSH-Browser) DisplayCurrentTab(7): ActiverPanel14 +[16:48.11.304] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.11.304] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.11.304] (SSH-Browser) END DesactiverPanel14 +[16:48.11.304] (SSH-Browser) END ActiverPanel14; +[16:48.11.331] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.11.331] DisplayCurrentTab: Cts1.EndUpdates +[16:48.11.399] DisplayCurrentTab: 显示所选标签页 +[16:48.11.407] SetTitle(7, 192.168.127.10 (root)); +[16:48.11.414] DisplayCurrentTab: 隐藏其他标签页 +[16:48.11.417] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.11.417] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.11.417] DisplayCurrentTab: DistribuerLeFocus +[16:48.11.417] END DisplayCurrentTab +[16:48.11.417] NEWTAB: NewTab_ReEnable_Timer1 +[16:48.11.417] NEWTAB: MajVerticalTabs +[16:48.11.417] NEWTAB: Cts1.Resize; +[16:48.11.487] END NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.11.487] +[16:48.11.487] LaunchSession6 +[16:48.11.487] ExecuteSelectedSession5 +[16:48.11.487] END ExecuteSelectedSession +[16:48.11.487] END ExecuteSessionTree +[16:48.11.577] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:48.11.577] 主机密钥与缓存中的密钥是一致的 +[16:48.11.587] BEGIN GetPassword +[16:48.11.587] BEGIN GetnSaveCredPassword +[16:48.11.587] END GetnSaveCredPassword +[16:48.11.587] END GetPassword +[16:48.11.713] BEGIN ExecuteSessionTree +[16:48.11.713] ExecuteSessionTree: FormClick +[16:48.11.718] BEGIN ExecuteSelectedSession +[16:48.11.718] ExecuteSelectedSession: FormClick +[16:48.11.718] ExecuteSelectedSession0 +[16:48.11.718] ExecuteSelectedSession1 +[16:48.11.718] ExecuteSelectedSession2 +[16:48.11.719] ExecuteSelectedSession3 +[16:48.11.719] BEGIN ChargerLaSession +[16:48.11.719] ChargerLaSession1 +[16:48.11.731] ChargerLaSession2 +[16:48.11.731] ChargerLaSession3 +[16:48.11.731] ChargerLaSession4 +[16:48.11.731] ChargerLaSession5 +[16:48.11.731] ChargerLaSession6 +[16:48.11.731] ChargerLaSession7 +[16:48.11.732] ChargerLaSession8 +[16:48.11.732] ChargerLaSession8_ssh_1 +[16:48.11.732] ChargerLaSession8_ssh_2 +[16:48.11.732] ChargerLaSession8_ssh_3 +[16:48.11.732] ChargerLaSession8_ssh_4 +[16:48.11.732] ChargerLaSession9 +[16:48.11.756] ChargerLaSession10 +[16:48.11.756] END ChargerLaSession +[16:48.11.756] ExecuteSelectedSession4 +[16:48.11.756] LaunchSession0 +[16:48.11.760] LaunchSession1 +[16:48.11.760] LaunchSession4 +[16:48.11.760] LaunchSession5 +[16:48.11.760] +[16:48.11.760] BEGIN NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.11.760] NEWTAB: Application.ProcessMessages +[16:48.11.763] NEWTAB: Timer1_Disable +[16:48.11.763] NEWTAB: 检查是否已达到最大标签数... +[16:48.11.763] NEWTAB: 创建 SFTPRecord... +[16:48.11.767] NEWTAB: 为新标签页创建菜单项和弹出菜单条目... +[16:48.11.767] NEWTAB: 尝试查找旧索引... +[16:48.11.767] NEWTAB: Cts1.BeginUpdate; +[16:48.11.767] NEWTAB: 创建新标签页... +[16:48.11.767] NEWTAB: 标签页索引: 8 +[16:48.11.767] NEWTAB: 终端编号 : 13 +[16:48.11.767] NEWTAB: 标题 : 192.168.127.10 (root) +[16:48.11.767] NEWTAB: 命令 : ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j +[16:48.11.767] Cts1ActiveTabChanged: New index = 8 +[16:48.11.767] NEWTAB: Cts1.EndUpdates +[16:48.11.781] NEWTAB: 更改标签页索引 A = 8 +[16:48.11.781] BEGIN WaitForAllThreads +[16:48.11.781] END WaitForAllThreads +[16:48.11.781] +[16:48.11.781] LaunchTabContent(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)); +[16:48.11.781] +[16:48.11.781] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.11.782] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.11.783] MOBANOACL=onlyslash +[16:48.11.783] +[16:48.11.783] ShellExecute: motty.exe +[16:48.11.783] +[16:48.11.783] CreerSessionMoTTY(13, ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 192.168.127.10 (root)) +[16:48.11.793] SetEnvironmentVariable(LOCALE, zh_CN.UTF-8) +[16:48.11.795] SetEnvironmentVariable(PATH, C:\Users\31554\AppData\Local\Temp\Mxt252\bin;C:\WINDOWS\;C:\WINDOWS\system32\;D:\VMware\bin\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Git\cmd;C:\Program Files\dotnet\;D:\cursor\resources\app\bin;D:\anaconda;D:\anaconda\Library\usr\bin;D:\anaconda\Library\bin;D:\anaconda\Scripts;C:\Users\31554\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\31554\AppData\Local\Programs\Python\Python38\;C:\Users\31554\AppData\Local\Microsoft\WindowsApps;C:\Users\31554\AppData\Local\Programs\Microsoft VS Code\bin;C:\WINDOWS\sysnative\) +[16:48.11.795] MOBANOACL=onlyslash +[16:48.11.797] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM1317566613") +[16:48.11.819] ShellExecuteS: ShellExecuteEx 成功. +[16:48.11.914] ShellExecuteS: WaitForInputIdle 成功. +[16:48.11.914] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\motty.exe, -load "TERM1317566613") +[16:48.11.914] +[16:48.11.914] FindWindow(CMoTTY) +[16:48.11.914] 潜在窗口 3147838 成功通过第二次验证. +[16:48.11.914] --> 成功 +[16:48.11.916] BEGIN MoTTY.SetParent +[16:48.11.950] END MoTTY.SetParent +[16:48.11.950] NEWTAB: Application.OnMessage:=AppMessage +[16:48.11.963] NEWTAB: 更改标签页索引 C = 8 +[16:48.11.963] NEWTAB: 正在启动 DisplayCurrentTab... +[16:48.11.963] BEGIN DisplayCurrentTab +[16:48.11.963] DisplayCurrentTab: FormClick +[16:48.11.963] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.11.963] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.11.963] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.11.963] (SSH-Browser) END DesactiverPanel14 +[16:48.11.963] (SSH-Browser) END ActiverPanel14; +[16:48.11.992] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.11.992] DisplayCurrentTab: Cts1.EndUpdates +[16:48.12.073] DisplayCurrentTab: 显示所选标签页 +[16:48.12.082] SetTitle(8, 192.168.127.10 (root)); +[16:48.12.090] DisplayCurrentTab: 隐藏其他标签页 +[16:48.12.093] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.12.093] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.12.093] DisplayCurrentTab: DistribuerLeFocus +[16:48.12.093] END DisplayCurrentTab +[16:48.12.093] NEWTAB: NewTab_ReEnable_Timer1 +[16:48.12.093] NEWTAB: MajVerticalTabs +[16:48.12.093] NEWTAB: Cts1.Resize; +[16:48.12.181] END NEWTAB(ssh "192.168.127.10" -l "root" -p 22 -Y -o ForwardX11Trusted=yes -o ForwardX11=yes -C -o Compression=yes -Z -j , 109, 0) +[16:48.12.181] +[16:48.12.181] LaunchSession6 +[16:48.12.181] ExecuteSelectedSession5 +[16:48.12.181] END ExecuteSelectedSession +[16:48.12.181] END ExecuteSessionTree +[16:48.12.181] BEGIN WMNewTab: 20 +[16:48.12.181] END WMNewTab: 20 +[16:48.12.258] 收到主机密钥验证请求: ssh-ed25519@22:192.168.127.10 +[16:48.12.258] 主机密钥与缓存中的密钥是一致的 +[16:48.12.269] BEGIN GetPassword +[16:48.12.269] BEGIN GetnSaveCredPassword +[16:48.12.269] END GetnSaveCredPassword +[16:48.12.269] END GetPassword +[16:48.12.407] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.13.124] Multiterminalcommand1Click: FormClick +[16:48.13.125] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.13.125] (SSH-Browser) END DesactiverPanel14 +[16:48.13.210] BEGIN TFormXterm.FormResize +[16:48.13.210] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.13.210] TFormXterm.FormResize: SplitModeResize +[16:48.13.210] BEGIN ResizeTerminal +[16:48.13.210] END ResizeTerminal +[16:48.13.210] BEGIN ResizeTerminal +[16:48.13.223] END ResizeTerminal +[16:48.13.223] BEGIN ResizeTerminal +[16:48.13.237] END ResizeTerminal +[16:48.13.237] BEGIN ResizeTerminal +[16:48.13.242] END ResizeTerminal +[16:48.13.243] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.13.243] BEGIN AdaptSidebarArrows +[16:48.13.243] END AdaptSidebarArrows +[16:48.13.243] TFormXterm.FormResize: AdaptTV2; +[16:48.13.243] END TFormXterm.FormResize +[16:48.13.243] BEGIN WMSize +[16:48.13.243] BEGIN TFormXterm.FormResize +[16:48.13.243] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.13.243] TFormXterm.FormResize: SplitModeResize +[16:48.13.243] BEGIN ResizeTerminal +[16:48.13.243] END ResizeTerminal +[16:48.13.243] BEGIN ResizeTerminal +[16:48.13.243] END ResizeTerminal +[16:48.13.243] BEGIN ResizeTerminal +[16:48.13.243] END ResizeTerminal +[16:48.13.243] BEGIN ResizeTerminal +[16:48.13.244] END ResizeTerminal +[16:48.13.244] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.13.244] BEGIN AdaptSidebarArrows +[16:48.13.244] END AdaptSidebarArrows +[16:48.13.244] TFormXterm.FormResize: AdaptTV2; +[16:48.13.244] END TFormXterm.FormResize +[16:48.13.244] END WMSize +[16:48.13.599] BEGIN WMNewTab: 20 +[16:48.13.599] END WMNewTab: 20 +[16:48.13.660] BEGIN DisplayCurrentTab +[16:48.13.660] DisplayCurrentTab: FormClick +[16:48.13.660] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.13.660] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.13.660] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.13.660] (SSH-Browser) END DesactiverPanel14 +[16:48.13.660] (SSH-Browser) END ActiverPanel14; +[16:48.13.686] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.13.687] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.13.687] DisplayCurrentTab: DistribuerLeFocus +[16:48.13.687] END DisplayCurrentTab +[16:48.13.704] ReEnable_Timer1_12 +[16:48.14.013] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.15.019] BEGIN WMNewTab: 20 +[16:48.15.019] END WMNewTab: 20 + +[16:48.15.631] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.16.003] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:48.16.003] BEGIN SauvegarderMotDePasseSSH +[16:48.16.003] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:48.16.003] SetTitle(4, root@192.168.127.10); +[16:48.16.003] +[16:48.16.003] (SSH-Browser) BEGIN ConnectSSH(4,192.168.127.10,root,) +[16:48.16.003] (SSH-Browser) ConnectSSH(4): 初始化 TabSFTP +[16:48.16.004] (SSH-Browser) ConnectSSH(4): 未使用代理 +[16:48.16.004] (SSH-Browser) ConnectSSH(4): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:48.16.006] (SSH-Browser) ConnectSSH(4): 已成功连接到 192.168.127.10. +[16:48.16.006] (SSH-Browser) ConnectSSH(4): SSH.Open +[16:48.16.006] (SSH-Browser) END ConnectSSH(4) +[16:48.16.006] BEGIN DisplayCurrentTab +[16:48.16.006] DisplayCurrentTab: FormClick +[16:48.16.006] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.16.006] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.16.006] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.16.006] (SSH-Browser) END DesactiverPanel14 +[16:48.16.006] (SSH-Browser) END ActiverPanel14; +[16:48.16.031] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.16.031] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.16.031] DisplayCurrentTab: DistribuerLeFocus +[16:48.16.031] END DisplayCurrentTab +[16:48.16.031] BEGIN SavePassword +[16:48.16.031] END SavePassword +[16:48.16.031] END SauvegarderMotDePasseSSH +[16:48.16.032] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:48.16.032] BEGIN SauvegarderMotDePasseSSH +[16:48.16.032] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:48.16.032] SetTitle(5, root@192.168.127.10); +[16:48.16.032] +[16:48.16.032] (SSH-Browser) BEGIN ConnectSSH(5,192.168.127.10,root,) +[16:48.16.032] (SSH-Browser) ConnectSSH(5): 初始化 TabSFTP +[16:48.16.032] (SSH-Browser) ConnectSSH(5): 未使用代理 +[16:48.16.033] (SSH-Browser) ConnectSSH(5): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:48.16.034] (SSH-Browser) ConnectSSH(5): 已成功连接到 192.168.127.10. +[16:48.16.034] (SSH-Browser) ConnectSSH(5): SSH.Open +[16:48.16.034] (SSH-Browser) END ConnectSSH(5) +[16:48.16.034] BEGIN DisplayCurrentTab +[16:48.16.034] DisplayCurrentTab: FormClick +[16:48.16.034] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.16.034] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.16.034] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.16.034] (SSH-Browser) END DesactiverPanel14 +[16:48.16.034] (SSH-Browser) END ActiverPanel14; +[16:48.16.056] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.16.056] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.16.056] DisplayCurrentTab: DistribuerLeFocus +[16:48.16.056] END DisplayCurrentTab +[16:48.16.057] BEGIN SavePassword +[16:48.16.057] END SavePassword +[16:48.16.057] END SauvegarderMotDePasseSSH +[16:48.16.057] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:48.16.057] BEGIN SauvegarderMotDePasseSSH +[16:48.16.057] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:48.16.057] SetTitle(6, root@192.168.127.10); +[16:48.16.057] +[16:48.16.057] (SSH-Browser) BEGIN ConnectSSH(6,192.168.127.10,root,) +[16:48.16.057] (SSH-Browser) ConnectSSH(6): 初始化 TabSFTP +[16:48.16.059] (SSH-Browser) ConnectSSH(6): 未使用代理 +[16:48.16.059] (SSH-Browser) ConnectSSH(6): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:48.16.061] (SSH-Browser) ConnectSSH(6): 已成功连接到 192.168.127.10. +[16:48.16.061] (SSH-Browser) ConnectSSH(6): SSH.Open +[16:48.16.061] (SSH-Browser) END ConnectSSH(6) +[16:48.16.061] BEGIN DisplayCurrentTab +[16:48.16.061] DisplayCurrentTab: FormClick +[16:48.16.061] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.16.061] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.16.061] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.16.061] (SSH-Browser) END DesactiverPanel14 +[16:48.16.061] (SSH-Browser) END ActiverPanel14; +[16:48.16.083] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.16.084] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.16.084] DisplayCurrentTab: DistribuerLeFocus +[16:48.16.084] END DisplayCurrentTab +[16:48.16.084] BEGIN SavePassword +[16:48.16.084] END SavePassword +[16:48.16.084] END SauvegarderMotDePasseSSH +[16:48.16.084] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:48.16.084] BEGIN SauvegarderMotDePasseSSH +[16:48.16.084] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:48.16.084] SetTitle(8, root@192.168.127.10); +[16:48.16.084] +[16:48.16.084] (SSH-Browser) BEGIN ConnectSSH(8,192.168.127.10,root,) +[16:48.16.084] (SSH-Browser) ConnectSSH(8): 初始化 TabSFTP +[16:48.16.085] (SSH-Browser) ConnectSSH(8): 未使用代理 +[16:48.16.085] (SSH-Browser) ConnectSSH(8): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:48.16.086] (SSH-Browser) ConnectSSH(8): 已成功连接到 192.168.127.10. +[16:48.16.086] (SSH-Browser) ConnectSSH(8): SSH.Open +[16:48.16.086] (SSH-Browser) END ConnectSSH(8) +[16:48.16.086] BEGIN DisplayCurrentTab +[16:48.16.086] DisplayCurrentTab: FormClick +[16:48.16.086] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.16.086] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.16.086] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.16.086] (SSH-Browser) END DesactiverPanel14 +[16:48.16.086] (SSH-Browser) END ActiverPanel14; +[16:48.16.112] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.16.112] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.16.112] DisplayCurrentTab: DistribuerLeFocus +[16:48.16.112] END DisplayCurrentTab +[16:48.16.112] BEGIN SavePassword +[16:48.16.112] END SavePassword +[16:48.16.112] END SauvegarderMotDePasseSSH +[16:48.16.112] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:48.16.112] BEGIN SauvegarderMotDePasseSSH +[16:48.16.112] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:48.16.112] SetTitle(2, root@192.168.127.10); +[16:48.16.112] +[16:48.16.112] (SSH-Browser) BEGIN ConnectSSH(2,192.168.127.10,root,) +[16:48.16.112] (SSH-Browser) ConnectSSH(2): 初始化 TabSFTP +[16:48.16.113] (SSH-Browser) ConnectSSH(2): 未使用代理 +[16:48.16.113] (SSH-Browser) ConnectSSH(2): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:48.16.115] (SSH-Browser) ConnectSSH(2): 已成功连接到 192.168.127.10. +[16:48.16.115] (SSH-Browser) ConnectSSH(2): SSH.Open +[16:48.16.115] (SSH-Browser) END ConnectSSH(2) +[16:48.16.115] BEGIN DisplayCurrentTab +[16:48.16.115] DisplayCurrentTab: FormClick +[16:48.16.115] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.16.115] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.16.115] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.16.115] (SSH-Browser) END DesactiverPanel14 +[16:48.16.115] (SSH-Browser) END ActiverPanel14; +[16:48.16.140] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.16.140] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.16.140] DisplayCurrentTab: DistribuerLeFocus +[16:48.16.140] END DisplayCurrentTab +[16:48.16.140] BEGIN SavePassword +[16:48.16.140] END SavePassword +[16:48.16.140] END SauvegarderMotDePasseSSH +[16:48.16.140] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:48.16.140] BEGIN SauvegarderMotDePasseSSH +[16:48.16.140] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:48.16.140] SetTitle(3, root@192.168.127.10); +[16:48.16.140] +[16:48.16.140] (SSH-Browser) BEGIN ConnectSSH(3,192.168.127.10,root,) +[16:48.16.140] (SSH-Browser) ConnectSSH(3): 初始化 TabSFTP +[16:48.16.141] (SSH-Browser) ConnectSSH(3): 未使用代理 +[16:48.16.141] (SSH-Browser) ConnectSSH(3): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:48.16.142] (SSH-Browser) ConnectSSH(3): 已成功连接到 192.168.127.10. +[16:48.16.142] (SSH-Browser) ConnectSSH(3): SSH.Open +[16:48.16.142] (SSH-Browser) END ConnectSSH(3) +[16:48.16.142] BEGIN DisplayCurrentTab +[16:48.16.142] DisplayCurrentTab: FormClick +[16:48.16.142] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.16.142] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.16.142] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.16.142] (SSH-Browser) END DesactiverPanel14 +[16:48.16.142] (SSH-Browser) END ActiverPanel14; +[16:48.16.164] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.16.164] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.16.164] DisplayCurrentTab: DistribuerLeFocus +[16:48.16.164] END DisplayCurrentTab +[16:48.16.164] BEGIN SavePassword +[16:48.16.164] END SavePassword +[16:48.16.164] END SauvegarderMotDePasseSSH +[16:48.16.165] WMNewTab2: 正在保存密码, 并连接 SSH 文件浏览器... +[16:48.16.165] BEGIN SauvegarderMotDePasseSSH +[16:48.16.165] SauvegarderMotDePasseSSH: 正在连接 SSH 文件浏览器... +[16:48.16.165] SetTitle(7, root@192.168.127.10); +[16:48.16.165] +[16:48.16.165] (SSH-Browser) BEGIN ConnectSSH(7,192.168.127.10,root,) +[16:48.16.165] (SSH-Browser) ConnectSSH(7): 初始化 TabSFTP +[16:48.16.166] (SSH-Browser) ConnectSSH(7): 未使用代理 +[16:48.16.166] (SSH-Browser) ConnectSSH(7): 未提供密钥 --> 使用其他身份验证类型进行连接 +[16:48.16.167] (SSH-Browser) ConnectSSH(7): 已成功连接到 192.168.127.10. +[16:48.16.167] (SSH-Browser) ConnectSSH(7): SSH.Open +[16:48.16.167] (SSH-Browser) END ConnectSSH(7) +[16:48.16.167] BEGIN DisplayCurrentTab +[16:48.16.167] DisplayCurrentTab: FormClick +[16:48.16.167] (SSH-Browser) DisplayCurrentTab(8): ActiverPanel14 +[16:48.16.167] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.16.167] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.16.167] (SSH-Browser) END DesactiverPanel14 +[16:48.16.167] (SSH-Browser) END ActiverPanel14; +[16:48.16.189] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.16.189] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.16.189] DisplayCurrentTab: DistribuerLeFocus +[16:48.16.189] END DisplayCurrentTab +[16:48.16.189] BEGIN SavePassword +[16:48.16.189] END SavePassword +[16:48.16.189] END SauvegarderMotDePasseSSH +[16:48.16.189] BEGIN WMNewTab: 80 +[16:48.16.189] 收到消息: 正在启动远程监控 终端 #9 +[16:48.16.189] END WMNewTab: 80 +[16:48.16.191] BEGIN WMNewTab: 80 +[16:48.16.191] 收到消息: 正在启动远程监控 终端 #10 +[16:48.16.191] END WMNewTab: 80 +[16:48.16.191] BEGIN WMNewTab: 80 +[16:48.16.191] 收到消息: 正在启动远程监控 终端 #11 +[16:48.16.191] END WMNewTab: 80 +[16:48.16.191] BEGIN WMNewTab: 80 +[16:48.16.191] 收到消息: 正在启动远程监控 终端 #13 +[16:48.16.221] BEGIN TFormXterm.FormResize +[16:48.16.221] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.16.222] TFormXterm.FormResize: SplitModeResize +[16:48.16.222] TFormXterm.FormResize: sPanel7.Visible +[16:48.16.437] BEGIN WMNewTab: 20 +[16:48.16.437] END WMNewTab: 20 +[16:48.16.689] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.16.689] BEGIN AdaptSidebarArrows +[16:48.16.689] END AdaptSidebarArrows +[16:48.16.689] TFormXterm.FormResize: AdaptTV2; +[16:48.16.689] END TFormXterm.FormResize +[16:48.16.691] (SSH-Browser) 正在启动 MobaSCP(13, remotemonitoring, ., ) +[16:48.16.691] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566613" -remotemonitoring mobauser@mobaserver:".") +[16:48.16.692] BEGIN WMNewTab: 80 +[16:48.16.692] 收到消息: 正在启动远程监控 终端 #7 +[16:48.16.692] END WMNewTab: 80 +[16:48.16.692] BEGIN WMNewTab: 80 +[16:48.16.692] 收到消息: 正在启动远程监控 终端 #8 +[16:48.16.692] END WMNewTab: 80 +[16:48.16.692] BEGIN WMNewTab: 80 +[16:48.16.692] 收到消息: 正在启动远程监控 终端 #12 +[16:48.16.692] END WMNewTab: 80 +[16:48.16.716] ShellExecuteS: ShellExecuteEx 成功. +[16:48.16.716] ShellExecuteS: WaitForInputIdle 失败. +[16:48.16.716] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566613" -remotemonitoring mobauser@mobaserver:".") +[16:48.16.717] END WMNewTab: 80 +[16:48.16.812] [MobaSCP13] Launching remote monitoring in normal mode +[16:48.16.813] [MobaSCP13] Multiplex=1 +[16:48.16.814] [MobaSCP13] HOSTNAME: 192.168.127.10 +[16:48.16.814] [MobaSCP13] USERNAME: root +[16:48.16.840] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:48.16.840] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:48.16.840] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[16:48.16.840] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[16:48.16.840] (SSH-Browser) END GetSftpOnValidateStatus +[16:48.16.859] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:48.16.859] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:48.16.859] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[16:48.16.859] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[16:48.16.859] (SSH-Browser) END GetSftpOnValidateStatus +[16:48.16.896] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:48.16.896] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:48.16.896] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[16:48.16.896] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[16:48.16.896] (SSH-Browser) END GetSftpOnValidateStatus +[16:48.16.915] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:48.16.915] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:48.16.915] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[16:48.16.915] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[16:48.16.915] (SSH-Browser) END GetSftpOnValidateStatus +[16:48.16.934] [MobaSCP13] Using SCP1 +[16:48.16.934] [MobaSCP13] Connected to 192.168.127.10 +[16:48.16.960] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:48.16.965] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:48.16.965] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[16:48.16.965] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[16:48.16.965] (SSH-Browser) END GetSftpOnValidateStatus +[16:48.16.985] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:48.16.985] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:48.16.985] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[16:48.16.985] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[16:48.16.985] (SSH-Browser) END GetSftpOnValidateStatus +[16:48.17.021] (SSH-Browser) BEGIN GetSftpOnValidateStatus +[16:48.17.021] (SSH-Browser) 解析主机密钥 "ssh-ed25519@22:192.168.127.10" +[16:48.17.021] (SSH-Browser) 主机密钥指纹信息 (Sha256): 1c:01:43:cb:90:3f:5e:c0:aa:55:99:1a:ed:d7:c6:1c:94:95:6b:4f:4e:8a:d9:b7:bc:d1:c3:42:79:ec:af:28 +[16:48.17.021] (SSH-Browser) 主机密钥指纹已存在于 INI 文件中 +[16:48.17.021] (SSH-Browser) END GetSftpOnValidateStatus +[16:48.17.032] +[16:48.17.032] (SSH-Browser) ElSSH1AuthenticationStart(6, 134) +[16:48.17.032] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:48.17.032] (SSH-Browser) 服务器支持以下认证方式: +[16:48.17.032] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.032] (SSH-Browser) . PUBLICKEY +[16:48.17.032] (SSH-Browser) . PASSWORD +[16:48.17.032] (SSH-Browser) 客户端支持以下认证方式: +[16:48.17.032] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.032] (SSH-Browser) . PUBLICKEY +[16:48.17.032] (SSH-Browser) . RHOSTS +[16:48.17.032] (SSH-Browser) . HOSTBASED +[16:48.17.032] (SSH-Browser) . PASSWORD +[16:48.17.032] (SSH-Browser) . KEYBOARD +[16:48.17.032] +[16:48.17.032] +[16:48.17.032] (SSH-Browser) ElSSH1AuthenticationFailed(6, PUBLICKEY) +[16:48.17.032] (SSH-Browser) ElSSH1AuthenticationFailed(6, PUBLICKEYAGENT) +[16:48.17.032] (SSH-Browser) ElSSH1AuthenticationAttempt(6, PASSWORD) +[16:48.17.032] +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationStart(5, 134) +[16:48.17.034] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:48.17.034] (SSH-Browser) 服务器支持以下认证方式: +[16:48.17.034] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.034] (SSH-Browser) . PUBLICKEY +[16:48.17.034] (SSH-Browser) . PASSWORD +[16:48.17.034] (SSH-Browser) 客户端支持以下认证方式: +[16:48.17.034] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.034] (SSH-Browser) . PUBLICKEY +[16:48.17.034] (SSH-Browser) . RHOSTS +[16:48.17.034] (SSH-Browser) . HOSTBASED +[16:48.17.034] (SSH-Browser) . PASSWORD +[16:48.17.034] (SSH-Browser) . KEYBOARD +[16:48.17.034] +[16:48.17.034] +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationFailed(5, PUBLICKEY) +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationFailed(5, PUBLICKEYAGENT) +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationAttempt(5, PASSWORD) +[16:48.17.034] +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationStart(8, 134) +[16:48.17.034] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:48.17.034] (SSH-Browser) 服务器支持以下认证方式: +[16:48.17.034] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.034] (SSH-Browser) . PUBLICKEY +[16:48.17.034] (SSH-Browser) . PASSWORD +[16:48.17.034] (SSH-Browser) 客户端支持以下认证方式: +[16:48.17.034] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.034] (SSH-Browser) . PUBLICKEY +[16:48.17.034] (SSH-Browser) . RHOSTS +[16:48.17.034] (SSH-Browser) . HOSTBASED +[16:48.17.034] (SSH-Browser) . PASSWORD +[16:48.17.034] (SSH-Browser) . KEYBOARD +[16:48.17.034] +[16:48.17.034] +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationFailed(8, PUBLICKEY) +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationFailed(8, PUBLICKEYAGENT) +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationAttempt(8, PASSWORD) +[16:48.17.034] +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationStart(4, 134) +[16:48.17.034] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:48.17.034] (SSH-Browser) 服务器支持以下认证方式: +[16:48.17.034] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.034] (SSH-Browser) . PUBLICKEY +[16:48.17.034] (SSH-Browser) . PASSWORD +[16:48.17.034] (SSH-Browser) 客户端支持以下认证方式: +[16:48.17.034] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.034] (SSH-Browser) . PUBLICKEY +[16:48.17.034] (SSH-Browser) . RHOSTS +[16:48.17.034] (SSH-Browser) . HOSTBASED +[16:48.17.034] (SSH-Browser) . PASSWORD +[16:48.17.034] (SSH-Browser) . KEYBOARD +[16:48.17.034] +[16:48.17.034] +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationFailed(4, PUBLICKEY) +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationFailed(4, PUBLICKEYAGENT) +[16:48.17.034] (SSH-Browser) ElSSH1AuthenticationAttempt(4, PASSWORD) +[16:48.17.079] +[16:48.17.079] (SSH-Browser) ElSSH1AuthenticationStart(2, 134) +[16:48.17.079] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:48.17.079] (SSH-Browser) 服务器支持以下认证方式: +[16:48.17.079] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.079] (SSH-Browser) . PUBLICKEY +[16:48.17.079] (SSH-Browser) . PASSWORD +[16:48.17.079] (SSH-Browser) 客户端支持以下认证方式: +[16:48.17.079] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.079] (SSH-Browser) . PUBLICKEY +[16:48.17.079] (SSH-Browser) . RHOSTS +[16:48.17.079] (SSH-Browser) . HOSTBASED +[16:48.17.079] (SSH-Browser) . PASSWORD +[16:48.17.079] (SSH-Browser) . KEYBOARD +[16:48.17.079] +[16:48.17.079] +[16:48.17.079] (SSH-Browser) ElSSH1AuthenticationFailed(2, PUBLICKEY) +[16:48.17.079] (SSH-Browser) ElSSH1AuthenticationFailed(2, PUBLICKEYAGENT) +[16:48.17.079] (SSH-Browser) ElSSH1AuthenticationAttempt(2, PASSWORD) +[16:48.17.095] +[16:48.17.095] (SSH-Browser) ElSSH1AuthenticationStart(7, 134) +[16:48.17.095] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:48.17.095] (SSH-Browser) 服务器支持以下认证方式: +[16:48.17.095] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.095] (SSH-Browser) . PUBLICKEY +[16:48.17.095] (SSH-Browser) . PASSWORD +[16:48.17.095] (SSH-Browser) 客户端支持以下认证方式: +[16:48.17.095] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.095] (SSH-Browser) . PUBLICKEY +[16:48.17.095] (SSH-Browser) . RHOSTS +[16:48.17.095] (SSH-Browser) . HOSTBASED +[16:48.17.095] (SSH-Browser) . PASSWORD +[16:48.17.095] (SSH-Browser) . KEYBOARD +[16:48.17.095] +[16:48.17.095] +[16:48.17.095] (SSH-Browser) ElSSH1AuthenticationFailed(7, PUBLICKEY) +[16:48.17.095] (SSH-Browser) ElSSH1AuthenticationFailed(7, PUBLICKEYAGENT) +[16:48.17.095] (SSH-Browser) ElSSH1AuthenticationAttempt(7, PASSWORD) +[16:48.17.109] +[16:48.17.109] (SSH-Browser) ElSSH1AuthenticationStart(3, 134) +[16:48.17.109] (SSH-Browser) 服务器不支持 GSSAPI 身份验证. +[16:48.17.109] (SSH-Browser) 服务器支持以下认证方式: +[16:48.17.109] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.109] (SSH-Browser) . PUBLICKEY +[16:48.17.109] (SSH-Browser) . PASSWORD +[16:48.17.109] (SSH-Browser) 客户端支持以下认证方式: +[16:48.17.109] (SSH-Browser) . PUBLICKEYAGENT +[16:48.17.109] (SSH-Browser) . PUBLICKEY +[16:48.17.109] (SSH-Browser) . RHOSTS +[16:48.17.109] (SSH-Browser) . HOSTBASED +[16:48.17.109] (SSH-Browser) . PASSWORD +[16:48.17.109] (SSH-Browser) . KEYBOARD +[16:48.17.109] +[16:48.17.109] +[16:48.17.109] (SSH-Browser) ElSSH1AuthenticationFailed(3, PUBLICKEY) +[16:48.17.109] (SSH-Browser) ElSSH1AuthenticationFailed(3, PUBLICKEYAGENT) +[16:48.17.109] (SSH-Browser) ElSSH1AuthenticationAttempt(3, PASSWORD) +[16:48.17.230] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.17.504] BEGIN WMNewTab: 20 +[16:48.17.504] END WMNewTab: 20 +[16:48.17.505] BEGIN WMNewTab: 20 +[16:48.17.505] END WMNewTab: 20 +[16:48.17.505] BEGIN WMNewTab: 20 +[16:48.17.505] END WMNewTab: 20 +[16:48.17.505] BEGIN WMNewTab: 20 +[16:48.17.505] END WMNewTab: 20 +[16:48.17.535] (SSH-Browser) ElSSH1AuthenticationSuccess(5) +[16:48.17.535] (SSH-Browser) ElSSH1OpenConnection(5) +[16:48.17.535] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:48.17.535] +[16:48.17.535] (SSH-Browser) ElSSH1AuthenticationSuccess(8) +[16:48.17.535] (SSH-Browser) ElSSH1OpenConnection(8) +[16:48.17.535] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:48.17.535] +[16:48.17.550] BEGIN WMNewTab: 20 +[16:48.17.550] END WMNewTab: 20 +[16:48.17.565] BEGIN WMNewTab: 20 +[16:48.17.565] END WMNewTab: 20 +[16:48.17.580] BEGIN WMNewTab: 20 +[16:48.17.580] END WMNewTab: 20 +[16:48.17.580] (SSH-Browser) ElSSH1AuthenticationSuccess(2) +[16:48.17.580] (SSH-Browser) ElSSH1OpenConnection(2) +[16:48.17.580] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:48.17.580] +[16:48.17.596] (SSH-Browser) ElSSH1AuthenticationSuccess(7) +[16:48.17.596] (SSH-Browser) ElSSH1OpenConnection(7) +[16:48.17.596] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:48.17.596] +[16:48.17.611] (SSH-Browser) ElSSH1AuthenticationSuccess(3) +[16:48.17.611] (SSH-Browser) ElSSH1OpenConnection(3) +[16:48.17.611] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:48.17.611] +[16:48.17.823] (SSH-Browser) BEGIN ElSFTP1OpenConnection(5) +[16:48.17.823] (SSH-Browser) ElSFTP1OpenConnection(5): SFTP 已正确连接 +[16:48.17.823] (SSH-Browser) ElSFTP1OpenConnection(5): (i<>Indice) --> not activating Panel14 +[16:48.17.823] (SSH-Browser) ElSFTP1OpenConnection(5): 已成功打开连接 --> 正在退出 +[16:48.17.823] (SSH-Browser) END ElSFTP1OpenConnection(5) +[16:48.17.854] BEGIN WMNewTab: 20 +[16:48.17.854] END WMNewTab: 20 +[16:48.18.109] BEGIN TFormXterm.FormResize +[16:48.18.109] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.18.109] TFormXterm.FormResize: SplitModeResize +[16:48.18.109] TFormXterm.FormResize: sPanel7.Visible +[16:48.18.280] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.18.280] BEGIN AdaptSidebarArrows +[16:48.18.280] END AdaptSidebarArrows +[16:48.18.280] TFormXterm.FormResize: AdaptTV2; +[16:48.18.280] END TFormXterm.FormResize +[16:48.18.280] (SSH-Browser) BEGIN ElSFTP1OpenConnection(8) +[16:48.18.280] (SSH-Browser) ElSFTP1OpenConnection(8): SFTP 已正确连接 +[16:48.18.280] (SSH-Browser) ElSFTP1OpenConnection(8): ActiverPanel14 +[16:48.18.280] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.18.280] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.18.280] (SSH-Browser) END DesactiverPanel14 +[16:48.18.280] (SSH-Browser) END ActiverPanel14; +[16:48.18.303] (SSH-Browser) ElSFTP1OpenConnection(8): 已成功打开连接 --> 正在退出 +[16:48.18.303] (SSH-Browser) END ElSFTP1OpenConnection(8) +[16:48.18.313] (SSH-Browser) ElSSH1AuthenticationSuccess(6) +[16:48.18.313] (SSH-Browser) ElSSH1OpenConnection(6) +[16:48.18.313] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:48.18.313] +[16:48.18.314] (SSH-Browser) ElSSH1AuthenticationSuccess(4) +[16:48.18.314] (SSH-Browser) ElSSH1OpenConnection(4) +[16:48.18.314] (SSH-Browser) 远程服务器名称: OpenSSH_8.9p1 Ubuntu-3ubuntu0.13 +[16:48.18.314] +[16:48.18.329] (SSH-Browser) BEGIN ElSFTP1OpenConnection(2) +[16:48.18.329] (SSH-Browser) ElSFTP1OpenConnection(2): SFTP 已正确连接 +[16:48.18.329] (SSH-Browser) ElSFTP1OpenConnection(2): (i<>Indice) --> not activating Panel14 +[16:48.18.329] (SSH-Browser) ElSFTP1OpenConnection(2): 已成功打开连接 --> 正在退出 +[16:48.18.329] (SSH-Browser) END ElSFTP1OpenConnection(2) +[16:48.18.344] (SSH-Browser) BEGIN ElSFTP1OpenConnection(7) +[16:48.18.344] (SSH-Browser) ElSFTP1OpenConnection(7): SFTP 已正确连接 +[16:48.18.344] (SSH-Browser) ElSFTP1OpenConnection(7): (i<>Indice) --> not activating Panel14 +[16:48.18.344] (SSH-Browser) ElSFTP1OpenConnection(7): 已成功打开连接 --> 正在退出 +[16:48.18.344] (SSH-Browser) END ElSFTP1OpenConnection(7) +[16:48.18.344] (SSH-Browser) BEGIN ElSFTP1OpenConnection(3) +[16:48.18.344] (SSH-Browser) ElSFTP1OpenConnection(3): SFTP 已正确连接 +[16:48.18.344] (SSH-Browser) ElSFTP1OpenConnection(3): (i<>Indice) --> not activating Panel14 +[16:48.18.344] (SSH-Browser) ElSFTP1OpenConnection(3): 已成功打开连接 --> 正在退出 +[16:48.18.344] (SSH-Browser) END ElSFTP1OpenConnection(3) +[16:48.18.465] (SSH-Browser) BEGIN ElSFTP1OpenConnection(6) +[16:48.18.465] (SSH-Browser) ElSFTP1OpenConnection(6): SFTP 已正确连接 +[16:48.18.465] (SSH-Browser) ElSFTP1OpenConnection(6): (i<>Indice) --> not activating Panel14 +[16:48.18.465] (SSH-Browser) ElSFTP1OpenConnection(6): 已成功打开连接 --> 正在退出 +[16:48.18.465] (SSH-Browser) END ElSFTP1OpenConnection(6) +[16:48.18.465] (SSH-Browser) BEGIN ElSFTP1OpenConnection(4) +[16:48.18.465] (SSH-Browser) ElSFTP1OpenConnection(4): SFTP 已正确连接 +[16:48.18.465] (SSH-Browser) ElSFTP1OpenConnection(4): (i<>Indice) --> not activating Panel14 +[16:48.18.465] (SSH-Browser) ElSFTP1OpenConnection(4): 已成功打开连接 --> 正在退出 +[16:48.18.465] (SSH-Browser) END ElSFTP1OpenConnection(4) +[16:48.18.772] BEGIN WMNewTab: 20 +[16:48.18.772] END WMNewTab: 20 +[16:48.18.772] BEGIN WMNewTab: 20 +[16:48.18.772] END WMNewTab: 20 +[16:48.18.803] BEGIN WMNewTab: 20 +[16:48.18.803] END WMNewTab: 20 +[16:48.18.818] BEGIN WMNewTab: 20 +[16:48.18.818] END WMNewTab: 20 +[16:48.18.818] BEGIN WMNewTab: 20 +[16:48.18.818] END WMNewTab: 20 +[16:48.18.849] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.18.939] BEGIN WMNewTab: 20 +[16:48.18.939] END WMNewTab: 20 +[16:48.18.939] BEGIN WMNewTab: 20 +[16:48.18.939] END WMNewTab: 20 +[16:48.19.274] BEGIN WMNewTab: 20 +[16:48.19.274] END WMNewTab: 20 + +[16:48.20.185] BEGIN WMNewTab: 20 +[16:48.20.185] END WMNewTab: 20 +[16:48.20.185] BEGIN WMNewTab: 20 +[16:48.20.185] END WMNewTab: 20 +[16:48.20.216] BEGIN WMNewTab: 20 +[16:48.20.216] END WMNewTab: 20 +[16:48.20.231] BEGIN WMNewTab: 20 +[16:48.20.231] END WMNewTab: 20 +[16:48.20.231] BEGIN WMNewTab: 20 +[16:48.20.231] END WMNewTab: 20 +[16:48.20.353] BEGIN WMNewTab: 20 +[16:48.20.353] END WMNewTab: 20 +[16:48.20.353] BEGIN WMNewTab: 20 +[16:48.20.353] END WMNewTab: 20 +[16:48.20.461] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.20.687] BEGIN WMNewTab: 20 +[16:48.20.687] END WMNewTab: 20 + +[16:48.21.596] BEGIN WMNewTab: 20 +[16:48.21.596] END WMNewTab: 20 +[16:48.21.596] BEGIN WMNewTab: 20 +[16:48.21.596] END WMNewTab: 20 +[16:48.21.626] BEGIN WMNewTab: 20 +[16:48.21.626] END WMNewTab: 20 +[16:48.21.641] BEGIN WMNewTab: 20 +[16:48.21.641] END WMNewTab: 20 +[16:48.21.641] BEGIN WMNewTab: 20 +[16:48.21.641] END WMNewTab: 20 +[16:48.21.763] BEGIN WMNewTab: 20 +[16:48.21.763] END WMNewTab: 20 +[16:48.21.763] BEGIN WMNewTab: 20 +[16:48.21.763] END WMNewTab: 20 +[16:48.22.077] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.22.095] BEGIN WMNewTab: 20 +[16:48.22.095] END WMNewTab: 20 + +[16:48.23.009] BEGIN WMNewTab: 20 +[16:48.23.009] END WMNewTab: 20 +[16:48.23.011] BEGIN WMNewTab: 20 +[16:48.23.011] END WMNewTab: 20 +[16:48.23.040] BEGIN WMNewTab: 20 +[16:48.23.040] END WMNewTab: 20 +[16:48.23.055] BEGIN WMNewTab: 20 +[16:48.23.055] END WMNewTab: 20 +[16:48.23.055] BEGIN WMNewTab: 20 +[16:48.23.055] END WMNewTab: 20 +[16:48.23.178] BEGIN WMNewTab: 20 +[16:48.23.178] END WMNewTab: 20 +[16:48.23.178] BEGIN WMNewTab: 20 +[16:48.23.178] END WMNewTab: 20 +[16:48.23.515] BEGIN WMNewTab: 20 +[16:48.23.515] END WMNewTab: 20 +[16:48.23.681] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.24.433] BEGIN WMNewTab: 20 +[16:48.24.433] END WMNewTab: 20 +[16:48.24.433] BEGIN WMNewTab: 20 +[16:48.24.433] END WMNewTab: 20 +[16:48.24.464] BEGIN WMNewTab: 20 +[16:48.24.464] END WMNewTab: 20 +[16:48.24.479] BEGIN WMNewTab: 20 +[16:48.24.479] END WMNewTab: 20 +[16:48.24.479] BEGIN WMNewTab: 20 +[16:48.24.479] END WMNewTab: 20 +[16:48.24.602] BEGIN WMNewTab: 20 +[16:48.24.602] END WMNewTab: 20 +[16:48.24.602] BEGIN WMNewTab: 20 +[16:48.24.602] END WMNewTab: 20 +[16:48.24.936] BEGIN WMNewTab: 20 +[16:48.24.936] END WMNewTab: 20 +[16:48.25.287] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.25.851] BEGIN WMNewTab: 20 +[16:48.25.851] END WMNewTab: 20 +[16:48.25.851] BEGIN WMNewTab: 20 +[16:48.25.851] END WMNewTab: 20 +[16:48.25.881] BEGIN WMNewTab: 20 +[16:48.25.881] END WMNewTab: 20 +[16:48.25.897] BEGIN WMNewTab: 20 +[16:48.25.897] END WMNewTab: 20 +[16:48.25.897] BEGIN WMNewTab: 20 +[16:48.25.897] END WMNewTab: 20 +[16:48.26.018] BEGIN WMNewTab: 20 +[16:48.26.018] END WMNewTab: 20 +[16:48.26.019] BEGIN WMNewTab: 20 +[16:48.26.019] END WMNewTab: 20 +[16:48.26.354] BEGIN WMNewTab: 20 +[16:48.26.354] END WMNewTab: 20 + +[16:48.26.887] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.27.265] BEGIN WMNewTab: 20 +[16:48.27.265] END WMNewTab: 20 +[16:48.27.265] BEGIN WMNewTab: 20 +[16:48.27.265] END WMNewTab: 20 +[16:48.27.296] BEGIN WMNewTab: 20 +[16:48.27.296] END WMNewTab: 20 +[16:48.27.312] BEGIN WMNewTab: 20 +[16:48.27.312] END WMNewTab: 20 +[16:48.27.313] BEGIN WMNewTab: 20 +[16:48.27.313] END WMNewTab: 20 +[16:48.27.434] BEGIN WMNewTab: 20 +[16:48.27.434] END WMNewTab: 20 +[16:48.27.434] BEGIN WMNewTab: 20 +[16:48.27.434] END WMNewTab: 20 +[16:48.27.767] BEGIN WMNewTab: 20 +[16:48.27.767] END WMNewTab: 20 +[16:48.28.036] BEGIN LockControl(sPanel1, sBitBtn16Click) +[16:48.28.036] END LockControl(sPanel1, sBitBtn16Click) +[16:48.28.079] BEGIN TFormXterm.FormResize +[16:48.28.079] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.28.079] TFormXterm.FormResize: SplitModeResize +[16:48.28.079] TFormXterm.FormResize: sPanel7.Visible +[16:48.28.151] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.28.151] BEGIN AdaptSidebarArrows +[16:48.28.151] END AdaptSidebarArrows +[16:48.28.151] TFormXterm.FormResize: AdaptTV2; +[16:48.28.151] END TFormXterm.FormResize +[16:48.28.151] BEGIN WMSize +[16:48.28.151] BEGIN TFormXterm.FormResize +[16:48.28.151] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.28.151] TFormXterm.FormResize: SplitModeResize +[16:48.28.151] TFormXterm.FormResize: sPanel7.Visible +[16:48.28.317] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.28.317] BEGIN AdaptSidebarArrows +[16:48.28.317] END AdaptSidebarArrows +[16:48.28.317] TFormXterm.FormResize: AdaptTV2; +[16:48.28.317] END TFormXterm.FormResize +[16:48.28.317] END WMSize +[16:48.28.366] BtnSplitNoClick: FormClick +[16:48.28.366] BEGIN LockControl(sPanel1, BtnSplitNoClick) +[16:48.28.366] END LockControl(sPanel1, BtnSplitNoClick) +[16:48.28.521] 更改标签页索引 K = 0 +[16:48.28.521] BEGIN DisplayCurrentTab +[16:48.28.521] DisplayCurrentTab: FormClick +[16:48.28.521] (SSH-Browser) DisplayCurrentTab(0): ActiverPanel14 +[16:48.28.521] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.28.521] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.28.536] (SSH-Browser) END DesactiverPanel14 +[16:48.28.536] (SSH-Browser) END ActiverPanel14; +[16:48.28.666] BEGIN TFormXterm.FormResize +[16:48.28.666] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.28.667] TFormXterm.FormResize: SplitModeResize +[16:48.28.667] TFormXterm.FormResize: BtnSplitNo.Down +[16:48.28.668] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:48.28.668] BEGIN ResizeTerminal +[16:48.28.668] END ResizeTerminal +[16:48.28.668] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.28.668] BEGIN AdaptSidebarArrows +[16:48.28.668] END AdaptSidebarArrows +[16:48.28.668] TFormXterm.FormResize: AdaptTV2; +[16:48.28.668] END TFormXterm.FormResize +[16:48.28.668] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.28.668] Cts1ActiveTabChanged: New index = 0 +[16:48.28.668] DisplayCurrentTab: Cts1.EndUpdates +[16:48.28.760] DisplayCurrentTab: 显示所选标签页 +[16:48.28.780] BEGIN ResizeTerminal +[16:48.28.780] END ResizeTerminal +[16:48.28.780] DisplayCurrentTab: 隐藏其他标签页 +[16:48.28.780] BEGIN WMNewTab: 20 +[16:48.28.780] END WMNewTab: 20 +[16:48.28.781] BEGIN WMNewTab: 20 +[16:48.28.781] END WMNewTab: 20 +[16:48.28.781] BEGIN WMNewTab: 20 +[16:48.28.781] END WMNewTab: 20 +[16:48.28.781] BEGIN WMNewTab: 20 +[16:48.28.781] END WMNewTab: 20 +[16:48.28.781] BEGIN WMNewTab: 20 +[16:48.28.781] END WMNewTab: 20 +[16:48.28.827] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.28.828] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.28.828] DisplayCurrentTab: DistribuerLeFocus +[16:48.28.828] BEGIN WMNewTab: 0 +[16:48.28.828] WMNewTab: FormClick +[16:48.28.828] WMNewTab: LooseFocus +[16:48.28.828] END WMNewTab: 0 +[16:48.28.828] BEGIN WMNewTab: 0 +[16:48.28.828] WMNewTab: FormClick +[16:48.28.828] WMNewTab: LooseFocus +[16:48.28.829] END WMNewTab: 0 +[16:48.28.829] BEGIN WMNewTab: 0 +[16:48.28.829] WMNewTab: FormClick +[16:48.28.829] WMNewTab: LooseFocus +[16:48.28.829] END WMNewTab: 0 +[16:48.28.829] BEGIN WMNewTab: 0 +[16:48.28.829] WMNewTab: FormClick +[16:48.28.829] WMNewTab: LooseFocus +[16:48.28.829] END WMNewTab: 0 +[16:48.28.829] END DisplayCurrentTab +[16:48.28.829] BEGIN TFormXterm.FormResize +[16:48.28.829] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.28.829] TFormXterm.FormResize: SplitModeResize +[16:48.28.829] TFormXterm.FormResize: BtnSplitNo.Down +[16:48.28.829] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:48.28.829] BEGIN ResizeTerminal +[16:48.28.829] END ResizeTerminal +[16:48.28.829] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.28.830] BEGIN AdaptSidebarArrows +[16:48.28.830] END AdaptSidebarArrows +[16:48.28.830] TFormXterm.FormResize: AdaptTV2; +[16:48.28.830] END TFormXterm.FormResize +[16:48.28.830] ReEnable_Timer1_7 +[16:48.28.830] BEGIN UnlockControl(sPanel1, BtnSplitNoClick) +[16:48.28.830] END UnlockControl(sPanel1, BtnSplitNoClick) +[16:48.28.830] 释放对象 PanTerm_7 (TPanel) +[16:48.28.835] 释放对象 TsCheckBox +[16:48.28.838] 释放对象 PanTerm_6 (TPanel) +[16:48.28.842] 释放对象 TsCheckBox +[16:48.28.844] 释放对象 PanTerm_5 (TPanel) +[16:48.28.846] 释放对象 TsCheckBox +[16:48.28.852] 释放对象 PanTerm_4 (TPanel) +[16:48.28.855] 释放对象 TsCheckBox +[16:48.28.857] 释放对象 PanTerm_3 (TPanel) +[16:48.28.860] 释放对象 TsCheckBox +[16:48.28.861] 释放对象 PanTerm_2 (TPanel) +[16:48.28.865] 释放对象 TsCheckBox +[16:48.28.867] 释放对象 PanTerm_1 (TPanel) +[16:48.28.869] 释放对象 TsCheckBox +[16:48.28.871] 释放对象 PanTerm_0 (TPanel) +[16:48.28.873] 释放对象 TsCheckBox +[16:48.28.908] BEGIN TFormXterm.FormResize +[16:48.28.908] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.28.914] TFormXterm.FormResize: SplitModeResize +[16:48.28.914] TFormXterm.FormResize: BtnSplitNo.Down +[16:48.28.916] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:48.28.916] BEGIN ResizeTerminal +[16:48.28.916] END ResizeTerminal +[16:48.28.916] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.28.916] BEGIN AdaptSidebarArrows +[16:48.28.916] END AdaptSidebarArrows +[16:48.28.916] TFormXterm.FormResize: AdaptTV2; +[16:48.28.916] END TFormXterm.FormResize +[16:48.28.916] BEGIN UnlockControl(sPanel1, sBitBtn16Click) +[16:48.28.916] END UnlockControl(sPanel1, sBitBtn16Click) +[16:48.28.920] sBitBtn16Click_ReEnable_Timer1 +[16:48.28.920] BEGIN WMNewTab: 20 +[16:48.28.920] END WMNewTab: 20 +[16:48.28.920] BEGIN WMNewTab: 20 +[16:48.28.920] END WMNewTab: 20 +[16:48.29.016] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.29.185] BEGIN WMNewTab: 20 +[16:48.29.185] END WMNewTab: 20 + +[16:48.29.562] Cts1MouseDown: FormClick +[16:48.29.574] Cts1ActiveTabChanged: New index = 1 +[16:48.29.574] BEGIN DisplayCurrentTab +[16:48.29.574] DisplayCurrentTab: FormClick +[16:48.29.574] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:48.29.574] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.29.574] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:48.29.579] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:48.29.579] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:48.29.579] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:48.29.580] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:48.29.627] (SSH-Browser) END ActiverPanel14; +[16:48.29.667] BEGIN TFormXterm.FormResize +[16:48.29.667] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.29.667] TFormXterm.FormResize: SplitModeResize +[16:48.29.667] TFormXterm.FormResize: BtnSplitNo.Down +[16:48.29.669] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:48.29.669] BEGIN ResizeTerminal +[16:48.29.675] END ResizeTerminal +[16:48.29.675] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.29.675] BEGIN AdaptSidebarArrows +[16:48.29.675] END AdaptSidebarArrows +[16:48.29.675] TFormXterm.FormResize: AdaptTV2; +[16:48.29.675] END TFormXterm.FormResize +[16:48.29.675] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:48.29.675] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:48.29.718] ShellExecuteS: ShellExecuteEx 成功. +[16:48.29.718] ShellExecuteS: WaitForInputIdle 失败. +[16:48.29.718] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:48.29.718] DisplayCurrentTab: Cts1.BeginUpdate; +[16:48.29.718] DisplayCurrentTab: Cts1.EndUpdates +[16:48.29.829] DisplayCurrentTab: 显示所选标签页 +[16:48.29.829] [MobaSCP2] Launching remote monitoring in normal mode +[16:48.29.830] [MobaSCP2] Multiplex=1 +[16:48.29.830] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:48.29.830] [MobaSCP2] USERNAME: root +[16:48.29.831] DisplayCurrentTab: 隐藏其他标签页 +[16:48.29.887] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.29.891] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.29.891] DisplayCurrentTab: DistribuerLeFocus +[16:48.29.891] END DisplayCurrentTab +[16:48.29.980] [MobaSCP2] Using SCP1 +[16:48.29.986] [MobaSCP2] Connected to 192.168.127.10 +[16:48.30.116] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.30.191] BEGIN WMNewTab: 20 +[16:48.30.191] END WMNewTab: 20 +[16:48.30.191] BEGIN WMNewTab: 20 +[16:48.30.191] END WMNewTab: 20 +[16:48.30.191] BEGIN WMNewTab: 20 +[16:48.30.191] END WMNewTab: 20 +[16:48.30.192] BEGIN WMNewTab: 20 +[16:48.30.192] END WMNewTab: 20 +[16:48.30.192] BEGIN WMNewTab: 20 +[16:48.30.192] END WMNewTab: 20 +[16:48.30.327] BEGIN WMNewTab: 20 +[16:48.30.327] END WMNewTab: 20 +[16:48.30.327] BEGIN WMNewTab: 20 +[16:48.30.327] END WMNewTab: 20 +[16:48.30.602] BEGIN WMNewTab: 20 +[16:48.30.602] END WMNewTab: 20 +[16:48.30.626] BEGIN WMNewTab: 0 +[16:48.30.626] WMNewTab: FormClick +[16:48.30.626] WMNewTab: LooseFocus +[16:48.30.627] END WMNewTab: 0 +[16:48.30.761] BEGIN WMNewTab: 0 +[16:48.30.761] WMNewTab: FormClick +[16:48.30.761] WMNewTab: LooseFocus +[16:48.30.762] END WMNewTab: 0 +[16:48.31.059] BEGIN TFormXterm.FormResize +[16:48.31.059] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.31.059] TFormXterm.FormResize: SplitModeResize +[16:48.31.059] TFormXterm.FormResize: BtnSplitNo.Down +[16:48.31.059] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:48.31.059] BEGIN ResizeTerminal +[16:48.31.059] END ResizeTerminal +[16:48.31.059] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.31.059] BEGIN AdaptSidebarArrows +[16:48.31.059] END AdaptSidebarArrows +[16:48.31.059] TFormXterm.FormResize: AdaptTV2; +[16:48.31.059] END TFormXterm.FormResize + +[16:48.31.609] BEGIN WMNewTab: 20 +[16:48.31.609] END WMNewTab: 20 +[16:48.31.609] BEGIN WMNewTab: 20 +[16:48.31.609] END WMNewTab: 20 +[16:48.31.609] BEGIN WMNewTab: 20 +[16:48.31.609] END WMNewTab: 20 +[16:48.31.609] BEGIN WMNewTab: 20 +[16:48.31.609] END WMNewTab: 20 +[16:48.31.609] BEGIN WMNewTab: 20 +[16:48.31.609] END WMNewTab: 20 +[16:48.31.716] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.31.746] BEGIN WMNewTab: 20 +[16:48.31.746] END WMNewTab: 20 +[16:48.31.746] BEGIN WMNewTab: 20 +[16:48.31.746] END WMNewTab: 20 +[16:48.32.019] BEGIN WMNewTab: 20 +[16:48.32.019] END WMNewTab: 20 + +[16:48.33.029] BEGIN WMNewTab: 20 +[16:48.33.029] END WMNewTab: 20 +[16:48.33.029] BEGIN WMNewTab: 20 +[16:48.33.029] END WMNewTab: 20 +[16:48.33.029] BEGIN WMNewTab: 20 +[16:48.33.029] END WMNewTab: 20 +[16:48.33.029] BEGIN WMNewTab: 20 +[16:48.33.029] END WMNewTab: 20 +[16:48.33.030] BEGIN WMNewTab: 20 +[16:48.33.030] END WMNewTab: 20 +[16:48.33.165] BEGIN WMNewTab: 20 +[16:48.33.165] END WMNewTab: 20 +[16:48.33.166] BEGIN WMNewTab: 20 +[16:48.33.166] END WMNewTab: 20 +[16:48.33.239] BEGIN WMNewTab: 0 +[16:48.33.239] WMNewTab: FormClick +[16:48.33.239] WMNewTab: LooseFocus +[16:48.33.239] END WMNewTab: 0 +[16:48.33.333] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.33.368] BEGIN WMNewTab: 0 +[16:48.33.368] WMNewTab: FormClick +[16:48.33.368] WMNewTab: LooseFocus +[16:48.33.369] END WMNewTab: 0 +[16:48.33.440] BEGIN WMNewTab: 20 +[16:48.33.440] END WMNewTab: 20 + +[16:48.34.444] BEGIN WMNewTab: 20 +[16:48.34.444] END WMNewTab: 20 +[16:48.34.444] BEGIN WMNewTab: 20 +[16:48.34.444] END WMNewTab: 20 +[16:48.34.444] BEGIN WMNewTab: 20 +[16:48.34.444] END WMNewTab: 20 +[16:48.34.444] BEGIN WMNewTab: 20 +[16:48.34.444] END WMNewTab: 20 +[16:48.34.444] BEGIN WMNewTab: 20 +[16:48.34.444] END WMNewTab: 20 +[16:48.34.582] BEGIN WMNewTab: 20 +[16:48.34.582] END WMNewTab: 20 +[16:48.34.582] BEGIN WMNewTab: 20 +[16:48.34.582] END WMNewTab: 20 +[16:48.34.858] BEGIN WMNewTab: 20 +[16:48.34.858] END WMNewTab: 20 +[16:48.34.935] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.35.864] BEGIN WMNewTab: 20 +[16:48.35.864] END WMNewTab: 20 +[16:48.35.864] BEGIN WMNewTab: 20 +[16:48.35.864] END WMNewTab: 20 +[16:48.35.864] BEGIN WMNewTab: 20 +[16:48.35.864] END WMNewTab: 20 +[16:48.35.864] BEGIN WMNewTab: 20 +[16:48.35.864] END WMNewTab: 20 +[16:48.35.864] BEGIN WMNewTab: 20 +[16:48.35.864] END WMNewTab: 20 +[16:48.36.002] BEGIN WMNewTab: 20 +[16:48.36.002] END WMNewTab: 20 +[16:48.36.002] BEGIN WMNewTab: 20 +[16:48.36.002] END WMNewTab: 20 +[16:48.36.279] BEGIN WMNewTab: 20 +[16:48.36.279] END WMNewTab: 20 +[16:48.36.552] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.36.785] sListView1Click: FormClick +[16:48.36.846] (SSH-Browser) BEGIN OpenDir(1) +[16:48.36.846] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.36.846] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.36.846] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.36.846] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:48.36.848] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/root/../); +[16:48.36.848] (SSH-Browser) END OpenDir(1) +[16:48.36.857] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:48.36.857] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/) +[16:48.36.890] (SSH-Browser) ElSFTP1OpenFile(1) +[16:48.36.890] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:48.36.952] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:48.36.952] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:48.36.952] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:48.36.952] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.36.952] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.36.952] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.36.952] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:48.36.952] (SSH-Browser) END CloseCurrentHandle(1) +[16:48.36.952] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:48.36.952] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=28 +[16:48.36.952] (SSH-Browser) 对项目进行排序 +[16:48.36.953] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:48.36.965] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:48.37.013] (SSH-Browser) ElSFTP1Success(1) +[16:48.37.300] BEGIN WMNewTab: 20 +[16:48.37.300] END WMNewTab: 20 +[16:48.37.300] BEGIN WMNewTab: 20 +[16:48.37.300] END WMNewTab: 20 +[16:48.37.300] BEGIN WMNewTab: 20 +[16:48.37.300] END WMNewTab: 20 +[16:48.37.300] BEGIN WMNewTab: 20 +[16:48.37.300] END WMNewTab: 20 +[16:48.37.300] BEGIN WMNewTab: 20 +[16:48.37.300] END WMNewTab: 20 +[16:48.37.426] BEGIN WMNewTab: 20 +[16:48.37.426] END WMNewTab: 20 +[16:48.37.426] BEGIN WMNewTab: 20 +[16:48.37.426] END WMNewTab: 20 +[16:48.37.488] BEGIN WMNewTab: 20 +[16:48.37.488] END WMNewTab: 20 + +[16:48.38.396] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.38.723] BEGIN WMNewTab: 20 +[16:48.38.723] END WMNewTab: 20 +[16:48.38.723] BEGIN WMNewTab: 20 +[16:48.38.723] END WMNewTab: 20 +[16:48.38.723] BEGIN WMNewTab: 20 +[16:48.38.723] END WMNewTab: 20 +[16:48.38.723] BEGIN WMNewTab: 20 +[16:48.38.723] END WMNewTab: 20 +[16:48.38.723] BEGIN WMNewTab: 20 +[16:48.38.723] END WMNewTab: 20 +[16:48.38.749] sListView1Click: FormClick +[16:48.38.841] BEGIN WMNewTab: 20 +[16:48.38.841] END WMNewTab: 20 +[16:48.38.841] BEGIN WMNewTab: 20 +[16:48.38.841] END WMNewTab: 20 +[16:48.38.846] (SSH-Browser) BEGIN OpenDir(1) +[16:48.38.846] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.38.846] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.38.846] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.38.846] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:48.38.847] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/userdata/); +[16:48.38.847] (SSH-Browser) END OpenDir(1) +[16:48.38.904] BEGIN WMNewTab: 20 +[16:48.38.904] END WMNewTab: 20 +[16:48.38.935] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:48.38.935] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/userdata) +[16:48.38.965] (SSH-Browser) ElSFTP1OpenFile(1) +[16:48.38.965] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:48.39.027] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:48.39.027] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:48.39.027] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:48.39.027] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.39.027] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.39.027] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.39.027] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:48.39.027] (SSH-Browser) END CloseCurrentHandle(1) +[16:48.39.027] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:48.39.027] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=3 +[16:48.39.027] (SSH-Browser) 对项目进行排序 +[16:48.39.027] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:48.39.030] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:48.39.058] (SSH-Browser) ElSFTP1Success(1) + +[16:48.39.774] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.39.929] sListView1Click: FormClick +[16:48.40.019] (SSH-Browser) BEGIN OpenDir(1) +[16:48.40.019] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.40.019] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.40.019] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.40.019] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:48.40.020] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/userdata/dev_ws/); +[16:48.40.020] (SSH-Browser) END OpenDir(1) +[16:48.40.032] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:48.40.032] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/userdata/dev_ws) +[16:48.40.063] (SSH-Browser) ElSFTP1OpenFile(1) +[16:48.40.065] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:48.40.111] BEGIN WMNewTab: 20 +[16:48.40.111] END WMNewTab: 20 +[16:48.40.124] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:48.40.124] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:48.40.125] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:48.40.125] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.40.125] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.40.125] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.40.125] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:48.40.125] (SSH-Browser) END CloseCurrentHandle(1) +[16:48.40.125] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:48.40.125] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=8 +[16:48.40.125] (SSH-Browser) 对项目进行排序 +[16:48.40.125] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:48.40.129] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:48.40.177] BEGIN WMNewTab: 20 +[16:48.40.177] END WMNewTab: 20 +[16:48.40.177] BEGIN WMNewTab: 20 +[16:48.40.177] END WMNewTab: 20 +[16:48.40.177] BEGIN WMNewTab: 20 +[16:48.40.177] END WMNewTab: 20 +[16:48.40.177] BEGIN WMNewTab: 20 +[16:48.40.177] END WMNewTab: 20 +[16:48.40.177] BEGIN WMNewTab: 20 +[16:48.40.177] END WMNewTab: 20 +[16:48.40.185] (SSH-Browser) ElSFTP1Success(1) +[16:48.40.260] BEGIN WMNewTab: 20 +[16:48.40.260] END WMNewTab: 20 +[16:48.40.260] BEGIN WMNewTab: 20 +[16:48.40.260] END WMNewTab: 20 + +[16:48.41.097] sListView1Click: FormClick +[16:48.41.257] (SSH-Browser) BEGIN OpenDir(1) +[16:48.41.257] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.41.257] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.41.257] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.41.257] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:48.41.259] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/); +[16:48.41.259] (SSH-Browser) END OpenDir(1) +[16:48.41.270] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:48.41.270] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/userdata/dev_ws/src) +[16:48.41.300] (SSH-Browser) ElSFTP1OpenFile(1) +[16:48.41.300] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:48.41.316] BEGIN WMNewTab: 20 +[16:48.41.316] END WMNewTab: 20 +[16:48.41.360] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:48.41.360] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:48.41.360] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:48.41.360] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.41.360] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.41.360] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.41.360] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:48.41.360] (SSH-Browser) END CloseCurrentHandle(1) +[16:48.41.360] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:48.41.360] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=10 +[16:48.41.360] (SSH-Browser) 对项目进行排序 +[16:48.41.360] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:48.41.364] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:48.41.379] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.41.391] (SSH-Browser) ElSFTP1Success(1) +[16:48.41.587] BEGIN WMNewTab: 20 +[16:48.41.587] END WMNewTab: 20 +[16:48.41.587] BEGIN WMNewTab: 20 +[16:48.41.587] END WMNewTab: 20 +[16:48.41.587] BEGIN WMNewTab: 20 +[16:48.41.587] END WMNewTab: 20 +[16:48.41.587] BEGIN WMNewTab: 20 +[16:48.41.587] END WMNewTab: 20 +[16:48.41.587] BEGIN WMNewTab: 20 +[16:48.41.587] END WMNewTab: 20 +[16:48.41.683] BEGIN WMNewTab: 20 +[16:48.41.683] END WMNewTab: 20 +[16:48.41.683] BEGIN WMNewTab: 20 +[16:48.41.683] END WMNewTab: 20 + +[16:48.42.806] BEGIN WMNewTab: 20 +[16:48.42.806] END WMNewTab: 20 +[16:48.42.983] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.42.998] BEGIN WMNewTab: 20 +[16:48.42.998] END WMNewTab: 20 +[16:48.42.998] BEGIN WMNewTab: 20 +[16:48.42.998] END WMNewTab: 20 +[16:48.42.998] BEGIN WMNewTab: 20 +[16:48.42.998] END WMNewTab: 20 +[16:48.43.000] BEGIN WMNewTab: 20 +[16:48.43.000] END WMNewTab: 20 +[16:48.43.000] BEGIN WMNewTab: 20 +[16:48.43.000] END WMNewTab: 20 +[16:48.43.098] BEGIN WMNewTab: 20 +[16:48.43.098] END WMNewTab: 20 +[16:48.43.098] BEGIN WMNewTab: 20 +[16:48.43.098] END WMNewTab: 20 + +[16:48.44.263] BEGIN WMNewTab: 20 +[16:48.44.263] END WMNewTab: 20 +[16:48.44.415] BEGIN WMNewTab: 20 +[16:48.44.415] END WMNewTab: 20 +[16:48.44.415] BEGIN WMNewTab: 20 +[16:48.44.415] END WMNewTab: 20 +[16:48.44.415] BEGIN WMNewTab: 20 +[16:48.44.415] END WMNewTab: 20 +[16:48.44.415] BEGIN WMNewTab: 20 +[16:48.44.415] END WMNewTab: 20 +[16:48.44.415] BEGIN WMNewTab: 20 +[16:48.44.415] END WMNewTab: 20 +[16:48.44.505] BEGIN WMNewTab: 20 +[16:48.44.505] END WMNewTab: 20 +[16:48.44.505] BEGIN WMNewTab: 20 +[16:48.44.505] END WMNewTab: 20 +[16:48.44.579] sListView1Click: FormClick +[16:48.44.601] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.44.615] (SSH-Browser) BEGIN OpenDir(1) +[16:48.44.615] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.44.615] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.44.615] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.44.615] (SSH-Browser) OpenDir(1): 列出远程文件夹 +[16:48.44.616] (SSH-Browser) OpenDir(1): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/); +[16:48.44.616] (SSH-Browser) END OpenDir(1) +[16:48.44.629] (SSH-Browser) ElSFTP1AbsolutePath(1) +[16:48.44.629] (SSH-Browser) ElSFTP1AbsolutePath(1): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code) +[16:48.44.659] (SSH-Browser) ElSFTP1OpenFile(1) +[16:48.44.659] (SSH-Browser) ElSFTP1OpenFile(1): SFTP.ReadDirectory +[16:48.44.721] (SSH-Browser) ElSFTP1Error(1): #1 - End of file +[16:48.44.721] (SSH-Browser) ElSFTP1Error(1): CloseCurrentHandle1 +[16:48.44.721] (SSH-Browser) BEGIN CloseCurrentHandle(1) +[16:48.44.721] (SSH-Browser) BEGIN VerifySFTPConnection(1) +[16:48.44.721] (SSH-Browser) VerifySFTPConnection(1): result=true (Sftp 连接) +[16:48.44.721] (SSH-Browser) END VerifySFTPConnection(1) +[16:48.44.721] (SSH-Browser) CloseCurrentHandle(1): SFTP.CloseHandle +[16:48.44.721] (SSH-Browser) END CloseCurrentHandle(1) +[16:48.44.721] (SSH-Browser) BEGIN CopySFTPFileListToListView(1) +[16:48.44.721] (SSH-Browser) CopySFTPFileListToListView(1): FileList.Count=8 +[16:48.44.721] (SSH-Browser) 对项目进行排序 +[16:48.44.721] (SSH-Browser) CopySFTPFileListToListView(1): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:48.44.725] (SSH-Browser) END CopySFTPFileListToListView(1) +[16:48.44.751] (SSH-Browser) ElSFTP1Success(1) + +[16:48.45.699] BEGIN WMNewTab: 20 +[16:48.45.699] END WMNewTab: 20 +[16:48.45.833] BEGIN WMNewTab: 20 +[16:48.45.833] END WMNewTab: 20 +[16:48.45.833] BEGIN WMNewTab: 20 +[16:48.45.833] END WMNewTab: 20 +[16:48.45.833] BEGIN WMNewTab: 20 +[16:48.45.833] END WMNewTab: 20 +[16:48.45.833] BEGIN WMNewTab: 20 +[16:48.45.833] END WMNewTab: 20 +[16:48.45.833] BEGIN WMNewTab: 20 +[16:48.45.833] END WMNewTab: 20 +[16:48.45.924] BEGIN WMNewTab: 20 +[16:48.45.924] END WMNewTab: 20 +[16:48.45.924] BEGIN WMNewTab: 20 +[16:48.45.924] END WMNewTab: 20 +[16:48.46.201] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.47.115] BEGIN WMNewTab: 20 +[16:48.47.115] END WMNewTab: 20 +[16:48.47.253] BEGIN WMNewTab: 20 +[16:48.47.253] END WMNewTab: 20 +[16:48.47.253] BEGIN WMNewTab: 20 +[16:48.47.253] END WMNewTab: 20 +[16:48.47.253] BEGIN WMNewTab: 20 +[16:48.47.253] END WMNewTab: 20 +[16:48.47.253] BEGIN WMNewTab: 20 +[16:48.47.253] END WMNewTab: 20 +[16:48.47.253] BEGIN WMNewTab: 20 +[16:48.47.253] END WMNewTab: 20 +[16:48.47.343] BEGIN WMNewTab: 20 +[16:48.47.343] END WMNewTab: 20 +[16:48.47.345] BEGIN WMNewTab: 20 +[16:48.47.345] END WMNewTab: 20 +[16:48.47.439] BEGIN WMNewTab: 0 +[16:48.47.439] WMNewTab: FormClick +[16:48.47.439] WMNewTab: LooseFocus +[16:48.47.443] END WMNewTab: 0 +[16:48.47.555] BEGIN WMNewTab: 0 +[16:48.47.555] WMNewTab: FormClick +[16:48.47.555] WMNewTab: LooseFocus +[16:48.47.555] END WMNewTab: 0 +[16:48.47.818] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.48.525] Multiterminalcommand1Click: FormClick +[16:48.48.525] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.48.542] (SSH-Browser) END DesactiverPanel14 +[16:48.48.604] BEGIN TFormXterm.FormResize +[16:48.48.604] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.48.604] TFormXterm.FormResize: SplitModeResize +[16:48.48.604] BEGIN ResizeTerminal +[16:48.48.604] END ResizeTerminal +[16:48.48.604] BEGIN ResizeTerminal +[16:48.48.604] BEGIN WMNewTab: 20 +[16:48.48.604] END WMNewTab: 20 +[16:48.48.613] END ResizeTerminal +[16:48.48.613] BEGIN ResizeTerminal +[16:48.48.617] END ResizeTerminal +[16:48.48.617] BEGIN ResizeTerminal +[16:48.48.620] END ResizeTerminal +[16:48.48.620] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.48.620] BEGIN AdaptSidebarArrows +[16:48.48.620] END AdaptSidebarArrows +[16:48.48.620] TFormXterm.FormResize: AdaptTV2; +[16:48.48.620] END TFormXterm.FormResize +[16:48.48.620] BEGIN WMSize +[16:48.48.620] BEGIN TFormXterm.FormResize +[16:48.48.620] TFormXterm.FormResize: CenterBtnReattachTab +[16:48.48.620] TFormXterm.FormResize: SplitModeResize +[16:48.48.620] BEGIN ResizeTerminal +[16:48.48.620] END ResizeTerminal +[16:48.48.620] BEGIN ResizeTerminal +[16:48.48.622] END ResizeTerminal +[16:48.48.622] BEGIN ResizeTerminal +[16:48.48.623] END ResizeTerminal +[16:48.48.623] BEGIN ResizeTerminal +[16:48.48.625] END ResizeTerminal +[16:48.48.625] TFormXterm.FormResize: AdaptSidebarArrows; +[16:48.48.625] BEGIN AdaptSidebarArrows +[16:48.48.625] END AdaptSidebarArrows +[16:48.48.625] TFormXterm.FormResize: AdaptTV2; +[16:48.48.625] END TFormXterm.FormResize +[16:48.48.625] END WMSize +[16:48.48.711] BEGIN WMNewTab: 20 +[16:48.48.711] END WMNewTab: 20 +[16:48.48.711] BEGIN WMNewTab: 20 +[16:48.48.711] END WMNewTab: 20 +[16:48.48.711] BEGIN WMNewTab: 20 +[16:48.48.711] END WMNewTab: 20 +[16:48.48.711] BEGIN WMNewTab: 20 +[16:48.48.711] END WMNewTab: 20 +[16:48.48.711] BEGIN WMNewTab: 20 +[16:48.48.711] END WMNewTab: 20 +[16:48.48.780] BEGIN WMNewTab: 20 +[16:48.48.780] END WMNewTab: 20 +[16:48.48.780] BEGIN WMNewTab: 20 +[16:48.48.780] END WMNewTab: 20 +[16:48.48.958] BEGIN DisplayCurrentTab +[16:48.48.958] DisplayCurrentTab: FormClick +[16:48.48.958] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:48.48.958] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.48.958] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.48.958] (SSH-Browser) END DesactiverPanel14 +[16:48.48.958] (SSH-Browser) END ActiverPanel14; +[16:48.48.960] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.48.960] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.48.960] DisplayCurrentTab: DistribuerLeFocus +[16:48.48.960] END DisplayCurrentTab +[16:48.48.965] ReEnable_Timer1_12 +[16:48.48.967] BEGIN WMNewTab: 0 +[16:48.48.967] WMNewTab: FormClick +[16:48.48.967] WMNewTab: LooseFocus +[16:48.48.967] 更改标签页索引 I = 1 +[16:48.48.967] BEGIN DisplayCurrentTab +[16:48.48.967] DisplayCurrentTab: FormClick +[16:48.48.967] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:48.48.968] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.48.968] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.48.968] (SSH-Browser) END DesactiverPanel14 +[16:48.48.968] (SSH-Browser) END ActiverPanel14; +[16:48.48.968] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.48.968] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.48.968] DisplayCurrentTab: DistribuerLeFocus +[16:48.48.968] END DisplayCurrentTab +[16:48.48.968] END WMNewTab: 0 +[16:48.49.069] BEGIN WMNewTab: 0 +[16:48.49.069] WMNewTab: FormClick +[16:48.49.070] WMNewTab: LooseFocus +[16:48.49.070] 更改标签页索引 I = 1 +[16:48.49.070] BEGIN DisplayCurrentTab +[16:48.49.070] DisplayCurrentTab: FormClick +[16:48.49.070] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:48.49.070] (SSH-Browser) BEGIN ActiverPanel14 +[16:48.49.070] (SSH-Browser) BEGIN DesactiverPanel14 +[16:48.49.070] (SSH-Browser) END DesactiverPanel14 +[16:48.49.070] (SSH-Browser) END ActiverPanel14; +[16:48.49.070] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:48.49.071] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:48.49.071] DisplayCurrentTab: DistribuerLeFocus +[16:48.49.071] END DisplayCurrentTab +[16:48.49.071] END WMNewTab: 0 +[16:48.49.432] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.50.013] BEGIN WMNewTab: 20 +[16:48.50.013] END WMNewTab: 20 +[16:48.50.121] BEGIN WMNewTab: 20 +[16:48.50.121] END WMNewTab: 20 +[16:48.50.121] BEGIN WMNewTab: 20 +[16:48.50.121] END WMNewTab: 20 +[16:48.50.121] BEGIN WMNewTab: 20 +[16:48.50.121] END WMNewTab: 20 +[16:48.50.121] BEGIN WMNewTab: 20 +[16:48.50.121] END WMNewTab: 20 +[16:48.50.121] BEGIN WMNewTab: 20 +[16:48.50.121] END WMNewTab: 20 +[16:48.50.197] BEGIN WMNewTab: 20 +[16:48.50.197] END WMNewTab: 20 +[16:48.50.198] BEGIN WMNewTab: 20 +[16:48.50.198] END WMNewTab: 20 + +[16:48.51.038] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.51.435] BEGIN WMNewTab: 20 +[16:48.51.435] END WMNewTab: 20 +[16:48.51.541] BEGIN WMNewTab: 20 +[16:48.51.541] END WMNewTab: 20 +[16:48.51.541] BEGIN WMNewTab: 20 +[16:48.51.541] END WMNewTab: 20 +[16:48.51.541] BEGIN WMNewTab: 20 +[16:48.51.541] END WMNewTab: 20 +[16:48.51.541] BEGIN WMNewTab: 20 +[16:48.51.541] END WMNewTab: 20 +[16:48.51.541] BEGIN WMNewTab: 20 +[16:48.51.541] END WMNewTab: 20 +[16:48.51.618] BEGIN WMNewTab: 20 +[16:48.51.618] END WMNewTab: 20 +[16:48.51.618] BEGIN WMNewTab: 20 +[16:48.51.618] END WMNewTab: 20 + +[16:48.52.642] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.52.855] BEGIN WMNewTab: 20 +[16:48.52.855] END WMNewTab: 20 +[16:48.52.962] BEGIN WMNewTab: 20 +[16:48.52.962] END WMNewTab: 20 +[16:48.52.962] BEGIN WMNewTab: 20 +[16:48.52.962] END WMNewTab: 20 +[16:48.52.962] BEGIN WMNewTab: 20 +[16:48.52.962] END WMNewTab: 20 +[16:48.52.962] BEGIN WMNewTab: 20 +[16:48.52.963] END WMNewTab: 20 +[16:48.52.963] BEGIN WMNewTab: 20 +[16:48.52.963] END WMNewTab: 20 +[16:48.53.039] BEGIN WMNewTab: 20 +[16:48.53.039] END WMNewTab: 20 +[16:48.53.039] BEGIN WMNewTab: 20 +[16:48.53.039] END WMNewTab: 20 + + +[16:48.54.247] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.54.278] BEGIN WMNewTab: 20 +[16:48.54.278] END WMNewTab: 20 +[16:48.54.386] BEGIN WMNewTab: 20 +[16:48.54.386] END WMNewTab: 20 +[16:48.54.386] BEGIN WMNewTab: 20 +[16:48.54.386] END WMNewTab: 20 +[16:48.54.387] BEGIN WMNewTab: 20 +[16:48.54.387] END WMNewTab: 20 +[16:48.54.387] BEGIN WMNewTab: 20 +[16:48.54.387] END WMNewTab: 20 +[16:48.54.387] BEGIN WMNewTab: 20 +[16:48.54.387] END WMNewTab: 20 +[16:48.54.464] BEGIN WMNewTab: 20 +[16:48.54.464] END WMNewTab: 20 +[16:48.54.464] BEGIN WMNewTab: 20 +[16:48.54.464] END WMNewTab: 20 + + +[16:48.55.701] BEGIN WMNewTab: 20 +[16:48.55.701] END WMNewTab: 20 +[16:48.55.808] BEGIN WMNewTab: 20 +[16:48.55.808] END WMNewTab: 20 +[16:48.55.808] BEGIN WMNewTab: 20 +[16:48.55.808] END WMNewTab: 20 +[16:48.55.808] BEGIN WMNewTab: 20 +[16:48.55.808] END WMNewTab: 20 +[16:48.55.808] BEGIN WMNewTab: 20 +[16:48.55.808] END WMNewTab: 20 +[16:48.55.808] BEGIN WMNewTab: 20 +[16:48.55.808] END WMNewTab: 20 +[16:48.55.869] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:48.55.884] BEGIN WMNewTab: 20 +[16:48.55.885] END WMNewTab: 20 +[16:48.55.885] BEGIN WMNewTab: 20 +[16:48.55.885] END WMNewTab: 20 + + +[16:48.57.117] BEGIN WMNewTab: 20 +[16:48.57.117] END WMNewTab: 20 +[16:48.57.224] BEGIN WMNewTab: 20 +[16:48.57.224] END WMNewTab: 20 +[16:48.57.224] BEGIN WMNewTab: 20 +[16:48.57.224] END WMNewTab: 20 +[16:48.57.225] BEGIN WMNewTab: 20 +[16:48.57.225] END WMNewTab: 20 +[16:48.57.225] BEGIN WMNewTab: 20 +[16:48.57.225] END WMNewTab: 20 +[16:48.57.225] BEGIN WMNewTab: 20 +[16:48.57.225] END WMNewTab: 20 +[16:48.57.300] BEGIN WMNewTab: 20 +[16:48.57.300] END WMNewTab: 20 +[16:48.57.300] BEGIN WMNewTab: 20 +[16:48.57.300] END WMNewTab: 20 +[16:48.57.469] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.58.545] BEGIN WMNewTab: 20 +[16:48.58.545] END WMNewTab: 20 +[16:48.58.650] BEGIN WMNewTab: 20 +[16:48.58.650] END WMNewTab: 20 +[16:48.58.650] BEGIN WMNewTab: 20 +[16:48.58.650] END WMNewTab: 20 +[16:48.58.650] BEGIN WMNewTab: 20 +[16:48.58.650] END WMNewTab: 20 +[16:48.58.650] BEGIN WMNewTab: 20 +[16:48.58.650] END WMNewTab: 20 +[16:48.58.650] BEGIN WMNewTab: 20 +[16:48.58.650] END WMNewTab: 20 +[16:48.58.727] BEGIN WMNewTab: 20 +[16:48.58.727] END WMNewTab: 20 +[16:48.58.727] BEGIN WMNewTab: 20 +[16:48.58.727] END WMNewTab: 20 +[16:48.59.077] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:48.59.960] BEGIN WMNewTab: 20 +[16:48.59.960] END WMNewTab: 20 +[16:49.00.067] BEGIN WMNewTab: 20 +[16:49.00.067] END WMNewTab: 20 +[16:49.00.067] BEGIN WMNewTab: 20 +[16:49.00.067] END WMNewTab: 20 +[16:49.00.067] BEGIN WMNewTab: 20 +[16:49.00.067] END WMNewTab: 20 +[16:49.00.067] BEGIN WMNewTab: 20 +[16:49.00.067] END WMNewTab: 20 +[16:49.00.067] BEGIN WMNewTab: 20 +[16:49.00.067] END WMNewTab: 20 +[16:49.00.142] BEGIN WMNewTab: 20 +[16:49.00.143] END WMNewTab: 20 +[16:49.00.143] BEGIN WMNewTab: 20 +[16:49.00.143] END WMNewTab: 20 + +[16:49.00.689] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.01.370] BEGIN WMNewTab: 20 +[16:49.01.370] END WMNewTab: 20 +[16:49.01.477] BEGIN WMNewTab: 20 +[16:49.01.477] END WMNewTab: 20 +[16:49.01.477] BEGIN WMNewTab: 20 +[16:49.01.477] END WMNewTab: 20 +[16:49.01.477] BEGIN WMNewTab: 20 +[16:49.01.477] END WMNewTab: 20 +[16:49.01.477] BEGIN WMNewTab: 20 +[16:49.01.477] END WMNewTab: 20 +[16:49.01.477] BEGIN WMNewTab: 20 +[16:49.01.477] END WMNewTab: 20 +[16:49.01.552] BEGIN WMNewTab: 20 +[16:49.01.552] END WMNewTab: 20 +[16:49.01.552] BEGIN WMNewTab: 20 +[16:49.01.552] END WMNewTab: 20 + +[16:49.02.293] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.02.780] BEGIN WMNewTab: 20 +[16:49.02.780] END WMNewTab: 20 +[16:49.02.888] BEGIN WMNewTab: 20 +[16:49.02.888] END WMNewTab: 20 +[16:49.02.888] BEGIN WMNewTab: 20 +[16:49.02.888] END WMNewTab: 20 +[16:49.02.888] BEGIN WMNewTab: 20 +[16:49.02.888] END WMNewTab: 20 +[16:49.02.888] BEGIN WMNewTab: 20 +[16:49.02.888] END WMNewTab: 20 +[16:49.02.888] BEGIN WMNewTab: 20 +[16:49.02.888] END WMNewTab: 20 +[16:49.02.963] BEGIN WMNewTab: 20 +[16:49.02.963] END WMNewTab: 20 +[16:49.02.963] BEGIN WMNewTab: 20 +[16:49.02.963] END WMNewTab: 20 + +[16:49.03.909] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.04.198] BEGIN WMNewTab: 20 +[16:49.04.198] END WMNewTab: 20 +[16:49.04.305] BEGIN WMNewTab: 20 +[16:49.04.305] END WMNewTab: 20 +[16:49.04.305] BEGIN WMNewTab: 20 +[16:49.04.305] END WMNewTab: 20 +[16:49.04.305] BEGIN WMNewTab: 20 +[16:49.04.305] END WMNewTab: 20 +[16:49.04.305] BEGIN WMNewTab: 20 +[16:49.04.305] END WMNewTab: 20 +[16:49.04.305] BEGIN WMNewTab: 20 +[16:49.04.305] END WMNewTab: 20 +[16:49.04.382] BEGIN WMNewTab: 20 +[16:49.04.382] END WMNewTab: 20 +[16:49.04.382] BEGIN WMNewTab: 20 +[16:49.04.382] END WMNewTab: 20 + +[16:49.05.522] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.05.614] BEGIN WMNewTab: 20 +[16:49.05.614] END WMNewTab: 20 +[16:49.05.720] BEGIN WMNewTab: 20 +[16:49.05.720] END WMNewTab: 20 +[16:49.05.720] BEGIN WMNewTab: 20 +[16:49.05.720] END WMNewTab: 20 +[16:49.05.720] BEGIN WMNewTab: 20 +[16:49.05.720] END WMNewTab: 20 +[16:49.05.720] BEGIN WMNewTab: 20 +[16:49.05.720] END WMNewTab: 20 +[16:49.05.720] BEGIN WMNewTab: 20 +[16:49.05.720] END WMNewTab: 20 +[16:49.05.847] BEGIN WMNewTab: 20 +[16:49.05.847] END WMNewTab: 20 +[16:49.05.847] BEGIN WMNewTab: 20 +[16:49.05.847] END WMNewTab: 20 + +[16:49.06.808] BEGIN LockControl(sPanel1, sBitBtn16Click) +[16:49.06.809] END LockControl(sPanel1, sBitBtn16Click) +[16:49.06.841] BEGIN TFormXterm.FormResize +[16:49.06.841] TFormXterm.FormResize: CenterBtnReattachTab +[16:49.06.842] TFormXterm.FormResize: SplitModeResize +[16:49.06.842] TFormXterm.FormResize: sPanel7.Visible +[16:49.06.950] TFormXterm.FormResize: AdaptSidebarArrows; +[16:49.06.950] BEGIN AdaptSidebarArrows +[16:49.06.950] END AdaptSidebarArrows +[16:49.06.950] TFormXterm.FormResize: AdaptTV2; +[16:49.06.950] END TFormXterm.FormResize +[16:49.06.950] BEGIN WMSize +[16:49.06.950] BEGIN TFormXterm.FormResize +[16:49.06.950] TFormXterm.FormResize: CenterBtnReattachTab +[16:49.06.950] TFormXterm.FormResize: SplitModeResize +[16:49.06.950] TFormXterm.FormResize: sPanel7.Visible +[16:49.07.047] BEGIN WMNewTab: 20 +[16:49.07.047] END WMNewTab: 20 +[16:49.07.080] TFormXterm.FormResize: AdaptSidebarArrows; +[16:49.07.080] BEGIN AdaptSidebarArrows +[16:49.07.080] END AdaptSidebarArrows +[16:49.07.080] TFormXterm.FormResize: AdaptTV2; +[16:49.07.080] END TFormXterm.FormResize +[16:49.07.080] END WMSize +[16:49.07.120] BtnSplitNoClick: FormClick +[16:49.07.120] BEGIN LockControl(sPanel1, BtnSplitNoClick) +[16:49.07.120] END LockControl(sPanel1, BtnSplitNoClick) +[16:49.07.159] BEGIN WMNewTab: 20 +[16:49.07.159] END WMNewTab: 20 +[16:49.07.159] BEGIN WMNewTab: 20 +[16:49.07.159] END WMNewTab: 20 +[16:49.07.159] BEGIN WMNewTab: 20 +[16:49.07.159] END WMNewTab: 20 +[16:49.07.159] BEGIN WMNewTab: 20 +[16:49.07.159] END WMNewTab: 20 +[16:49.07.159] BEGIN WMNewTab: 20 +[16:49.07.159] END WMNewTab: 20 +[16:49.07.252] 更改标签页索引 K = 0 +[16:49.07.253] BEGIN DisplayCurrentTab +[16:49.07.253] DisplayCurrentTab: FormClick +[16:49.07.253] (SSH-Browser) DisplayCurrentTab(0): ActiverPanel14 +[16:49.07.253] (SSH-Browser) BEGIN ActiverPanel14 +[16:49.07.253] (SSH-Browser) BEGIN DesactiverPanel14 +[16:49.07.253] (SSH-Browser) END DesactiverPanel14 +[16:49.07.253] (SSH-Browser) END ActiverPanel14; +[16:49.07.386] BEGIN TFormXterm.FormResize +[16:49.07.386] TFormXterm.FormResize: CenterBtnReattachTab +[16:49.07.387] TFormXterm.FormResize: SplitModeResize +[16:49.07.387] TFormXterm.FormResize: BtnSplitNo.Down +[16:49.07.389] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:49.07.389] BEGIN ResizeTerminal +[16:49.07.389] END ResizeTerminal +[16:49.07.389] TFormXterm.FormResize: AdaptSidebarArrows; +[16:49.07.389] BEGIN AdaptSidebarArrows +[16:49.07.389] END AdaptSidebarArrows +[16:49.07.389] TFormXterm.FormResize: AdaptTV2; +[16:49.07.389] END TFormXterm.FormResize +[16:49.07.389] DisplayCurrentTab: Cts1.BeginUpdate; +[16:49.07.389] Cts1ActiveTabChanged: New index = 0 +[16:49.07.389] DisplayCurrentTab: Cts1.EndUpdates +[16:49.07.475] DisplayCurrentTab: 显示所选标签页 +[16:49.07.482] BEGIN ResizeTerminal +[16:49.07.482] END ResizeTerminal +[16:49.07.482] DisplayCurrentTab: 隐藏其他标签页 +[16:49.07.482] BEGIN WMNewTab: 20 +[16:49.07.482] END WMNewTab: 20 +[16:49.07.482] BEGIN WMNewTab: 20 +[16:49.07.482] END WMNewTab: 20 +[16:49.07.524] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:49.07.525] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:49.07.525] DisplayCurrentTab: DistribuerLeFocus +[16:49.07.525] BEGIN WMNewTab: 0 +[16:49.07.525] WMNewTab: FormClick +[16:49.07.525] WMNewTab: LooseFocus +[16:49.07.525] END WMNewTab: 0 +[16:49.07.525] BEGIN WMNewTab: 0 +[16:49.07.525] WMNewTab: FormClick +[16:49.07.525] WMNewTab: LooseFocus +[16:49.07.526] END WMNewTab: 0 +[16:49.07.526] BEGIN WMNewTab: 0 +[16:49.07.526] WMNewTab: FormClick +[16:49.07.526] WMNewTab: LooseFocus +[16:49.07.526] END WMNewTab: 0 +[16:49.07.526] BEGIN WMNewTab: 0 +[16:49.07.526] WMNewTab: FormClick +[16:49.07.526] WMNewTab: LooseFocus +[16:49.07.526] END WMNewTab: 0 +[16:49.07.526] END DisplayCurrentTab +[16:49.07.527] BEGIN TFormXterm.FormResize +[16:49.07.527] TFormXterm.FormResize: CenterBtnReattachTab +[16:49.07.527] TFormXterm.FormResize: SplitModeResize +[16:49.07.527] TFormXterm.FormResize: BtnSplitNo.Down +[16:49.07.527] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:49.07.527] BEGIN ResizeTerminal +[16:49.07.527] END ResizeTerminal +[16:49.07.527] TFormXterm.FormResize: AdaptSidebarArrows; +[16:49.07.527] BEGIN AdaptSidebarArrows +[16:49.07.527] END AdaptSidebarArrows +[16:49.07.527] TFormXterm.FormResize: AdaptTV2; +[16:49.07.527] END TFormXterm.FormResize +[16:49.07.527] ReEnable_Timer1_7 +[16:49.07.527] BEGIN UnlockControl(sPanel1, BtnSplitNoClick) +[16:49.07.527] END UnlockControl(sPanel1, BtnSplitNoClick) +[16:49.07.527] 释放对象 PanTerm_7 (TPanel) +[16:49.07.536] 释放对象 TsCheckBox +[16:49.07.539] 释放对象 PanTerm_6 (TPanel) +[16:49.07.544] 释放对象 TsCheckBox +[16:49.07.547] 释放对象 PanTerm_5 (TPanel) +[16:49.07.557] 释放对象 TsCheckBox +[16:49.07.559] 释放对象 PanTerm_4 (TPanel) +[16:49.07.562] 释放对象 TsCheckBox +[16:49.07.566] 释放对象 PanTerm_3 (TPanel) +[16:49.07.568] 释放对象 TsCheckBox +[16:49.07.570] 释放对象 PanTerm_2 (TPanel) +[16:49.07.572] 释放对象 TsCheckBox +[16:49.07.575] 释放对象 PanTerm_1 (TPanel) +[16:49.07.579] 释放对象 TsCheckBox +[16:49.07.581] 释放对象 PanTerm_0 (TPanel) +[16:49.07.584] 释放对象 TsCheckBox +[16:49.07.623] BEGIN TFormXterm.FormResize +[16:49.07.623] TFormXterm.FormResize: CenterBtnReattachTab +[16:49.07.624] TFormXterm.FormResize: SplitModeResize +[16:49.07.624] TFormXterm.FormResize: BtnSplitNo.Down +[16:49.07.626] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:49.07.626] BEGIN ResizeTerminal +[16:49.07.626] END ResizeTerminal +[16:49.07.626] TFormXterm.FormResize: AdaptSidebarArrows; +[16:49.07.626] BEGIN AdaptSidebarArrows +[16:49.07.626] END AdaptSidebarArrows +[16:49.07.626] TFormXterm.FormResize: AdaptTV2; +[16:49.07.626] END TFormXterm.FormResize +[16:49.07.626] BEGIN UnlockControl(sPanel1, sBitBtn16Click) +[16:49.07.626] END UnlockControl(sPanel1, sBitBtn16Click) +[16:49.07.628] sBitBtn16Click_ReEnable_Timer1 +[16:49.07.690] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.08.306] Cts1MouseDown: FormClick +[16:49.08.320] Cts1ActiveTabChanged: New index = 1 +[16:49.08.320] BEGIN DisplayCurrentTab +[16:49.08.320] DisplayCurrentTab: FormClick +[16:49.08.320] (SSH-Browser) DisplayCurrentTab(1): ActiverPanel14 +[16:49.08.320] (SSH-Browser) BEGIN ActiverPanel14 +[16:49.08.320] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:49.08.327] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:49.08.327] (SSH-Browser) ActiverPanel14: 列出远程目录 +[16:49.08.327] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[1].RemList +[16:49.08.328] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[1].RemList +[16:49.08.360] (SSH-Browser) END ActiverPanel14; +[16:49.08.398] BEGIN TFormXterm.FormResize +[16:49.08.398] TFormXterm.FormResize: CenterBtnReattachTab +[16:49.08.399] TFormXterm.FormResize: SplitModeResize +[16:49.08.399] TFormXterm.FormResize: BtnSplitNo.Down +[16:49.08.401] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:49.08.401] BEGIN ResizeTerminal +[16:49.08.405] END ResizeTerminal +[16:49.08.405] TFormXterm.FormResize: AdaptSidebarArrows; +[16:49.08.405] BEGIN AdaptSidebarArrows +[16:49.08.405] END AdaptSidebarArrows +[16:49.08.405] TFormXterm.FormResize: AdaptTV2; +[16:49.08.405] END TFormXterm.FormResize +[16:49.08.405] (SSH-Browser) 正在启动 MobaSCP(2, remotemonitoring, ., ) +[16:49.08.405] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:49.08.446] ShellExecuteS: ShellExecuteEx 成功. +[16:49.08.446] ShellExecuteS: WaitForInputIdle 失败. +[16:49.08.446] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756662" -remotemonitoring mobauser@mobaserver:".") +[16:49.08.446] DisplayCurrentTab: Cts1.BeginUpdate; +[16:49.08.446] DisplayCurrentTab: Cts1.EndUpdates +[16:49.08.555] DisplayCurrentTab: 显示所选标签页 +[16:49.08.555] BEGIN WMNewTab: 20 +[16:49.08.555] END WMNewTab: 20 +[16:49.08.555] [MobaSCP2] Launching remote monitoring in normal mode +[16:49.08.556] [MobaSCP2] Multiplex=1 +[16:49.08.557] [MobaSCP2] HOSTNAME: 192.168.127.10 +[16:49.08.557] [MobaSCP2] USERNAME: root +[16:49.08.557] DisplayCurrentTab: 隐藏其他标签页 +[16:49.08.570] BEGIN WMNewTab: 20 +[16:49.08.570] END WMNewTab: 20 +[16:49.08.571] BEGIN WMNewTab: 20 +[16:49.08.571] END WMNewTab: 20 +[16:49.08.571] BEGIN WMNewTab: 20 +[16:49.08.571] END WMNewTab: 20 +[16:49.08.571] BEGIN WMNewTab: 20 +[16:49.08.571] END WMNewTab: 20 +[16:49.08.571] BEGIN WMNewTab: 20 +[16:49.08.571] END WMNewTab: 20 +[16:49.08.622] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:49.08.626] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:49.08.626] DisplayCurrentTab: DistribuerLeFocus +[16:49.08.626] END DisplayCurrentTab +[16:49.08.724] [MobaSCP2] Using SCP1 +[16:49.08.724] [MobaSCP2] Connected to 192.168.127.10 +[16:49.08.746] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.08.889] BEGIN WMNewTab: 20 +[16:49.08.889] END WMNewTab: 20 +[16:49.08.889] BEGIN WMNewTab: 20 +[16:49.08.889] END WMNewTab: 20 + +[16:49.09.863] BEGIN TFormXterm.FormResize +[16:49.09.863] TFormXterm.FormResize: CenterBtnReattachTab +[16:49.09.863] TFormXterm.FormResize: SplitModeResize +[16:49.09.863] TFormXterm.FormResize: BtnSplitNo.Down +[16:49.09.863] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:49.09.863] BEGIN ResizeTerminal +[16:49.09.864] END ResizeTerminal +[16:49.09.864] TFormXterm.FormResize: AdaptSidebarArrows; +[16:49.09.864] BEGIN AdaptSidebarArrows +[16:49.09.864] END AdaptSidebarArrows +[16:49.09.864] TFormXterm.FormResize: AdaptTV2; +[16:49.09.864] END TFormXterm.FormResize +[16:49.09.969] BEGIN WMNewTab: 20 +[16:49.09.969] END WMNewTab: 20 +[16:49.09.984] BEGIN WMNewTab: 20 +[16:49.09.984] END WMNewTab: 20 +[16:49.09.984] BEGIN WMNewTab: 20 +[16:49.09.984] END WMNewTab: 20 +[16:49.09.984] BEGIN WMNewTab: 20 +[16:49.09.984] END WMNewTab: 20 +[16:49.09.984] BEGIN WMNewTab: 20 +[16:49.09.984] END WMNewTab: 20 +[16:49.09.984] BEGIN WMNewTab: 20 +[16:49.09.984] END WMNewTab: 20 +[16:49.10.304] BEGIN WMNewTab: 20 +[16:49.10.304] END WMNewTab: 20 +[16:49.10.304] BEGIN WMNewTab: 20 +[16:49.10.304] END WMNewTab: 20 +[16:49.10.341] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.11.382] BEGIN WMNewTab: 20 +[16:49.11.382] END WMNewTab: 20 +[16:49.11.398] BEGIN WMNewTab: 20 +[16:49.11.398] END WMNewTab: 20 +[16:49.11.398] BEGIN WMNewTab: 20 +[16:49.11.398] END WMNewTab: 20 +[16:49.11.398] BEGIN WMNewTab: 20 +[16:49.11.398] END WMNewTab: 20 +[16:49.11.398] BEGIN WMNewTab: 20 +[16:49.11.398] END WMNewTab: 20 +[16:49.11.398] BEGIN WMNewTab: 20 +[16:49.11.398] END WMNewTab: 20 +[16:49.11.717] BEGIN WMNewTab: 20 +[16:49.11.717] END WMNewTab: 20 +[16:49.11.717] BEGIN WMNewTab: 20 +[16:49.11.717] END WMNewTab: 20 +[16:49.11.959] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.12.195] BEGIN WMNCLButtonDown +[16:49.12.254] BEGIN WMSysCommand (minimize/restore) +[16:49.12.375] BEGIN WMSize +[16:49.12.375] END WMSize +[16:49.12.414] END WMSysCommand +[16:49.12.414] END WMNCLButtonDown + +[16:49.12.813] BEGIN WMNewTab: 20 +[16:49.12.813] END WMNewTab: 20 +[16:49.12.815] BEGIN WMNewTab: 20 +[16:49.12.815] END WMNewTab: 20 +[16:49.12.815] BEGIN WMNewTab: 20 +[16:49.12.815] END WMNewTab: 20 +[16:49.12.815] BEGIN WMNewTab: 20 +[16:49.12.815] END WMNewTab: 20 +[16:49.12.815] BEGIN WMNewTab: 20 +[16:49.12.815] END WMNewTab: 20 +[16:49.12.815] BEGIN WMNewTab: 20 +[16:49.12.815] END WMNewTab: 20 +[16:49.13.135] BEGIN WMNewTab: 20 +[16:49.13.135] END WMNewTab: 20 +[16:49.13.135] BEGIN WMNewTab: 20 +[16:49.13.135] END WMNewTab: 20 + +[16:49.13.565] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.14.233] BEGIN WMNewTab: 20 +[16:49.14.233] END WMNewTab: 20 +[16:49.14.234] BEGIN WMNewTab: 20 +[16:49.14.234] END WMNewTab: 20 +[16:49.14.234] BEGIN WMNewTab: 20 +[16:49.14.234] END WMNewTab: 20 +[16:49.14.235] BEGIN WMNewTab: 20 +[16:49.14.235] END WMNewTab: 20 +[16:49.14.235] BEGIN WMNewTab: 20 +[16:49.14.235] END WMNewTab: 20 +[16:49.14.235] BEGIN WMNewTab: 20 +[16:49.14.235] END WMNewTab: 20 +[16:49.14.554] BEGIN WMNewTab: 20 +[16:49.14.554] END WMNewTab: 20 +[16:49.14.554] BEGIN WMNewTab: 20 +[16:49.14.554] END WMNewTab: 20 + +[16:49.15.178] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.15.653] BEGIN WMNewTab: 20 +[16:49.15.653] END WMNewTab: 20 +[16:49.15.653] BEGIN WMNewTab: 20 +[16:49.15.653] END WMNewTab: 20 +[16:49.15.654] BEGIN WMNewTab: 20 +[16:49.15.654] END WMNewTab: 20 +[16:49.15.654] BEGIN WMNewTab: 20 +[16:49.15.654] END WMNewTab: 20 +[16:49.15.654] BEGIN WMNewTab: 20 +[16:49.15.654] END WMNewTab: 20 +[16:49.15.654] BEGIN WMNewTab: 20 +[16:49.15.654] END WMNewTab: 20 +[16:49.15.976] BEGIN WMNewTab: 20 +[16:49.15.976] END WMNewTab: 20 +[16:49.15.976] BEGIN WMNewTab: 20 +[16:49.15.976] END WMNewTab: 20 + +[16:49.16.783] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.17.070] BEGIN WMNewTab: 20 +[16:49.17.070] END WMNewTab: 20 +[16:49.17.071] BEGIN WMNewTab: 20 +[16:49.17.071] END WMNewTab: 20 +[16:49.17.071] BEGIN WMNewTab: 20 +[16:49.17.071] END WMNewTab: 20 +[16:49.17.071] BEGIN WMNewTab: 20 +[16:49.17.071] END WMNewTab: 20 +[16:49.17.071] BEGIN WMNewTab: 20 +[16:49.17.071] END WMNewTab: 20 +[16:49.17.071] BEGIN WMNewTab: 20 +[16:49.17.071] END WMNewTab: 20 +[16:49.17.389] BEGIN WMNewTab: 20 +[16:49.17.389] END WMNewTab: 20 +[16:49.17.389] BEGIN WMNewTab: 20 +[16:49.17.389] END WMNewTab: 20 + +[16:49.18.401] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.18.492] BEGIN WMNewTab: 20 +[16:49.18.492] END WMNewTab: 20 +[16:49.18.492] BEGIN WMNewTab: 20 +[16:49.18.492] END WMNewTab: 20 +[16:49.18.492] BEGIN WMNewTab: 20 +[16:49.18.492] END WMNewTab: 20 +[16:49.18.492] BEGIN WMNewTab: 20 +[16:49.18.492] END WMNewTab: 20 +[16:49.18.492] BEGIN WMNewTab: 20 +[16:49.18.492] END WMNewTab: 20 +[16:49.18.492] BEGIN WMNewTab: 20 +[16:49.18.492] END WMNewTab: 20 +[16:49.18.811] BEGIN WMNewTab: 20 +[16:49.18.811] END WMNewTab: 20 +[16:49.18.811] BEGIN WMNewTab: 20 +[16:49.18.811] END WMNewTab: 20 + +[16:49.19.916] BEGIN WMNewTab: 20 +[16:49.19.916] END WMNewTab: 20 +[16:49.19.921] BEGIN WMNewTab: 20 +[16:49.19.921] END WMNewTab: 20 +[16:49.19.925] BEGIN WMNewTab: 20 +[16:49.19.925] END WMNewTab: 20 +[16:49.19.932] BEGIN WMNewTab: 20 +[16:49.19.932] END WMNewTab: 20 +[16:49.19.934] BEGIN WMNewTab: 20 +[16:49.19.934] END WMNewTab: 20 +[16:49.19.937] BEGIN WMNewTab: 20 +[16:49.19.937] END WMNewTab: 20 +[16:49.20.081] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.20.227] BEGIN WMNewTab: 20 +[16:49.20.227] END WMNewTab: 20 +[16:49.20.227] BEGIN WMNewTab: 20 +[16:49.20.227] END WMNewTab: 20 + +[16:49.21.344] BEGIN WMNewTab: 20 +[16:49.21.344] END WMNewTab: 20 +[16:49.21.344] BEGIN WMNewTab: 20 +[16:49.21.344] END WMNewTab: 20 +[16:49.21.344] BEGIN WMNewTab: 20 +[16:49.21.344] END WMNewTab: 20 +[16:49.21.360] BEGIN WMNewTab: 20 +[16:49.21.360] END WMNewTab: 20 +[16:49.21.361] BEGIN WMNewTab: 20 +[16:49.21.361] END WMNewTab: 20 +[16:49.21.361] BEGIN WMNewTab: 20 +[16:49.21.361] END WMNewTab: 20 +[16:49.21.606] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.21.651] BEGIN WMNewTab: 20 +[16:49.21.651] END WMNewTab: 20 +[16:49.21.651] BEGIN WMNewTab: 20 +[16:49.21.651] END WMNewTab: 20 + +[16:49.22.758] BEGIN WMNewTab: 20 +[16:49.22.758] END WMNewTab: 20 +[16:49.22.758] BEGIN WMNewTab: 20 +[16:49.22.758] END WMNewTab: 20 +[16:49.22.758] BEGIN WMNewTab: 20 +[16:49.22.758] END WMNewTab: 20 +[16:49.22.774] BEGIN WMNewTab: 20 +[16:49.22.774] END WMNewTab: 20 +[16:49.22.774] BEGIN WMNewTab: 20 +[16:49.22.774] END WMNewTab: 20 +[16:49.22.774] BEGIN WMNewTab: 20 +[16:49.22.774] END WMNewTab: 20 +[16:49.23.062] BEGIN WMNewTab: 20 +[16:49.23.062] END WMNewTab: 20 +[16:49.23.062] BEGIN WMNewTab: 20 +[16:49.23.062] END WMNewTab: 20 +[16:49.23.222] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.24.176] BEGIN WMNewTab: 20 +[16:49.24.177] END WMNewTab: 20 +[16:49.24.177] BEGIN WMNewTab: 20 +[16:49.24.177] END WMNewTab: 20 +[16:49.24.177] BEGIN WMNewTab: 20 +[16:49.24.177] END WMNewTab: 20 +[16:49.24.192] BEGIN WMNewTab: 20 +[16:49.24.192] END WMNewTab: 20 +[16:49.24.192] BEGIN WMNewTab: 20 +[16:49.24.192] END WMNewTab: 20 +[16:49.24.192] BEGIN WMNewTab: 20 +[16:49.24.192] END WMNewTab: 20 +[16:49.24.481] BEGIN WMNewTab: 20 +[16:49.24.481] END WMNewTab: 20 +[16:49.24.481] BEGIN WMNewTab: 20 +[16:49.24.481] END WMNewTab: 20 +[16:49.24.830] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.25.595] BEGIN WMNewTab: 20 +[16:49.25.595] END WMNewTab: 20 +[16:49.25.595] BEGIN WMNewTab: 20 +[16:49.25.595] END WMNewTab: 20 +[16:49.25.595] BEGIN WMNewTab: 20 +[16:49.25.595] END WMNewTab: 20 +[16:49.25.610] BEGIN WMNewTab: 20 +[16:49.25.610] END WMNewTab: 20 +[16:49.25.612] BEGIN WMNewTab: 20 +[16:49.25.612] END WMNewTab: 20 +[16:49.25.612] BEGIN WMNewTab: 20 +[16:49.25.612] END WMNewTab: 20 +[16:49.25.900] BEGIN WMNewTab: 20 +[16:49.25.900] END WMNewTab: 20 +[16:49.25.900] BEGIN WMNewTab: 20 +[16:49.25.900] END WMNewTab: 20 + +[16:49.26.439] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.27.017] BEGIN WMNewTab: 20 +[16:49.27.017] END WMNewTab: 20 +[16:49.27.017] BEGIN WMNewTab: 20 +[16:49.27.017] END WMNewTab: 20 +[16:49.27.017] BEGIN WMNewTab: 20 +[16:49.27.017] END WMNewTab: 20 +[16:49.27.031] BEGIN WMNewTab: 20 +[16:49.27.031] END WMNewTab: 20 +[16:49.27.031] BEGIN WMNewTab: 20 +[16:49.27.031] END WMNewTab: 20 +[16:49.27.033] BEGIN WMNewTab: 20 +[16:49.27.033] END WMNewTab: 20 +[16:49.27.364] BEGIN WMNewTab: 20 +[16:49.27.364] END WMNewTab: 20 +[16:49.27.365] BEGIN WMNewTab: 20 +[16:49.27.365] END WMNewTab: 20 + +[16:49.28.054] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.28.437] BEGIN WMNewTab: 20 +[16:49.28.437] END WMNewTab: 20 +[16:49.28.437] BEGIN WMNewTab: 20 +[16:49.28.437] END WMNewTab: 20 +[16:49.28.437] BEGIN WMNewTab: 20 +[16:49.28.437] END WMNewTab: 20 +[16:49.28.452] BEGIN WMNewTab: 20 +[16:49.28.453] END WMNewTab: 20 +[16:49.28.453] BEGIN WMNewTab: 20 +[16:49.28.453] END WMNewTab: 20 +[16:49.28.453] BEGIN WMNewTab: 20 +[16:49.28.453] END WMNewTab: 20 +[16:49.28.772] BEGIN WMNewTab: 20 +[16:49.28.772] END WMNewTab: 20 +[16:49.28.788] BEGIN WMNewTab: 20 +[16:49.28.788] END WMNewTab: 20 + +[16:49.29.655] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.29.856] BEGIN WMNewTab: 20 +[16:49.29.856] END WMNewTab: 20 +[16:49.29.856] BEGIN WMNewTab: 20 +[16:49.29.856] END WMNewTab: 20 +[16:49.29.856] BEGIN WMNewTab: 20 +[16:49.29.856] END WMNewTab: 20 +[16:49.29.868] BEGIN WMNewTab: 20 +[16:49.29.868] END WMNewTab: 20 +[16:49.29.868] BEGIN WMNewTab: 20 +[16:49.29.868] END WMNewTab: 20 +[16:49.29.868] BEGIN WMNewTab: 20 +[16:49.29.868] END WMNewTab: 20 +[16:49.30.188] BEGIN WMNewTab: 20 +[16:49.30.188] END WMNewTab: 20 +[16:49.30.203] BEGIN WMNewTab: 20 +[16:49.30.203] END WMNewTab: 20 + +[16:49.31.270] BEGIN WMNewTab: 20 +[16:49.31.270] END WMNewTab: 20 +[16:49.31.270] BEGIN WMNewTab: 20 +[16:49.31.270] END WMNewTab: 20 +[16:49.31.270] BEGIN WMNewTab: 20 +[16:49.31.270] END WMNewTab: 20 +[16:49.31.270] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.31.286] BEGIN WMNewTab: 20 +[16:49.31.286] END WMNewTab: 20 +[16:49.31.287] BEGIN WMNewTab: 20 +[16:49.31.287] END WMNewTab: 20 +[16:49.31.287] BEGIN WMNewTab: 20 +[16:49.31.287] END WMNewTab: 20 +[16:49.31.605] BEGIN WMNewTab: 20 +[16:49.31.605] END WMNewTab: 20 +[16:49.31.620] BEGIN WMNewTab: 20 +[16:49.31.620] END WMNewTab: 20 + +[16:49.32.687] BEGIN WMNewTab: 20 +[16:49.32.687] END WMNewTab: 20 +[16:49.32.687] BEGIN WMNewTab: 20 +[16:49.32.687] END WMNewTab: 20 +[16:49.32.688] BEGIN WMNewTab: 20 +[16:49.32.688] END WMNewTab: 20 +[16:49.32.701] BEGIN WMNewTab: 20 +[16:49.32.701] END WMNewTab: 20 +[16:49.32.701] BEGIN WMNewTab: 20 +[16:49.32.701] END WMNewTab: 20 +[16:49.32.702] BEGIN WMNewTab: 20 +[16:49.32.702] END WMNewTab: 20 +[16:49.32.872] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.33.020] BEGIN WMNewTab: 20 +[16:49.33.020] END WMNewTab: 20 +[16:49.33.036] BEGIN WMNewTab: 20 +[16:49.33.036] END WMNewTab: 20 + +[16:49.34.102] BEGIN WMNewTab: 20 +[16:49.34.102] END WMNewTab: 20 +[16:49.34.103] BEGIN WMNewTab: 20 +[16:49.34.103] END WMNewTab: 20 +[16:49.34.103] BEGIN WMNewTab: 20 +[16:49.34.103] END WMNewTab: 20 +[16:49.34.117] BEGIN WMNewTab: 20 +[16:49.34.117] END WMNewTab: 20 +[16:49.34.117] BEGIN WMNewTab: 20 +[16:49.34.117] END WMNewTab: 20 +[16:49.34.117] BEGIN WMNewTab: 20 +[16:49.34.117] END WMNewTab: 20 +[16:49.34.438] BEGIN WMNewTab: 20 +[16:49.34.438] END WMNewTab: 20 +[16:49.34.452] BEGIN WMNewTab: 20 +[16:49.34.452] END WMNewTab: 20 +[16:49.34.482] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.35.517] BEGIN WMNewTab: 20 +[16:49.35.517] END WMNewTab: 20 +[16:49.35.518] BEGIN WMNewTab: 20 +[16:49.35.518] END WMNewTab: 20 +[16:49.35.518] BEGIN WMNewTab: 20 +[16:49.35.518] END WMNewTab: 20 +[16:49.35.532] BEGIN WMNewTab: 20 +[16:49.35.532] END WMNewTab: 20 +[16:49.35.532] BEGIN WMNewTab: 20 +[16:49.35.532] END WMNewTab: 20 +[16:49.35.533] BEGIN WMNewTab: 20 +[16:49.35.533] END WMNewTab: 20 +[16:49.35.854] BEGIN WMNewTab: 20 +[16:49.35.854] END WMNewTab: 20 +[16:49.35.869] BEGIN WMNewTab: 20 +[16:49.35.869] END WMNewTab: 20 +[16:49.36.098] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.36.931] BEGIN WMNewTab: 20 +[16:49.36.931] END WMNewTab: 20 +[16:49.36.931] BEGIN WMNewTab: 20 +[16:49.36.931] END WMNewTab: 20 +[16:49.36.931] BEGIN WMNewTab: 20 +[16:49.36.931] END WMNewTab: 20 +[16:49.36.947] BEGIN WMNewTab: 20 +[16:49.36.947] END WMNewTab: 20 +[16:49.36.948] BEGIN WMNewTab: 20 +[16:49.36.948] END WMNewTab: 20 +[16:49.36.948] BEGIN WMNewTab: 20 +[16:49.36.948] END WMNewTab: 20 + +[16:49.37.369] BEGIN WMNewTab: 20 +[16:49.37.369] END WMNewTab: 20 +[16:49.37.369] BEGIN WMNewTab: 20 +[16:49.37.369] END WMNewTab: 20 +[16:49.37.709] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.38.349] BEGIN WMNewTab: 20 +[16:49.38.349] END WMNewTab: 20 +[16:49.38.349] BEGIN WMNewTab: 20 +[16:49.38.349] END WMNewTab: 20 +[16:49.38.349] BEGIN WMNewTab: 20 +[16:49.38.349] END WMNewTab: 20 +[16:49.38.361] BEGIN WMNewTab: 20 +[16:49.38.361] END WMNewTab: 20 +[16:49.38.361] BEGIN WMNewTab: 20 +[16:49.38.361] END WMNewTab: 20 +[16:49.38.361] BEGIN WMNewTab: 20 +[16:49.38.361] END WMNewTab: 20 + +[16:49.38.771] BEGIN WMNewTab: 20 +[16:49.38.771] END WMNewTab: 20 +[16:49.38.771] BEGIN WMNewTab: 20 +[16:49.38.771] END WMNewTab: 20 + +[16:49.39.345] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.39.762] BEGIN WMNewTab: 20 +[16:49.39.762] END WMNewTab: 20 +[16:49.39.762] BEGIN WMNewTab: 20 +[16:49.39.762] END WMNewTab: 20 +[16:49.39.763] BEGIN WMNewTab: 20 +[16:49.39.763] END WMNewTab: 20 +[16:49.39.777] BEGIN WMNewTab: 20 +[16:49.39.777] END WMNewTab: 20 +[16:49.39.777] BEGIN WMNewTab: 20 +[16:49.39.777] END WMNewTab: 20 +[16:49.39.777] BEGIN WMNewTab: 20 +[16:49.39.777] END WMNewTab: 20 + +[16:49.40.190] BEGIN WMNewTab: 20 +[16:49.40.190] END WMNewTab: 20 +[16:49.40.190] BEGIN WMNewTab: 20 +[16:49.40.190] END WMNewTab: 20 + +[16:49.40.924] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.41.183] BEGIN WMNewTab: 20 +[16:49.41.183] END WMNewTab: 20 +[16:49.41.183] BEGIN WMNewTab: 20 +[16:49.41.183] END WMNewTab: 20 +[16:49.41.183] BEGIN WMNewTab: 20 +[16:49.41.183] END WMNewTab: 20 +[16:49.41.197] BEGIN WMNewTab: 20 +[16:49.41.197] END WMNewTab: 20 +[16:49.41.197] BEGIN WMNewTab: 20 +[16:49.41.197] END WMNewTab: 20 +[16:49.41.198] BEGIN WMNewTab: 20 +[16:49.41.198] END WMNewTab: 20 + +[16:49.41.607] BEGIN WMNewTab: 20 +[16:49.41.607] END WMNewTab: 20 +[16:49.41.607] BEGIN WMNewTab: 20 +[16:49.41.607] END WMNewTab: 20 + +[16:49.42.534] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.42.597] BEGIN WMNewTab: 20 +[16:49.42.597] END WMNewTab: 20 +[16:49.42.597] BEGIN WMNewTab: 20 +[16:49.42.597] END WMNewTab: 20 +[16:49.42.597] BEGIN WMNewTab: 20 +[16:49.42.597] END WMNewTab: 20 +[16:49.42.613] BEGIN WMNewTab: 20 +[16:49.42.613] END WMNewTab: 20 +[16:49.42.613] BEGIN WMNewTab: 20 +[16:49.42.613] END WMNewTab: 20 +[16:49.42.613] BEGIN WMNewTab: 20 +[16:49.42.613] END WMNewTab: 20 + +[16:49.43.022] BEGIN WMNewTab: 20 +[16:49.43.022] END WMNewTab: 20 +[16:49.43.022] BEGIN WMNewTab: 20 +[16:49.43.022] END WMNewTab: 20 + +[16:49.44.012] BEGIN WMNewTab: 20 +[16:49.44.012] END WMNewTab: 20 +[16:49.44.012] BEGIN WMNewTab: 20 +[16:49.44.012] END WMNewTab: 20 +[16:49.44.012] BEGIN WMNewTab: 20 +[16:49.44.012] END WMNewTab: 20 +[16:49.44.028] BEGIN WMNewTab: 20 +[16:49.44.028] END WMNewTab: 20 +[16:49.44.028] BEGIN WMNewTab: 20 +[16:49.44.028] END WMNewTab: 20 +[16:49.44.028] BEGIN WMNewTab: 20 +[16:49.44.028] END WMNewTab: 20 +[16:49.44.149] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.44.471] BEGIN WMNewTab: 20 +[16:49.44.471] END WMNewTab: 20 +[16:49.44.471] BEGIN WMNewTab: 20 +[16:49.44.471] END WMNewTab: 20 + +[16:49.45.426] BEGIN WMNewTab: 20 +[16:49.45.426] END WMNewTab: 20 +[16:49.45.426] BEGIN WMNewTab: 20 +[16:49.45.426] END WMNewTab: 20 +[16:49.45.426] BEGIN WMNewTab: 20 +[16:49.45.426] END WMNewTab: 20 +[16:49.45.476] BEGIN WMNewTab: 20 +[16:49.45.476] END WMNewTab: 20 +[16:49.45.476] BEGIN WMNewTab: 20 +[16:49.45.476] END WMNewTab: 20 +[16:49.45.476] BEGIN WMNewTab: 20 +[16:49.45.476] END WMNewTab: 20 +[16:49.45.761] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.45.883] BEGIN WMNewTab: 20 +[16:49.45.883] END WMNewTab: 20 +[16:49.45.883] BEGIN WMNewTab: 20 +[16:49.45.883] END WMNewTab: 20 + +[16:49.46.842] BEGIN WMNewTab: 20 +[16:49.46.842] END WMNewTab: 20 +[16:49.46.842] BEGIN WMNewTab: 20 +[16:49.46.842] END WMNewTab: 20 +[16:49.46.842] BEGIN WMNewTab: 20 +[16:49.46.842] END WMNewTab: 20 +[16:49.46.888] BEGIN WMNewTab: 20 +[16:49.46.888] END WMNewTab: 20 +[16:49.46.888] BEGIN WMNewTab: 20 +[16:49.46.888] END WMNewTab: 20 +[16:49.46.888] BEGIN WMNewTab: 20 +[16:49.46.888] END WMNewTab: 20 + +[16:49.47.299] BEGIN WMNewTab: 20 +[16:49.47.299] END WMNewTab: 20 +[16:49.47.299] BEGIN WMNewTab: 20 +[16:49.47.299] END WMNewTab: 20 +[16:49.47.360] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.48.264] BEGIN WMNewTab: 20 +[16:49.48.264] END WMNewTab: 20 +[16:49.48.264] BEGIN WMNewTab: 20 +[16:49.48.264] END WMNewTab: 20 +[16:49.48.265] BEGIN WMNewTab: 20 +[16:49.48.265] END WMNewTab: 20 +[16:49.48.310] BEGIN WMNewTab: 20 +[16:49.48.310] END WMNewTab: 20 +[16:49.48.310] BEGIN WMNewTab: 20 +[16:49.48.310] END WMNewTab: 20 +[16:49.48.310] BEGIN WMNewTab: 20 +[16:49.48.310] END WMNewTab: 20 + +[16:49.48.717] BEGIN WMNewTab: 20 +[16:49.48.717] END WMNewTab: 20 +[16:49.48.718] BEGIN WMNewTab: 20 +[16:49.48.718] END WMNewTab: 20 +[16:49.48.977] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.49.677] BEGIN WMNewTab: 20 +[16:49.49.677] END WMNewTab: 20 +[16:49.49.677] BEGIN WMNewTab: 20 +[16:49.49.677] END WMNewTab: 20 +[16:49.49.677] BEGIN WMNewTab: 20 +[16:49.49.677] END WMNewTab: 20 +[16:49.49.721] BEGIN WMNewTab: 20 +[16:49.49.721] END WMNewTab: 20 +[16:49.49.721] BEGIN WMNewTab: 20 +[16:49.49.721] END WMNewTab: 20 +[16:49.49.721] BEGIN WMNewTab: 20 +[16:49.49.721] END WMNewTab: 20 + +[16:49.50.139] BEGIN WMNewTab: 20 +[16:49.50.139] END WMNewTab: 20 +[16:49.50.139] BEGIN WMNewTab: 20 +[16:49.50.139] END WMNewTab: 20 + +[16:49.50.582] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.51.102] BEGIN WMNewTab: 20 +[16:49.51.102] END WMNewTab: 20 +[16:49.51.102] BEGIN WMNewTab: 20 +[16:49.51.102] END WMNewTab: 20 +[16:49.51.102] BEGIN WMNewTab: 20 +[16:49.51.102] END WMNewTab: 20 +[16:49.51.148] BEGIN WMNewTab: 20 +[16:49.51.148] END WMNewTab: 20 +[16:49.51.148] BEGIN WMNewTab: 20 +[16:49.51.148] END WMNewTab: 20 +[16:49.51.148] BEGIN WMNewTab: 20 +[16:49.51.149] END WMNewTab: 20 + +[16:49.51.561] BEGIN WMNewTab: 20 +[16:49.51.561] END WMNewTab: 20 +[16:49.51.561] BEGIN WMNewTab: 20 +[16:49.51.561] END WMNewTab: 20 + +[16:49.52.185] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.52.520] BEGIN WMNewTab: 20 +[16:49.52.520] END WMNewTab: 20 +[16:49.52.520] BEGIN WMNewTab: 20 +[16:49.52.520] END WMNewTab: 20 +[16:49.52.520] BEGIN WMNewTab: 20 +[16:49.52.520] END WMNewTab: 20 +[16:49.52.566] BEGIN WMNewTab: 20 +[16:49.52.566] END WMNewTab: 20 +[16:49.52.566] BEGIN WMNewTab: 20 +[16:49.52.566] END WMNewTab: 20 +[16:49.52.566] BEGIN WMNewTab: 20 +[16:49.52.566] END WMNewTab: 20 + +[16:49.52.977] BEGIN WMNewTab: 20 +[16:49.52.977] END WMNewTab: 20 +[16:49.52.977] BEGIN WMNewTab: 20 +[16:49.52.977] END WMNewTab: 20 + +[16:49.53.798] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.53.934] BEGIN WMNewTab: 20 +[16:49.53.934] END WMNewTab: 20 +[16:49.53.934] BEGIN WMNewTab: 20 +[16:49.53.934] END WMNewTab: 20 +[16:49.53.934] BEGIN WMNewTab: 20 +[16:49.53.934] END WMNewTab: 20 +[16:49.53.980] BEGIN WMNewTab: 20 +[16:49.53.980] END WMNewTab: 20 +[16:49.53.981] BEGIN WMNewTab: 20 +[16:49.53.981] END WMNewTab: 20 +[16:49.53.981] BEGIN WMNewTab: 20 +[16:49.53.981] END WMNewTab: 20 + +[16:49.54.395] BEGIN WMNewTab: 20 +[16:49.54.395] END WMNewTab: 20 +[16:49.54.395] BEGIN WMNewTab: 20 +[16:49.54.395] END WMNewTab: 20 + +[16:49.55.354] BEGIN WMNewTab: 20 +[16:49.55.354] END WMNewTab: 20 +[16:49.55.354] BEGIN WMNewTab: 20 +[16:49.55.354] END WMNewTab: 20 +[16:49.55.354] BEGIN WMNewTab: 20 +[16:49.55.354] END WMNewTab: 20 +[16:49.55.398] BEGIN WMNewTab: 20 +[16:49.55.398] END WMNewTab: 20 +[16:49.55.398] BEGIN WMNewTab: 20 +[16:49.55.398] END WMNewTab: 20 +[16:49.55.400] BEGIN WMNewTab: 20 +[16:49.55.400] END WMNewTab: 20 +[16:49.55.413] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:49.55.811] BEGIN WMNewTab: 20 +[16:49.55.811] END WMNewTab: 20 +[16:49.55.811] BEGIN WMNewTab: 20 +[16:49.55.811] END WMNewTab: 20 + +[16:49.56.771] BEGIN WMNewTab: 20 +[16:49.56.771] END WMNewTab: 20 +[16:49.56.771] BEGIN WMNewTab: 20 +[16:49.56.771] END WMNewTab: 20 +[16:49.56.771] BEGIN WMNewTab: 20 +[16:49.56.771] END WMNewTab: 20 +[16:49.56.817] BEGIN WMNewTab: 20 +[16:49.56.817] END WMNewTab: 20 +[16:49.56.817] BEGIN WMNewTab: 20 +[16:49.56.817] END WMNewTab: 20 +[16:49.56.817] BEGIN WMNewTab: 20 +[16:49.56.817] END WMNewTab: 20 +[16:49.57.014] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.57.229] BEGIN WMNewTab: 20 +[16:49.57.229] END WMNewTab: 20 +[16:49.57.229] BEGIN WMNewTab: 20 +[16:49.57.229] END WMNewTab: 20 + +[16:49.58.190] BEGIN WMNewTab: 20 +[16:49.58.190] END WMNewTab: 20 +[16:49.58.190] BEGIN WMNewTab: 20 +[16:49.58.190] END WMNewTab: 20 +[16:49.58.190] BEGIN WMNewTab: 20 +[16:49.58.190] END WMNewTab: 20 +[16:49.58.234] BEGIN WMNewTab: 20 +[16:49.58.234] END WMNewTab: 20 +[16:49.58.234] BEGIN WMNewTab: 20 +[16:49.58.234] END WMNewTab: 20 +[16:49.58.235] BEGIN WMNewTab: 20 +[16:49.58.235] END WMNewTab: 20 + +[16:49.58.630] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:49.58.644] BEGIN WMNewTab: 20 +[16:49.58.644] END WMNewTab: 20 +[16:49.58.645] BEGIN WMNewTab: 20 +[16:49.58.645] END WMNewTab: 20 + +[16:49.59.601] BEGIN WMNewTab: 20 +[16:49.59.601] END WMNewTab: 20 +[16:49.59.601] BEGIN WMNewTab: 20 +[16:49.59.601] END WMNewTab: 20 +[16:49.59.601] BEGIN WMNewTab: 20 +[16:49.59.601] END WMNewTab: 20 +[16:49.59.644] BEGIN WMNewTab: 20 +[16:49.59.644] END WMNewTab: 20 +[16:49.59.644] BEGIN WMNewTab: 20 +[16:49.59.644] END WMNewTab: 20 +[16:49.59.644] BEGIN WMNewTab: 20 +[16:49.59.644] END WMNewTab: 20 + +[16:50.00.056] BEGIN WMNewTab: 20 +[16:50.00.056] END WMNewTab: 20 +[16:50.00.057] BEGIN WMNewTab: 20 +[16:50.00.057] END WMNewTab: 20 +[16:50.00.238] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.01.015] BEGIN WMNewTab: 20 +[16:50.01.015] END WMNewTab: 20 +[16:50.01.015] BEGIN WMNewTab: 20 +[16:50.01.015] END WMNewTab: 20 +[16:50.01.015] BEGIN WMNewTab: 20 +[16:50.01.015] END WMNewTab: 20 +[16:50.01.063] BEGIN WMNewTab: 20 +[16:50.01.063] END WMNewTab: 20 +[16:50.01.063] BEGIN WMNewTab: 20 +[16:50.01.063] END WMNewTab: 20 +[16:50.01.063] BEGIN WMNewTab: 20 +[16:50.01.063] END WMNewTab: 20 + +[16:50.01.473] BEGIN WMNewTab: 20 +[16:50.01.473] END WMNewTab: 20 +[16:50.01.473] BEGIN WMNewTab: 20 +[16:50.01.473] END WMNewTab: 20 + +[16:50.01.853] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.02.432] BEGIN WMNewTab: 20 +[16:50.02.432] END WMNewTab: 20 +[16:50.02.432] BEGIN WMNewTab: 20 +[16:50.02.432] END WMNewTab: 20 +[16:50.02.432] BEGIN WMNewTab: 20 +[16:50.02.432] END WMNewTab: 20 +[16:50.02.476] BEGIN WMNewTab: 20 +[16:50.02.476] END WMNewTab: 20 +[16:50.02.476] BEGIN WMNewTab: 20 +[16:50.02.476] END WMNewTab: 20 +[16:50.02.476] BEGIN WMNewTab: 20 +[16:50.02.476] END WMNewTab: 20 + +[16:50.02.884] BEGIN WMNewTab: 20 +[16:50.02.884] END WMNewTab: 20 +[16:50.02.884] BEGIN WMNewTab: 20 +[16:50.02.884] END WMNewTab: 20 + +[16:50.03.454] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.03.839] BEGIN WMNewTab: 20 +[16:50.03.839] END WMNewTab: 20 +[16:50.03.839] BEGIN WMNewTab: 20 +[16:50.03.839] END WMNewTab: 20 +[16:50.03.839] BEGIN WMNewTab: 20 +[16:50.03.839] END WMNewTab: 20 +[16:50.03.885] BEGIN WMNewTab: 20 +[16:50.03.885] END WMNewTab: 20 +[16:50.03.885] BEGIN WMNewTab: 20 +[16:50.03.885] END WMNewTab: 20 +[16:50.03.885] BEGIN WMNewTab: 20 +[16:50.03.886] END WMNewTab: 20 + +[16:50.04.297] BEGIN WMNewTab: 20 +[16:50.04.297] END WMNewTab: 20 +[16:50.04.297] BEGIN WMNewTab: 20 +[16:50.04.297] END WMNewTab: 20 + +[16:50.05.072] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.05.256] BEGIN WMNewTab: 20 +[16:50.05.256] END WMNewTab: 20 +[16:50.05.256] BEGIN WMNewTab: 20 +[16:50.05.256] END WMNewTab: 20 +[16:50.05.256] BEGIN WMNewTab: 20 +[16:50.05.256] END WMNewTab: 20 +[16:50.05.301] BEGIN WMNewTab: 20 +[16:50.05.301] END WMNewTab: 20 +[16:50.05.301] BEGIN WMNewTab: 20 +[16:50.05.301] END WMNewTab: 20 +[16:50.05.301] BEGIN WMNewTab: 20 +[16:50.05.301] END WMNewTab: 20 + +[16:50.05.714] BEGIN WMNewTab: 20 +[16:50.05.714] END WMNewTab: 20 +[16:50.05.714] BEGIN WMNewTab: 20 +[16:50.05.714] END WMNewTab: 20 + +[16:50.06.674] BEGIN WMNewTab: 20 +[16:50.06.674] END WMNewTab: 20 +[16:50.06.674] BEGIN WMNewTab: 20 +[16:50.06.674] END WMNewTab: 20 +[16:50.06.674] BEGIN WMNewTab: 20 +[16:50.06.674] END WMNewTab: 20 +[16:50.06.674] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.06.720] BEGIN WMNewTab: 20 +[16:50.06.720] END WMNewTab: 20 +[16:50.06.720] BEGIN WMNewTab: 20 +[16:50.06.720] END WMNewTab: 20 +[16:50.06.720] BEGIN WMNewTab: 20 +[16:50.06.720] END WMNewTab: 20 + +[16:50.07.133] BEGIN WMNewTab: 20 +[16:50.07.133] END WMNewTab: 20 +[16:50.07.133] BEGIN WMNewTab: 20 +[16:50.07.133] END WMNewTab: 20 + +[16:50.08.094] BEGIN WMNewTab: 20 +[16:50.08.094] END WMNewTab: 20 +[16:50.08.094] BEGIN WMNewTab: 20 +[16:50.08.094] END WMNewTab: 20 +[16:50.08.094] BEGIN WMNewTab: 20 +[16:50.08.094] END WMNewTab: 20 +[16:50.08.141] BEGIN WMNewTab: 20 +[16:50.08.141] END WMNewTab: 20 +[16:50.08.142] BEGIN WMNewTab: 20 +[16:50.08.142] END WMNewTab: 20 +[16:50.08.142] BEGIN WMNewTab: 20 +[16:50.08.142] END WMNewTab: 20 +[16:50.08.279] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.08.552] BEGIN WMNewTab: 20 +[16:50.08.552] END WMNewTab: 20 +[16:50.08.552] BEGIN WMNewTab: 20 +[16:50.08.552] END WMNewTab: 20 + +[16:50.09.514] BEGIN WMNewTab: 20 +[16:50.09.514] END WMNewTab: 20 +[16:50.09.514] BEGIN WMNewTab: 20 +[16:50.09.514] END WMNewTab: 20 +[16:50.09.514] BEGIN WMNewTab: 20 +[16:50.09.514] END WMNewTab: 20 +[16:50.09.559] BEGIN WMNewTab: 20 +[16:50.09.559] END WMNewTab: 20 +[16:50.09.559] BEGIN WMNewTab: 20 +[16:50.09.559] END WMNewTab: 20 +[16:50.09.561] BEGIN WMNewTab: 20 +[16:50.09.561] END WMNewTab: 20 +[16:50.09.895] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.09.969] BEGIN WMNewTab: 20 +[16:50.09.969] END WMNewTab: 20 +[16:50.09.969] BEGIN WMNewTab: 20 +[16:50.09.969] END WMNewTab: 20 + +[16:50.10.928] BEGIN WMNewTab: 20 +[16:50.10.928] END WMNewTab: 20 +[16:50.10.928] BEGIN WMNewTab: 20 +[16:50.10.928] END WMNewTab: 20 +[16:50.10.928] BEGIN WMNewTab: 20 +[16:50.10.928] END WMNewTab: 20 +[16:50.10.974] BEGIN WMNewTab: 20 +[16:50.10.974] END WMNewTab: 20 +[16:50.10.974] BEGIN WMNewTab: 20 +[16:50.10.974] END WMNewTab: 20 +[16:50.10.974] BEGIN WMNewTab: 20 +[16:50.10.974] END WMNewTab: 20 + +[16:50.11.385] BEGIN WMNewTab: 20 +[16:50.11.385] END WMNewTab: 20 +[16:50.11.385] BEGIN WMNewTab: 20 +[16:50.11.385] END WMNewTab: 20 +[16:50.11.506] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.12.346] BEGIN WMNewTab: 20 +[16:50.12.346] END WMNewTab: 20 +[16:50.12.346] BEGIN WMNewTab: 20 +[16:50.12.346] END WMNewTab: 20 +[16:50.12.346] BEGIN WMNewTab: 20 +[16:50.12.346] END WMNewTab: 20 +[16:50.12.392] BEGIN WMNewTab: 20 +[16:50.12.392] END WMNewTab: 20 +[16:50.12.392] BEGIN WMNewTab: 20 +[16:50.12.392] END WMNewTab: 20 +[16:50.12.392] BEGIN WMNewTab: 20 +[16:50.12.392] END WMNewTab: 20 + +[16:50.12.805] BEGIN WMNewTab: 20 +[16:50.12.805] END WMNewTab: 20 +[16:50.12.805] BEGIN WMNewTab: 20 +[16:50.12.805] END WMNewTab: 20 +[16:50.13.110] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.13.764] BEGIN WMNewTab: 20 +[16:50.13.764] END WMNewTab: 20 +[16:50.13.764] BEGIN WMNewTab: 20 +[16:50.13.764] END WMNewTab: 20 +[16:50.13.764] BEGIN WMNewTab: 20 +[16:50.13.764] END WMNewTab: 20 +[16:50.13.809] BEGIN WMNewTab: 20 +[16:50.13.809] END WMNewTab: 20 +[16:50.13.809] BEGIN WMNewTab: 20 +[16:50.13.809] END WMNewTab: 20 +[16:50.13.811] BEGIN WMNewTab: 20 +[16:50.13.811] END WMNewTab: 20 + +[16:50.14.221] BEGIN WMNewTab: 20 +[16:50.14.221] END WMNewTab: 20 +[16:50.14.221] BEGIN WMNewTab: 20 +[16:50.14.221] END WMNewTab: 20 + +[16:50.14.728] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.15.186] BEGIN WMNewTab: 20 +[16:50.15.186] END WMNewTab: 20 +[16:50.15.186] BEGIN WMNewTab: 20 +[16:50.15.186] END WMNewTab: 20 +[16:50.15.186] BEGIN WMNewTab: 20 +[16:50.15.186] END WMNewTab: 20 +[16:50.15.232] BEGIN WMNewTab: 20 +[16:50.15.232] END WMNewTab: 20 +[16:50.15.232] BEGIN WMNewTab: 20 +[16:50.15.232] END WMNewTab: 20 +[16:50.15.232] BEGIN WMNewTab: 20 +[16:50.15.232] END WMNewTab: 20 + +[16:50.15.642] BEGIN WMNewTab: 20 +[16:50.15.642] END WMNewTab: 20 +[16:50.15.642] BEGIN WMNewTab: 20 +[16:50.15.642] END WMNewTab: 20 + +[16:50.16.326] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.16.602] BEGIN WMNewTab: 20 +[16:50.16.602] END WMNewTab: 20 +[16:50.16.602] BEGIN WMNewTab: 20 +[16:50.16.602] END WMNewTab: 20 +[16:50.16.602] BEGIN WMNewTab: 20 +[16:50.16.602] END WMNewTab: 20 +[16:50.16.645] BEGIN WMNewTab: 20 +[16:50.16.645] END WMNewTab: 20 +[16:50.16.645] BEGIN WMNewTab: 20 +[16:50.16.645] END WMNewTab: 20 +[16:50.16.645] BEGIN WMNewTab: 20 +[16:50.16.645] END WMNewTab: 20 + +[16:50.17.062] BEGIN WMNewTab: 20 +[16:50.17.062] END WMNewTab: 20 +[16:50.17.062] BEGIN WMNewTab: 20 +[16:50.17.062] END WMNewTab: 20 + +[16:50.17.945] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.18.021] BEGIN WMNewTab: 20 +[16:50.18.021] END WMNewTab: 20 +[16:50.18.021] BEGIN WMNewTab: 20 +[16:50.18.021] END WMNewTab: 20 +[16:50.18.021] BEGIN WMNewTab: 20 +[16:50.18.021] END WMNewTab: 20 +[16:50.18.068] BEGIN WMNewTab: 20 +[16:50.18.068] END WMNewTab: 20 +[16:50.18.068] BEGIN WMNewTab: 20 +[16:50.18.068] END WMNewTab: 20 +[16:50.18.068] BEGIN WMNewTab: 20 +[16:50.18.068] END WMNewTab: 20 + +[16:50.18.478] BEGIN WMNewTab: 20 +[16:50.18.478] END WMNewTab: 20 +[16:50.18.478] BEGIN WMNewTab: 20 +[16:50.18.478] END WMNewTab: 20 + +[16:50.19.439] BEGIN WMNewTab: 20 +[16:50.19.439] END WMNewTab: 20 +[16:50.19.439] BEGIN WMNewTab: 20 +[16:50.19.439] END WMNewTab: 20 +[16:50.19.439] BEGIN WMNewTab: 20 +[16:50.19.439] END WMNewTab: 20 +[16:50.19.484] BEGIN WMNewTab: 20 +[16:50.19.484] END WMNewTab: 20 +[16:50.19.484] BEGIN WMNewTab: 20 +[16:50.19.484] END WMNewTab: 20 +[16:50.19.485] BEGIN WMNewTab: 20 +[16:50.19.485] END WMNewTab: 20 +[16:50.19.545] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.19.897] BEGIN WMNewTab: 20 +[16:50.19.897] END WMNewTab: 20 +[16:50.19.898] BEGIN WMNewTab: 20 +[16:50.19.898] END WMNewTab: 20 + +[16:50.20.863] BEGIN WMNewTab: 20 +[16:50.20.863] END WMNewTab: 20 +[16:50.20.863] BEGIN WMNewTab: 20 +[16:50.20.863] END WMNewTab: 20 +[16:50.20.863] BEGIN WMNewTab: 20 +[16:50.20.863] END WMNewTab: 20 +[16:50.20.909] BEGIN WMNewTab: 20 +[16:50.20.909] END WMNewTab: 20 +[16:50.20.909] BEGIN WMNewTab: 20 +[16:50.20.909] END WMNewTab: 20 +[16:50.20.911] BEGIN WMNewTab: 20 +[16:50.20.911] END WMNewTab: 20 +[16:50.21.155] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.21.331] BEGIN WMNewTab: 20 +[16:50.21.331] END WMNewTab: 20 +[16:50.21.331] BEGIN WMNewTab: 20 +[16:50.21.331] END WMNewTab: 20 + +[16:50.22.360] BEGIN WMNewTab: 20 +[16:50.22.360] END WMNewTab: 20 +[16:50.22.360] BEGIN WMNewTab: 20 +[16:50.22.360] END WMNewTab: 20 +[16:50.22.361] BEGIN WMNewTab: 20 +[16:50.22.361] END WMNewTab: 20 +[16:50.22.361] BEGIN WMNewTab: 20 +[16:50.22.361] END WMNewTab: 20 +[16:50.22.361] BEGIN WMNewTab: 20 +[16:50.22.361] END WMNewTab: 20 +[16:50.22.361] BEGIN WMNewTab: 20 +[16:50.22.361] END WMNewTab: 20 + +[16:50.22.737] BEGIN WMNewTab: 20 +[16:50.22.737] END WMNewTab: 20 +[16:50.22.737] BEGIN WMNewTab: 20 +[16:50.22.737] END WMNewTab: 20 +[16:50.22.763] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.23.774] BEGIN WMNewTab: 20 +[16:50.23.774] END WMNewTab: 20 +[16:50.23.774] BEGIN WMNewTab: 20 +[16:50.23.774] END WMNewTab: 20 +[16:50.23.774] BEGIN WMNewTab: 20 +[16:50.23.774] END WMNewTab: 20 +[16:50.23.774] BEGIN WMNewTab: 20 +[16:50.23.774] END WMNewTab: 20 +[16:50.23.774] BEGIN WMNewTab: 20 +[16:50.23.774] END WMNewTab: 20 +[16:50.23.774] BEGIN WMNewTab: 20 +[16:50.23.774] END WMNewTab: 20 + +[16:50.24.154] BEGIN WMNewTab: 20 +[16:50.24.154] END WMNewTab: 20 +[16:50.24.154] BEGIN WMNewTab: 20 +[16:50.24.154] END WMNewTab: 20 +[16:50.24.383] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.25.190] BEGIN WMNewTab: 20 +[16:50.25.190] END WMNewTab: 20 +[16:50.25.192] BEGIN WMNewTab: 20 +[16:50.25.192] END WMNewTab: 20 +[16:50.25.192] BEGIN WMNewTab: 20 +[16:50.25.192] END WMNewTab: 20 +[16:50.25.192] BEGIN WMNewTab: 20 +[16:50.25.192] END WMNewTab: 20 +[16:50.25.192] BEGIN WMNewTab: 20 +[16:50.25.192] END WMNewTab: 20 +[16:50.25.192] BEGIN WMNewTab: 20 +[16:50.25.192] END WMNewTab: 20 + +[16:50.25.572] BEGIN WMNewTab: 20 +[16:50.25.572] END WMNewTab: 20 +[16:50.25.573] BEGIN WMNewTab: 20 +[16:50.25.573] END WMNewTab: 20 + +[16:50.25.981] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.26.613] BEGIN WMNewTab: 20 +[16:50.26.613] END WMNewTab: 20 +[16:50.26.613] BEGIN WMNewTab: 20 +[16:50.26.613] END WMNewTab: 20 +[16:50.26.613] BEGIN WMNewTab: 20 +[16:50.26.613] END WMNewTab: 20 +[16:50.26.613] BEGIN WMNewTab: 20 +[16:50.26.613] END WMNewTab: 20 +[16:50.26.613] BEGIN WMNewTab: 20 +[16:50.26.613] END WMNewTab: 20 +[16:50.26.613] BEGIN WMNewTab: 20 +[16:50.26.613] END WMNewTab: 20 + +[16:50.26.993] BEGIN WMNewTab: 20 +[16:50.26.993] END WMNewTab: 20 +[16:50.26.993] BEGIN WMNewTab: 20 +[16:50.26.993] END WMNewTab: 20 + +[16:50.27.601] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.28.026] BEGIN WMNewTab: 20 +[16:50.28.026] END WMNewTab: 20 +[16:50.28.026] BEGIN WMNewTab: 20 +[16:50.28.026] END WMNewTab: 20 +[16:50.28.027] BEGIN WMNewTab: 20 +[16:50.28.027] END WMNewTab: 20 +[16:50.28.027] BEGIN WMNewTab: 20 +[16:50.28.027] END WMNewTab: 20 +[16:50.28.027] BEGIN WMNewTab: 20 +[16:50.28.027] END WMNewTab: 20 +[16:50.28.027] BEGIN WMNewTab: 20 +[16:50.28.027] END WMNewTab: 20 + +[16:50.28.477] BEGIN WMNewTab: 20 +[16:50.28.477] END WMNewTab: 20 +[16:50.28.477] BEGIN WMNewTab: 20 +[16:50.28.477] END WMNewTab: 20 + +[16:50.29.201] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.29.480] BEGIN WMNewTab: 20 +[16:50.29.480] END WMNewTab: 20 +[16:50.29.480] BEGIN WMNewTab: 20 +[16:50.29.480] END WMNewTab: 20 +[16:50.29.480] BEGIN WMNewTab: 20 +[16:50.29.480] END WMNewTab: 20 +[16:50.29.481] BEGIN WMNewTab: 20 +[16:50.29.481] END WMNewTab: 20 +[16:50.29.481] BEGIN WMNewTab: 20 +[16:50.29.481] END WMNewTab: 20 +[16:50.29.481] BEGIN WMNewTab: 20 +[16:50.29.481] END WMNewTab: 20 + +[16:50.29.886] BEGIN WMNewTab: 20 +[16:50.29.886] END WMNewTab: 20 +[16:50.29.886] BEGIN WMNewTab: 20 +[16:50.29.886] END WMNewTab: 20 + +[16:50.30.812] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.30.891] BEGIN WMNewTab: 20 +[16:50.30.891] END WMNewTab: 20 +[16:50.30.891] BEGIN WMNewTab: 20 +[16:50.30.891] END WMNewTab: 20 +[16:50.30.891] BEGIN WMNewTab: 20 +[16:50.30.891] END WMNewTab: 20 +[16:50.30.891] BEGIN WMNewTab: 20 +[16:50.30.891] END WMNewTab: 20 +[16:50.30.891] BEGIN WMNewTab: 20 +[16:50.30.891] END WMNewTab: 20 +[16:50.30.891] BEGIN WMNewTab: 20 +[16:50.30.891] END WMNewTab: 20 + +[16:50.31.302] BEGIN WMNewTab: 20 +[16:50.31.302] END WMNewTab: 20 +[16:50.31.302] BEGIN WMNewTab: 20 +[16:50.31.302] END WMNewTab: 20 + +[16:50.32.309] BEGIN WMNewTab: 20 +[16:50.32.309] END WMNewTab: 20 +[16:50.32.309] BEGIN WMNewTab: 20 +[16:50.32.309] END WMNewTab: 20 +[16:50.32.309] BEGIN WMNewTab: 20 +[16:50.32.309] END WMNewTab: 20 +[16:50.32.309] BEGIN WMNewTab: 20 +[16:50.32.309] END WMNewTab: 20 +[16:50.32.309] BEGIN WMNewTab: 20 +[16:50.32.309] END WMNewTab: 20 +[16:50.32.309] BEGIN WMNewTab: 20 +[16:50.32.309] END WMNewTab: 20 +[16:50.32.431] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.32.720] BEGIN WMNewTab: 20 +[16:50.32.720] END WMNewTab: 20 +[16:50.32.720] BEGIN WMNewTab: 20 +[16:50.32.720] END WMNewTab: 20 + +[16:50.33.728] BEGIN WMNewTab: 20 +[16:50.33.728] END WMNewTab: 20 +[16:50.33.728] BEGIN WMNewTab: 20 +[16:50.33.728] END WMNewTab: 20 +[16:50.33.728] BEGIN WMNewTab: 20 +[16:50.33.728] END WMNewTab: 20 +[16:50.33.729] BEGIN WMNewTab: 20 +[16:50.33.729] END WMNewTab: 20 +[16:50.33.729] BEGIN WMNewTab: 20 +[16:50.33.729] END WMNewTab: 20 +[16:50.33.729] BEGIN WMNewTab: 20 +[16:50.33.729] END WMNewTab: 20 +[16:50.34.033] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.34.138] BEGIN WMNewTab: 20 +[16:50.34.138] END WMNewTab: 20 +[16:50.34.138] BEGIN WMNewTab: 20 +[16:50.34.138] END WMNewTab: 20 + +[16:50.35.144] BEGIN WMNewTab: 20 +[16:50.35.144] END WMNewTab: 20 +[16:50.35.144] BEGIN WMNewTab: 20 +[16:50.35.144] END WMNewTab: 20 +[16:50.35.144] BEGIN WMNewTab: 20 +[16:50.35.144] END WMNewTab: 20 +[16:50.35.144] BEGIN WMNewTab: 20 +[16:50.35.144] END WMNewTab: 20 +[16:50.35.144] BEGIN WMNewTab: 20 +[16:50.35.144] END WMNewTab: 20 +[16:50.35.144] BEGIN WMNewTab: 20 +[16:50.35.144] END WMNewTab: 20 + +[16:50.35.645] BEGIN WMNewTab: 20 +[16:50.35.645] END WMNewTab: 20 +[16:50.35.645] BEGIN WMNewTab: 20 +[16:50.35.645] END WMNewTab: 20 +[16:50.35.645] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.36.645] BEGIN WMNewTab: 20 +[16:50.36.645] END WMNewTab: 20 +[16:50.36.645] BEGIN WMNewTab: 20 +[16:50.36.645] END WMNewTab: 20 +[16:50.36.645] BEGIN WMNewTab: 20 +[16:50.36.645] END WMNewTab: 20 +[16:50.36.645] BEGIN WMNewTab: 20 +[16:50.36.645] END WMNewTab: 20 +[16:50.36.645] BEGIN WMNewTab: 20 +[16:50.36.645] END WMNewTab: 20 +[16:50.36.645] BEGIN WMNewTab: 20 +[16:50.36.645] END WMNewTab: 20 + +[16:50.37.063] BEGIN WMNewTab: 20 +[16:50.37.063] END WMNewTab: 20 +[16:50.37.064] BEGIN WMNewTab: 20 +[16:50.37.064] END WMNewTab: 20 +[16:50.37.260] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.38.048] BEGIN WMNewTab: 20 +[16:50.38.048] END WMNewTab: 20 +[16:50.38.048] BEGIN WMNewTab: 20 +[16:50.38.048] END WMNewTab: 20 +[16:50.38.048] BEGIN WMNewTab: 20 +[16:50.38.048] END WMNewTab: 20 +[16:50.38.048] BEGIN WMNewTab: 20 +[16:50.38.048] END WMNewTab: 20 +[16:50.38.048] BEGIN WMNewTab: 20 +[16:50.38.048] END WMNewTab: 20 +[16:50.38.048] BEGIN WMNewTab: 20 +[16:50.38.048] END WMNewTab: 20 + +[16:50.38.472] BEGIN WMNewTab: 20 +[16:50.38.472] END WMNewTab: 20 +[16:50.38.472] BEGIN WMNewTab: 20 +[16:50.38.472] END WMNewTab: 20 + +[16:50.38.860] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.39.459] BEGIN WMNewTab: 20 +[16:50.39.459] END WMNewTab: 20 +[16:50.39.459] BEGIN WMNewTab: 20 +[16:50.39.459] END WMNewTab: 20 +[16:50.39.459] BEGIN WMNewTab: 20 +[16:50.39.459] END WMNewTab: 20 +[16:50.39.459] BEGIN WMNewTab: 20 +[16:50.39.459] END WMNewTab: 20 +[16:50.39.459] BEGIN WMNewTab: 20 +[16:50.39.459] END WMNewTab: 20 +[16:50.39.459] BEGIN WMNewTab: 20 +[16:50.39.459] END WMNewTab: 20 + +[16:50.39.883] BEGIN WMNewTab: 20 +[16:50.39.883] END WMNewTab: 20 +[16:50.39.884] BEGIN WMNewTab: 20 +[16:50.39.884] END WMNewTab: 20 + +[16:50.40.477] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.40.874] BEGIN WMNewTab: 20 +[16:50.40.874] END WMNewTab: 20 +[16:50.40.874] BEGIN WMNewTab: 20 +[16:50.40.874] END WMNewTab: 20 +[16:50.40.874] BEGIN WMNewTab: 20 +[16:50.40.874] END WMNewTab: 20 +[16:50.40.874] BEGIN WMNewTab: 20 +[16:50.40.874] END WMNewTab: 20 +[16:50.40.874] BEGIN WMNewTab: 20 +[16:50.40.874] END WMNewTab: 20 +[16:50.40.874] BEGIN WMNewTab: 20 +[16:50.40.874] END WMNewTab: 20 + +[16:50.41.300] BEGIN WMNewTab: 20 +[16:50.41.300] END WMNewTab: 20 +[16:50.41.301] BEGIN WMNewTab: 20 +[16:50.41.301] END WMNewTab: 20 + +[16:50.42.078] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.42.290] BEGIN WMNewTab: 20 +[16:50.42.290] END WMNewTab: 20 +[16:50.42.290] BEGIN WMNewTab: 20 +[16:50.42.290] END WMNewTab: 20 +[16:50.42.290] BEGIN WMNewTab: 20 +[16:50.42.290] END WMNewTab: 20 +[16:50.42.290] BEGIN WMNewTab: 20 +[16:50.42.290] END WMNewTab: 20 +[16:50.42.290] BEGIN WMNewTab: 20 +[16:50.42.290] END WMNewTab: 20 +[16:50.42.290] BEGIN WMNewTab: 20 +[16:50.42.290] END WMNewTab: 20 + +[16:50.42.776] BEGIN WMNewTab: 20 +[16:50.42.776] END WMNewTab: 20 +[16:50.42.776] BEGIN WMNewTab: 20 +[16:50.42.776] END WMNewTab: 20 + +[16:50.43.693] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.43.886] BEGIN WMNewTab: 20 +[16:50.43.886] END WMNewTab: 20 +[16:50.43.886] BEGIN WMNewTab: 20 +[16:50.43.886] END WMNewTab: 20 +[16:50.43.886] BEGIN WMNewTab: 20 +[16:50.43.886] END WMNewTab: 20 +[16:50.43.886] BEGIN WMNewTab: 20 +[16:50.43.886] END WMNewTab: 20 +[16:50.43.886] BEGIN WMNewTab: 20 +[16:50.43.886] END WMNewTab: 20 +[16:50.43.886] BEGIN WMNewTab: 20 +[16:50.43.886] END WMNewTab: 20 +[16:50.44.199] BEGIN WMNewTab: 20 +[16:50.44.199] END WMNewTab: 20 +[16:50.44.199] BEGIN WMNewTab: 20 +[16:50.44.199] END WMNewTab: 20 + +[16:50.45.302] BEGIN WMNewTab: 20 +[16:50.45.302] END WMNewTab: 20 +[16:50.45.302] BEGIN WMNewTab: 20 +[16:50.45.302] END WMNewTab: 20 +[16:50.45.302] BEGIN WMNewTab: 20 +[16:50.45.302] END WMNewTab: 20 +[16:50.45.302] BEGIN WMNewTab: 20 +[16:50.45.302] END WMNewTab: 20 +[16:50.45.302] BEGIN WMNewTab: 20 +[16:50.45.302] END WMNewTab: 20 +[16:50.45.302] BEGIN WMNewTab: 20 +[16:50.45.302] END WMNewTab: 20 +[16:50.45.302] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.45.624] BEGIN WMNewTab: 20 +[16:50.45.624] END WMNewTab: 20 +[16:50.45.624] BEGIN WMNewTab: 20 +[16:50.45.624] END WMNewTab: 20 + +[16:50.46.722] BEGIN WMNewTab: 20 +[16:50.46.722] END WMNewTab: 20 +[16:50.46.722] BEGIN WMNewTab: 20 +[16:50.46.722] END WMNewTab: 20 +[16:50.46.722] BEGIN WMNewTab: 20 +[16:50.46.722] END WMNewTab: 20 +[16:50.46.722] BEGIN WMNewTab: 20 +[16:50.46.722] END WMNewTab: 20 +[16:50.46.722] BEGIN WMNewTab: 20 +[16:50.46.722] END WMNewTab: 20 +[16:50.46.722] BEGIN WMNewTab: 20 +[16:50.46.722] END WMNewTab: 20 +[16:50.46.907] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.47.045] BEGIN WMNewTab: 20 +[16:50.47.045] END WMNewTab: 20 +[16:50.47.045] BEGIN WMNewTab: 20 +[16:50.47.045] END WMNewTab: 20 + +[16:50.48.140] BEGIN WMNewTab: 20 +[16:50.48.140] END WMNewTab: 20 +[16:50.48.140] BEGIN WMNewTab: 20 +[16:50.48.140] END WMNewTab: 20 +[16:50.48.140] BEGIN WMNewTab: 20 +[16:50.48.140] END WMNewTab: 20 +[16:50.48.141] BEGIN WMNewTab: 20 +[16:50.48.141] END WMNewTab: 20 +[16:50.48.141] BEGIN WMNewTab: 20 +[16:50.48.141] END WMNewTab: 20 +[16:50.48.141] BEGIN WMNewTab: 20 +[16:50.48.141] END WMNewTab: 20 +[16:50.48.462] BEGIN WMNewTab: 20 +[16:50.48.462] END WMNewTab: 20 +[16:50.48.462] BEGIN WMNewTab: 20 +[16:50.48.462] END WMNewTab: 20 +[16:50.48.522] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.49.562] BEGIN WMNewTab: 20 +[16:50.49.562] END WMNewTab: 20 +[16:50.49.563] BEGIN WMNewTab: 20 +[16:50.49.563] END WMNewTab: 20 +[16:50.49.563] BEGIN WMNewTab: 20 +[16:50.49.563] END WMNewTab: 20 +[16:50.49.563] BEGIN WMNewTab: 20 +[16:50.49.563] END WMNewTab: 20 +[16:50.49.563] BEGIN WMNewTab: 20 +[16:50.49.563] END WMNewTab: 20 +[16:50.49.564] BEGIN WMNewTab: 20 +[16:50.49.564] END WMNewTab: 20 +[16:50.49.901] BEGIN WMNewTab: 20 +[16:50.49.901] END WMNewTab: 20 +[16:50.49.901] BEGIN WMNewTab: 20 +[16:50.49.901] END WMNewTab: 20 +[16:50.50.122] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.50.978] BEGIN WMNewTab: 20 +[16:50.50.978] END WMNewTab: 20 +[16:50.50.980] BEGIN WMNewTab: 20 +[16:50.50.980] END WMNewTab: 20 +[16:50.50.980] BEGIN WMNewTab: 20 +[16:50.50.980] END WMNewTab: 20 +[16:50.50.980] BEGIN WMNewTab: 20 +[16:50.50.980] END WMNewTab: 20 +[16:50.50.980] BEGIN WMNewTab: 20 +[16:50.50.980] END WMNewTab: 20 +[16:50.50.980] BEGIN WMNewTab: 20 +[16:50.50.980] END WMNewTab: 20 +[16:50.51.313] BEGIN WMNewTab: 20 +[16:50.51.313] END WMNewTab: 20 +[16:50.51.313] BEGIN WMNewTab: 20 +[16:50.51.313] END WMNewTab: 20 + +[16:50.51.730] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.52.394] BEGIN WMNewTab: 20 +[16:50.52.394] END WMNewTab: 20 +[16:50.52.394] BEGIN WMNewTab: 20 +[16:50.52.394] END WMNewTab: 20 +[16:50.52.394] BEGIN WMNewTab: 20 +[16:50.52.394] END WMNewTab: 20 +[16:50.52.394] BEGIN WMNewTab: 20 +[16:50.52.394] END WMNewTab: 20 +[16:50.52.394] BEGIN WMNewTab: 20 +[16:50.52.394] END WMNewTab: 20 +[16:50.52.394] BEGIN WMNewTab: 20 +[16:50.52.394] END WMNewTab: 20 +[16:50.52.729] BEGIN WMNewTab: 20 +[16:50.52.729] END WMNewTab: 20 +[16:50.52.729] BEGIN WMNewTab: 20 +[16:50.52.729] END WMNewTab: 20 + +[16:50.53.352] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:50.53.810] BEGIN WMNewTab: 20 +[16:50.53.810] END WMNewTab: 20 +[16:50.53.810] BEGIN WMNewTab: 20 +[16:50.53.810] END WMNewTab: 20 +[16:50.53.810] BEGIN WMNewTab: 20 +[16:50.53.810] END WMNewTab: 20 +[16:50.53.810] BEGIN WMNewTab: 20 +[16:50.53.810] END WMNewTab: 20 +[16:50.53.810] BEGIN WMNewTab: 20 +[16:50.53.810] END WMNewTab: 20 +[16:50.53.810] BEGIN WMNewTab: 20 +[16:50.53.810] END WMNewTab: 20 +[16:50.54.145] BEGIN WMNewTab: 20 +[16:50.54.145] END WMNewTab: 20 +[16:50.54.145] BEGIN WMNewTab: 20 +[16:50.54.145] END WMNewTab: 20 + +[16:50.55.004] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.55.229] BEGIN WMNewTab: 20 +[16:50.55.229] END WMNewTab: 20 +[16:50.55.230] BEGIN WMNewTab: 20 +[16:50.55.230] END WMNewTab: 20 +[16:50.55.230] BEGIN WMNewTab: 20 +[16:50.55.230] END WMNewTab: 20 +[16:50.55.230] BEGIN WMNewTab: 20 +[16:50.55.230] END WMNewTab: 20 +[16:50.55.230] BEGIN WMNewTab: 20 +[16:50.55.230] END WMNewTab: 20 +[16:50.55.230] BEGIN WMNewTab: 20 +[16:50.55.230] END WMNewTab: 20 +[16:50.55.564] BEGIN WMNewTab: 20 +[16:50.55.564] END WMNewTab: 20 +[16:50.55.564] BEGIN WMNewTab: 20 +[16:50.55.564] END WMNewTab: 20 + +[16:50.56.572] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.56.648] BEGIN WMNewTab: 20 +[16:50.56.648] END WMNewTab: 20 +[16:50.56.648] BEGIN WMNewTab: 20 +[16:50.56.648] END WMNewTab: 20 +[16:50.56.648] BEGIN WMNewTab: 20 +[16:50.56.648] END WMNewTab: 20 +[16:50.56.648] BEGIN WMNewTab: 20 +[16:50.56.648] END WMNewTab: 20 +[16:50.56.648] BEGIN WMNewTab: 20 +[16:50.56.648] END WMNewTab: 20 +[16:50.56.648] BEGIN WMNewTab: 20 +[16:50.56.648] END WMNewTab: 20 +[16:50.56.826] BEGIN WMSysCommand (minimize/restore) +[16:50.56.828] BEGIN WMNewTab: 0 +[16:50.56.828] WMNewTab: FormClick +[16:50.56.828] WMNewTab: LooseFocus +[16:50.56.828] END WMNewTab: 0 +[16:50.57.063] BEGIN WMSize +[16:50.57.063] BEGIN TFormXterm.FormResize +[16:50.57.063] TFormXterm.FormResize: CenterBtnReattachTab +[16:50.57.063] TFormXterm.FormResize: SplitModeResize +[16:50.57.063] TFormXterm.FormResize: BtnSplitNo.Down +[16:50.57.063] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:50.57.063] BEGIN ResizeTerminal +[16:50.57.064] BEGIN WMNewTab: 20 +[16:50.57.064] END WMNewTab: 20 +[16:50.57.064] BEGIN WMNewTab: 20 +[16:50.57.064] END WMNewTab: 20 +[16:50.57.065] END ResizeTerminal +[16:50.57.065] TFormXterm.FormResize: AdaptSidebarArrows; +[16:50.57.065] BEGIN AdaptSidebarArrows +[16:50.57.065] END AdaptSidebarArrows +[16:50.57.065] TFormXterm.FormResize: AdaptTV2; +[16:50.57.065] END TFormXterm.FormResize +[16:50.57.065] END WMSize +[16:50.57.073] END WMSysCommand + +[16:50.58.074] BEGIN WMNewTab: 20 +[16:50.58.074] END WMNewTab: 20 +[16:50.58.074] BEGIN WMNewTab: 20 +[16:50.58.074] END WMNewTab: 20 +[16:50.58.074] BEGIN WMNewTab: 20 +[16:50.58.074] END WMNewTab: 20 +[16:50.58.074] BEGIN WMNewTab: 20 +[16:50.58.074] END WMNewTab: 20 +[16:50.58.074] BEGIN WMNewTab: 20 +[16:50.58.074] END WMNewTab: 20 +[16:50.58.074] BEGIN WMNewTab: 20 +[16:50.58.074] END WMNewTab: 20 +[16:50.58.129] BEGIN WMNewTab: 0 +[16:50.58.129] WMNewTab: FormClick +[16:50.58.129] WMNewTab: LooseFocus +[16:50.58.129] END WMNewTab: 0 +[16:50.58.129] BEGIN WMNewTab: 31 +[16:50.58.129] END WMNewTab: 31 +[16:50.58.171] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.58.265] BEGIN WMNewTab: 0 +[16:50.58.265] WMNewTab: FormClick +[16:50.58.265] WMNewTab: LooseFocus +[16:50.58.266] END WMNewTab: 0 +[16:50.58.475] BEGIN WMNewTab: 20 +[16:50.58.475] END WMNewTab: 20 +[16:50.58.476] BEGIN WMNewTab: 20 +[16:50.58.476] END WMNewTab: 20 + +[16:50.59.483] BEGIN WMNewTab: 20 +[16:50.59.483] END WMNewTab: 20 +[16:50.59.483] BEGIN WMNewTab: 20 +[16:50.59.483] END WMNewTab: 20 +[16:50.59.483] BEGIN WMNewTab: 20 +[16:50.59.483] END WMNewTab: 20 +[16:50.59.483] BEGIN WMNewTab: 20 +[16:50.59.483] END WMNewTab: 20 +[16:50.59.483] BEGIN WMNewTab: 20 +[16:50.59.483] END WMNewTab: 20 +[16:50.59.483] BEGIN WMNewTab: 20 +[16:50.59.483] END WMNewTab: 20 +[16:50.59.777] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:50.59.897] BEGIN WMNewTab: 20 +[16:50.59.897] END WMNewTab: 20 +[16:50.59.897] BEGIN WMNewTab: 20 +[16:50.59.897] END WMNewTab: 20 + +[16:51.00.643] BEGIN WMSysCommand (minimize/restore) +[16:51.00.677] BEGIN WMSize +[16:51.00.677] END WMSize +[16:51.00.711] END WMSysCommand +[16:51.00.898] BEGIN WMNewTab: 20 +[16:51.00.898] END WMNewTab: 20 +[16:51.00.898] BEGIN WMNewTab: 20 +[16:51.00.898] END WMNewTab: 20 +[16:51.00.898] BEGIN WMNewTab: 20 +[16:51.00.898] END WMNewTab: 20 +[16:51.00.898] BEGIN WMNewTab: 20 +[16:51.00.898] END WMNewTab: 20 +[16:51.00.898] BEGIN WMNewTab: 20 +[16:51.00.898] END WMNewTab: 20 +[16:51.00.899] BEGIN WMNewTab: 20 +[16:51.00.899] END WMNewTab: 20 + +[16:51.01.310] BEGIN WMNewTab: 20 +[16:51.01.310] END WMNewTab: 20 +[16:51.01.310] BEGIN WMNewTab: 20 +[16:51.01.310] END WMNewTab: 20 +[16:51.01.387] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.02.319] BEGIN WMNewTab: 20 +[16:51.02.319] END WMNewTab: 20 +[16:51.02.319] BEGIN WMNewTab: 20 +[16:51.02.319] END WMNewTab: 20 +[16:51.02.319] BEGIN WMNewTab: 20 +[16:51.02.319] END WMNewTab: 20 +[16:51.02.319] BEGIN WMNewTab: 20 +[16:51.02.319] END WMNewTab: 20 +[16:51.02.319] BEGIN WMNewTab: 20 +[16:51.02.319] END WMNewTab: 20 +[16:51.02.319] BEGIN WMNewTab: 20 +[16:51.02.319] END WMNewTab: 20 + +[16:51.02.729] BEGIN WMNewTab: 20 +[16:51.02.729] END WMNewTab: 20 +[16:51.02.729] BEGIN WMNewTab: 20 +[16:51.02.729] END WMNewTab: 20 +[16:51.03.002] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.03.736] BEGIN WMNewTab: 20 +[16:51.03.736] END WMNewTab: 20 +[16:51.03.736] BEGIN WMNewTab: 20 +[16:51.03.737] END WMNewTab: 20 +[16:51.03.737] BEGIN WMNewTab: 20 +[16:51.03.737] END WMNewTab: 20 +[16:51.03.737] BEGIN WMNewTab: 20 +[16:51.03.737] END WMNewTab: 20 +[16:51.03.737] BEGIN WMNewTab: 20 +[16:51.03.737] END WMNewTab: 20 +[16:51.03.737] BEGIN WMNewTab: 20 +[16:51.03.737] END WMNewTab: 20 + +[16:51.04.149] BEGIN WMNewTab: 20 +[16:51.04.149] END WMNewTab: 20 +[16:51.04.149] BEGIN WMNewTab: 20 +[16:51.04.149] END WMNewTab: 20 + +[16:51.04.606] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.05.147] BEGIN WMSysCommand (minimize/restore) +[16:51.05.147] BEGIN WMNewTab: 0 +[16:51.05.147] WMNewTab: FormClick +[16:51.05.147] WMNewTab: LooseFocus +[16:51.05.147] END WMNewTab: 0 +[16:51.05.357] BEGIN WMSize +[16:51.05.357] BEGIN TFormXterm.FormResize +[16:51.05.357] TFormXterm.FormResize: CenterBtnReattachTab +[16:51.05.357] TFormXterm.FormResize: SplitModeResize +[16:51.05.357] TFormXterm.FormResize: BtnSplitNo.Down +[16:51.05.357] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:51.05.357] BEGIN ResizeTerminal +[16:51.05.358] BEGIN WMNewTab: 20 +[16:51.05.358] END WMNewTab: 20 +[16:51.05.358] BEGIN WMNewTab: 20 +[16:51.05.358] END WMNewTab: 20 +[16:51.05.358] BEGIN WMNewTab: 20 +[16:51.05.358] END WMNewTab: 20 +[16:51.05.358] BEGIN WMNewTab: 20 +[16:51.05.358] END WMNewTab: 20 +[16:51.05.358] BEGIN WMNewTab: 20 +[16:51.05.358] END WMNewTab: 20 +[16:51.05.358] BEGIN WMNewTab: 20 +[16:51.05.358] END WMNewTab: 20 +[16:51.05.361] END ResizeTerminal +[16:51.05.361] TFormXterm.FormResize: AdaptSidebarArrows; +[16:51.05.361] BEGIN AdaptSidebarArrows +[16:51.05.361] END AdaptSidebarArrows +[16:51.05.361] TFormXterm.FormResize: AdaptTV2; +[16:51.05.361] END TFormXterm.FormResize +[16:51.05.361] END WMSize +[16:51.05.367] END WMSysCommand +[16:51.05.570] BEGIN WMNewTab: 20 +[16:51.05.570] END WMNewTab: 20 +[16:51.05.570] BEGIN WMNewTab: 20 +[16:51.05.570] END WMNewTab: 20 + +[16:51.06.253] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.06.554] Cts1MouseDown: FormClick +[16:51.06.563] Cts1ActiveTabChanged: New index = 2 +[16:51.06.565] BEGIN DisplayCurrentTab +[16:51.06.565] DisplayCurrentTab: FormClick +[16:51.06.565] (SSH-Browser) DisplayCurrentTab(2): ActiverPanel14 +[16:51.06.565] (SSH-Browser) BEGIN ActiverPanel14 +[16:51.06.565] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:51.06.580] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:51.06.580] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/userdata/dev_ws/src/marm_code/ +[16:51.06.648] (SSH-Browser) ActiverPanel14: OpenDir(.); +[16:51.06.648] (SSH-Browser) BEGIN OpenDir(2) +[16:51.06.648] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.06.648] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.06.648] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.06.648] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.06.648] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(.); +[16:51.06.649] (SSH-Browser) END OpenDir(2) +[16:51.06.649] (SSH-Browser) END ActiverPanel14; +[16:51.06.779] (SSH-Browser) 正在启动 MobaSCP(7, remotemonitoring, ., ) +[16:51.06.779] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756667" -remotemonitoring mobauser@mobaserver:".") +[16:51.06.780] BEGIN WMNewTab: 20 +[16:51.06.780] END WMNewTab: 20 +[16:51.06.780] BEGIN WMNewTab: 20 +[16:51.06.780] END WMNewTab: 20 +[16:51.06.780] BEGIN WMNewTab: 20 +[16:51.06.780] END WMNewTab: 20 +[16:51.06.780] BEGIN WMNewTab: 20 +[16:51.06.780] END WMNewTab: 20 +[16:51.06.780] BEGIN WMNewTab: 20 +[16:51.06.780] END WMNewTab: 20 +[16:51.06.781] BEGIN WMNewTab: 20 +[16:51.06.781] END WMNewTab: 20 +[16:51.06.796] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.06.796] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/root) +[16:51.06.816] ShellExecuteS: ShellExecuteEx 成功. +[16:51.06.816] ShellExecuteS: WaitForInputIdle 失败. +[16:51.06.816] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756667" -remotemonitoring mobauser@mobaserver:".") +[16:51.06.816] DisplayCurrentTab: Cts1.BeginUpdate; +[16:51.06.816] DisplayCurrentTab: Cts1.EndUpdates +[16:51.06.935] DisplayCurrentTab: 显示所选标签页 +[16:51.06.936] [MobaSCP7] Launching remote monitoring in normal mode +[16:51.06.938] [MobaSCP7] Multiplex=1 +[16:51.06.939] [MobaSCP7] HOSTNAME: 192.168.127.10 +[16:51.06.939] [MobaSCP7] USERNAME: root +[16:51.06.939] DisplayCurrentTab: 隐藏其他标签页 +[16:51.06.944] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:51.06.947] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:51.06.947] DisplayCurrentTab: DistribuerLeFocus +[16:51.06.947] END DisplayCurrentTab +[16:51.07.041] BEGIN WMNewTab: 20 +[16:51.07.041] END WMNewTab: 20 +[16:51.07.041] BEGIN WMNewTab: 20 +[16:51.07.041] END WMNewTab: 20 +[16:51.07.041] [MobaSCP7] Using SCP1 +[16:51.07.041] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.07.041] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.07.041] [MobaSCP7] Connected to 192.168.127.10 +[16:51.07.109] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.07.109] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.07.109] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.07.109] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.07.109] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.07.109] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.07.109] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.07.109] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.07.109] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.07.109] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=18 +[16:51.07.109] (SSH-Browser) 对项目进行排序 +[16:51.07.109] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.07.113] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.07.155] (SSH-Browser) ElSFTP1Success(2) +[16:51.07.193] BEGIN WMNewTab: 0 +[16:51.07.193] WMNewTab: FormClick +[16:51.07.193] WMNewTab: LooseFocus +[16:51.07.193] END WMNewTab: 0 +[16:51.07.193] BEGIN WMNewTab: 31 +[16:51.07.193] END WMNewTab: 31 +[16:51.07.305] BEGIN WMNewTab: 0 +[16:51.07.305] WMNewTab: FormClick +[16:51.07.305] WMNewTab: LooseFocus +[16:51.07.306] END WMNewTab: 0 + +[16:51.07.824] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.08.170] BEGIN TFormXterm.FormResize +[16:51.08.170] TFormXterm.FormResize: CenterBtnReattachTab +[16:51.08.170] TFormXterm.FormResize: SplitModeResize +[16:51.08.170] TFormXterm.FormResize: BtnSplitNo.Down +[16:51.08.170] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:51.08.171] BEGIN ResizeTerminal +[16:51.08.171] BEGIN WMNewTab: 20 +[16:51.08.171] END WMNewTab: 20 +[16:51.08.171] END ResizeTerminal +[16:51.08.171] TFormXterm.FormResize: AdaptSidebarArrows; +[16:51.08.171] BEGIN AdaptSidebarArrows +[16:51.08.171] END AdaptSidebarArrows +[16:51.08.171] TFormXterm.FormResize: AdaptTV2; +[16:51.08.171] END TFormXterm.FormResize +[16:51.08.197] BEGIN WMNewTab: 20 +[16:51.08.197] END WMNewTab: 20 +[16:51.08.198] BEGIN WMNewTab: 20 +[16:51.08.198] END WMNewTab: 20 +[16:51.08.198] BEGIN WMNewTab: 20 +[16:51.08.198] END WMNewTab: 20 +[16:51.08.198] BEGIN WMNewTab: 20 +[16:51.08.198] END WMNewTab: 20 +[16:51.08.198] BEGIN WMNewTab: 20 +[16:51.08.198] END WMNewTab: 20 +[16:51.08.472] BEGIN WMNewTab: 20 +[16:51.08.472] END WMNewTab: 20 +[16:51.08.472] BEGIN WMNewTab: 20 +[16:51.08.472] END WMNewTab: 20 + +[16:51.09.438] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.09.554] sListView1Click: FormClick +[16:51.09.578] BEGIN WMNewTab: 20 +[16:51.09.578] END WMNewTab: 20 +[16:51.09.607] BEGIN WMNewTab: 20 +[16:51.09.607] END WMNewTab: 20 +[16:51.09.607] BEGIN WMNewTab: 20 +[16:51.09.607] END WMNewTab: 20 +[16:51.09.607] BEGIN WMNewTab: 20 +[16:51.09.607] END WMNewTab: 20 +[16:51.09.607] BEGIN WMNewTab: 20 +[16:51.09.607] END WMNewTab: 20 +[16:51.09.607] BEGIN WMNewTab: 20 +[16:51.09.607] END WMNewTab: 20 +[16:51.09.626] (SSH-Browser) BEGIN OpenDir(2) +[16:51.09.626] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.09.626] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.09.626] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.09.626] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.09.627] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/root/../); +[16:51.09.629] (SSH-Browser) END OpenDir(2) +[16:51.09.639] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.09.639] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/) +[16:51.09.668] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.09.668] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.09.730] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.09.730] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.09.730] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.09.730] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.09.730] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.09.730] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.09.730] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.09.730] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.09.730] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.09.730] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=28 +[16:51.09.731] (SSH-Browser) 对项目进行排序 +[16:51.09.731] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.09.742] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.09.791] (SSH-Browser) ElSFTP1Success(2) +[16:51.09.882] BEGIN WMNewTab: 20 +[16:51.09.882] END WMNewTab: 20 +[16:51.09.882] BEGIN WMNewTab: 20 +[16:51.09.882] END WMNewTab: 20 +[16:51.10.180] sListView1Click: FormClick + +[16:51.11.024] BEGIN WMNewTab: 20 +[16:51.11.024] END WMNewTab: 20 +[16:51.11.024] BEGIN WMNewTab: 20 +[16:51.11.024] END WMNewTab: 20 +[16:51.11.025] BEGIN WMNewTab: 20 +[16:51.11.025] END WMNewTab: 20 +[16:51.11.025] BEGIN WMNewTab: 20 +[16:51.11.025] END WMNewTab: 20 +[16:51.11.025] BEGIN WMNewTab: 20 +[16:51.11.025] END WMNewTab: 20 +[16:51.11.070] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.11.227] BEGIN WMNewTab: 20 +[16:51.11.227] END WMNewTab: 20 +[16:51.11.333] BEGIN WMNewTab: 20 +[16:51.11.333] END WMNewTab: 20 +[16:51.11.333] BEGIN WMNewTab: 20 +[16:51.11.333] END WMNewTab: 20 +[16:51.11.354] sListView1Click: FormClick +[16:51.11.443] (SSH-Browser) BEGIN OpenDir(2) +[16:51.11.443] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.11.443] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.11.443] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.11.443] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.11.445] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/); +[16:51.11.445] (SSH-Browser) END OpenDir(2) +[16:51.11.463] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.11.463] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata) +[16:51.11.495] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.11.495] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.11.557] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.11.557] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.11.557] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.11.557] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.11.557] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.11.557] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.11.557] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.11.557] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.11.557] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.11.557] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=3 +[16:51.11.557] (SSH-Browser) 对项目进行排序 +[16:51.11.557] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.11.560] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.11.588] (SSH-Browser) ElSFTP1Success(2) + +[16:51.12.043] sListView1Click: FormClick +[16:51.12.116] (SSH-Browser) BEGIN OpenDir(2) +[16:51.12.116] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.12.116] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.12.116] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.12.116] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.12.117] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/); +[16:51.12.117] (SSH-Browser) END OpenDir(2) +[16:51.12.187] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.12.187] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws) +[16:51.12.214] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.12.214] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.12.274] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.12.274] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.12.274] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.12.274] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.12.274] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.12.274] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.12.274] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.12.274] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.12.274] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.12.274] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=8 +[16:51.12.274] (SSH-Browser) 对项目进行排序 +[16:51.12.274] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.12.279] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.12.309] (SSH-Browser) ElSFTP1Success(2) +[16:51.12.444] BEGIN WMNewTab: 20 +[16:51.12.444] END WMNewTab: 20 +[16:51.12.444] BEGIN WMNewTab: 20 +[16:51.12.444] END WMNewTab: 20 +[16:51.12.444] BEGIN WMNewTab: 20 +[16:51.12.444] END WMNewTab: 20 +[16:51.12.444] BEGIN WMNewTab: 20 +[16:51.12.444] END WMNewTab: 20 +[16:51.12.444] BEGIN WMNewTab: 20 +[16:51.12.444] END WMNewTab: 20 +[16:51.12.656] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.12.749] BEGIN WMNewTab: 20 +[16:51.12.749] END WMNewTab: 20 +[16:51.12.749] BEGIN WMNewTab: 20 +[16:51.12.749] END WMNewTab: 20 +[16:51.12.776] BEGIN WMNewTab: 20 +[16:51.12.776] END WMNewTab: 20 +[16:51.12.987] sListView1Click: FormClick +[16:51.13.083] (SSH-Browser) BEGIN OpenDir(2) +[16:51.13.083] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.13.083] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.13.083] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.13.083] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.13.085] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/); +[16:51.13.085] (SSH-Browser) END OpenDir(2) +[16:51.13.097] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.13.097] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src) +[16:51.13.129] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.13.129] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.13.221] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.13.221] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.13.221] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.13.221] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.13.221] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.13.221] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.13.221] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.13.221] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.13.221] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.13.221] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=10 +[16:51.13.221] (SSH-Browser) 对项目进行排序 +[16:51.13.221] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.13.224] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.13.252] (SSH-Browser) ElSFTP1Success(2) + +[16:51.13.860] BEGIN WMNewTab: 20 +[16:51.13.860] END WMNewTab: 20 +[16:51.13.860] BEGIN WMNewTab: 20 +[16:51.13.860] END WMNewTab: 20 +[16:51.13.860] BEGIN WMNewTab: 20 +[16:51.13.860] END WMNewTab: 20 +[16:51.13.860] BEGIN WMNewTab: 20 +[16:51.13.860] END WMNewTab: 20 +[16:51.13.860] BEGIN WMNewTab: 20 +[16:51.13.860] END WMNewTab: 20 +[16:51.14.204] BEGIN WMNewTab: 20 +[16:51.14.204] END WMNewTab: 20 +[16:51.14.204] BEGIN WMNewTab: 20 +[16:51.14.204] END WMNewTab: 20 +[16:51.14.204] BEGIN WMNewTab: 20 +[16:51.14.204] END WMNewTab: 20 +[16:51.14.271] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.15.277] BEGIN WMNewTab: 20 +[16:51.15.277] END WMNewTab: 20 +[16:51.15.277] BEGIN WMNewTab: 20 +[16:51.15.277] END WMNewTab: 20 +[16:51.15.277] BEGIN WMNewTab: 20 +[16:51.15.277] END WMNewTab: 20 +[16:51.15.277] BEGIN WMNewTab: 20 +[16:51.15.277] END WMNewTab: 20 +[16:51.15.277] BEGIN WMNewTab: 20 +[16:51.15.277] END WMNewTab: 20 +[16:51.15.614] BEGIN WMNewTab: 20 +[16:51.15.614] END WMNewTab: 20 +[16:51.15.614] BEGIN WMNewTab: 20 +[16:51.15.614] END WMNewTab: 20 +[16:51.15.614] BEGIN WMNewTab: 20 +[16:51.15.614] END WMNewTab: 20 +[16:51.15.874] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.16.244] sListView1Click: FormClick +[16:51.16.307] (SSH-Browser) BEGIN OpenDir(2) +[16:51.16.307] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.16.307] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.16.307] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.16.307] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.16.308] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/); +[16:51.16.308] (SSH-Browser) END OpenDir(2) +[16:51.16.321] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.16.321] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code) +[16:51.16.349] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.16.349] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.16.410] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.16.410] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.16.410] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.16.410] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.16.411] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.16.411] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.16.411] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.16.411] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.16.411] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.16.411] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=8 +[16:51.16.411] (SSH-Browser) 对项目进行排序 +[16:51.16.411] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.16.415] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.16.442] (SSH-Browser) ElSFTP1Success(2) +[16:51.16.699] BEGIN WMNewTab: 20 +[16:51.16.699] END WMNewTab: 20 +[16:51.16.699] BEGIN WMNewTab: 20 +[16:51.16.699] END WMNewTab: 20 +[16:51.16.699] BEGIN WMNewTab: 20 +[16:51.16.699] END WMNewTab: 20 +[16:51.16.701] BEGIN WMNewTab: 20 +[16:51.16.701] END WMNewTab: 20 +[16:51.16.701] BEGIN WMNewTab: 20 +[16:51.16.701] END WMNewTab: 20 +[16:51.16.916] BEGIN WMNewTab: 20 +[16:51.16.916] END WMNewTab: 20 +[16:51.17.034] BEGIN WMNewTab: 20 +[16:51.17.034] END WMNewTab: 20 +[16:51.17.034] BEGIN WMNewTab: 20 +[16:51.17.034] END WMNewTab: 20 + +[16:51.17.494] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.17.867] sListView1Click: FormClick +[16:51.17.954] (SSH-Browser) BEGIN OpenDir(2) +[16:51.17.954] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.17.954] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.17.954] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.17.954] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.17.956] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/custom_interface/); +[16:51.17.956] (SSH-Browser) END OpenDir(2) +[16:51.17.971] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.17.971] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code/custom_interface) +[16:51.17.997] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.17.997] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.18.058] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.18.058] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.18.058] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.18.058] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.18.058] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.18.058] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.18.058] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.18.058] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.18.058] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.18.058] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=5 +[16:51.18.058] (SSH-Browser) 对项目进行排序 +[16:51.18.058] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.18.069] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.18.121] BEGIN WMNewTab: 20 +[16:51.18.121] END WMNewTab: 20 +[16:51.18.121] BEGIN WMNewTab: 20 +[16:51.18.121] END WMNewTab: 20 +[16:51.18.121] BEGIN WMNewTab: 20 +[16:51.18.121] END WMNewTab: 20 +[16:51.18.121] BEGIN WMNewTab: 20 +[16:51.18.121] END WMNewTab: 20 +[16:51.18.121] BEGIN WMNewTab: 20 +[16:51.18.121] END WMNewTab: 20 +[16:51.18.121] (SSH-Browser) ElSFTP1Success(2) +[16:51.18.122] BEGIN WMNewTab: 20 +[16:51.18.122] END WMNewTab: 20 +[16:51.18.455] BEGIN WMNewTab: 20 +[16:51.18.455] END WMNewTab: 20 +[16:51.18.455] BEGIN WMNewTab: 20 +[16:51.18.455] END WMNewTab: 20 + +[16:51.19.093] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.19.098] sListView1Click: FormClick +[16:51.19.158] (SSH-Browser) BEGIN OpenDir(2) +[16:51.19.158] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.19.158] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.19.158] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.19.158] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.19.159] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/custom_interface/../); +[16:51.19.159] (SSH-Browser) END OpenDir(2) +[16:51.19.169] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.19.169] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code) +[16:51.19.200] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.19.200] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.19.260] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.19.260] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.19.260] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.19.260] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.19.260] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.19.260] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.19.260] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.19.260] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.19.260] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.19.260] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=8 +[16:51.19.260] (SSH-Browser) 对项目进行排序 +[16:51.19.260] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.19.272] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.19.323] (SSH-Browser) ElSFTP1Success(2) +[16:51.19.535] BEGIN WMNewTab: 20 +[16:51.19.535] END WMNewTab: 20 +[16:51.19.536] BEGIN WMNewTab: 20 +[16:51.19.536] END WMNewTab: 20 +[16:51.19.536] BEGIN WMNewTab: 20 +[16:51.19.536] END WMNewTab: 20 +[16:51.19.536] BEGIN WMNewTab: 20 +[16:51.19.536] END WMNewTab: 20 +[16:51.19.536] BEGIN WMNewTab: 20 +[16:51.19.536] END WMNewTab: 20 +[16:51.19.795] BEGIN WMNewTab: 20 +[16:51.19.795] END WMNewTab: 20 +[16:51.19.869] BEGIN WMNewTab: 20 +[16:51.19.869] END WMNewTab: 20 +[16:51.19.870] BEGIN WMNewTab: 20 +[16:51.19.870] END WMNewTab: 20 + +[16:51.20.547] sListView1Click: FormClick +[16:51.20.620] (SSH-Browser) BEGIN OpenDir(2) +[16:51.20.620] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.20.620] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.20.620] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.20.620] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.20.622] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/arm_controller/); +[16:51.20.622] (SSH-Browser) END OpenDir(2) +[16:51.20.638] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.20.638] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code/arm_controller) +[16:51.20.667] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.20.667] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.20.700] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.20.728] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.20.728] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.20.728] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.20.728] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.20.728] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.20.728] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.20.728] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.20.728] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.20.728] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.20.728] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=11 +[16:51.20.728] (SSH-Browser) 对项目进行排序 +[16:51.20.728] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.20.733] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.20.792] (SSH-Browser) ElSFTP1Success(2) +[16:51.20.961] BEGIN WMNewTab: 20 +[16:51.20.961] END WMNewTab: 20 +[16:51.20.961] BEGIN WMNewTab: 20 +[16:51.20.961] END WMNewTab: 20 +[16:51.20.961] BEGIN WMNewTab: 20 +[16:51.20.961] END WMNewTab: 20 +[16:51.20.961] BEGIN WMNewTab: 20 +[16:51.20.961] END WMNewTab: 20 +[16:51.20.961] BEGIN WMNewTab: 20 +[16:51.20.961] END WMNewTab: 20 +[16:51.21.265] BEGIN WMNewTab: 20 +[16:51.21.265] END WMNewTab: 20 +[16:51.21.295] BEGIN WMNewTab: 20 +[16:51.21.295] END WMNewTab: 20 +[16:51.21.295] BEGIN WMNewTab: 20 +[16:51.21.295] END WMNewTab: 20 +[16:51.21.403] sListView1Click: FormClick +[16:51.21.509] (SSH-Browser) BEGIN OpenDir(2) +[16:51.21.509] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.21.509] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.21.509] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.21.509] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.21.511] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/arm_controller/../); +[16:51.21.511] (SSH-Browser) END OpenDir(2) +[16:51.21.523] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.21.523] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code) +[16:51.21.553] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.21.553] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.21.616] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.21.616] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.21.616] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.21.616] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.21.616] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.21.616] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.21.616] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.21.616] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.21.616] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.21.616] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=8 +[16:51.21.616] (SSH-Browser) 对项目进行排序 +[16:51.21.616] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.21.626] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.21.647] (SSH-Browser) ElSFTP1Success(2) + +[16:51.22.229] sListView1Click: FormClick +[16:51.22.317] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.22.371] (SSH-Browser) BEGIN OpenDir(2) +[16:51.22.371] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.22.371] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.22.371] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.22.371] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.22.372] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/a1_description/); +[16:51.22.372] (SSH-Browser) END OpenDir(2) +[16:51.22.379] BEGIN WMNewTab: 20 +[16:51.22.379] END WMNewTab: 20 +[16:51.22.379] BEGIN WMNewTab: 20 +[16:51.22.379] END WMNewTab: 20 +[16:51.22.380] BEGIN WMNewTab: 20 +[16:51.22.380] END WMNewTab: 20 +[16:51.22.380] BEGIN WMNewTab: 20 +[16:51.22.380] END WMNewTab: 20 +[16:51.22.380] BEGIN WMNewTab: 20 +[16:51.22.380] END WMNewTab: 20 +[16:51.22.381] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.22.381] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code/a1_description) +[16:51.22.410] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.22.410] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.22.472] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.22.472] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.22.472] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.22.472] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.22.472] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.22.472] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.22.472] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.22.472] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.22.472] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.22.472] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=10 +[16:51.22.472] (SSH-Browser) 对项目进行排序 +[16:51.22.472] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.22.482] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.22.482] BEGIN WMNewTab: 20 +[16:51.22.482] END WMNewTab: 20 +[16:51.22.504] (SSH-Browser) ElSFTP1Success(2) +[16:51.22.715] BEGIN WMNewTab: 20 +[16:51.22.715] END WMNewTab: 20 +[16:51.22.715] BEGIN WMNewTab: 20 +[16:51.22.715] END WMNewTab: 20 + +[16:51.23.797] BEGIN WMNewTab: 20 +[16:51.23.797] END WMNewTab: 20 +[16:51.23.797] BEGIN WMNewTab: 20 +[16:51.23.797] END WMNewTab: 20 +[16:51.23.798] BEGIN WMNewTab: 20 +[16:51.23.798] END WMNewTab: 20 +[16:51.23.798] BEGIN WMNewTab: 20 +[16:51.23.798] END WMNewTab: 20 +[16:51.23.798] BEGIN WMNewTab: 20 +[16:51.23.798] END WMNewTab: 20 +[16:51.23.801] sListView1Click: FormClick +[16:51.23.916] (SSH-Browser) BEGIN OpenDir(2) +[16:51.23.916] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.23.916] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.23.916] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.23.916] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.23.919] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/a1_description/../); +[16:51.23.919] (SSH-Browser) END OpenDir(2) +[16:51.23.919] BEGIN WMNewTab: 20 +[16:51.23.919] END WMNewTab: 20 +[16:51.23.928] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.23.948] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.23.948] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code) +[16:51.23.979] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.23.979] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.24.040] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.24.040] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.24.040] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.24.040] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.24.040] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.24.040] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.24.040] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.24.040] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.24.040] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.24.040] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=8 +[16:51.24.040] (SSH-Browser) 对项目进行排序 +[16:51.24.040] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.24.051] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.24.070] (SSH-Browser) ElSFTP1Success(2) +[16:51.24.130] BEGIN WMNewTab: 20 +[16:51.24.130] END WMNewTab: 20 +[16:51.24.130] BEGIN WMNewTab: 20 +[16:51.24.130] END WMNewTab: 20 + +[16:51.24.553] sListView1Click: FormClick +[16:51.24.650] (SSH-Browser) BEGIN OpenDir(2) +[16:51.24.651] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.24.651] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.24.651] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.24.651] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.24.652] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/a1_moveit_config/); +[16:51.24.652] (SSH-Browser) END OpenDir(2) +[16:51.24.662] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.24.662] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code/a1_moveit_config) +[16:51.24.693] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.24.693] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.24.755] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.24.755] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.24.755] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.24.755] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.24.755] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.24.755] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.24.755] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.24.755] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.24.755] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.24.755] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=7 +[16:51.24.755] (SSH-Browser) 对项目进行排序 +[16:51.24.755] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.24.764] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.24.788] (SSH-Browser) ElSFTP1Success(2) + +[16:51.25.211] BEGIN WMNewTab: 20 +[16:51.25.211] END WMNewTab: 20 +[16:51.25.211] BEGIN WMNewTab: 20 +[16:51.25.211] END WMNewTab: 20 +[16:51.25.211] BEGIN WMNewTab: 20 +[16:51.25.211] END WMNewTab: 20 +[16:51.25.211] BEGIN WMNewTab: 20 +[16:51.25.211] END WMNewTab: 20 +[16:51.25.211] BEGIN WMNewTab: 20 +[16:51.25.211] END WMNewTab: 20 +[16:51.25.258] BEGIN WMNewTab: 20 +[16:51.25.258] END WMNewTab: 20 +[16:51.25.532] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.25.555] BEGIN WMNewTab: 20 +[16:51.25.555] END WMNewTab: 20 +[16:51.25.555] BEGIN WMNewTab: 20 +[16:51.25.555] END WMNewTab: 20 + +[16:51.26.059] sListView1Click: FormClick +[16:51.26.173] (SSH-Browser) BEGIN OpenDir(2) +[16:51.26.173] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.26.173] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.26.173] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.26.173] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.26.174] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/a1_moveit_config/../); +[16:51.26.175] (SSH-Browser) END OpenDir(2) +[16:51.26.232] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.26.232] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code) +[16:51.26.262] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.26.262] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.26.323] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.26.323] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.26.323] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.26.323] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.26.323] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.26.323] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.26.323] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.26.324] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.26.324] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.26.324] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=8 +[16:51.26.324] (SSH-Browser) 对项目进行排序 +[16:51.26.324] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.26.336] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.26.369] (SSH-Browser) ElSFTP1Success(2) +[16:51.26.630] BEGIN WMNewTab: 20 +[16:51.26.630] END WMNewTab: 20 +[16:51.26.630] BEGIN WMNewTab: 20 +[16:51.26.630] END WMNewTab: 20 +[16:51.26.630] BEGIN WMNewTab: 20 +[16:51.26.630] END WMNewTab: 20 +[16:51.26.630] BEGIN WMNewTab: 20 +[16:51.26.630] END WMNewTab: 20 +[16:51.26.630] BEGIN WMNewTab: 20 +[16:51.26.630] END WMNewTab: 20 +[16:51.26.846] BEGIN WMNewTab: 20 +[16:51.26.846] END WMNewTab: 20 +[16:51.26.969] BEGIN WMNewTab: 20 +[16:51.26.969] END WMNewTab: 20 +[16:51.26.969] BEGIN WMNewTab: 20 +[16:51.26.969] END WMNewTab: 20 +[16:51.27.149] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.28.049] BEGIN WMNewTab: 20 +[16:51.28.049] END WMNewTab: 20 +[16:51.28.049] BEGIN WMNewTab: 20 +[16:51.28.049] END WMNewTab: 20 +[16:51.28.049] BEGIN WMNewTab: 20 +[16:51.28.049] END WMNewTab: 20 +[16:51.28.049] BEGIN WMNewTab: 20 +[16:51.28.049] END WMNewTab: 20 +[16:51.28.050] BEGIN WMNewTab: 20 +[16:51.28.050] END WMNewTab: 20 +[16:51.28.263] BEGIN WMNewTab: 20 +[16:51.28.263] END WMNewTab: 20 +[16:51.28.399] BEGIN WMNewTab: 20 +[16:51.28.399] END WMNewTab: 20 +[16:51.28.399] BEGIN WMNewTab: 20 +[16:51.28.399] END WMNewTab: 20 +[16:51.28.750] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.29.489] BEGIN WMNewTab: 20 +[16:51.29.489] END WMNewTab: 20 +[16:51.29.489] BEGIN WMNewTab: 20 +[16:51.29.489] END WMNewTab: 20 +[16:51.29.489] BEGIN WMNewTab: 20 +[16:51.29.489] END WMNewTab: 20 +[16:51.29.489] BEGIN WMNewTab: 20 +[16:51.29.489] END WMNewTab: 20 +[16:51.29.489] BEGIN WMNewTab: 20 +[16:51.29.489] END WMNewTab: 20 +[16:51.29.679] BEGIN WMNewTab: 20 +[16:51.29.679] END WMNewTab: 20 +[16:51.29.815] BEGIN WMNewTab: 20 +[16:51.29.815] END WMNewTab: 20 +[16:51.29.815] BEGIN WMNewTab: 20 +[16:51.29.815] END WMNewTab: 20 + +[16:51.30.362] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.30.475] BEGIN WMSysCommand (minimize/restore) +[16:51.30.511] BEGIN WMSize +[16:51.30.511] END WMSize +[16:51.30.538] END WMSysCommand + +[16:51.30.920] BEGIN WMNewTab: 20 +[16:51.30.920] END WMNewTab: 20 +[16:51.30.920] BEGIN WMNewTab: 20 +[16:51.30.920] END WMNewTab: 20 +[16:51.30.920] BEGIN WMNewTab: 20 +[16:51.30.920] END WMNewTab: 20 +[16:51.30.920] BEGIN WMNewTab: 20 +[16:51.30.920] END WMNewTab: 20 +[16:51.30.920] BEGIN WMNewTab: 20 +[16:51.30.920] END WMNewTab: 20 +[16:51.30.921] BEGIN WMSysCommand (minimize/restore) +[16:51.30.922] BEGIN WMNewTab: 0 +[16:51.30.922] WMNewTab: FormClick +[16:51.30.922] WMNewTab: LooseFocus +[16:51.30.923] END WMNewTab: 0 +[16:51.31.130] BEGIN WMSize +[16:51.31.130] BEGIN TFormXterm.FormResize +[16:51.31.131] TFormXterm.FormResize: CenterBtnReattachTab +[16:51.31.131] TFormXterm.FormResize: SplitModeResize +[16:51.31.131] TFormXterm.FormResize: BtnSplitNo.Down +[16:51.31.131] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:51.31.131] BEGIN ResizeTerminal +[16:51.31.131] BEGIN WMNewTab: 20 +[16:51.31.131] END WMNewTab: 20 +[16:51.31.132] END ResizeTerminal +[16:51.31.132] TFormXterm.FormResize: AdaptSidebarArrows; +[16:51.31.132] BEGIN AdaptSidebarArrows +[16:51.31.132] END AdaptSidebarArrows +[16:51.31.132] TFormXterm.FormResize: AdaptTV2; +[16:51.31.132] END TFormXterm.FormResize +[16:51.31.132] END WMSize +[16:51.31.136] END WMSysCommand +[16:51.31.231] BEGIN WMNewTab: 20 +[16:51.31.231] END WMNewTab: 20 +[16:51.31.232] BEGIN WMNewTab: 20 +[16:51.31.232] END WMNewTab: 20 + +[16:51.31.974] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.32.327] BEGIN WMNewTab: 20 +[16:51.32.327] END WMNewTab: 20 +[16:51.32.327] BEGIN WMNewTab: 20 +[16:51.32.328] END WMNewTab: 20 +[16:51.32.328] BEGIN WMNewTab: 20 +[16:51.32.328] END WMNewTab: 20 +[16:51.32.328] BEGIN WMNewTab: 20 +[16:51.32.328] END WMNewTab: 20 +[16:51.32.328] BEGIN WMNewTab: 20 +[16:51.32.328] END WMNewTab: 20 +[16:51.32.577] BEGIN WMNewTab: 20 +[16:51.32.577] END WMNewTab: 20 +[16:51.32.648] BEGIN WMNewTab: 20 +[16:51.32.648] END WMNewTab: 20 +[16:51.32.648] BEGIN WMNewTab: 20 +[16:51.32.648] END WMNewTab: 20 + +[16:51.33.649] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.33.744] BEGIN WMNewTab: 20 +[16:51.33.744] END WMNewTab: 20 +[16:51.33.744] BEGIN WMNewTab: 20 +[16:51.33.744] END WMNewTab: 20 +[16:51.33.744] BEGIN WMNewTab: 20 +[16:51.33.744] END WMNewTab: 20 +[16:51.33.744] BEGIN WMNewTab: 20 +[16:51.33.744] END WMNewTab: 20 +[16:51.33.744] BEGIN WMNewTab: 20 +[16:51.33.744] END WMNewTab: 20 +[16:51.33.993] BEGIN WMNewTab: 20 +[16:51.33.993] END WMNewTab: 20 +[16:51.34.068] BEGIN WMNewTab: 20 +[16:51.34.068] END WMNewTab: 20 +[16:51.34.068] BEGIN WMNewTab: 20 +[16:51.34.068] END WMNewTab: 20 +[16:51.34.410] sListView1Click: FormClick +[16:51.34.484] (SSH-Browser) BEGIN OpenDir(2) +[16:51.34.484] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.34.484] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.34.484] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.34.484] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.34.485] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/arm_controller/); +[16:51.34.486] (SSH-Browser) END OpenDir(2) +[16:51.34.503] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.34.503] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code/arm_controller) +[16:51.34.535] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.34.535] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.34.625] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.34.625] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.34.625] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.34.625] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.34.625] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.34.625] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.34.625] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.34.625] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.34.625] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.34.625] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=11 +[16:51.34.626] (SSH-Browser) 对项目进行排序 +[16:51.34.626] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.34.628] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.34.656] (SSH-Browser) ElSFTP1Success(2) + +[16:51.35.158] BEGIN WMNewTab: 20 +[16:51.35.158] END WMNewTab: 20 +[16:51.35.158] BEGIN WMNewTab: 20 +[16:51.35.158] END WMNewTab: 20 +[16:51.35.158] BEGIN WMNewTab: 20 +[16:51.35.158] END WMNewTab: 20 +[16:51.35.158] BEGIN WMNewTab: 20 +[16:51.35.158] END WMNewTab: 20 +[16:51.35.158] BEGIN WMNewTab: 20 +[16:51.35.158] END WMNewTab: 20 +[16:51.35.186] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.35.478] BEGIN WMNewTab: 20 +[16:51.35.478] END WMNewTab: 20 +[16:51.35.478] BEGIN WMNewTab: 20 +[16:51.35.478] END WMNewTab: 20 +[16:51.35.555] sListView1Click: FormClick +[16:51.35.635] BEGIN WMNewTab: 20 +[16:51.35.635] END WMNewTab: 20 +[16:51.35.638] (SSH-Browser) BEGIN OpenDir(2) +[16:51.35.638] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.35.638] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.35.638] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.35.638] (SSH-Browser) OpenDir(2): 列出远程文件夹 +[16:51.35.639] (SSH-Browser) OpenDir(2): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/marm_code/arm_controller/arm_controller/); +[16:51.35.639] (SSH-Browser) END OpenDir(2) +[16:51.35.665] (SSH-Browser) ElSFTP1AbsolutePath(2) +[16:51.35.665] (SSH-Browser) ElSFTP1AbsolutePath(2): SFTP.OpenDirectory(/userdata/dev_ws/src/marm_code/arm_controller/arm_controller) +[16:51.35.693] (SSH-Browser) ElSFTP1OpenFile(2) +[16:51.35.693] (SSH-Browser) ElSFTP1OpenFile(2): SFTP.ReadDirectory +[16:51.35.755] (SSH-Browser) ElSFTP1Error(2): #1 - End of file +[16:51.35.755] (SSH-Browser) ElSFTP1Error(2): CloseCurrentHandle1 +[16:51.35.755] (SSH-Browser) BEGIN CloseCurrentHandle(2) +[16:51.35.755] (SSH-Browser) BEGIN VerifySFTPConnection(2) +[16:51.35.755] (SSH-Browser) VerifySFTPConnection(2): result=true (Sftp 连接) +[16:51.35.755] (SSH-Browser) END VerifySFTPConnection(2) +[16:51.35.755] (SSH-Browser) CloseCurrentHandle(2): SFTP.CloseHandle +[16:51.35.755] (SSH-Browser) END CloseCurrentHandle(2) +[16:51.35.755] (SSH-Browser) BEGIN CopySFTPFileListToListView(2) +[16:51.35.755] (SSH-Browser) CopySFTPFileListToListView(2): FileList.Count=5 +[16:51.35.755] (SSH-Browser) 对项目进行排序 +[16:51.35.755] (SSH-Browser) CopySFTPFileListToListView(2): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.35.758] (SSH-Browser) END CopySFTPFileListToListView(2) +[16:51.35.784] (SSH-Browser) ElSFTP1Success(2) + +[16:51.36.577] BEGIN WMNewTab: 20 +[16:51.36.577] END WMNewTab: 20 +[16:51.36.580] BEGIN WMNewTab: 20 +[16:51.36.580] END WMNewTab: 20 +[16:51.36.582] BEGIN WMNewTab: 20 +[16:51.36.582] END WMNewTab: 20 +[16:51.36.582] BEGIN WMNewTab: 20 +[16:51.36.582] END WMNewTab: 20 +[16:51.36.582] BEGIN WMNewTab: 20 +[16:51.36.582] END WMNewTab: 20 +[16:51.36.779] sListView1Click: FormClick +[16:51.36.807] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.36.895] BEGIN WMNewTab: 20 +[16:51.36.895] END WMNewTab: 20 +[16:51.36.895] BEGIN WMNewTab: 20 +[16:51.36.895] END WMNewTab: 20 +[16:51.37.201] BEGIN WMNewTab: 20 +[16:51.37.201] END WMNewTab: 20 + +[16:51.37.998] BEGIN WMNewTab: 20 +[16:51.37.998] END WMNewTab: 20 +[16:51.37.998] BEGIN WMNewTab: 20 +[16:51.37.998] END WMNewTab: 20 +[16:51.37.998] BEGIN WMNewTab: 20 +[16:51.37.998] END WMNewTab: 20 +[16:51.37.998] BEGIN WMNewTab: 20 +[16:51.37.998] END WMNewTab: 20 +[16:51.37.998] BEGIN WMNewTab: 20 +[16:51.37.998] END WMNewTab: 20 +[16:51.38.318] BEGIN WMNewTab: 20 +[16:51.38.318] END WMNewTab: 20 +[16:51.38.318] BEGIN WMNewTab: 20 +[16:51.38.318] END WMNewTab: 20 +[16:51.38.411] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.38.428] BEGIN WMNewTab: 0 +[16:51.38.428] WMNewTab: FormClick +[16:51.38.428] WMNewTab: LooseFocus +[16:51.38.431] END WMNewTab: 0 +[16:51.38.554] BEGIN WMNewTab: 0 +[16:51.38.554] WMNewTab: FormClick +[16:51.38.554] WMNewTab: LooseFocus +[16:51.38.554] END WMNewTab: 0 +[16:51.38.621] BEGIN WMNewTab: 20 +[16:51.38.621] END WMNewTab: 20 +[16:51.38.707] BEGIN WMNewTab: 0 +[16:51.38.707] WMNewTab: FormClick +[16:51.38.707] WMNewTab: LooseFocus +[16:51.38.707] END WMNewTab: 0 +[16:51.38.707] BEGIN WMNewTab: 31 +[16:51.38.707] END WMNewTab: 31 +[16:51.38.826] BEGIN WMNewTab: 0 +[16:51.38.826] WMNewTab: FormClick +[16:51.38.826] WMNewTab: LooseFocus +[16:51.38.826] END WMNewTab: 0 + +[16:51.39.417] BEGIN WMNewTab: 20 +[16:51.39.417] END WMNewTab: 20 +[16:51.39.418] BEGIN WMNewTab: 20 +[16:51.39.418] END WMNewTab: 20 +[16:51.39.418] BEGIN WMNewTab: 20 +[16:51.39.418] END WMNewTab: 20 +[16:51.39.418] BEGIN WMNewTab: 20 +[16:51.39.418] END WMNewTab: 20 +[16:51.39.418] BEGIN WMNewTab: 20 +[16:51.39.418] END WMNewTab: 20 +[16:51.39.738] BEGIN WMNewTab: 20 +[16:51.39.738] END WMNewTab: 20 +[16:51.39.738] BEGIN WMNewTab: 20 +[16:51.39.738] END WMNewTab: 20 +[16:51.40.013] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.40.043] BEGIN WMNewTab: 20 +[16:51.40.043] END WMNewTab: 20 + +[16:51.40.835] BEGIN WMNewTab: 20 +[16:51.40.835] END WMNewTab: 20 +[16:51.40.835] BEGIN WMNewTab: 20 +[16:51.40.835] END WMNewTab: 20 +[16:51.40.835] BEGIN WMNewTab: 20 +[16:51.40.835] END WMNewTab: 20 +[16:51.40.835] BEGIN WMNewTab: 20 +[16:51.40.835] END WMNewTab: 20 +[16:51.40.835] BEGIN WMNewTab: 20 +[16:51.40.835] END WMNewTab: 20 +[16:51.41.154] BEGIN WMNewTab: 20 +[16:51.41.154] END WMNewTab: 20 +[16:51.41.154] BEGIN WMNewTab: 20 +[16:51.41.154] END WMNewTab: 20 +[16:51.41.458] BEGIN WMNewTab: 20 +[16:51.41.458] END WMNewTab: 20 +[16:51.41.626] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.42.257] BEGIN WMNewTab: 20 +[16:51.42.257] END WMNewTab: 20 +[16:51.42.257] BEGIN WMNewTab: 20 +[16:51.42.257] END WMNewTab: 20 +[16:51.42.257] BEGIN WMNewTab: 20 +[16:51.42.257] END WMNewTab: 20 +[16:51.42.257] BEGIN WMNewTab: 20 +[16:51.42.257] END WMNewTab: 20 +[16:51.42.257] BEGIN WMNewTab: 20 +[16:51.42.257] END WMNewTab: 20 +[16:51.42.576] BEGIN WMNewTab: 20 +[16:51.42.576] END WMNewTab: 20 +[16:51.42.576] BEGIN WMNewTab: 20 +[16:51.42.576] END WMNewTab: 20 +[16:51.42.880] BEGIN WMNewTab: 20 +[16:51.42.880] END WMNewTab: 20 +[16:51.43.231] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.43.673] BEGIN WMNewTab: 20 +[16:51.43.673] END WMNewTab: 20 +[16:51.43.673] BEGIN WMNewTab: 20 +[16:51.43.673] END WMNewTab: 20 +[16:51.43.673] BEGIN WMNewTab: 20 +[16:51.43.673] END WMNewTab: 20 +[16:51.43.673] BEGIN WMNewTab: 20 +[16:51.43.673] END WMNewTab: 20 +[16:51.43.673] BEGIN WMNewTab: 20 +[16:51.43.673] END WMNewTab: 20 +[16:51.43.991] BEGIN WMNewTab: 20 +[16:51.43.991] END WMNewTab: 20 +[16:51.43.991] BEGIN WMNewTab: 20 +[16:51.43.992] END WMNewTab: 20 +[16:51.44.295] BEGIN WMNewTab: 20 +[16:51.44.295] END WMNewTab: 20 + +[16:51.44.844] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.45.088] BEGIN WMNewTab: 20 +[16:51.45.088] END WMNewTab: 20 +[16:51.45.088] BEGIN WMNewTab: 20 +[16:51.45.088] END WMNewTab: 20 +[16:51.45.088] BEGIN WMNewTab: 20 +[16:51.45.088] END WMNewTab: 20 +[16:51.45.088] BEGIN WMNewTab: 20 +[16:51.45.088] END WMNewTab: 20 +[16:51.45.088] BEGIN WMNewTab: 20 +[16:51.45.088] END WMNewTab: 20 +[16:51.45.405] BEGIN WMNewTab: 20 +[16:51.45.405] END WMNewTab: 20 +[16:51.45.405] BEGIN WMNewTab: 20 +[16:51.45.405] END WMNewTab: 20 +[16:51.45.712] BEGIN WMNewTab: 20 +[16:51.45.712] END WMNewTab: 20 +[16:51.45.836] Cts1MouseDown: FormClick +[16:51.45.848] Cts1ActiveTabChanged: New index = 3 +[16:51.45.848] BEGIN DisplayCurrentTab +[16:51.45.848] DisplayCurrentTab: FormClick +[16:51.45.848] (SSH-Browser) DisplayCurrentTab(3): ActiverPanel14 +[16:51.45.848] (SSH-Browser) BEGIN ActiverPanel14 +[16:51.45.848] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:51.45.860] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:51.45.860] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/userdata/dev_ws/src/marm_code/arm_controller/arm_controller/ +[16:51.45.914] (SSH-Browser) ActiverPanel14: OpenDir(.); +[16:51.45.914] (SSH-Browser) BEGIN OpenDir(3) +[16:51.45.914] (SSH-Browser) BEGIN VerifySFTPConnection(3) +[16:51.45.914] (SSH-Browser) VerifySFTPConnection(3): result=true (Sftp 连接) +[16:51.45.914] (SSH-Browser) END VerifySFTPConnection(3) +[16:51.45.914] (SSH-Browser) OpenDir(3): 列出远程文件夹 +[16:51.45.914] (SSH-Browser) OpenDir(3): SFTP.RequestAbsolutePath(.); +[16:51.45.915] (SSH-Browser) END OpenDir(3) +[16:51.45.915] (SSH-Browser) END ActiverPanel14; +[16:51.46.053] (SSH-Browser) 正在启动 MobaSCP(8, remotemonitoring, ., ) +[16:51.46.053] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756668" -remotemonitoring mobauser@mobaserver:".") +[16:51.46.070] (SSH-Browser) ElSFTP1AbsolutePath(3) +[16:51.46.070] (SSH-Browser) ElSFTP1AbsolutePath(3): SFTP.OpenDirectory(/root) +[16:51.46.081] ShellExecuteS: ShellExecuteEx 成功. +[16:51.46.081] ShellExecuteS: WaitForInputIdle 失败. +[16:51.46.081] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756668" -remotemonitoring mobauser@mobaserver:".") +[16:51.46.081] DisplayCurrentTab: Cts1.BeginUpdate; +[16:51.46.081] DisplayCurrentTab: Cts1.EndUpdates +[16:51.46.203] DisplayCurrentTab: 显示所选标签页 +[16:51.46.203] [MobaSCP8] Launching remote monitoring in normal mode +[16:51.46.205] [MobaSCP8] Multiplex=1 +[16:51.46.206] [MobaSCP8] HOSTNAME: 192.168.127.10 +[16:51.46.206] [MobaSCP8] USERNAME: root +[16:51.46.207] DisplayCurrentTab: 隐藏其他标签页 +[16:51.46.210] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:51.46.214] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:51.46.214] DisplayCurrentTab: DistribuerLeFocus +[16:51.46.214] END DisplayCurrentTab +[16:51.46.305] [MobaSCP8] Using SCP1 +[16:51.46.305] (SSH-Browser) ElSFTP1OpenFile(3) +[16:51.46.305] (SSH-Browser) ElSFTP1OpenFile(3): SFTP.ReadDirectory +[16:51.46.305] [MobaSCP8] Connected to 192.168.127.10 +[16:51.46.306] BEGIN WMNewTab: 20 +[16:51.46.306] END WMNewTab: 20 +[16:51.46.368] (SSH-Browser) ElSFTP1Error(3): #1 - End of file +[16:51.46.368] (SSH-Browser) ElSFTP1Error(3): CloseCurrentHandle1 +[16:51.46.368] (SSH-Browser) BEGIN CloseCurrentHandle(3) +[16:51.46.368] (SSH-Browser) BEGIN VerifySFTPConnection(3) +[16:51.46.368] (SSH-Browser) VerifySFTPConnection(3): result=true (Sftp 连接) +[16:51.46.368] (SSH-Browser) END VerifySFTPConnection(3) +[16:51.46.368] (SSH-Browser) CloseCurrentHandle(3): SFTP.CloseHandle +[16:51.46.368] (SSH-Browser) END CloseCurrentHandle(3) +[16:51.46.368] (SSH-Browser) BEGIN CopySFTPFileListToListView(3) +[16:51.46.368] (SSH-Browser) CopySFTPFileListToListView(3): FileList.Count=18 +[16:51.46.368] (SSH-Browser) 对项目进行排序 +[16:51.46.368] (SSH-Browser) CopySFTPFileListToListView(3): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:51.46.378] (SSH-Browser) END CopySFTPFileListToListView(3) +[16:51.46.413] (SSH-Browser) ElSFTP1Success(3) +[16:51.46.459] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.46.504] BEGIN WMNewTab: 20 +[16:51.46.504] END WMNewTab: 20 +[16:51.46.504] BEGIN WMNewTab: 20 +[16:51.46.504] END WMNewTab: 20 +[16:51.46.504] BEGIN WMNewTab: 20 +[16:51.46.504] END WMNewTab: 20 +[16:51.46.504] BEGIN WMNewTab: 20 +[16:51.46.504] END WMNewTab: 20 +[16:51.46.823] BEGIN WMNewTab: 20 +[16:51.46.823] END WMNewTab: 20 +[16:51.46.824] BEGIN WMNewTab: 20 +[16:51.46.824] END WMNewTab: 20 +[16:51.47.129] BEGIN WMNewTab: 20 +[16:51.47.129] END WMNewTab: 20 +[16:51.47.435] BEGIN TFormXterm.FormResize +[16:51.47.435] TFormXterm.FormResize: CenterBtnReattachTab +[16:51.47.435] TFormXterm.FormResize: SplitModeResize +[16:51.47.435] TFormXterm.FormResize: BtnSplitNo.Down +[16:51.47.435] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:51.47.435] BEGIN ResizeTerminal +[16:51.47.435] END ResizeTerminal +[16:51.47.435] TFormXterm.FormResize: AdaptSidebarArrows; +[16:51.47.435] BEGIN AdaptSidebarArrows +[16:51.47.435] END AdaptSidebarArrows +[16:51.47.435] TFormXterm.FormResize: AdaptTV2; +[16:51.47.435] END TFormXterm.FormResize + +[16:51.47.826] BEGIN WMNewTab: 20 +[16:51.47.826] END WMNewTab: 20 +[16:51.47.916] BEGIN WMNewTab: 20 +[16:51.47.916] END WMNewTab: 20 +[16:51.47.916] BEGIN WMNewTab: 20 +[16:51.47.916] END WMNewTab: 20 +[16:51.47.916] BEGIN WMNewTab: 20 +[16:51.47.916] END WMNewTab: 20 +[16:51.47.916] BEGIN WMNewTab: 20 +[16:51.47.916] END WMNewTab: 20 +[16:51.48.069] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.48.236] BEGIN WMNewTab: 20 +[16:51.48.236] END WMNewTab: 20 +[16:51.48.236] BEGIN WMNewTab: 20 +[16:51.48.236] END WMNewTab: 20 +[16:51.48.544] BEGIN WMNewTab: 20 +[16:51.48.544] END WMNewTab: 20 + +[16:51.49.247] BEGIN WMNewTab: 20 +[16:51.49.247] END WMNewTab: 20 +[16:51.49.338] BEGIN WMNewTab: 20 +[16:51.49.338] END WMNewTab: 20 +[16:51.49.339] BEGIN WMNewTab: 20 +[16:51.49.339] END WMNewTab: 20 +[16:51.49.339] BEGIN WMNewTab: 20 +[16:51.49.339] END WMNewTab: 20 +[16:51.49.339] BEGIN WMNewTab: 20 +[16:51.49.339] END WMNewTab: 20 +[16:51.49.659] BEGIN WMNewTab: 20 +[16:51.49.659] END WMNewTab: 20 +[16:51.49.659] BEGIN WMNewTab: 20 +[16:51.49.659] END WMNewTab: 20 +[16:51.49.673] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.49.964] BEGIN WMNewTab: 20 +[16:51.49.964] END WMNewTab: 20 + +[16:51.50.671] BEGIN WMNewTab: 20 +[16:51.50.671] END WMNewTab: 20 +[16:51.50.762] BEGIN WMNewTab: 20 +[16:51.50.762] END WMNewTab: 20 +[16:51.50.762] BEGIN WMNewTab: 20 +[16:51.50.762] END WMNewTab: 20 +[16:51.50.762] BEGIN WMNewTab: 20 +[16:51.50.762] END WMNewTab: 20 +[16:51.50.762] BEGIN WMNewTab: 20 +[16:51.50.762] END WMNewTab: 20 +[16:51.51.082] BEGIN WMNewTab: 20 +[16:51.51.082] END WMNewTab: 20 +[16:51.51.082] BEGIN WMNewTab: 20 +[16:51.51.082] END WMNewTab: 20 +[16:51.51.281] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.51.388] BEGIN WMNewTab: 20 +[16:51.51.388] END WMNewTab: 20 + +[16:51.52.092] BEGIN WMNewTab: 20 +[16:51.52.092] END WMNewTab: 20 +[16:51.52.183] BEGIN WMNewTab: 20 +[16:51.52.183] END WMNewTab: 20 +[16:51.52.183] BEGIN WMNewTab: 20 +[16:51.52.183] END WMNewTab: 20 +[16:51.52.183] BEGIN WMNewTab: 20 +[16:51.52.183] END WMNewTab: 20 +[16:51.52.183] BEGIN WMNewTab: 20 +[16:51.52.183] END WMNewTab: 20 +[16:51.52.506] BEGIN WMNewTab: 20 +[16:51.52.506] END WMNewTab: 20 +[16:51.52.506] BEGIN WMNewTab: 20 +[16:51.52.506] END WMNewTab: 20 +[16:51.52.810] BEGIN WMNewTab: 20 +[16:51.52.810] END WMNewTab: 20 +[16:51.52.895] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.53.493] BEGIN WMNewTab: 31 +[16:51.53.493] END WMNewTab: 31 +[16:51.53.493] BEGIN WMNewTab: 0 +[16:51.53.493] WMNewTab: FormClick +[16:51.53.493] WMNewTab: LooseFocus +[16:51.53.495] END WMNewTab: 0 +[16:51.53.510] BEGIN WMNewTab: 20 +[16:51.53.510] END WMNewTab: 20 +[16:51.53.571] BEGIN WMNewTab: 0 +[16:51.53.571] WMNewTab: FormClick +[16:51.53.571] WMNewTab: LooseFocus +[16:51.53.573] END WMNewTab: 0 +[16:51.53.606] BEGIN WMNewTab: 20 +[16:51.53.606] END WMNewTab: 20 +[16:51.53.607] BEGIN WMNewTab: 20 +[16:51.53.607] END WMNewTab: 20 +[16:51.53.607] BEGIN WMNewTab: 20 +[16:51.53.607] END WMNewTab: 20 +[16:51.53.607] BEGIN WMNewTab: 20 +[16:51.53.607] END WMNewTab: 20 +[16:51.53.923] BEGIN WMNewTab: 20 +[16:51.53.923] END WMNewTab: 20 +[16:51.53.923] BEGIN WMNewTab: 20 +[16:51.53.923] END WMNewTab: 20 +[16:51.54.229] BEGIN WMNewTab: 20 +[16:51.54.229] END WMNewTab: 20 +[16:51.54.529] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:51.54.931] BEGIN WMNewTab: 20 +[16:51.54.931] END WMNewTab: 20 +[16:51.55.023] BEGIN WMNewTab: 20 +[16:51.55.023] END WMNewTab: 20 +[16:51.55.023] BEGIN WMNewTab: 20 +[16:51.55.023] END WMNewTab: 20 +[16:51.55.023] BEGIN WMNewTab: 20 +[16:51.55.023] END WMNewTab: 20 +[16:51.55.023] BEGIN WMNewTab: 20 +[16:51.55.023] END WMNewTab: 20 +[16:51.55.344] BEGIN WMNewTab: 20 +[16:51.55.344] END WMNewTab: 20 +[16:51.55.344] BEGIN WMNewTab: 20 +[16:51.55.344] END WMNewTab: 20 +[16:51.55.648] BEGIN WMNewTab: 20 +[16:51.55.648] END WMNewTab: 20 + +[16:51.56.120] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.56.351] BEGIN WMNewTab: 20 +[16:51.56.351] END WMNewTab: 20 +[16:51.56.442] BEGIN WMNewTab: 20 +[16:51.56.442] END WMNewTab: 20 +[16:51.56.442] BEGIN WMNewTab: 20 +[16:51.56.442] END WMNewTab: 20 +[16:51.56.442] BEGIN WMNewTab: 20 +[16:51.56.442] END WMNewTab: 20 +[16:51.56.442] BEGIN WMNewTab: 20 +[16:51.56.442] END WMNewTab: 20 +[16:51.56.762] BEGIN WMNewTab: 20 +[16:51.56.762] END WMNewTab: 20 +[16:51.56.762] BEGIN WMNewTab: 20 +[16:51.56.762] END WMNewTab: 20 +[16:51.57.068] BEGIN WMNewTab: 20 +[16:51.57.068] END WMNewTab: 20 + +[16:51.57.725] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.57.771] BEGIN WMNewTab: 20 +[16:51.57.771] END WMNewTab: 20 +[16:51.57.861] BEGIN WMNewTab: 20 +[16:51.57.861] END WMNewTab: 20 +[16:51.57.861] BEGIN WMNewTab: 20 +[16:51.57.861] END WMNewTab: 20 +[16:51.57.861] BEGIN WMNewTab: 20 +[16:51.57.861] END WMNewTab: 20 +[16:51.57.861] BEGIN WMNewTab: 20 +[16:51.57.861] END WMNewTab: 20 +[16:51.58.182] BEGIN WMNewTab: 20 +[16:51.58.182] END WMNewTab: 20 +[16:51.58.182] BEGIN WMNewTab: 20 +[16:51.58.182] END WMNewTab: 20 +[16:51.58.488] BEGIN WMNewTab: 20 +[16:51.58.488] END WMNewTab: 20 + +[16:51.59.188] BEGIN WMNewTab: 20 +[16:51.59.188] END WMNewTab: 20 +[16:51.59.281] BEGIN WMNewTab: 20 +[16:51.59.281] END WMNewTab: 20 +[16:51.59.281] BEGIN WMNewTab: 20 +[16:51.59.281] END WMNewTab: 20 +[16:51.59.281] BEGIN WMNewTab: 20 +[16:51.59.281] END WMNewTab: 20 +[16:51.59.281] BEGIN WMNewTab: 20 +[16:51.59.281] END WMNewTab: 20 +[16:51.59.325] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:51.59.624] BEGIN WMNewTab: 20 +[16:51.59.624] END WMNewTab: 20 +[16:51.59.624] BEGIN WMNewTab: 20 +[16:51.59.624] END WMNewTab: 20 +[16:51.59.903] BEGIN WMNewTab: 20 +[16:51.59.903] END WMNewTab: 20 + +[16:52.00.640] BEGIN WMNewTab: 20 +[16:52.00.640] END WMNewTab: 20 +[16:52.00.695] BEGIN WMNewTab: 20 +[16:52.00.695] END WMNewTab: 20 +[16:52.00.695] BEGIN WMNewTab: 20 +[16:52.00.695] END WMNewTab: 20 +[16:52.00.695] BEGIN WMNewTab: 20 +[16:52.00.695] END WMNewTab: 20 +[16:52.00.695] BEGIN WMNewTab: 20 +[16:52.00.695] END WMNewTab: 20 +[16:52.00.939] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.01.030] BEGIN WMNewTab: 20 +[16:52.01.030] END WMNewTab: 20 +[16:52.01.030] BEGIN WMNewTab: 20 +[16:52.01.030] END WMNewTab: 20 +[16:52.01.321] BEGIN WMNewTab: 20 +[16:52.01.321] END WMNewTab: 20 + +[16:52.02.051] BEGIN WMNewTab: 20 +[16:52.02.051] END WMNewTab: 20 +[16:52.02.113] BEGIN WMNewTab: 20 +[16:52.02.113] END WMNewTab: 20 +[16:52.02.113] BEGIN WMNewTab: 20 +[16:52.02.113] END WMNewTab: 20 +[16:52.02.113] BEGIN WMNewTab: 20 +[16:52.02.113] END WMNewTab: 20 +[16:52.02.113] BEGIN WMNewTab: 20 +[16:52.02.113] END WMNewTab: 20 +[16:52.02.448] BEGIN WMNewTab: 20 +[16:52.02.448] END WMNewTab: 20 +[16:52.02.448] BEGIN WMNewTab: 20 +[16:52.02.448] END WMNewTab: 20 +[16:52.02.548] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.02.737] BEGIN WMNewTab: 20 +[16:52.02.737] END WMNewTab: 20 + +[16:52.03.467] BEGIN WMNewTab: 20 +[16:52.03.467] END WMNewTab: 20 +[16:52.03.528] BEGIN WMNewTab: 20 +[16:52.03.528] END WMNewTab: 20 +[16:52.03.528] BEGIN WMNewTab: 20 +[16:52.03.528] END WMNewTab: 20 +[16:52.03.528] BEGIN WMNewTab: 20 +[16:52.03.528] END WMNewTab: 20 +[16:52.03.528] BEGIN WMNewTab: 20 +[16:52.03.528] END WMNewTab: 20 +[16:52.03.865] BEGIN WMNewTab: 20 +[16:52.03.865] END WMNewTab: 20 +[16:52.03.865] BEGIN WMNewTab: 20 +[16:52.03.865] END WMNewTab: 20 +[16:52.04.155] BEGIN WMNewTab: 20 +[16:52.04.155] END WMNewTab: 20 +[16:52.04.155] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.04.889] BEGIN WMNewTab: 20 +[16:52.04.889] END WMNewTab: 20 +[16:52.04.951] BEGIN WMNewTab: 20 +[16:52.04.951] END WMNewTab: 20 +[16:52.04.951] BEGIN WMNewTab: 20 +[16:52.04.951] END WMNewTab: 20 +[16:52.04.951] BEGIN WMNewTab: 20 +[16:52.04.951] END WMNewTab: 20 +[16:52.04.951] BEGIN WMNewTab: 20 +[16:52.04.952] END WMNewTab: 20 +[16:52.05.284] BEGIN WMNewTab: 20 +[16:52.05.284] END WMNewTab: 20 +[16:52.05.284] BEGIN WMNewTab: 20 +[16:52.05.284] END WMNewTab: 20 +[16:52.05.573] BEGIN WMNewTab: 20 +[16:52.05.573] END WMNewTab: 20 +[16:52.05.805] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.06.302] BEGIN WMNewTab: 20 +[16:52.06.302] END WMNewTab: 20 +[16:52.06.364] BEGIN WMNewTab: 20 +[16:52.06.364] END WMNewTab: 20 +[16:52.06.364] BEGIN WMNewTab: 20 +[16:52.06.364] END WMNewTab: 20 +[16:52.06.364] BEGIN WMNewTab: 20 +[16:52.06.364] END WMNewTab: 20 +[16:52.06.364] BEGIN WMNewTab: 20 +[16:52.06.364] END WMNewTab: 20 +[16:52.06.699] BEGIN WMNewTab: 20 +[16:52.06.699] END WMNewTab: 20 +[16:52.06.699] BEGIN WMNewTab: 20 +[16:52.06.699] END WMNewTab: 20 +[16:52.06.991] BEGIN WMNewTab: 20 +[16:52.06.991] END WMNewTab: 20 + +[16:52.07.386] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.07.722] BEGIN WMNewTab: 20 +[16:52.07.722] END WMNewTab: 20 +[16:52.07.817] BEGIN WMNewTab: 20 +[16:52.07.817] END WMNewTab: 20 +[16:52.07.817] BEGIN WMNewTab: 20 +[16:52.07.817] END WMNewTab: 20 +[16:52.07.817] BEGIN WMNewTab: 20 +[16:52.07.818] END WMNewTab: 20 +[16:52.07.818] BEGIN WMNewTab: 20 +[16:52.07.818] END WMNewTab: 20 +[16:52.08.118] BEGIN WMNewTab: 20 +[16:52.08.118] END WMNewTab: 20 +[16:52.08.118] BEGIN WMNewTab: 20 +[16:52.08.118] END WMNewTab: 20 +[16:52.08.409] BEGIN WMNewTab: 20 +[16:52.08.409] END WMNewTab: 20 + +[16:52.08.988] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.09.139] BEGIN WMNewTab: 20 +[16:52.09.139] END WMNewTab: 20 +[16:52.09.231] BEGIN WMNewTab: 20 +[16:52.09.231] END WMNewTab: 20 +[16:52.09.231] BEGIN WMNewTab: 20 +[16:52.09.231] END WMNewTab: 20 +[16:52.09.231] BEGIN WMNewTab: 20 +[16:52.09.231] END WMNewTab: 20 +[16:52.09.231] BEGIN WMNewTab: 20 +[16:52.09.231] END WMNewTab: 20 +[16:52.09.539] BEGIN WMNewTab: 20 +[16:52.09.539] END WMNewTab: 20 +[16:52.09.539] BEGIN WMNewTab: 20 +[16:52.09.539] END WMNewTab: 20 +[16:52.09.841] BEGIN WMNewTab: 20 +[16:52.09.841] END WMNewTab: 20 + +[16:52.10.561] BEGIN WMNewTab: 20 +[16:52.10.561] END WMNewTab: 20 +[16:52.10.592] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.10.654] BEGIN WMNewTab: 20 +[16:52.10.654] END WMNewTab: 20 +[16:52.10.654] BEGIN WMNewTab: 20 +[16:52.10.654] END WMNewTab: 20 +[16:52.10.654] BEGIN WMNewTab: 20 +[16:52.10.654] END WMNewTab: 20 +[16:52.10.654] BEGIN WMNewTab: 20 +[16:52.10.654] END WMNewTab: 20 +[16:52.10.959] BEGIN WMNewTab: 20 +[16:52.10.959] END WMNewTab: 20 +[16:52.10.959] BEGIN WMNewTab: 20 +[16:52.10.959] END WMNewTab: 20 +[16:52.11.249] BEGIN WMNewTab: 20 +[16:52.11.249] END WMNewTab: 20 + +[16:52.11.787] Cts1MouseDown: FormClick +[16:52.11.799] Cts1ActiveTabChanged: New index = 4 +[16:52.11.799] BEGIN DisplayCurrentTab +[16:52.11.799] DisplayCurrentTab: FormClick +[16:52.11.799] (SSH-Browser) DisplayCurrentTab(4): ActiverPanel14 +[16:52.11.799] (SSH-Browser) BEGIN ActiverPanel14 +[16:52.11.799] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:52.11.811] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:52.11.811] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/root/ +[16:52.11.876] (SSH-Browser) ActiverPanel14: OpenDir(.); +[16:52.11.876] (SSH-Browser) BEGIN OpenDir(4) +[16:52.11.876] (SSH-Browser) BEGIN VerifySFTPConnection(4) +[16:52.11.876] (SSH-Browser) VerifySFTPConnection(4): result=true (Sftp 连接) +[16:52.11.876] (SSH-Browser) END VerifySFTPConnection(4) +[16:52.11.876] (SSH-Browser) OpenDir(4): 列出远程文件夹 +[16:52.11.876] (SSH-Browser) OpenDir(4): SFTP.RequestAbsolutePath(.); +[16:52.11.877] (SSH-Browser) END OpenDir(4) +[16:52.11.877] (SSH-Browser) END ActiverPanel14; +[16:52.12.016] (SSH-Browser) 正在启动 MobaSCP(9, remotemonitoring, ., ) +[16:52.12.016] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756669" -remotemonitoring mobauser@mobaserver:".") +[16:52.12.017] BEGIN WMNewTab: 20 +[16:52.12.017] END WMNewTab: 20 +[16:52.12.028] (SSH-Browser) ElSFTP1AbsolutePath(4) +[16:52.12.028] (SSH-Browser) ElSFTP1AbsolutePath(4): SFTP.OpenDirectory(/root) +[16:52.12.048] ShellExecuteS: ShellExecuteEx 成功. +[16:52.12.048] ShellExecuteS: WaitForInputIdle 失败. +[16:52.12.048] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM131756669" -remotemonitoring mobauser@mobaserver:".") +[16:52.12.048] DisplayCurrentTab: Cts1.BeginUpdate; +[16:52.12.048] DisplayCurrentTab: Cts1.EndUpdates +[16:52.12.170] DisplayCurrentTab: 显示所选标签页 +[16:52.12.171] BEGIN WMNewTab: 20 +[16:52.12.171] END WMNewTab: 20 +[16:52.12.171] BEGIN WMNewTab: 20 +[16:52.12.171] END WMNewTab: 20 +[16:52.12.171] BEGIN WMNewTab: 20 +[16:52.12.171] END WMNewTab: 20 +[16:52.12.172] BEGIN WMNewTab: 20 +[16:52.12.172] END WMNewTab: 20 +[16:52.12.172] [MobaSCP9] Launching remote monitoring in normal mode +[16:52.12.172] [MobaSCP9] Multiplex=1 +[16:52.12.174] [MobaSCP9] HOSTNAME: 192.168.127.10 +[16:52.12.174] [MobaSCP9] USERNAME: root +[16:52.12.175] DisplayCurrentTab: 隐藏其他标签页 +[16:52.12.178] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:52.12.182] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:52.12.182] DisplayCurrentTab: DistribuerLeFocus +[16:52.12.182] END DisplayCurrentTab +[16:52.12.272] [MobaSCP9] Using SCP1 +[16:52.12.272] (SSH-Browser) ElSFTP1OpenFile(4) +[16:52.12.272] (SSH-Browser) ElSFTP1OpenFile(4): SFTP.ReadDirectory +[16:52.12.274] [MobaSCP9] Connected to 192.168.127.10 +[16:52.12.274] BEGIN WMNewTab: 20 +[16:52.12.274] END WMNewTab: 20 +[16:52.12.279] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.12.341] (SSH-Browser) ElSFTP1Error(4): #1 - End of file +[16:52.12.341] (SSH-Browser) ElSFTP1Error(4): CloseCurrentHandle1 +[16:52.12.341] (SSH-Browser) BEGIN CloseCurrentHandle(4) +[16:52.12.341] (SSH-Browser) BEGIN VerifySFTPConnection(4) +[16:52.12.341] (SSH-Browser) VerifySFTPConnection(4): result=true (Sftp 连接) +[16:52.12.341] (SSH-Browser) END VerifySFTPConnection(4) +[16:52.12.341] (SSH-Browser) CloseCurrentHandle(4): SFTP.CloseHandle +[16:52.12.341] (SSH-Browser) END CloseCurrentHandle(4) +[16:52.12.341] (SSH-Browser) BEGIN CopySFTPFileListToListView(4) +[16:52.12.341] (SSH-Browser) CopySFTPFileListToListView(4): FileList.Count=18 +[16:52.12.341] (SSH-Browser) 对项目进行排序 +[16:52.12.341] (SSH-Browser) CopySFTPFileListToListView(4): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:52.12.345] (SSH-Browser) END CopySFTPFileListToListView(4) +[16:52.12.371] BEGIN WMNewTab: 0 +[16:52.12.371] WMNewTab: FormClick +[16:52.12.371] WMNewTab: LooseFocus +[16:52.12.371] END WMNewTab: 0 +[16:52.12.371] BEGIN WMNewTab: 31 +[16:52.12.371] END WMNewTab: 31 +[16:52.12.372] BEGIN WMNewTab: 20 +[16:52.12.372] END WMNewTab: 20 +[16:52.12.372] (SSH-Browser) ElSFTP1Success(4) +[16:52.12.471] BEGIN WMNewTab: 0 +[16:52.12.471] WMNewTab: FormClick +[16:52.12.471] WMNewTab: LooseFocus +[16:52.12.473] END WMNewTab: 0 +[16:52.12.660] BEGIN WMNewTab: 20 +[16:52.12.660] END WMNewTab: 20 + +[16:52.13.415] BEGIN TFormXterm.FormResize +[16:52.13.415] TFormXterm.FormResize: CenterBtnReattachTab +[16:52.13.415] TFormXterm.FormResize: SplitModeResize +[16:52.13.415] TFormXterm.FormResize: BtnSplitNo.Down +[16:52.13.415] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:52.13.415] BEGIN ResizeTerminal +[16:52.13.415] END ResizeTerminal +[16:52.13.415] TFormXterm.FormResize: AdaptSidebarArrows; +[16:52.13.415] BEGIN AdaptSidebarArrows +[16:52.13.415] END AdaptSidebarArrows +[16:52.13.415] TFormXterm.FormResize: AdaptTV2; +[16:52.13.415] END TFormXterm.FormResize +[16:52.13.420] BEGIN WMNewTab: 20 +[16:52.13.420] END WMNewTab: 20 +[16:52.13.572] BEGIN WMNewTab: 20 +[16:52.13.572] END WMNewTab: 20 +[16:52.13.572] BEGIN WMNewTab: 20 +[16:52.13.572] END WMNewTab: 20 +[16:52.13.587] BEGIN WMNewTab: 20 +[16:52.13.587] END WMNewTab: 20 +[16:52.13.587] BEGIN WMNewTab: 20 +[16:52.13.587] END WMNewTab: 20 +[16:52.13.783] BEGIN WMNewTab: 20 +[16:52.13.783] END WMNewTab: 20 +[16:52.13.783] BEGIN WMNewTab: 20 +[16:52.13.783] END WMNewTab: 20 +[16:52.13.815] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.14.074] BEGIN WMNewTab: 20 +[16:52.14.074] END WMNewTab: 20 + +[16:52.14.837] BEGIN WMNewTab: 20 +[16:52.14.837] END WMNewTab: 20 +[16:52.14.987] BEGIN WMNewTab: 20 +[16:52.14.987] END WMNewTab: 20 +[16:52.14.987] BEGIN WMNewTab: 20 +[16:52.14.988] END WMNewTab: 20 +[16:52.15.003] BEGIN WMNewTab: 20 +[16:52.15.003] END WMNewTab: 20 +[16:52.15.003] BEGIN WMNewTab: 20 +[16:52.15.003] END WMNewTab: 20 +[16:52.15.199] BEGIN WMNewTab: 20 +[16:52.15.199] END WMNewTab: 20 +[16:52.15.199] BEGIN WMNewTab: 20 +[16:52.15.199] END WMNewTab: 20 +[16:52.15.427] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.15.487] BEGIN WMNewTab: 20 +[16:52.15.487] END WMNewTab: 20 + +[16:52.16.244] BEGIN WMNewTab: 20 +[16:52.16.244] END WMNewTab: 20 +[16:52.16.402] BEGIN WMNewTab: 20 +[16:52.16.402] END WMNewTab: 20 +[16:52.16.402] BEGIN WMNewTab: 20 +[16:52.16.402] END WMNewTab: 20 +[16:52.16.411] BEGIN WMNewTab: 20 +[16:52.16.411] END WMNewTab: 20 +[16:52.16.411] BEGIN WMNewTab: 20 +[16:52.16.411] END WMNewTab: 20 +[16:52.16.609] BEGIN WMNewTab: 20 +[16:52.16.609] END WMNewTab: 20 +[16:52.16.609] BEGIN WMNewTab: 20 +[16:52.16.609] END WMNewTab: 20 +[16:52.16.900] BEGIN WMNewTab: 20 +[16:52.16.900] END WMNewTab: 20 +[16:52.17.037] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.17.662] BEGIN WMNewTab: 20 +[16:52.17.662] END WMNewTab: 20 +[16:52.17.814] BEGIN WMNewTab: 20 +[16:52.17.814] END WMNewTab: 20 +[16:52.17.814] BEGIN WMNewTab: 20 +[16:52.17.814] END WMNewTab: 20 +[16:52.17.829] BEGIN WMNewTab: 20 +[16:52.17.829] END WMNewTab: 20 +[16:52.17.829] BEGIN WMNewTab: 20 +[16:52.17.829] END WMNewTab: 20 +[16:52.18.027] BEGIN WMNewTab: 20 +[16:52.18.027] END WMNewTab: 20 +[16:52.18.027] BEGIN WMNewTab: 20 +[16:52.18.027] END WMNewTab: 20 +[16:52.18.317] BEGIN WMNewTab: 20 +[16:52.18.317] END WMNewTab: 20 +[16:52.18.644] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.19.080] BEGIN WMNewTab: 20 +[16:52.19.080] END WMNewTab: 20 +[16:52.19.230] BEGIN WMNewTab: 20 +[16:52.19.230] END WMNewTab: 20 +[16:52.19.230] BEGIN WMNewTab: 20 +[16:52.19.230] END WMNewTab: 20 +[16:52.19.245] BEGIN WMNewTab: 20 +[16:52.19.245] END WMNewTab: 20 +[16:52.19.245] BEGIN WMNewTab: 20 +[16:52.19.245] END WMNewTab: 20 +[16:52.19.448] BEGIN WMNewTab: 20 +[16:52.19.448] END WMNewTab: 20 +[16:52.19.448] BEGIN WMNewTab: 20 +[16:52.19.448] END WMNewTab: 20 +[16:52.19.737] BEGIN WMNewTab: 20 +[16:52.19.737] END WMNewTab: 20 + +[16:52.20.254] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.20.500] BEGIN WMNewTab: 20 +[16:52.20.500] END WMNewTab: 20 +[16:52.20.652] BEGIN WMNewTab: 20 +[16:52.20.652] END WMNewTab: 20 +[16:52.20.652] BEGIN WMNewTab: 20 +[16:52.20.652] END WMNewTab: 20 +[16:52.20.667] BEGIN WMNewTab: 20 +[16:52.20.667] END WMNewTab: 20 +[16:52.20.667] BEGIN WMNewTab: 20 +[16:52.20.667] END WMNewTab: 20 +[16:52.20.865] BEGIN WMNewTab: 20 +[16:52.20.865] END WMNewTab: 20 +[16:52.20.865] BEGIN WMNewTab: 20 +[16:52.20.865] END WMNewTab: 20 +[16:52.21.156] BEGIN WMNewTab: 20 +[16:52.21.156] END WMNewTab: 20 + +[16:52.21.869] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.21.915] BEGIN WMNewTab: 20 +[16:52.21.915] END WMNewTab: 20 +[16:52.22.066] BEGIN WMNewTab: 20 +[16:52.22.066] END WMNewTab: 20 +[16:52.22.066] BEGIN WMNewTab: 20 +[16:52.22.066] END WMNewTab: 20 +[16:52.22.081] BEGIN WMNewTab: 20 +[16:52.22.081] END WMNewTab: 20 +[16:52.22.081] BEGIN WMNewTab: 20 +[16:52.22.081] END WMNewTab: 20 +[16:52.22.282] BEGIN WMNewTab: 20 +[16:52.22.282] END WMNewTab: 20 +[16:52.22.282] BEGIN WMNewTab: 20 +[16:52.22.282] END WMNewTab: 20 +[16:52.22.572] BEGIN WMNewTab: 20 +[16:52.22.572] END WMNewTab: 20 + +[16:52.23.336] BEGIN WMNewTab: 20 +[16:52.23.336] END WMNewTab: 20 +[16:52.23.473] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.23.588] BEGIN WMNewTab: 20 +[16:52.23.588] END WMNewTab: 20 +[16:52.23.588] BEGIN WMNewTab: 20 +[16:52.23.588] END WMNewTab: 20 +[16:52.23.588] BEGIN WMNewTab: 20 +[16:52.23.588] END WMNewTab: 20 +[16:52.23.588] BEGIN WMNewTab: 20 +[16:52.23.588] END WMNewTab: 20 +[16:52.23.702] BEGIN WMNewTab: 20 +[16:52.23.702] END WMNewTab: 20 +[16:52.23.702] BEGIN WMNewTab: 20 +[16:52.23.702] END WMNewTab: 20 +[16:52.23.990] BEGIN WMNewTab: 20 +[16:52.23.990] END WMNewTab: 20 + +[16:52.24.754] BEGIN WMNewTab: 20 +[16:52.24.754] END WMNewTab: 20 +[16:52.24.998] BEGIN WMNewTab: 20 +[16:52.24.998] END WMNewTab: 20 +[16:52.24.998] BEGIN WMNewTab: 20 +[16:52.24.998] END WMNewTab: 20 +[16:52.24.998] BEGIN WMNewTab: 20 +[16:52.24.998] END WMNewTab: 20 +[16:52.24.998] BEGIN WMNewTab: 20 +[16:52.24.998] END WMNewTab: 20 +[16:52.25.075] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.25.123] BEGIN WMNewTab: 20 +[16:52.25.123] END WMNewTab: 20 +[16:52.25.124] BEGIN WMNewTab: 20 +[16:52.25.124] END WMNewTab: 20 +[16:52.25.409] BEGIN WMNewTab: 20 +[16:52.25.409] END WMNewTab: 20 + +[16:52.26.172] BEGIN WMNewTab: 20 +[16:52.26.172] END WMNewTab: 20 +[16:52.26.412] BEGIN WMNewTab: 20 +[16:52.26.412] END WMNewTab: 20 +[16:52.26.412] BEGIN WMNewTab: 20 +[16:52.26.412] END WMNewTab: 20 +[16:52.26.412] BEGIN WMNewTab: 20 +[16:52.26.412] END WMNewTab: 20 +[16:52.26.412] BEGIN WMNewTab: 20 +[16:52.26.412] END WMNewTab: 20 +[16:52.26.534] BEGIN WMNewTab: 20 +[16:52.26.534] END WMNewTab: 20 +[16:52.26.534] BEGIN WMNewTab: 20 +[16:52.26.534] END WMNewTab: 20 +[16:52.26.685] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.26.823] BEGIN WMNewTab: 20 +[16:52.26.823] END WMNewTab: 20 + +[16:52.27.615] BEGIN WMNewTab: 20 +[16:52.27.615] END WMNewTab: 20 +[16:52.27.828] BEGIN WMNewTab: 20 +[16:52.27.828] END WMNewTab: 20 +[16:52.27.828] BEGIN WMNewTab: 20 +[16:52.27.828] END WMNewTab: 20 +[16:52.27.828] BEGIN WMNewTab: 20 +[16:52.27.828] END WMNewTab: 20 +[16:52.27.828] BEGIN WMNewTab: 20 +[16:52.27.828] END WMNewTab: 20 +[16:52.27.951] BEGIN WMNewTab: 20 +[16:52.27.951] END WMNewTab: 20 +[16:52.27.951] BEGIN WMNewTab: 20 +[16:52.27.951] END WMNewTab: 20 +[16:52.28.238] BEGIN WMNewTab: 20 +[16:52.28.238] END WMNewTab: 20 +[16:52.28.298] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.29.030] BEGIN WMNewTab: 20 +[16:52.29.030] END WMNewTab: 20 +[16:52.29.242] BEGIN WMNewTab: 20 +[16:52.29.242] END WMNewTab: 20 +[16:52.29.242] BEGIN WMNewTab: 20 +[16:52.29.242] END WMNewTab: 20 +[16:52.29.243] BEGIN WMNewTab: 20 +[16:52.29.243] END WMNewTab: 20 +[16:52.29.243] BEGIN WMNewTab: 20 +[16:52.29.243] END WMNewTab: 20 +[16:52.29.365] BEGIN WMNewTab: 20 +[16:52.29.365] END WMNewTab: 20 +[16:52.29.365] BEGIN WMNewTab: 20 +[16:52.29.365] END WMNewTab: 20 +[16:52.29.664] BEGIN WMNewTab: 20 +[16:52.29.664] END WMNewTab: 20 +[16:52.29.912] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.30.447] BEGIN WMNewTab: 20 +[16:52.30.447] END WMNewTab: 20 +[16:52.30.679] BEGIN WMNewTab: 20 +[16:52.30.679] END WMNewTab: 20 +[16:52.30.679] BEGIN WMNewTab: 20 +[16:52.30.679] END WMNewTab: 20 +[16:52.30.679] BEGIN WMNewTab: 20 +[16:52.30.679] END WMNewTab: 20 +[16:52.30.679] BEGIN WMNewTab: 20 +[16:52.30.679] END WMNewTab: 20 +[16:52.30.782] BEGIN WMNewTab: 20 +[16:52.30.782] END WMNewTab: 20 +[16:52.30.782] BEGIN WMNewTab: 20 +[16:52.30.782] END WMNewTab: 20 +[16:52.31.070] BEGIN WMNewTab: 20 +[16:52.31.070] END WMNewTab: 20 + +[16:52.31.512] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.31.866] BEGIN WMNewTab: 20 +[16:52.31.866] END WMNewTab: 20 +[16:52.32.093] BEGIN WMNewTab: 20 +[16:52.32.093] END WMNewTab: 20 +[16:52.32.093] BEGIN WMNewTab: 20 +[16:52.32.093] END WMNewTab: 20 +[16:52.32.093] BEGIN WMNewTab: 20 +[16:52.32.093] END WMNewTab: 20 +[16:52.32.093] BEGIN WMNewTab: 20 +[16:52.32.093] END WMNewTab: 20 +[16:52.32.200] BEGIN WMNewTab: 20 +[16:52.32.200] END WMNewTab: 20 +[16:52.32.200] BEGIN WMNewTab: 20 +[16:52.32.200] END WMNewTab: 20 +[16:52.32.490] BEGIN WMNewTab: 20 +[16:52.32.490] END WMNewTab: 20 + +[16:52.33.128] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.33.279] BEGIN WMNewTab: 20 +[16:52.33.279] END WMNewTab: 20 +[16:52.33.506] BEGIN WMNewTab: 20 +[16:52.33.506] END WMNewTab: 20 +[16:52.33.507] BEGIN WMNewTab: 20 +[16:52.33.507] END WMNewTab: 20 +[16:52.33.507] BEGIN WMNewTab: 20 +[16:52.33.507] END WMNewTab: 20 +[16:52.33.507] BEGIN WMNewTab: 20 +[16:52.33.507] END WMNewTab: 20 +[16:52.33.611] BEGIN WMNewTab: 20 +[16:52.33.611] END WMNewTab: 20 +[16:52.33.611] BEGIN WMNewTab: 20 +[16:52.33.611] END WMNewTab: 20 +[16:52.33.900] BEGIN WMNewTab: 20 +[16:52.33.900] END WMNewTab: 20 + +[16:52.34.688] BEGIN WMNewTab: 20 +[16:52.34.688] END WMNewTab: 20 +[16:52.34.781] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.34.915] BEGIN WMNewTab: 20 +[16:52.34.915] END WMNewTab: 20 +[16:52.34.915] BEGIN WMNewTab: 20 +[16:52.34.915] END WMNewTab: 20 +[16:52.34.915] BEGIN WMNewTab: 20 +[16:52.34.915] END WMNewTab: 20 +[16:52.34.915] BEGIN WMNewTab: 20 +[16:52.34.915] END WMNewTab: 20 +[16:52.35.022] BEGIN WMNewTab: 20 +[16:52.35.022] END WMNewTab: 20 +[16:52.35.022] BEGIN WMNewTab: 20 +[16:52.35.022] END WMNewTab: 20 +[16:52.35.312] BEGIN WMNewTab: 20 +[16:52.35.312] END WMNewTab: 20 + +[16:52.36.103] BEGIN WMNewTab: 20 +[16:52.36.103] END WMNewTab: 20 +[16:52.36.333] BEGIN WMNewTab: 20 +[16:52.36.333] END WMNewTab: 20 +[16:52.36.333] BEGIN WMNewTab: 20 +[16:52.36.333] END WMNewTab: 20 +[16:52.36.333] BEGIN WMNewTab: 20 +[16:52.36.333] END WMNewTab: 20 +[16:52.36.333] BEGIN WMNewTab: 20 +[16:52.36.333] END WMNewTab: 20 +[16:52.36.348] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.36.439] BEGIN WMNewTab: 20 +[16:52.36.439] END WMNewTab: 20 +[16:52.36.439] BEGIN WMNewTab: 20 +[16:52.36.439] END WMNewTab: 20 +[16:52.36.728] BEGIN WMNewTab: 20 +[16:52.36.728] END WMNewTab: 20 + +[16:52.37.523] BEGIN WMNewTab: 20 +[16:52.37.523] END WMNewTab: 20 +[16:52.37.752] BEGIN WMNewTab: 20 +[16:52.37.752] END WMNewTab: 20 +[16:52.37.752] BEGIN WMNewTab: 20 +[16:52.37.752] END WMNewTab: 20 +[16:52.37.752] BEGIN WMNewTab: 20 +[16:52.37.752] END WMNewTab: 20 +[16:52.37.752] BEGIN WMNewTab: 20 +[16:52.37.752] END WMNewTab: 20 +[16:52.37.860] BEGIN WMNewTab: 20 +[16:52.37.860] END WMNewTab: 20 +[16:52.37.860] BEGIN WMNewTab: 20 +[16:52.37.860] END WMNewTab: 20 +[16:52.37.953] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.38.152] BEGIN WMNewTab: 20 +[16:52.38.152] END WMNewTab: 20 + +[16:52.38.941] BEGIN WMNewTab: 20 +[16:52.38.941] END WMNewTab: 20 +[16:52.39.171] BEGIN WMNewTab: 20 +[16:52.39.171] END WMNewTab: 20 +[16:52.39.171] BEGIN WMNewTab: 20 +[16:52.39.171] END WMNewTab: 20 +[16:52.39.171] BEGIN WMNewTab: 20 +[16:52.39.171] END WMNewTab: 20 +[16:52.39.171] BEGIN WMNewTab: 20 +[16:52.39.171] END WMNewTab: 20 +[16:52.39.277] BEGIN WMNewTab: 20 +[16:52.39.277] END WMNewTab: 20 +[16:52.39.277] BEGIN WMNewTab: 20 +[16:52.39.277] END WMNewTab: 20 +[16:52.39.566] BEGIN WMNewTab: 20 +[16:52.39.566] END WMNewTab: 20 +[16:52.39.566] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.40.360] BEGIN WMNewTab: 20 +[16:52.40.360] END WMNewTab: 20 +[16:52.40.587] BEGIN WMNewTab: 20 +[16:52.40.587] END WMNewTab: 20 +[16:52.40.587] BEGIN WMNewTab: 20 +[16:52.40.587] END WMNewTab: 20 +[16:52.40.587] BEGIN WMNewTab: 20 +[16:52.40.587] END WMNewTab: 20 +[16:52.40.587] BEGIN WMNewTab: 20 +[16:52.40.587] END WMNewTab: 20 +[16:52.40.692] BEGIN WMNewTab: 20 +[16:52.40.692] END WMNewTab: 20 +[16:52.40.692] BEGIN WMNewTab: 20 +[16:52.40.692] END WMNewTab: 20 +[16:52.40.980] BEGIN WMNewTab: 20 +[16:52.40.980] END WMNewTab: 20 +[16:52.41.178] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.41.768] BEGIN WMNewTab: 20 +[16:52.41.768] END WMNewTab: 20 +[16:52.41.997] BEGIN WMNewTab: 20 +[16:52.41.997] END WMNewTab: 20 +[16:52.41.997] BEGIN WMNewTab: 20 +[16:52.41.997] END WMNewTab: 20 +[16:52.41.997] BEGIN WMNewTab: 20 +[16:52.41.997] END WMNewTab: 20 +[16:52.41.997] BEGIN WMNewTab: 20 +[16:52.41.998] END WMNewTab: 20 +[16:52.42.103] BEGIN WMNewTab: 20 +[16:52.42.103] END WMNewTab: 20 +[16:52.42.103] BEGIN WMNewTab: 20 +[16:52.42.103] END WMNewTab: 20 +[16:52.42.391] BEGIN WMNewTab: 20 +[16:52.42.391] END WMNewTab: 20 + +[16:52.42.784] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.43.182] BEGIN WMNewTab: 20 +[16:52.43.182] END WMNewTab: 20 +[16:52.43.412] BEGIN WMNewTab: 20 +[16:52.43.412] END WMNewTab: 20 +[16:52.43.412] BEGIN WMNewTab: 20 +[16:52.43.412] END WMNewTab: 20 +[16:52.43.412] BEGIN WMNewTab: 20 +[16:52.43.412] END WMNewTab: 20 +[16:52.43.412] BEGIN WMNewTab: 20 +[16:52.43.412] END WMNewTab: 20 +[16:52.43.519] BEGIN WMNewTab: 20 +[16:52.43.519] END WMNewTab: 20 +[16:52.43.519] BEGIN WMNewTab: 20 +[16:52.43.519] END WMNewTab: 20 +[16:52.43.812] BEGIN WMNewTab: 20 +[16:52.43.812] END WMNewTab: 20 + +[16:52.44.392] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.44.606] BEGIN WMNewTab: 20 +[16:52.44.606] END WMNewTab: 20 +[16:52.44.833] BEGIN WMNewTab: 20 +[16:52.44.834] END WMNewTab: 20 +[16:52.44.834] BEGIN WMNewTab: 20 +[16:52.44.834] END WMNewTab: 20 +[16:52.44.834] BEGIN WMNewTab: 20 +[16:52.44.834] END WMNewTab: 20 +[16:52.44.834] BEGIN WMNewTab: 20 +[16:52.44.834] END WMNewTab: 20 +[16:52.44.973] BEGIN WMNewTab: 20 +[16:52.44.973] END WMNewTab: 20 +[16:52.44.973] BEGIN WMNewTab: 20 +[16:52.44.973] END WMNewTab: 20 +[16:52.45.228] BEGIN WMNewTab: 20 +[16:52.45.228] END WMNewTab: 20 + +[16:52.46.008] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.46.024] BEGIN WMNewTab: 20 +[16:52.46.024] END WMNewTab: 20 +[16:52.46.252] BEGIN WMNewTab: 20 +[16:52.46.252] END WMNewTab: 20 +[16:52.46.252] BEGIN WMNewTab: 20 +[16:52.46.252] END WMNewTab: 20 +[16:52.46.252] BEGIN WMNewTab: 20 +[16:52.46.252] END WMNewTab: 20 +[16:52.46.253] BEGIN WMNewTab: 20 +[16:52.46.253] END WMNewTab: 20 +[16:52.46.391] BEGIN WMNewTab: 20 +[16:52.46.391] END WMNewTab: 20 +[16:52.46.391] BEGIN WMNewTab: 20 +[16:52.46.391] END WMNewTab: 20 +[16:52.46.648] BEGIN WMNewTab: 20 +[16:52.46.648] END WMNewTab: 20 + +[16:52.47.443] BEGIN WMNewTab: 20 +[16:52.47.443] END WMNewTab: 20 +[16:52.47.610] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.47.669] BEGIN WMNewTab: 20 +[16:52.47.669] END WMNewTab: 20 +[16:52.47.669] BEGIN WMNewTab: 20 +[16:52.47.669] END WMNewTab: 20 +[16:52.47.669] BEGIN WMNewTab: 20 +[16:52.47.669] END WMNewTab: 20 +[16:52.47.669] BEGIN WMNewTab: 20 +[16:52.47.669] END WMNewTab: 20 +[16:52.47.807] BEGIN WMNewTab: 20 +[16:52.47.807] END WMNewTab: 20 +[16:52.47.807] BEGIN WMNewTab: 20 +[16:52.47.807] END WMNewTab: 20 +[16:52.48.064] BEGIN WMNewTab: 20 +[16:52.48.064] END WMNewTab: 20 + +[16:52.48.853] BEGIN WMNewTab: 20 +[16:52.48.853] END WMNewTab: 20 +[16:52.49.082] BEGIN WMNewTab: 20 +[16:52.49.082] END WMNewTab: 20 +[16:52.49.082] BEGIN WMNewTab: 20 +[16:52.49.082] END WMNewTab: 20 +[16:52.49.082] BEGIN WMNewTab: 20 +[16:52.49.082] END WMNewTab: 20 +[16:52.49.082] BEGIN WMNewTab: 20 +[16:52.49.082] END WMNewTab: 20 +[16:52.49.219] BEGIN WMNewTab: 20 +[16:52.49.219] END WMNewTab: 20 +[16:52.49.219] BEGIN WMNewTab: 20 +[16:52.49.219] END WMNewTab: 20 +[16:52.49.219] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.49.480] BEGIN WMNewTab: 20 +[16:52.49.480] END WMNewTab: 20 + +[16:52.50.277] BEGIN WMNewTab: 20 +[16:52.50.277] END WMNewTab: 20 +[16:52.50.504] BEGIN WMNewTab: 20 +[16:52.50.504] END WMNewTab: 20 +[16:52.50.504] BEGIN WMNewTab: 20 +[16:52.50.504] END WMNewTab: 20 +[16:52.50.504] BEGIN WMNewTab: 20 +[16:52.50.504] END WMNewTab: 20 +[16:52.50.504] BEGIN WMNewTab: 20 +[16:52.50.504] END WMNewTab: 20 +[16:52.50.640] BEGIN WMNewTab: 20 +[16:52.50.640] END WMNewTab: 20 +[16:52.50.640] BEGIN WMNewTab: 20 +[16:52.50.640] END WMNewTab: 20 +[16:52.50.825] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.50.902] BEGIN WMNewTab: 20 +[16:52.50.902] END WMNewTab: 20 + +[16:52.51.689] BEGIN WMNewTab: 20 +[16:52.51.689] END WMNewTab: 20 +[16:52.51.920] BEGIN WMNewTab: 20 +[16:52.51.920] END WMNewTab: 20 +[16:52.51.920] BEGIN WMNewTab: 20 +[16:52.51.921] END WMNewTab: 20 +[16:52.51.921] BEGIN WMNewTab: 20 +[16:52.51.921] END WMNewTab: 20 +[16:52.51.921] BEGIN WMNewTab: 20 +[16:52.51.921] END WMNewTab: 20 +[16:52.52.056] BEGIN WMNewTab: 20 +[16:52.52.056] END WMNewTab: 20 +[16:52.52.056] BEGIN WMNewTab: 20 +[16:52.52.056] END WMNewTab: 20 +[16:52.52.317] BEGIN WMNewTab: 20 +[16:52.52.317] END WMNewTab: 20 +[16:52.52.437] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.53.142] BEGIN WMNewTab: 20 +[16:52.53.142] END WMNewTab: 20 +[16:52.53.335] BEGIN WMNewTab: 20 +[16:52.53.335] END WMNewTab: 20 +[16:52.53.335] BEGIN WMNewTab: 20 +[16:52.53.335] END WMNewTab: 20 +[16:52.53.335] BEGIN WMNewTab: 20 +[16:52.53.335] END WMNewTab: 20 +[16:52.53.335] BEGIN WMNewTab: 20 +[16:52.53.335] END WMNewTab: 20 +[16:52.53.474] BEGIN WMNewTab: 20 +[16:52.53.474] END WMNewTab: 20 +[16:52.53.474] BEGIN WMNewTab: 20 +[16:52.53.474] END WMNewTab: 20 +[16:52.53.736] BEGIN WMNewTab: 20 +[16:52.53.736] END WMNewTab: 20 +[16:52.54.055] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:52.54.561] BEGIN WMNewTab: 20 +[16:52.54.561] END WMNewTab: 20 +[16:52.54.760] BEGIN WMNewTab: 20 +[16:52.54.760] END WMNewTab: 20 +[16:52.54.760] BEGIN WMNewTab: 20 +[16:52.54.760] END WMNewTab: 20 +[16:52.54.760] BEGIN WMNewTab: 20 +[16:52.54.760] END WMNewTab: 20 +[16:52.54.760] BEGIN WMNewTab: 20 +[16:52.54.760] END WMNewTab: 20 +[16:52.54.897] BEGIN WMNewTab: 20 +[16:52.54.897] END WMNewTab: 20 +[16:52.54.897] BEGIN WMNewTab: 20 +[16:52.54.897] END WMNewTab: 20 +[16:52.55.185] BEGIN WMNewTab: 20 +[16:52.55.185] END WMNewTab: 20 + +[16:52.55.656] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.55.976] BEGIN WMNewTab: 20 +[16:52.55.976] END WMNewTab: 20 +[16:52.56.198] BEGIN WMNewTab: 20 +[16:52.56.198] END WMNewTab: 20 +[16:52.56.198] BEGIN WMNewTab: 20 +[16:52.56.198] END WMNewTab: 20 +[16:52.56.198] BEGIN WMNewTab: 20 +[16:52.56.198] END WMNewTab: 20 +[16:52.56.198] BEGIN WMNewTab: 20 +[16:52.56.198] END WMNewTab: 20 +[16:52.56.311] BEGIN WMNewTab: 20 +[16:52.56.311] END WMNewTab: 20 +[16:52.56.312] BEGIN WMNewTab: 20 +[16:52.56.312] END WMNewTab: 20 +[16:52.56.599] BEGIN WMNewTab: 20 +[16:52.56.599] END WMNewTab: 20 + +[16:52.57.267] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.57.389] BEGIN WMNewTab: 20 +[16:52.57.389] END WMNewTab: 20 +[16:52.57.600] BEGIN WMNewTab: 20 +[16:52.57.600] END WMNewTab: 20 +[16:52.57.600] BEGIN WMNewTab: 20 +[16:52.57.600] END WMNewTab: 20 +[16:52.57.600] BEGIN WMNewTab: 20 +[16:52.57.600] END WMNewTab: 20 +[16:52.57.600] BEGIN WMNewTab: 20 +[16:52.57.600] END WMNewTab: 20 +[16:52.57.722] BEGIN WMNewTab: 20 +[16:52.57.722] END WMNewTab: 20 +[16:52.57.723] BEGIN WMNewTab: 20 +[16:52.57.723] END WMNewTab: 20 +[16:52.58.011] BEGIN WMNewTab: 20 +[16:52.58.011] END WMNewTab: 20 + +[16:52.58.805] BEGIN WMNewTab: 20 +[16:52.58.805] END WMNewTab: 20 +[16:52.58.882] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:52.59.021] BEGIN WMNewTab: 20 +[16:52.59.021] END WMNewTab: 20 +[16:52.59.021] BEGIN WMNewTab: 20 +[16:52.59.021] END WMNewTab: 20 +[16:52.59.021] BEGIN WMNewTab: 20 +[16:52.59.021] END WMNewTab: 20 +[16:52.59.021] BEGIN WMNewTab: 20 +[16:52.59.021] END WMNewTab: 20 +[16:52.59.144] BEGIN WMNewTab: 20 +[16:52.59.144] END WMNewTab: 20 +[16:52.59.144] BEGIN WMNewTab: 20 +[16:52.59.144] END WMNewTab: 20 +[16:52.59.433] BEGIN WMNewTab: 20 +[16:52.59.433] END WMNewTab: 20 + +[16:53.00.282] BEGIN WMNewTab: 20 +[16:53.00.282] END WMNewTab: 20 +[16:53.00.438] BEGIN WMNewTab: 20 +[16:53.00.438] END WMNewTab: 20 +[16:53.00.438] BEGIN WMNewTab: 20 +[16:53.00.438] END WMNewTab: 20 +[16:53.00.438] BEGIN WMNewTab: 20 +[16:53.00.438] END WMNewTab: 20 +[16:53.00.438] BEGIN WMNewTab: 20 +[16:53.00.438] END WMNewTab: 20 +[16:53.00.482] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.00.560] BEGIN WMNewTab: 20 +[16:53.00.560] END WMNewTab: 20 +[16:53.00.561] BEGIN WMNewTab: 20 +[16:53.00.561] END WMNewTab: 20 +[16:53.00.852] BEGIN WMNewTab: 20 +[16:53.00.852] END WMNewTab: 20 + +[16:53.01.690] BEGIN WMNewTab: 20 +[16:53.01.690] END WMNewTab: 20 +[16:53.01.857] BEGIN WMNewTab: 20 +[16:53.01.857] END WMNewTab: 20 +[16:53.01.857] BEGIN WMNewTab: 20 +[16:53.01.857] END WMNewTab: 20 +[16:53.01.857] BEGIN WMNewTab: 20 +[16:53.01.857] END WMNewTab: 20 +[16:53.01.857] BEGIN WMNewTab: 20 +[16:53.01.857] END WMNewTab: 20 +[16:53.01.979] BEGIN WMNewTab: 20 +[16:53.01.979] END WMNewTab: 20 +[16:53.01.979] BEGIN WMNewTab: 20 +[16:53.01.979] END WMNewTab: 20 +[16:53.02.100] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.02.316] BEGIN WMNewTab: 20 +[16:53.02.316] END WMNewTab: 20 + +[16:53.03.107] BEGIN WMNewTab: 20 +[16:53.03.107] END WMNewTab: 20 +[16:53.03.274] BEGIN WMNewTab: 20 +[16:53.03.274] END WMNewTab: 20 +[16:53.03.274] BEGIN WMNewTab: 20 +[16:53.03.274] END WMNewTab: 20 +[16:53.03.274] BEGIN WMNewTab: 20 +[16:53.03.274] END WMNewTab: 20 +[16:53.03.274] BEGIN WMNewTab: 20 +[16:53.03.274] END WMNewTab: 20 +[16:53.03.396] BEGIN WMNewTab: 20 +[16:53.03.396] END WMNewTab: 20 +[16:53.03.396] BEGIN WMNewTab: 20 +[16:53.03.396] END WMNewTab: 20 +[16:53.03.703] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.03.734] BEGIN WMNewTab: 20 +[16:53.03.734] END WMNewTab: 20 + +[16:53.04.526] BEGIN WMNewTab: 20 +[16:53.04.526] END WMNewTab: 20 +[16:53.04.692] BEGIN WMNewTab: 20 +[16:53.04.692] END WMNewTab: 20 +[16:53.04.692] BEGIN WMNewTab: 20 +[16:53.04.692] END WMNewTab: 20 +[16:53.04.692] BEGIN WMNewTab: 20 +[16:53.04.692] END WMNewTab: 20 +[16:53.04.692] BEGIN WMNewTab: 20 +[16:53.04.692] END WMNewTab: 20 +[16:53.04.816] BEGIN WMNewTab: 20 +[16:53.04.816] END WMNewTab: 20 +[16:53.04.816] BEGIN WMNewTab: 20 +[16:53.04.816] END WMNewTab: 20 +[16:53.05.152] BEGIN WMNewTab: 20 +[16:53.05.152] END WMNewTab: 20 +[16:53.05.320] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.05.947] BEGIN WMNewTab: 20 +[16:53.05.947] END WMNewTab: 20 +[16:53.06.113] BEGIN WMNewTab: 20 +[16:53.06.113] END WMNewTab: 20 +[16:53.06.113] BEGIN WMNewTab: 20 +[16:53.06.113] END WMNewTab: 20 +[16:53.06.113] BEGIN WMNewTab: 20 +[16:53.06.113] END WMNewTab: 20 +[16:53.06.113] BEGIN WMNewTab: 20 +[16:53.06.113] END WMNewTab: 20 +[16:53.06.236] BEGIN WMNewTab: 20 +[16:53.06.236] END WMNewTab: 20 +[16:53.06.237] BEGIN WMNewTab: 20 +[16:53.06.237] END WMNewTab: 20 +[16:53.06.573] BEGIN WMNewTab: 20 +[16:53.06.573] END WMNewTab: 20 +[16:53.06.922] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.07.412] BEGIN WMNewTab: 20 +[16:53.07.412] END WMNewTab: 20 +[16:53.07.532] BEGIN WMNewTab: 20 +[16:53.07.532] END WMNewTab: 20 +[16:53.07.532] BEGIN WMNewTab: 20 +[16:53.07.532] END WMNewTab: 20 +[16:53.07.532] BEGIN WMNewTab: 20 +[16:53.07.532] END WMNewTab: 20 +[16:53.07.532] BEGIN WMNewTab: 20 +[16:53.07.532] END WMNewTab: 20 +[16:53.07.653] BEGIN WMNewTab: 20 +[16:53.07.653] END WMNewTab: 20 +[16:53.07.653] BEGIN WMNewTab: 20 +[16:53.07.653] END WMNewTab: 20 +[16:53.07.990] BEGIN WMNewTab: 20 +[16:53.07.990] END WMNewTab: 20 + +[16:53.08.538] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.08.849] BEGIN WMNewTab: 20 +[16:53.08.849] END WMNewTab: 20 +[16:53.08.961] BEGIN WMNewTab: 20 +[16:53.08.961] END WMNewTab: 20 +[16:53.08.961] BEGIN WMNewTab: 20 +[16:53.08.961] END WMNewTab: 20 +[16:53.08.961] BEGIN WMNewTab: 20 +[16:53.08.961] END WMNewTab: 20 +[16:53.08.961] BEGIN WMNewTab: 20 +[16:53.08.961] END WMNewTab: 20 +[16:53.09.073] BEGIN WMNewTab: 20 +[16:53.09.073] END WMNewTab: 20 +[16:53.09.073] BEGIN WMNewTab: 20 +[16:53.09.073] END WMNewTab: 20 +[16:53.09.408] BEGIN WMNewTab: 20 +[16:53.09.408] END WMNewTab: 20 +[16:53.09.746] sListView1Click: FormClick +[16:53.09.850] (SSH-Browser) BEGIN OpenDir(4) +[16:53.09.850] (SSH-Browser) BEGIN VerifySFTPConnection(4) +[16:53.09.850] (SSH-Browser) VerifySFTPConnection(4): result=true (Sftp 连接) +[16:53.09.850] (SSH-Browser) END VerifySFTPConnection(4) +[16:53.09.850] (SSH-Browser) OpenDir(4): 列出远程文件夹 +[16:53.09.853] (SSH-Browser) OpenDir(4): SFTP.RequestAbsolutePath(/root/../); +[16:53.09.853] (SSH-Browser) END OpenDir(4) +[16:53.09.866] (SSH-Browser) ElSFTP1AbsolutePath(4) +[16:53.09.866] (SSH-Browser) ElSFTP1AbsolutePath(4): SFTP.OpenDirectory(/) +[16:53.09.896] (SSH-Browser) ElSFTP1OpenFile(4) +[16:53.09.896] (SSH-Browser) ElSFTP1OpenFile(4): SFTP.ReadDirectory +[16:53.09.958] (SSH-Browser) ElSFTP1Error(4): #1 - End of file +[16:53.09.958] (SSH-Browser) ElSFTP1Error(4): CloseCurrentHandle1 +[16:53.09.958] (SSH-Browser) BEGIN CloseCurrentHandle(4) +[16:53.09.958] (SSH-Browser) BEGIN VerifySFTPConnection(4) +[16:53.09.958] (SSH-Browser) VerifySFTPConnection(4): result=true (Sftp 连接) +[16:53.09.958] (SSH-Browser) END VerifySFTPConnection(4) +[16:53.09.958] (SSH-Browser) CloseCurrentHandle(4): SFTP.CloseHandle +[16:53.09.958] (SSH-Browser) END CloseCurrentHandle(4) +[16:53.09.958] (SSH-Browser) BEGIN CopySFTPFileListToListView(4) +[16:53.09.958] (SSH-Browser) CopySFTPFileListToListView(4): FileList.Count=28 +[16:53.09.958] (SSH-Browser) 对项目进行排序 +[16:53.09.959] (SSH-Browser) CopySFTPFileListToListView(4): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:53.09.972] (SSH-Browser) END CopySFTPFileListToListView(4) +[16:53.10.018] (SSH-Browser) ElSFTP1Success(4) +[16:53.10.180] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.10.262] BEGIN WMNewTab: 20 +[16:53.10.262] END WMNewTab: 20 +[16:53.10.368] BEGIN WMNewTab: 20 +[16:53.10.368] END WMNewTab: 20 +[16:53.10.369] BEGIN WMNewTab: 20 +[16:53.10.369] END WMNewTab: 20 +[16:53.10.369] BEGIN WMNewTab: 20 +[16:53.10.369] END WMNewTab: 20 +[16:53.10.369] BEGIN WMNewTab: 20 +[16:53.10.369] END WMNewTab: 20 +[16:53.10.489] BEGIN WMNewTab: 20 +[16:53.10.489] END WMNewTab: 20 +[16:53.10.489] BEGIN WMNewTab: 20 +[16:53.10.489] END WMNewTab: 20 +[16:53.10.824] BEGIN WMNewTab: 20 +[16:53.10.824] END WMNewTab: 20 + +[16:53.11.674] BEGIN WMNewTab: 20 +[16:53.11.674] END WMNewTab: 20 +[16:53.11.750] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.11.780] BEGIN WMNewTab: 20 +[16:53.11.780] END WMNewTab: 20 +[16:53.11.780] BEGIN WMNewTab: 20 +[16:53.11.780] END WMNewTab: 20 +[16:53.11.780] BEGIN WMNewTab: 20 +[16:53.11.780] END WMNewTab: 20 +[16:53.11.780] BEGIN WMNewTab: 20 +[16:53.11.780] END WMNewTab: 20 +[16:53.11.903] BEGIN WMNewTab: 20 +[16:53.11.903] END WMNewTab: 20 +[16:53.11.903] BEGIN WMNewTab: 20 +[16:53.11.903] END WMNewTab: 20 +[16:53.12.236] BEGIN WMNewTab: 20 +[16:53.12.236] END WMNewTab: 20 + +[16:53.13.090] BEGIN WMNewTab: 20 +[16:53.13.090] END WMNewTab: 20 +[16:53.13.196] BEGIN WMNewTab: 20 +[16:53.13.196] END WMNewTab: 20 +[16:53.13.196] BEGIN WMNewTab: 20 +[16:53.13.196] END WMNewTab: 20 +[16:53.13.196] BEGIN WMNewTab: 20 +[16:53.13.196] END WMNewTab: 20 +[16:53.13.196] BEGIN WMNewTab: 20 +[16:53.13.196] END WMNewTab: 20 +[16:53.13.319] BEGIN WMNewTab: 20 +[16:53.13.319] END WMNewTab: 20 +[16:53.13.319] BEGIN WMNewTab: 20 +[16:53.13.319] END WMNewTab: 20 +[16:53.13.365] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.13.652] BEGIN WMNewTab: 20 +[16:53.13.652] END WMNewTab: 20 + +[16:53.14.504] BEGIN WMNewTab: 20 +[16:53.14.504] END WMNewTab: 20 +[16:53.14.611] BEGIN WMNewTab: 20 +[16:53.14.611] END WMNewTab: 20 +[16:53.14.611] BEGIN WMNewTab: 20 +[16:53.14.611] END WMNewTab: 20 +[16:53.14.611] BEGIN WMNewTab: 20 +[16:53.14.611] END WMNewTab: 20 +[16:53.14.611] BEGIN WMNewTab: 20 +[16:53.14.611] END WMNewTab: 20 +[16:53.14.733] BEGIN WMNewTab: 20 +[16:53.14.733] END WMNewTab: 20 +[16:53.14.734] BEGIN WMNewTab: 20 +[16:53.14.734] END WMNewTab: 20 +[16:53.14.977] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.15.068] BEGIN WMNewTab: 20 +[16:53.15.068] END WMNewTab: 20 + +[16:53.15.917] BEGIN WMNewTab: 20 +[16:53.15.917] END WMNewTab: 20 +[16:53.16.029] BEGIN WMNewTab: 20 +[16:53.16.029] END WMNewTab: 20 +[16:53.16.030] BEGIN WMNewTab: 20 +[16:53.16.030] END WMNewTab: 20 +[16:53.16.030] BEGIN WMNewTab: 20 +[16:53.16.030] END WMNewTab: 20 +[16:53.16.030] BEGIN WMNewTab: 20 +[16:53.16.030] END WMNewTab: 20 +[16:53.16.145] BEGIN WMNewTab: 20 +[16:53.16.145] END WMNewTab: 20 +[16:53.16.145] BEGIN WMNewTab: 20 +[16:53.16.145] END WMNewTab: 20 +[16:53.16.479] BEGIN WMNewTab: 20 +[16:53.16.479] END WMNewTab: 20 +[16:53.16.609] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.17.335] BEGIN WMNewTab: 20 +[16:53.17.335] END WMNewTab: 20 +[16:53.17.442] BEGIN WMNewTab: 20 +[16:53.17.442] END WMNewTab: 20 +[16:53.17.442] BEGIN WMNewTab: 20 +[16:53.17.442] END WMNewTab: 20 +[16:53.17.442] BEGIN WMNewTab: 20 +[16:53.17.442] END WMNewTab: 20 +[16:53.17.442] BEGIN WMNewTab: 20 +[16:53.17.442] END WMNewTab: 20 +[16:53.17.564] BEGIN WMNewTab: 20 +[16:53.17.564] END WMNewTab: 20 +[16:53.17.564] BEGIN WMNewTab: 20 +[16:53.17.564] END WMNewTab: 20 +[16:53.17.900] BEGIN WMNewTab: 20 +[16:53.17.900] END WMNewTab: 20 +[16:53.18.243] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.18.755] BEGIN WMNewTab: 20 +[16:53.18.755] END WMNewTab: 20 +[16:53.18.861] BEGIN WMNewTab: 20 +[16:53.18.861] END WMNewTab: 20 +[16:53.18.861] BEGIN WMNewTab: 20 +[16:53.18.861] END WMNewTab: 20 +[16:53.18.861] BEGIN WMNewTab: 20 +[16:53.18.861] END WMNewTab: 20 +[16:53.18.861] BEGIN WMNewTab: 20 +[16:53.18.861] END WMNewTab: 20 +[16:53.18.985] BEGIN WMNewTab: 20 +[16:53.18.985] END WMNewTab: 20 +[16:53.18.985] BEGIN WMNewTab: 20 +[16:53.18.985] END WMNewTab: 20 +[16:53.19.318] BEGIN WMNewTab: 20 +[16:53.19.318] END WMNewTab: 20 + +[16:53.19.800] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.20.170] BEGIN WMNewTab: 20 +[16:53.20.170] END WMNewTab: 20 +[16:53.20.277] BEGIN WMNewTab: 20 +[16:53.20.277] END WMNewTab: 20 +[16:53.20.277] BEGIN WMNewTab: 20 +[16:53.20.277] END WMNewTab: 20 +[16:53.20.277] BEGIN WMNewTab: 20 +[16:53.20.277] END WMNewTab: 20 +[16:53.20.277] BEGIN WMNewTab: 20 +[16:53.20.277] END WMNewTab: 20 +[16:53.20.399] BEGIN WMNewTab: 20 +[16:53.20.399] END WMNewTab: 20 +[16:53.20.399] BEGIN WMNewTab: 20 +[16:53.20.399] END WMNewTab: 20 +[16:53.20.735] BEGIN WMNewTab: 20 +[16:53.20.735] END WMNewTab: 20 + +[16:53.21.405] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.21.587] BEGIN WMNewTab: 20 +[16:53.21.587] END WMNewTab: 20 +[16:53.21.693] BEGIN WMNewTab: 20 +[16:53.21.693] END WMNewTab: 20 +[16:53.21.693] BEGIN WMNewTab: 20 +[16:53.21.693] END WMNewTab: 20 +[16:53.21.693] BEGIN WMNewTab: 20 +[16:53.21.693] END WMNewTab: 20 +[16:53.21.693] BEGIN WMNewTab: 20 +[16:53.21.693] END WMNewTab: 20 +[16:53.21.813] BEGIN WMNewTab: 20 +[16:53.21.813] END WMNewTab: 20 +[16:53.21.813] BEGIN WMNewTab: 20 +[16:53.21.813] END WMNewTab: 20 +[16:53.22.146] BEGIN WMNewTab: 20 +[16:53.22.146] END WMNewTab: 20 + +[16:53.22.997] BEGIN WMNewTab: 20 +[16:53.22.997] END WMNewTab: 20 +[16:53.23.012] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.23.104] BEGIN WMNewTab: 20 +[16:53.23.104] END WMNewTab: 20 +[16:53.23.104] BEGIN WMNewTab: 20 +[16:53.23.104] END WMNewTab: 20 +[16:53.23.104] BEGIN WMNewTab: 20 +[16:53.23.104] END WMNewTab: 20 +[16:53.23.104] BEGIN WMNewTab: 20 +[16:53.23.104] END WMNewTab: 20 +[16:53.23.225] BEGIN WMNewTab: 20 +[16:53.23.225] END WMNewTab: 20 +[16:53.23.225] BEGIN WMNewTab: 20 +[16:53.23.225] END WMNewTab: 20 +[16:53.23.562] BEGIN WMNewTab: 20 +[16:53.23.562] END WMNewTab: 20 + +[16:53.24.413] BEGIN WMNewTab: 20 +[16:53.24.413] END WMNewTab: 20 +[16:53.24.520] BEGIN WMNewTab: 20 +[16:53.24.520] END WMNewTab: 20 +[16:53.24.521] BEGIN WMNewTab: 20 +[16:53.24.521] END WMNewTab: 20 +[16:53.24.521] BEGIN WMNewTab: 20 +[16:53.24.521] END WMNewTab: 20 +[16:53.24.521] BEGIN WMNewTab: 20 +[16:53.24.521] END WMNewTab: 20 +[16:53.24.623] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.24.639] BEGIN WMNewTab: 20 +[16:53.24.639] END WMNewTab: 20 +[16:53.24.641] BEGIN WMNewTab: 20 +[16:53.24.641] END WMNewTab: 20 +[16:53.24.972] BEGIN WMNewTab: 20 +[16:53.24.972] END WMNewTab: 20 + +[16:53.25.828] BEGIN WMNewTab: 20 +[16:53.25.828] END WMNewTab: 20 +[16:53.25.935] BEGIN WMNewTab: 20 +[16:53.25.935] END WMNewTab: 20 +[16:53.25.935] BEGIN WMNewTab: 20 +[16:53.25.935] END WMNewTab: 20 +[16:53.25.935] BEGIN WMNewTab: 20 +[16:53.25.935] END WMNewTab: 20 +[16:53.25.935] BEGIN WMNewTab: 20 +[16:53.25.935] END WMNewTab: 20 +[16:53.26.056] BEGIN WMNewTab: 20 +[16:53.26.056] END WMNewTab: 20 +[16:53.26.056] BEGIN WMNewTab: 20 +[16:53.26.056] END WMNewTab: 20 +[16:53.26.232] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.26.393] BEGIN WMNewTab: 20 +[16:53.26.393] END WMNewTab: 20 + +[16:53.27.245] BEGIN WMNewTab: 20 +[16:53.27.245] END WMNewTab: 20 +[16:53.27.352] BEGIN WMNewTab: 20 +[16:53.27.352] END WMNewTab: 20 +[16:53.27.353] BEGIN WMNewTab: 20 +[16:53.27.353] END WMNewTab: 20 +[16:53.27.353] BEGIN WMNewTab: 20 +[16:53.27.353] END WMNewTab: 20 +[16:53.27.353] BEGIN WMNewTab: 20 +[16:53.27.353] END WMNewTab: 20 +[16:53.27.474] BEGIN WMNewTab: 20 +[16:53.27.474] END WMNewTab: 20 +[16:53.27.474] BEGIN WMNewTab: 20 +[16:53.27.474] END WMNewTab: 20 +[16:53.27.811] BEGIN WMNewTab: 20 +[16:53.27.811] END WMNewTab: 20 +[16:53.27.855] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.28.663] BEGIN WMNewTab: 20 +[16:53.28.663] END WMNewTab: 20 +[16:53.28.771] BEGIN WMNewTab: 20 +[16:53.28.771] END WMNewTab: 20 +[16:53.28.771] BEGIN WMNewTab: 20 +[16:53.28.771] END WMNewTab: 20 +[16:53.28.771] BEGIN WMNewTab: 20 +[16:53.28.771] END WMNewTab: 20 +[16:53.28.771] BEGIN WMNewTab: 20 +[16:53.28.771] END WMNewTab: 20 +[16:53.28.893] BEGIN WMNewTab: 20 +[16:53.28.893] END WMNewTab: 20 +[16:53.28.893] BEGIN WMNewTab: 20 +[16:53.28.893] END WMNewTab: 20 +[16:53.29.230] BEGIN WMNewTab: 20 +[16:53.29.230] END WMNewTab: 20 +[16:53.29.460] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.30.086] BEGIN WMNewTab: 20 +[16:53.30.086] END WMNewTab: 20 +[16:53.30.191] BEGIN WMNewTab: 20 +[16:53.30.191] END WMNewTab: 20 +[16:53.30.193] BEGIN WMNewTab: 20 +[16:53.30.193] END WMNewTab: 20 +[16:53.30.193] BEGIN WMNewTab: 20 +[16:53.30.193] END WMNewTab: 20 +[16:53.30.193] BEGIN WMNewTab: 20 +[16:53.30.193] END WMNewTab: 20 +[16:53.30.315] BEGIN WMNewTab: 20 +[16:53.30.315] END WMNewTab: 20 +[16:53.30.315] BEGIN WMNewTab: 20 +[16:53.30.315] END WMNewTab: 20 +[16:53.30.651] BEGIN WMNewTab: 20 +[16:53.30.651] END WMNewTab: 20 + +[16:53.31.060] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.31.504] BEGIN WMNewTab: 20 +[16:53.31.504] END WMNewTab: 20 +[16:53.31.612] BEGIN WMNewTab: 20 +[16:53.31.612] END WMNewTab: 20 +[16:53.31.612] BEGIN WMNewTab: 20 +[16:53.31.612] END WMNewTab: 20 +[16:53.31.612] BEGIN WMNewTab: 20 +[16:53.31.612] END WMNewTab: 20 +[16:53.31.612] BEGIN WMNewTab: 20 +[16:53.31.612] END WMNewTab: 20 +[16:53.31.734] BEGIN WMNewTab: 20 +[16:53.31.734] END WMNewTab: 20 +[16:53.31.734] BEGIN WMNewTab: 20 +[16:53.31.734] END WMNewTab: 20 +[16:53.32.069] BEGIN WMNewTab: 20 +[16:53.32.069] END WMNewTab: 20 + +[16:53.32.681] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.32.923] BEGIN WMNewTab: 20 +[16:53.32.923] END WMNewTab: 20 +[16:53.33.031] BEGIN WMNewTab: 20 +[16:53.33.031] END WMNewTab: 20 +[16:53.33.031] BEGIN WMNewTab: 20 +[16:53.33.031] END WMNewTab: 20 +[16:53.33.031] BEGIN WMNewTab: 20 +[16:53.33.031] END WMNewTab: 20 +[16:53.33.031] BEGIN WMNewTab: 20 +[16:53.33.031] END WMNewTab: 20 +[16:53.33.153] BEGIN WMNewTab: 20 +[16:53.33.153] END WMNewTab: 20 +[16:53.33.153] BEGIN WMNewTab: 20 +[16:53.33.153] END WMNewTab: 20 +[16:53.33.486] BEGIN WMNewTab: 20 +[16:53.33.486] END WMNewTab: 20 + +[16:53.34.281] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.34.340] BEGIN WMNewTab: 20 +[16:53.34.340] END WMNewTab: 20 +[16:53.34.447] BEGIN WMNewTab: 20 +[16:53.34.447] END WMNewTab: 20 +[16:53.34.447] BEGIN WMNewTab: 20 +[16:53.34.447] END WMNewTab: 20 +[16:53.34.447] BEGIN WMNewTab: 20 +[16:53.34.447] END WMNewTab: 20 +[16:53.34.447] BEGIN WMNewTab: 20 +[16:53.34.447] END WMNewTab: 20 +[16:53.34.568] BEGIN WMNewTab: 20 +[16:53.34.568] END WMNewTab: 20 +[16:53.34.568] BEGIN WMNewTab: 20 +[16:53.34.568] END WMNewTab: 20 + +[16:53.34.954] BEGIN WMNewTab: 20 +[16:53.34.954] END WMNewTab: 20 + +[16:53.35.753] BEGIN WMNewTab: 20 +[16:53.35.753] END WMNewTab: 20 +[16:53.35.859] BEGIN WMNewTab: 20 +[16:53.35.859] END WMNewTab: 20 +[16:53.35.859] BEGIN WMNewTab: 20 +[16:53.35.859] END WMNewTab: 20 +[16:53.35.860] BEGIN WMNewTab: 20 +[16:53.35.860] END WMNewTab: 20 +[16:53.35.860] BEGIN WMNewTab: 20 +[16:53.35.860] END WMNewTab: 20 +[16:53.35.890] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.35.982] BEGIN WMNewTab: 20 +[16:53.35.982] END WMNewTab: 20 +[16:53.35.983] BEGIN WMNewTab: 20 +[16:53.35.983] END WMNewTab: 20 + +[16:53.36.364] BEGIN WMNewTab: 20 +[16:53.36.364] END WMNewTab: 20 + +[16:53.37.172] BEGIN WMNewTab: 20 +[16:53.37.173] END WMNewTab: 20 +[16:53.37.280] BEGIN WMNewTab: 20 +[16:53.37.280] END WMNewTab: 20 +[16:53.37.280] BEGIN WMNewTab: 20 +[16:53.37.280] END WMNewTab: 20 +[16:53.37.280] BEGIN WMNewTab: 20 +[16:53.37.280] END WMNewTab: 20 +[16:53.37.280] BEGIN WMNewTab: 20 +[16:53.37.280] END WMNewTab: 20 +[16:53.37.403] BEGIN WMNewTab: 20 +[16:53.37.403] END WMNewTab: 20 +[16:53.37.404] BEGIN WMNewTab: 20 +[16:53.37.404] END WMNewTab: 20 +[16:53.37.509] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.37.782] BEGIN WMNewTab: 20 +[16:53.37.782] END WMNewTab: 20 + +[16:53.38.592] BEGIN WMNewTab: 20 +[16:53.38.592] END WMNewTab: 20 +[16:53.38.699] BEGIN WMNewTab: 20 +[16:53.38.699] END WMNewTab: 20 +[16:53.38.699] BEGIN WMNewTab: 20 +[16:53.38.699] END WMNewTab: 20 +[16:53.38.699] BEGIN WMNewTab: 20 +[16:53.38.699] END WMNewTab: 20 +[16:53.38.699] BEGIN WMNewTab: 20 +[16:53.38.699] END WMNewTab: 20 +[16:53.38.820] BEGIN WMNewTab: 20 +[16:53.38.820] END WMNewTab: 20 +[16:53.38.820] BEGIN WMNewTab: 20 +[16:53.38.820] END WMNewTab: 20 +[16:53.39.110] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.39.200] BEGIN WMNewTab: 20 +[16:53.39.200] END WMNewTab: 20 + +[16:53.40.007] BEGIN WMNewTab: 20 +[16:53.40.007] END WMNewTab: 20 +[16:53.40.114] BEGIN WMNewTab: 20 +[16:53.40.114] END WMNewTab: 20 +[16:53.40.114] BEGIN WMNewTab: 20 +[16:53.40.114] END WMNewTab: 20 +[16:53.40.114] BEGIN WMNewTab: 20 +[16:53.40.114] END WMNewTab: 20 +[16:53.40.114] BEGIN WMNewTab: 20 +[16:53.40.114] END WMNewTab: 20 +[16:53.40.236] BEGIN WMNewTab: 20 +[16:53.40.236] END WMNewTab: 20 +[16:53.40.236] BEGIN WMNewTab: 20 +[16:53.40.236] END WMNewTab: 20 + +[16:53.40.618] BEGIN WMNewTab: 20 +[16:53.40.618] END WMNewTab: 20 +[16:53.40.726] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.41.428] BEGIN WMNewTab: 20 +[16:53.41.428] END WMNewTab: 20 +[16:53.41.533] BEGIN WMNewTab: 20 +[16:53.41.533] END WMNewTab: 20 +[16:53.41.533] BEGIN WMNewTab: 20 +[16:53.41.533] END WMNewTab: 20 +[16:53.41.533] BEGIN WMNewTab: 20 +[16:53.41.533] END WMNewTab: 20 +[16:53.41.533] BEGIN WMNewTab: 20 +[16:53.41.533] END WMNewTab: 20 +[16:53.41.654] BEGIN WMNewTab: 20 +[16:53.41.654] END WMNewTab: 20 +[16:53.41.654] BEGIN WMNewTab: 20 +[16:53.41.654] END WMNewTab: 20 + +[16:53.42.036] BEGIN WMNewTab: 20 +[16:53.42.036] END WMNewTab: 20 +[16:53.42.329] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.42.845] BEGIN WMNewTab: 20 +[16:53.42.845] END WMNewTab: 20 +[16:53.42.952] BEGIN WMNewTab: 20 +[16:53.42.952] END WMNewTab: 20 +[16:53.42.952] BEGIN WMNewTab: 20 +[16:53.42.952] END WMNewTab: 20 +[16:53.42.952] BEGIN WMNewTab: 20 +[16:53.42.952] END WMNewTab: 20 +[16:53.42.952] BEGIN WMNewTab: 20 +[16:53.42.952] END WMNewTab: 20 +[16:53.43.072] BEGIN WMNewTab: 20 +[16:53.43.072] END WMNewTab: 20 +[16:53.43.072] BEGIN WMNewTab: 20 +[16:53.43.072] END WMNewTab: 20 + +[16:53.43.456] BEGIN WMNewTab: 20 +[16:53.43.456] END WMNewTab: 20 + +[16:53.43.942] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.44.302] BEGIN WMNewTab: 20 +[16:53.44.302] END WMNewTab: 20 +[16:53.44.303] BEGIN WMNewTab: 0 +[16:53.44.303] WMNewTab: FormClick +[16:53.44.303] WMNewTab: LooseFocus +[16:53.44.307] END WMNewTab: 0 +[16:53.44.346] BEGIN WMNewTab: 0 +[16:53.44.346] WMNewTab: FormClick +[16:53.44.346] WMNewTab: LooseFocus +[16:53.44.346] END WMNewTab: 0 +[16:53.44.372] BEGIN WMNewTab: 20 +[16:53.44.372] END WMNewTab: 20 +[16:53.44.372] BEGIN WMNewTab: 20 +[16:53.44.372] END WMNewTab: 20 +[16:53.44.372] BEGIN WMNewTab: 20 +[16:53.44.372] END WMNewTab: 20 +[16:53.44.372] BEGIN WMNewTab: 20 +[16:53.44.372] END WMNewTab: 20 +[16:53.44.494] BEGIN WMNewTab: 20 +[16:53.44.494] END WMNewTab: 20 +[16:53.44.494] BEGIN WMNewTab: 20 +[16:53.44.494] END WMNewTab: 20 + +[16:53.44.874] BEGIN WMNewTab: 20 +[16:53.44.874] END WMNewTab: 20 + +[16:53.45.545] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.45.712] BEGIN WMNewTab: 20 +[16:53.45.712] END WMNewTab: 20 +[16:53.45.789] BEGIN WMNewTab: 20 +[16:53.45.789] END WMNewTab: 20 +[16:53.45.789] BEGIN WMNewTab: 20 +[16:53.45.789] END WMNewTab: 20 +[16:53.45.789] BEGIN WMNewTab: 20 +[16:53.45.789] END WMNewTab: 20 +[16:53.45.789] BEGIN WMNewTab: 20 +[16:53.45.789] END WMNewTab: 20 +[16:53.45.911] BEGIN WMNewTab: 20 +[16:53.45.911] END WMNewTab: 20 +[16:53.45.911] BEGIN WMNewTab: 20 +[16:53.45.911] END WMNewTab: 20 + +[16:53.46.295] BEGIN WMNewTab: 20 +[16:53.46.295] END WMNewTab: 20 + +[16:53.47.136] BEGIN WMNewTab: 20 +[16:53.47.136] END WMNewTab: 20 +[16:53.47.214] BEGIN WMNewTab: 20 +[16:53.47.214] END WMNewTab: 20 +[16:53.47.214] BEGIN WMNewTab: 20 +[16:53.47.214] END WMNewTab: 20 +[16:53.47.214] BEGIN WMNewTab: 20 +[16:53.47.214] END WMNewTab: 20 +[16:53.47.214] BEGIN WMNewTab: 20 +[16:53.47.214] END WMNewTab: 20 +[16:53.47.219] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.47.335] BEGIN WMNewTab: 20 +[16:53.47.335] END WMNewTab: 20 +[16:53.47.335] BEGIN WMNewTab: 20 +[16:53.47.335] END WMNewTab: 20 + +[16:53.47.714] BEGIN WMNewTab: 20 +[16:53.47.714] END WMNewTab: 20 + +[16:53.48.551] BEGIN WMNewTab: 20 +[16:53.48.552] END WMNewTab: 20 +[16:53.48.627] BEGIN WMNewTab: 20 +[16:53.48.627] END WMNewTab: 20 +[16:53.48.627] BEGIN WMNewTab: 20 +[16:53.48.627] END WMNewTab: 20 +[16:53.48.627] BEGIN WMNewTab: 20 +[16:53.48.627] END WMNewTab: 20 +[16:53.48.627] BEGIN WMNewTab: 20 +[16:53.48.627] END WMNewTab: 20 +[16:53.48.749] BEGIN WMNewTab: 20 +[16:53.48.749] END WMNewTab: 20 +[16:53.48.749] BEGIN WMNewTab: 20 +[16:53.48.749] END WMNewTab: 20 +[16:53.48.765] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.49.134] BEGIN WMNewTab: 20 +[16:53.49.134] END WMNewTab: 20 + +[16:53.49.706] BEGIN WMNewTab: 0 +[16:53.49.706] WMNewTab: FormClick +[16:53.49.706] WMNewTab: LooseFocus +[16:53.49.706] END WMNewTab: 0 +[16:53.49.707] BEGIN WMNewTab: 0 +[16:53.49.707] WMNewTab: FormClick +[16:53.49.707] WMNewTab: LooseFocus +[16:53.49.708] END WMNewTab: 0 +[16:53.49.972] BEGIN WMNewTab: 20 +[16:53.49.972] END WMNewTab: 20 +[16:53.50.046] BEGIN WMNewTab: 20 +[16:53.50.046] END WMNewTab: 20 +[16:53.50.046] BEGIN WMNewTab: 20 +[16:53.50.046] END WMNewTab: 20 +[16:53.50.046] BEGIN WMNewTab: 20 +[16:53.50.046] END WMNewTab: 20 +[16:53.50.047] BEGIN WMNewTab: 20 +[16:53.50.047] END WMNewTab: 20 +[16:53.50.168] BEGIN WMNewTab: 20 +[16:53.50.168] END WMNewTab: 20 +[16:53.50.170] BEGIN WMNewTab: 20 +[16:53.50.170] END WMNewTab: 20 +[16:53.50.383] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.50.551] BEGIN WMNewTab: 20 +[16:53.50.551] END WMNewTab: 20 +[16:53.50.732] BEGIN WMSysCommand (minimize/restore) +[16:53.50.760] BEGIN WMSize +[16:53.50.760] END WMSize +[16:53.50.818] END WMSysCommand + +[16:53.51.361] BEGIN WMSysCommand (minimize/restore) +[16:53.51.361] BEGIN WMNewTab: 0 +[16:53.51.361] WMNewTab: FormClick +[16:53.51.361] WMNewTab: LooseFocus +[16:53.51.361] END WMNewTab: 0 +[16:53.51.610] BEGIN WMSize +[16:53.51.610] BEGIN TFormXterm.FormResize +[16:53.51.610] TFormXterm.FormResize: CenterBtnReattachTab +[16:53.51.610] TFormXterm.FormResize: SplitModeResize +[16:53.51.610] TFormXterm.FormResize: BtnSplitNo.Down +[16:53.51.610] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:53.51.610] BEGIN ResizeTerminal +[16:53.51.610] BEGIN WMNewTab: 20 +[16:53.51.610] END WMNewTab: 20 +[16:53.51.610] BEGIN WMNewTab: 20 +[16:53.51.610] END WMNewTab: 20 +[16:53.51.610] BEGIN WMNewTab: 20 +[16:53.51.610] END WMNewTab: 20 +[16:53.51.610] BEGIN WMNewTab: 20 +[16:53.51.610] END WMNewTab: 20 +[16:53.51.610] BEGIN WMNewTab: 20 +[16:53.51.610] END WMNewTab: 20 +[16:53.51.610] BEGIN WMNewTab: 20 +[16:53.51.610] END WMNewTab: 20 +[16:53.51.610] BEGIN WMNewTab: 20 +[16:53.51.610] END WMNewTab: 20 +[16:53.51.613] END ResizeTerminal +[16:53.51.613] TFormXterm.FormResize: AdaptSidebarArrows; +[16:53.51.613] BEGIN AdaptSidebarArrows +[16:53.51.613] END AdaptSidebarArrows +[16:53.51.613] TFormXterm.FormResize: AdaptTV2; +[16:53.51.613] END TFormXterm.FormResize +[16:53.51.613] END WMSize +[16:53.51.618] END WMSysCommand +[16:53.51.969] BEGIN WMNewTab: 20 +[16:53.51.969] END WMNewTab: 20 +[16:53.51.984] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.53.020] BEGIN WMNewTab: 20 +[16:53.53.020] END WMNewTab: 20 +[16:53.53.020] BEGIN WMNewTab: 20 +[16:53.53.020] END WMNewTab: 20 +[16:53.53.021] BEGIN WMNewTab: 20 +[16:53.53.021] END WMNewTab: 20 +[16:53.53.021] BEGIN WMNewTab: 20 +[16:53.53.021] END WMNewTab: 20 +[16:53.53.021] BEGIN WMNewTab: 20 +[16:53.53.021] END WMNewTab: 20 +[16:53.53.021] BEGIN WMNewTab: 20 +[16:53.53.021] END WMNewTab: 20 +[16:53.53.021] BEGIN WMNewTab: 20 +[16:53.53.021] END WMNewTab: 20 + +[16:53.53.387] BEGIN WMNewTab: 20 +[16:53.53.387] END WMNewTab: 20 +[16:53.53.601] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.54.440] BEGIN WMNewTab: 20 +[16:53.54.440] END WMNewTab: 20 +[16:53.54.440] BEGIN WMNewTab: 20 +[16:53.54.440] END WMNewTab: 20 +[16:53.54.440] BEGIN WMNewTab: 20 +[16:53.54.440] END WMNewTab: 20 +[16:53.54.440] BEGIN WMNewTab: 20 +[16:53.54.440] END WMNewTab: 20 +[16:53.54.440] BEGIN WMNewTab: 20 +[16:53.54.440] END WMNewTab: 20 +[16:53.54.440] BEGIN WMNewTab: 20 +[16:53.54.440] END WMNewTab: 20 +[16:53.54.440] BEGIN WMNewTab: 20 +[16:53.54.440] END WMNewTab: 20 + +[16:53.54.806] BEGIN WMNewTab: 20 +[16:53.54.806] END WMNewTab: 20 + +[16:53.55.204] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.55.862] BEGIN WMNewTab: 20 +[16:53.55.862] END WMNewTab: 20 +[16:53.55.862] BEGIN WMNewTab: 20 +[16:53.55.862] END WMNewTab: 20 +[16:53.55.862] BEGIN WMNewTab: 20 +[16:53.55.862] END WMNewTab: 20 +[16:53.55.863] BEGIN WMNewTab: 20 +[16:53.55.863] END WMNewTab: 20 +[16:53.55.863] BEGIN WMNewTab: 20 +[16:53.55.863] END WMNewTab: 20 +[16:53.55.863] BEGIN WMNewTab: 20 +[16:53.55.863] END WMNewTab: 20 +[16:53.55.863] BEGIN WMNewTab: 20 +[16:53.55.863] END WMNewTab: 20 + +[16:53.56.230] BEGIN WMNewTab: 20 +[16:53.56.230] END WMNewTab: 20 + +[16:53.56.810] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:53.57.283] BEGIN WMNewTab: 20 +[16:53.57.283] END WMNewTab: 20 +[16:53.57.284] BEGIN WMNewTab: 20 +[16:53.57.284] END WMNewTab: 20 +[16:53.57.284] BEGIN WMNewTab: 20 +[16:53.57.284] END WMNewTab: 20 +[16:53.57.284] BEGIN WMNewTab: 20 +[16:53.57.284] END WMNewTab: 20 +[16:53.57.284] BEGIN WMNewTab: 20 +[16:53.57.284] END WMNewTab: 20 +[16:53.57.285] BEGIN WMNewTab: 20 +[16:53.57.285] END WMNewTab: 20 +[16:53.57.285] BEGIN WMNewTab: 20 +[16:53.57.285] END WMNewTab: 20 + +[16:53.57.649] BEGIN WMNewTab: 20 +[16:53.57.649] END WMNewTab: 20 + +[16:53.58.438] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:53.58.700] BEGIN WMNewTab: 20 +[16:53.58.700] END WMNewTab: 20 +[16:53.58.700] BEGIN WMNewTab: 20 +[16:53.58.700] END WMNewTab: 20 +[16:53.58.700] BEGIN WMNewTab: 20 +[16:53.58.700] END WMNewTab: 20 +[16:53.58.700] BEGIN WMNewTab: 20 +[16:53.58.700] END WMNewTab: 20 +[16:53.58.700] BEGIN WMNewTab: 20 +[16:53.58.700] END WMNewTab: 20 +[16:53.58.700] BEGIN WMNewTab: 20 +[16:53.58.700] END WMNewTab: 20 +[16:53.58.700] BEGIN WMNewTab: 20 +[16:53.58.700] END WMNewTab: 20 + +[16:53.59.065] BEGIN WMNewTab: 20 +[16:53.59.065] END WMNewTab: 20 + +[16:54.00.040] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.00.117] BEGIN WMNewTab: 20 +[16:54.00.117] END WMNewTab: 20 +[16:54.00.117] BEGIN WMNewTab: 20 +[16:54.00.117] END WMNewTab: 20 +[16:54.00.117] BEGIN WMNewTab: 20 +[16:54.00.117] END WMNewTab: 20 +[16:54.00.118] BEGIN WMNewTab: 20 +[16:54.00.118] END WMNewTab: 20 +[16:54.00.118] BEGIN WMNewTab: 20 +[16:54.00.118] END WMNewTab: 20 +[16:54.00.118] BEGIN WMNewTab: 20 +[16:54.00.118] END WMNewTab: 20 +[16:54.00.118] BEGIN WMNewTab: 20 +[16:54.00.118] END WMNewTab: 20 + +[16:54.00.485] BEGIN WMNewTab: 20 +[16:54.00.485] END WMNewTab: 20 + +[16:54.01.540] BEGIN WMNewTab: 20 +[16:54.01.540] END WMNewTab: 20 +[16:54.01.540] BEGIN WMNewTab: 20 +[16:54.01.540] END WMNewTab: 20 +[16:54.01.540] BEGIN WMNewTab: 20 +[16:54.01.540] END WMNewTab: 20 +[16:54.01.540] BEGIN WMNewTab: 20 +[16:54.01.540] END WMNewTab: 20 +[16:54.01.540] BEGIN WMNewTab: 20 +[16:54.01.540] END WMNewTab: 20 +[16:54.01.540] BEGIN WMNewTab: 20 +[16:54.01.540] END WMNewTab: 20 +[16:54.01.540] BEGIN WMNewTab: 20 +[16:54.01.540] END WMNewTab: 20 +[16:54.01.638] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.01.907] BEGIN WMNewTab: 20 +[16:54.01.907] END WMNewTab: 20 + +[16:54.02.586] Cts1MouseDown: FormClick +[16:54.02.598] Cts1ActiveTabChanged: New index = 5 +[16:54.02.598] BEGIN DisplayCurrentTab +[16:54.02.598] DisplayCurrentTab: FormClick +[16:54.02.598] (SSH-Browser) DisplayCurrentTab(5): ActiverPanel14 +[16:54.02.598] (SSH-Browser) BEGIN ActiverPanel14 +[16:54.02.598] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:54.02.613] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:54.02.613] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/ +[16:54.02.680] (SSH-Browser) ActiverPanel14: OpenDir(.); +[16:54.02.680] (SSH-Browser) BEGIN OpenDir(5) +[16:54.02.680] (SSH-Browser) BEGIN VerifySFTPConnection(5) +[16:54.02.680] (SSH-Browser) VerifySFTPConnection(5): result=true (Sftp 连接) +[16:54.02.680] (SSH-Browser) END VerifySFTPConnection(5) +[16:54.02.680] (SSH-Browser) OpenDir(5): 列出远程文件夹 +[16:54.02.680] (SSH-Browser) OpenDir(5): SFTP.RequestAbsolutePath(.); +[16:54.02.681] (SSH-Browser) END OpenDir(5) +[16:54.02.681] (SSH-Browser) END ActiverPanel14; +[16:54.02.819] (SSH-Browser) 正在启动 MobaSCP(10, remotemonitoring, ., ) +[16:54.02.819] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566610" -remotemonitoring mobauser@mobaserver:".") +[16:54.02.823] BEGIN WMNewTab: 20 +[16:54.02.823] END WMNewTab: 20 +[16:54.02.841] (SSH-Browser) ElSFTP1AbsolutePath(5) +[16:54.02.841] (SSH-Browser) ElSFTP1AbsolutePath(5): SFTP.OpenDirectory(/root) +[16:54.02.848] ShellExecuteS: ShellExecuteEx 成功. +[16:54.02.848] ShellExecuteS: WaitForInputIdle 失败. +[16:54.02.848] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566610" -remotemonitoring mobauser@mobaserver:".") +[16:54.02.848] DisplayCurrentTab: Cts1.BeginUpdate; +[16:54.02.848] DisplayCurrentTab: Cts1.EndUpdates +[16:54.02.972] DisplayCurrentTab: 显示所选标签页 +[16:54.02.972] [MobaSCP10] Launching remote monitoring in normal mode +[16:54.02.973] BEGIN WMNewTab: 20 +[16:54.02.973] END WMNewTab: 20 +[16:54.02.973] BEGIN WMNewTab: 20 +[16:54.02.973] END WMNewTab: 20 +[16:54.02.973] BEGIN WMNewTab: 20 +[16:54.02.973] END WMNewTab: 20 +[16:54.02.973] BEGIN WMNewTab: 20 +[16:54.02.973] END WMNewTab: 20 +[16:54.02.973] BEGIN WMNewTab: 20 +[16:54.02.973] END WMNewTab: 20 +[16:54.02.974] BEGIN WMNewTab: 20 +[16:54.02.974] END WMNewTab: 20 +[16:54.02.974] [MobaSCP10] Multiplex=1 +[16:54.02.974] [MobaSCP10] HOSTNAME: 192.168.127.10 +[16:54.02.975] [MobaSCP10] USERNAME: root +[16:54.02.976] DisplayCurrentTab: 隐藏其他标签页 +[16:54.02.979] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:54.02.983] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:54.02.983] DisplayCurrentTab: DistribuerLeFocus +[16:54.02.983] END DisplayCurrentTab +[16:54.03.073] [MobaSCP10] Using SCP1 +[16:54.03.073] [MobaSCP10] Connected to 192.168.127.10 +[16:54.03.089] (SSH-Browser) ElSFTP1OpenFile(5) +[16:54.03.089] (SSH-Browser) ElSFTP1OpenFile(5): SFTP.ReadDirectory +[16:54.03.146] (SSH-Browser) ElSFTP1Error(5): #1 - End of file +[16:54.03.146] (SSH-Browser) ElSFTP1Error(5): CloseCurrentHandle1 +[16:54.03.146] (SSH-Browser) BEGIN CloseCurrentHandle(5) +[16:54.03.146] (SSH-Browser) BEGIN VerifySFTPConnection(5) +[16:54.03.146] (SSH-Browser) VerifySFTPConnection(5): result=true (Sftp 连接) +[16:54.03.146] (SSH-Browser) END VerifySFTPConnection(5) +[16:54.03.146] (SSH-Browser) CloseCurrentHandle(5): SFTP.CloseHandle +[16:54.03.146] (SSH-Browser) END CloseCurrentHandle(5) +[16:54.03.146] (SSH-Browser) BEGIN CopySFTPFileListToListView(5) +[16:54.03.146] (SSH-Browser) CopySFTPFileListToListView(5): FileList.Count=18 +[16:54.03.146] (SSH-Browser) 对项目进行排序 +[16:54.03.146] (SSH-Browser) CopySFTPFileListToListView(5): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:54.03.150] (SSH-Browser) END CopySFTPFileListToListView(5) +[16:54.03.193] (SSH-Browser) ElSFTP1Success(5) +[16:54.03.251] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.03.329] BEGIN WMNewTab: 20 +[16:54.03.329] END WMNewTab: 20 +[16:54.03.506] Cts1MouseDown: FormClick +[16:54.03.517] Cts1ActiveTabChanged: New index = 6 +[16:54.03.517] BEGIN DisplayCurrentTab +[16:54.03.517] DisplayCurrentTab: FormClick +[16:54.03.517] (SSH-Browser) DisplayCurrentTab(6): ActiverPanel14 +[16:54.03.517] (SSH-Browser) BEGIN ActiverPanel14 +[16:54.03.517] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:54.03.533] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:54.03.533] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/root/ +[16:54.03.597] (SSH-Browser) ActiverPanel14: OpenDir(.); +[16:54.03.597] (SSH-Browser) BEGIN OpenDir(6) +[16:54.03.597] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.03.597] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.03.597] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.03.597] (SSH-Browser) OpenDir(6): 列出远程文件夹 +[16:54.03.598] (SSH-Browser) OpenDir(6): SFTP.RequestAbsolutePath(.); +[16:54.03.598] (SSH-Browser) END OpenDir(6) +[16:54.03.598] (SSH-Browser) END ActiverPanel14; +[16:54.03.688] (SSH-Browser) 正在启动 MobaSCP(11, remotemonitoring, ., ) +[16:54.03.688] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566611" -remotemonitoring mobauser@mobaserver:".") +[16:54.03.695] (SSH-Browser) ElSFTP1AbsolutePath(6) +[16:54.03.695] (SSH-Browser) ElSFTP1AbsolutePath(6): SFTP.OpenDirectory(/root) +[16:54.03.715] ShellExecuteS: ShellExecuteEx 成功. +[16:54.03.715] ShellExecuteS: WaitForInputIdle 失败. +[16:54.03.715] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566611" -remotemonitoring mobauser@mobaserver:".") +[16:54.03.715] DisplayCurrentTab: Cts1.BeginUpdate; +[16:54.03.715] DisplayCurrentTab: Cts1.EndUpdates +[16:54.03.825] DisplayCurrentTab: 显示所选标签页 +[16:54.03.825] [MobaSCP11] Launching remote monitoring in normal mode +[16:54.03.827] [MobaSCP11] Multiplex=1 +[16:54.03.828] [MobaSCP11] HOSTNAME: 192.168.127.10 +[16:54.03.828] [MobaSCP11] USERNAME: root +[16:54.03.828] DisplayCurrentTab: 隐藏其他标签页 +[16:54.03.831] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:54.03.835] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:54.03.835] DisplayCurrentTab: DistribuerLeFocus +[16:54.03.835] END DisplayCurrentTab +[16:54.03.913] [MobaSCP11] Using SCP1 +[16:54.03.913] (SSH-Browser) ElSFTP1OpenFile(6) +[16:54.03.913] (SSH-Browser) ElSFTP1OpenFile(6): SFTP.ReadDirectory +[16:54.03.913] [MobaSCP11] Connected to 192.168.127.10 +[16:54.03.929] BEGIN WMNewTab: 0 +[16:54.03.929] WMNewTab: FormClick +[16:54.03.929] WMNewTab: LooseFocus +[16:54.03.929] END WMNewTab: 0 +[16:54.03.929] BEGIN WMNewTab: 31 +[16:54.03.929] END WMNewTab: 31 +[16:54.03.970] (SSH-Browser) ElSFTP1Error(6): #1 - End of file +[16:54.03.970] (SSH-Browser) ElSFTP1Error(6): CloseCurrentHandle1 +[16:54.03.970] (SSH-Browser) BEGIN CloseCurrentHandle(6) +[16:54.03.970] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.03.970] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.03.970] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.03.970] (SSH-Browser) CloseCurrentHandle(6): SFTP.CloseHandle +[16:54.03.970] (SSH-Browser) END CloseCurrentHandle(6) +[16:54.03.970] (SSH-Browser) BEGIN CopySFTPFileListToListView(6) +[16:54.03.970] (SSH-Browser) CopySFTPFileListToListView(6): FileList.Count=18 +[16:54.03.970] (SSH-Browser) 对项目进行排序 +[16:54.03.970] (SSH-Browser) CopySFTPFileListToListView(6): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:54.03.973] (SSH-Browser) END CopySFTPFileListToListView(6) +[16:54.03.994] BEGIN WMNewTab: 0 +[16:54.03.994] WMNewTab: FormClick +[16:54.03.994] WMNewTab: LooseFocus +[16:54.03.994] END WMNewTab: 0 +[16:54.04.004] (SSH-Browser) ElSFTP1Success(6) +[16:54.04.138] BEGIN WMNewTab: 20 +[16:54.04.138] END WMNewTab: 20 +[16:54.04.381] BEGIN WMNewTab: 20 +[16:54.04.381] END WMNewTab: 20 +[16:54.04.381] BEGIN WMNewTab: 20 +[16:54.04.381] END WMNewTab: 20 +[16:54.04.382] BEGIN WMNewTab: 20 +[16:54.04.382] END WMNewTab: 20 +[16:54.04.382] BEGIN WMNewTab: 20 +[16:54.04.382] END WMNewTab: 20 +[16:54.04.382] BEGIN WMNewTab: 20 +[16:54.04.382] END WMNewTab: 20 +[16:54.04.472] BEGIN WMNewTab: 20 +[16:54.04.472] END WMNewTab: 20 +[16:54.04.671] BEGIN CWD +[16:54.04.671] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.04.671] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.04.671] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.04.671] END CWD +[16:54.04.748] BEGIN WMNewTab: 20 +[16:54.04.748] END WMNewTab: 20 +[16:54.04.748] (SSH-Browser) ElCommandSSHTunnel1Open +[16:54.04.778] (SSH-Browser) ExecuteCommandData +[16:54.04.809] (SSH-Browser) ExecuteCommandData +[16:54.04.839] (SSH-Browser) ExecuteCommandData +[16:54.04.870] (SSH-Browser) ExecuteCommandData +[16:54.04.870] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.04.901] (SSH-Browser) ExecuteCommandData +[16:54.05.022] BEGIN TFormXterm.FormResize +[16:54.05.022] TFormXterm.FormResize: CenterBtnReattachTab +[16:54.05.022] TFormXterm.FormResize: SplitModeResize +[16:54.05.022] TFormXterm.FormResize: BtnSplitNo.Down +[16:54.05.022] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:54.05.022] BEGIN ResizeTerminal +[16:54.05.022] END ResizeTerminal +[16:54.05.022] TFormXterm.FormResize: AdaptSidebarArrows; +[16:54.05.022] BEGIN AdaptSidebarArrows +[16:54.05.022] END AdaptSidebarArrows +[16:54.05.022] TFormXterm.FormResize: AdaptTV2; +[16:54.05.022] END TFormXterm.FormResize +[16:54.05.100] (SSH-Browser) ExecuteCommandClose +[16:54.05.100] BEGIN CWD +[16:54.05.103] (CWD) TenterDeTrouverLeCWD: Minute=5 / Seconde=48 +[16:54.05.164] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.05.164] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.05.164] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.05.164] END CWD +[16:54.05.192] BEGIN CWD +[16:54.05.253] END CWD +[16:54.05.555] BEGIN WMNewTab: 20 +[16:54.05.555] END WMNewTab: 20 +[16:54.05.724] BEGIN WMNewTab: 20 +[16:54.05.724] END WMNewTab: 20 +[16:54.05.801] BEGIN WMNewTab: 20 +[16:54.05.801] END WMNewTab: 20 +[16:54.05.801] BEGIN WMNewTab: 20 +[16:54.05.801] END WMNewTab: 20 +[16:54.05.801] BEGIN WMNewTab: 20 +[16:54.05.801] END WMNewTab: 20 +[16:54.05.801] BEGIN WMNewTab: 20 +[16:54.05.801] END WMNewTab: 20 +[16:54.05.801] BEGIN WMNewTab: 20 +[16:54.05.801] END WMNewTab: 20 + +[16:54.06.165] BEGIN WMNewTab: 20 +[16:54.06.165] END WMNewTab: 20 +[16:54.06.472] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.07.009] BEGIN WMNewTab: 20 +[16:54.07.009] END WMNewTab: 20 +[16:54.07.142] BEGIN WMNewTab: 20 +[16:54.07.142] END WMNewTab: 20 +[16:54.07.218] BEGIN WMNewTab: 20 +[16:54.07.218] END WMNewTab: 20 +[16:54.07.219] BEGIN WMNewTab: 20 +[16:54.07.219] END WMNewTab: 20 +[16:54.07.219] BEGIN WMNewTab: 20 +[16:54.07.219] END WMNewTab: 20 +[16:54.07.219] BEGIN WMNewTab: 20 +[16:54.07.219] END WMNewTab: 20 +[16:54.07.219] BEGIN WMNewTab: 20 +[16:54.07.219] END WMNewTab: 20 + +[16:54.07.588] BEGIN WMNewTab: 20 +[16:54.07.588] END WMNewTab: 20 + +[16:54.08.103] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.08.426] BEGIN WMNewTab: 20 +[16:54.08.426] END WMNewTab: 20 +[16:54.08.562] BEGIN WMNewTab: 20 +[16:54.08.562] END WMNewTab: 20 +[16:54.08.637] BEGIN WMNewTab: 20 +[16:54.08.637] END WMNewTab: 20 +[16:54.08.637] BEGIN WMNewTab: 20 +[16:54.08.637] END WMNewTab: 20 +[16:54.08.637] BEGIN WMNewTab: 20 +[16:54.08.637] END WMNewTab: 20 +[16:54.08.638] BEGIN WMNewTab: 20 +[16:54.08.638] END WMNewTab: 20 +[16:54.08.638] BEGIN WMNewTab: 20 +[16:54.08.638] END WMNewTab: 20 + +[16:54.09.036] BEGIN WMNewTab: 20 +[16:54.09.036] END WMNewTab: 20 + +[16:54.09.685] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.09.841] BEGIN WMNewTab: 20 +[16:54.09.841] END WMNewTab: 20 +[16:54.09.978] BEGIN WMNewTab: 20 +[16:54.09.978] END WMNewTab: 20 +[16:54.10.062] BEGIN WMNewTab: 20 +[16:54.10.062] END WMNewTab: 20 +[16:54.10.062] BEGIN WMNewTab: 20 +[16:54.10.062] END WMNewTab: 20 +[16:54.10.062] BEGIN WMNewTab: 20 +[16:54.10.062] END WMNewTab: 20 +[16:54.10.062] BEGIN WMNewTab: 20 +[16:54.10.062] END WMNewTab: 20 +[16:54.10.062] BEGIN WMNewTab: 20 +[16:54.10.062] END WMNewTab: 20 + +[16:54.10.452] BEGIN WMNewTab: 20 +[16:54.10.452] END WMNewTab: 20 + +[16:54.11.257] BEGIN WMNewTab: 20 +[16:54.11.257] END WMNewTab: 20 +[16:54.11.303] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.11.395] BEGIN WMNewTab: 20 +[16:54.11.395] END WMNewTab: 20 +[16:54.11.472] BEGIN WMNewTab: 20 +[16:54.11.472] END WMNewTab: 20 +[16:54.11.472] BEGIN WMNewTab: 20 +[16:54.11.472] END WMNewTab: 20 +[16:54.11.472] BEGIN WMNewTab: 20 +[16:54.11.472] END WMNewTab: 20 +[16:54.11.472] BEGIN WMNewTab: 20 +[16:54.11.472] END WMNewTab: 20 +[16:54.11.472] BEGIN WMNewTab: 20 +[16:54.11.472] END WMNewTab: 20 + +[16:54.11.867] BEGIN WMNewTab: 20 +[16:54.11.867] END WMNewTab: 20 + +[16:54.12.677] BEGIN WMNewTab: 20 +[16:54.12.677] END WMNewTab: 20 +[16:54.12.814] BEGIN WMNewTab: 20 +[16:54.12.814] END WMNewTab: 20 +[16:54.12.891] BEGIN WMNewTab: 20 +[16:54.12.891] END WMNewTab: 20 +[16:54.12.891] BEGIN WMNewTab: 20 +[16:54.12.891] END WMNewTab: 20 +[16:54.12.891] BEGIN WMNewTab: 20 +[16:54.12.891] END WMNewTab: 20 +[16:54.12.891] BEGIN WMNewTab: 20 +[16:54.12.891] END WMNewTab: 20 +[16:54.12.891] BEGIN WMNewTab: 20 +[16:54.12.891] END WMNewTab: 20 +[16:54.12.905] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.13.122] Cts1MouseDown: FormClick +[16:54.13.134] Cts1ActiveTabChanged: New index = 7 +[16:54.13.135] BEGIN DisplayCurrentTab +[16:54.13.135] DisplayCurrentTab: FormClick +[16:54.13.135] (SSH-Browser) DisplayCurrentTab(7): ActiverPanel14 +[16:54.13.135] (SSH-Browser) BEGIN ActiverPanel14 +[16:54.13.135] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:54.13.147] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:54.13.147] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/root/ +[16:54.13.226] (SSH-Browser) ActiverPanel14: OpenDir(.); +[16:54.13.226] (SSH-Browser) BEGIN OpenDir(7) +[16:54.13.226] (SSH-Browser) BEGIN VerifySFTPConnection(7) +[16:54.13.226] (SSH-Browser) VerifySFTPConnection(7): result=true (Sftp 连接) +[16:54.13.226] (SSH-Browser) END VerifySFTPConnection(7) +[16:54.13.226] (SSH-Browser) OpenDir(7): 列出远程文件夹 +[16:54.13.226] (SSH-Browser) OpenDir(7): SFTP.RequestAbsolutePath(.); +[16:54.13.227] (SSH-Browser) END OpenDir(7) +[16:54.13.227] (SSH-Browser) END ActiverPanel14; +[16:54.13.368] (SSH-Browser) 正在启动 MobaSCP(12, remotemonitoring, ., ) +[16:54.13.368] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566612" -remotemonitoring mobauser@mobaserver:".") +[16:54.13.369] BEGIN WMNewTab: 20 +[16:54.13.369] END WMNewTab: 20 +[16:54.13.387] (SSH-Browser) ElSFTP1AbsolutePath(7) +[16:54.13.387] (SSH-Browser) ElSFTP1AbsolutePath(7): SFTP.OpenDirectory(/root) +[16:54.13.403] ShellExecuteS: ShellExecuteEx 成功. +[16:54.13.403] ShellExecuteS: WaitForInputIdle 失败. +[16:54.13.403] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566612" -remotemonitoring mobauser@mobaserver:".") +[16:54.13.403] DisplayCurrentTab: Cts1.BeginUpdate; +[16:54.13.403] DisplayCurrentTab: Cts1.EndUpdates +[16:54.13.529] DisplayCurrentTab: 显示所选标签页 +[16:54.13.530] [MobaSCP12] Launching remote monitoring in normal mode +[16:54.13.532] [MobaSCP12] Multiplex=1 +[16:54.13.532] [MobaSCP12] HOSTNAME: 192.168.127.10 +[16:54.13.532] [MobaSCP12] USERNAME: root +[16:54.13.534] DisplayCurrentTab: 隐藏其他标签页 +[16:54.13.535] BEGIN WMNewTab: 31 +[16:54.13.535] END WMNewTab: 31 +[16:54.13.539] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:54.13.543] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:54.13.543] DisplayCurrentTab: DistribuerLeFocus +[16:54.13.544] END DisplayCurrentTab +[16:54.13.631] [MobaSCP12] Using SCP1 +[16:54.13.631] (SSH-Browser) ElSFTP1OpenFile(7) +[16:54.13.631] (SSH-Browser) ElSFTP1OpenFile(7): SFTP.ReadDirectory +[16:54.13.631] [MobaSCP12] Connected to 192.168.127.10 +[16:54.13.631] BEGIN WMNewTab: 0 +[16:54.13.631] WMNewTab: FormClick +[16:54.13.631] WMNewTab: LooseFocus +[16:54.13.631] END WMNewTab: 0 +[16:54.13.651] BEGIN WMNewTab: 0 +[16:54.13.651] WMNewTab: FormClick +[16:54.13.651] WMNewTab: LooseFocus +[16:54.13.653] END WMNewTab: 0 +[16:54.13.697] (SSH-Browser) ElSFTP1Error(7): #1 - End of file +[16:54.13.697] (SSH-Browser) ElSFTP1Error(7): CloseCurrentHandle1 +[16:54.13.697] (SSH-Browser) BEGIN CloseCurrentHandle(7) +[16:54.13.697] (SSH-Browser) BEGIN VerifySFTPConnection(7) +[16:54.13.697] (SSH-Browser) VerifySFTPConnection(7): result=true (Sftp 连接) +[16:54.13.697] (SSH-Browser) END VerifySFTPConnection(7) +[16:54.13.697] (SSH-Browser) CloseCurrentHandle(7): SFTP.CloseHandle +[16:54.13.697] (SSH-Browser) END CloseCurrentHandle(7) +[16:54.13.697] (SSH-Browser) BEGIN CopySFTPFileListToListView(7) +[16:54.13.697] (SSH-Browser) CopySFTPFileListToListView(7): FileList.Count=18 +[16:54.13.698] (SSH-Browser) 对项目进行排序 +[16:54.13.698] (SSH-Browser) CopySFTPFileListToListView(7): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:54.13.701] (SSH-Browser) END CopySFTPFileListToListView(7) +[16:54.13.728] (SSH-Browser) ElSFTP1Success(7) + +[16:54.14.095] BEGIN WMNewTab: 20 +[16:54.14.095] END WMNewTab: 20 +[16:54.14.199] BEGIN WMNewTab: 20 +[16:54.14.199] END WMNewTab: 20 +[16:54.14.230] BEGIN WMNewTab: 20 +[16:54.14.230] END WMNewTab: 20 +[16:54.14.306] BEGIN WMNewTab: 20 +[16:54.14.306] END WMNewTab: 20 +[16:54.14.306] BEGIN CWD +[16:54.14.306] (SSH-Browser) BEGIN VerifySFTPConnection(7) +[16:54.14.306] (SSH-Browser) VerifySFTPConnection(7): result=true (Sftp 连接) +[16:54.14.306] (SSH-Browser) END VerifySFTPConnection(7) +[16:54.14.306] END CWD +[16:54.14.321] BEGIN WMNewTab: 20 +[16:54.14.321] END WMNewTab: 20 +[16:54.14.321] BEGIN WMNewTab: 20 +[16:54.14.321] END WMNewTab: 20 +[16:54.14.321] BEGIN WMNewTab: 20 +[16:54.14.321] END WMNewTab: 20 +[16:54.14.382] (SSH-Browser) ElCommandSSHTunnel1Open +[16:54.14.412] (SSH-Browser) ExecuteCommandData +[16:54.14.443] (SSH-Browser) ExecuteCommandData +[16:54.14.474] (SSH-Browser) ExecuteCommandData +[16:54.14.503] (SSH-Browser) ExecuteCommandData +[16:54.14.520] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.14.534] (SSH-Browser) ExecuteCommandData +[16:54.14.625] (SSH-Browser) ExecuteCommandClose +[16:54.14.625] BEGIN CWD +[16:54.14.627] (CWD) TenterDeTrouverLeCWD: Minute=5 / Seconde=58 +[16:54.14.770] BEGIN TFormXterm.FormResize +[16:54.14.770] TFormXterm.FormResize: CenterBtnReattachTab +[16:54.14.770] TFormXterm.FormResize: SplitModeResize +[16:54.14.770] TFormXterm.FormResize: BtnSplitNo.Down +[16:54.14.770] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:54.14.770] BEGIN ResizeTerminal +[16:54.14.770] END ResizeTerminal +[16:54.14.770] TFormXterm.FormResize: AdaptSidebarArrows; +[16:54.14.770] BEGIN AdaptSidebarArrows +[16:54.14.770] END AdaptSidebarArrows +[16:54.14.770] TFormXterm.FormResize: AdaptTV2; +[16:54.14.770] END TFormXterm.FormResize +[16:54.14.778] (SSH-Browser) BEGIN VerifySFTPConnection(7) +[16:54.14.778] (SSH-Browser) VerifySFTPConnection(7): result=true (Sftp 连接) +[16:54.14.778] (SSH-Browser) END VerifySFTPConnection(7) +[16:54.14.778] END CWD +[16:54.14.796] BEGIN WMNewTab: 20 +[16:54.14.796] END WMNewTab: 20 +[16:54.14.807] BEGIN CWD +[16:54.14.867] END CWD + +[16:54.15.230] Cts1MouseDown: FormClick +[16:54.15.240] Cts1ActiveTabChanged: New index = 6 +[16:54.15.240] BEGIN DisplayCurrentTab +[16:54.15.240] DisplayCurrentTab: FormClick +[16:54.15.240] (SSH-Browser) DisplayCurrentTab(6): ActiverPanel14 +[16:54.15.240] (SSH-Browser) BEGIN ActiverPanel14 +[16:54.15.240] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:54.15.257] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:54.15.257] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/root/ +[16:54.15.257] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[6].RemList +[16:54.15.307] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[6].RemList +[16:54.15.307] (SSH-Browser) END ActiverPanel14; +[16:54.15.454] (SSH-Browser) 正在启动 MobaSCP(11, remotemonitoring, ., ) +[16:54.15.455] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566611" -remotemonitoring mobauser@mobaserver:".") +[16:54.15.479] ShellExecuteS: ShellExecuteEx 成功. +[16:54.15.480] ShellExecuteS: WaitForInputIdle 失败. +[16:54.15.480] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566611" -remotemonitoring mobauser@mobaserver:".") +[16:54.15.480] DisplayCurrentTab: Cts1.BeginUpdate; +[16:54.15.480] DisplayCurrentTab: Cts1.EndUpdates +[16:54.15.593] DisplayCurrentTab: 显示所选标签页 +[16:54.15.594] BEGIN WMNewTab: 20 +[16:54.15.594] END WMNewTab: 20 +[16:54.15.594] [MobaSCP11] Launching remote monitoring in normal mode +[16:54.15.594] [MobaSCP11] Multiplex=1 +[16:54.15.595] [MobaSCP11] HOSTNAME: 192.168.127.10 +[16:54.15.595] [MobaSCP11] USERNAME: root +[16:54.15.596] DisplayCurrentTab: 隐藏其他标签页 +[16:54.15.599] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:54.15.602] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:54.15.602] DisplayCurrentTab: DistribuerLeFocus +[16:54.15.602] END DisplayCurrentTab +[16:54.15.683] [MobaSCP11] Using SCP1 +[16:54.15.683] BEGIN WMNewTab: 20 +[16:54.15.683] END WMNewTab: 20 +[16:54.15.683] [MobaSCP11] Connected to 192.168.127.10 +[16:54.15.722] BEGIN WMNewTab: 20 +[16:54.15.722] END WMNewTab: 20 +[16:54.15.737] BEGIN WMNewTab: 20 +[16:54.15.737] END WMNewTab: 20 +[16:54.15.737] BEGIN WMNewTab: 20 +[16:54.15.737] END WMNewTab: 20 +[16:54.15.738] BEGIN WMNewTab: 20 +[16:54.15.738] END WMNewTab: 20 +[16:54.15.812] BEGIN WMNewTab: 20 +[16:54.15.812] END WMNewTab: 20 +[16:54.16.134] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.16.211] BEGIN WMNewTab: 20 +[16:54.16.211] END WMNewTab: 20 + +[16:54.16.611] Cts1MouseDown: FormClick +[16:54.16.623] Cts1ActiveTabChanged: New index = 7 +[16:54.16.623] BEGIN DisplayCurrentTab +[16:54.16.623] DisplayCurrentTab: FormClick +[16:54.16.623] (SSH-Browser) DisplayCurrentTab(7): ActiverPanel14 +[16:54.16.623] (SSH-Browser) BEGIN ActiverPanel14 +[16:54.16.623] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:54.16.636] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:54.16.636] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/root/ +[16:54.16.636] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[7].RemList +[16:54.16.690] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[7].RemList +[16:54.16.691] (SSH-Browser) END ActiverPanel14; +[16:54.16.783] (SSH-Browser) 正在启动 MobaSCP(12, remotemonitoring, ., ) +[16:54.16.785] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566612" -remotemonitoring mobauser@mobaserver:".") +[16:54.16.821] ShellExecuteS: ShellExecuteEx 成功. +[16:54.16.821] ShellExecuteS: WaitForInputIdle 失败. +[16:54.16.821] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566612" -remotemonitoring mobauser@mobaserver:".") +[16:54.16.821] DisplayCurrentTab: Cts1.BeginUpdate; +[16:54.16.821] DisplayCurrentTab: Cts1.EndUpdates +[16:54.16.934] DisplayCurrentTab: 显示所选标签页 +[16:54.16.934] [MobaSCP12] Launching remote monitoring in normal mode +[16:54.16.934] [MobaSCP12] Multiplex=1 +[16:54.16.936] [MobaSCP12] HOSTNAME: 192.168.127.10 +[16:54.16.936] [MobaSCP12] USERNAME: root +[16:54.16.937] DisplayCurrentTab: 隐藏其他标签页 +[16:54.16.941] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:54.16.944] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:54.16.944] DisplayCurrentTab: DistribuerLeFocus +[16:54.16.945] END DisplayCurrentTab +[16:54.17.036] [MobaSCP12] Using SCP1 +[16:54.17.036] BEGIN WMNewTab: 20 +[16:54.17.036] END WMNewTab: 20 +[16:54.17.037] [MobaSCP12] Connected to 192.168.127.10 +[16:54.17.099] BEGIN WMNewTab: 20 +[16:54.17.099] END WMNewTab: 20 +[16:54.17.146] BEGIN WMNewTab: 20 +[16:54.17.146] END WMNewTab: 20 +[16:54.17.160] BEGIN WMNewTab: 20 +[16:54.17.160] END WMNewTab: 20 +[16:54.17.160] BEGIN WMNewTab: 20 +[16:54.17.160] END WMNewTab: 20 +[16:54.17.160] BEGIN WMNewTab: 20 +[16:54.17.160] END WMNewTab: 20 +[16:54.17.237] BEGIN WMNewTab: 20 +[16:54.17.237] END WMNewTab: 20 + +[16:54.17.635] BEGIN WMNewTab: 20 +[16:54.17.635] END WMNewTab: 20 +[16:54.17.741] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.18.170] BEGIN TFormXterm.FormResize +[16:54.18.170] TFormXterm.FormResize: CenterBtnReattachTab +[16:54.18.170] TFormXterm.FormResize: SplitModeResize +[16:54.18.170] TFormXterm.FormResize: BtnSplitNo.Down +[16:54.18.170] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:54.18.170] BEGIN ResizeTerminal +[16:54.18.171] END ResizeTerminal +[16:54.18.171] TFormXterm.FormResize: AdaptSidebarArrows; +[16:54.18.171] BEGIN AdaptSidebarArrows +[16:54.18.171] END AdaptSidebarArrows +[16:54.18.171] TFormXterm.FormResize: AdaptTV2; +[16:54.18.171] END TFormXterm.FormResize +[16:54.18.171] BEGIN WMNewTab: 60 +[16:54.18.248] END WMNewTab: 60 +[16:54.18.305] Cts1MouseDown: FormClick +[16:54.18.314] Cts1ActiveTabChanged: New index = 6 +[16:54.18.315] BEGIN DisplayCurrentTab +[16:54.18.315] DisplayCurrentTab: FormClick +[16:54.18.315] (SSH-Browser) DisplayCurrentTab(6): ActiverPanel14 +[16:54.18.315] (SSH-Browser) BEGIN ActiverPanel14 +[16:54.18.315] (SSH-Browser) ActiverPanel14: sTabSFTP.TabVisible:=true; +[16:54.18.328] (SSH-Browser) ActiverPanel14: FollowSSHBrowser 选项已勾选 +[16:54.18.328] (SSH-Browser) ActiverPanel14: 列出远程目录 root@192.168.127.10:/root/ +[16:54.18.328] (SSH-Browser) ActiverPanel14: 远程目录内容已存在于 TabSFTP[6].RemList +[16:54.18.375] (SSH-Browser) ActiverPanel14: 远程目录内容已复制自 TabSFTP[6].RemList +[16:54.18.375] (SSH-Browser) END ActiverPanel14; +[16:54.18.482] (SSH-Browser) 正在启动 MobaSCP(11, remotemonitoring, ., ) +[16:54.18.482] BEGIN ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566611" -remotemonitoring mobauser@mobaserver:".") +[16:54.18.483] BEGIN WMNewTab: 20 +[16:54.18.483] END WMNewTab: 20 +[16:54.18.501] ShellExecuteS: ShellExecuteEx 成功. +[16:54.18.501] ShellExecuteS: WaitForInputIdle 失败. +[16:54.18.501] END ShellExecuteS(C:\Users\31554\AppData\Local\Temp\Mxt252\bin\MobaSCPRi.exe, -v -batch -scp -load "TERM1317566611" -remotemonitoring mobauser@mobaserver:".") +[16:54.18.501] DisplayCurrentTab: Cts1.BeginUpdate; +[16:54.18.501] DisplayCurrentTab: Cts1.EndUpdates +[16:54.18.606] DisplayCurrentTab: 显示所选标签页 +[16:54.18.607] BEGIN WMNewTab: 20 +[16:54.18.607] END WMNewTab: 20 +[16:54.18.607] BEGIN WMNewTab: 20 +[16:54.18.607] END WMNewTab: 20 +[16:54.18.607] [MobaSCP11] Launching remote monitoring in normal mode +[16:54.18.607] BEGIN WMNewTab: 20 +[16:54.18.607] END WMNewTab: 20 +[16:54.18.607] BEGIN WMNewTab: 20 +[16:54.18.607] END WMNewTab: 20 +[16:54.18.607] BEGIN WMNewTab: 20 +[16:54.18.607] END WMNewTab: 20 +[16:54.18.607] [MobaSCP11] Multiplex=1 +[16:54.18.609] [MobaSCP11] HOSTNAME: 192.168.127.10 +[16:54.18.611] [MobaSCP11] USERNAME: root +[16:54.18.612] DisplayCurrentTab: 隐藏其他标签页 +[16:54.18.615] DisplayCurrentTab: 调整按钮的启用/禁用状态 +[16:54.18.618] DisplayCurrentTab: DeterminerBoutonDetachOuReattach +[16:54.18.618] DisplayCurrentTab: DistribuerLeFocus +[16:54.18.618] END DisplayCurrentTab +[16:54.18.700] BEGIN WMNewTab: 20 +[16:54.18.700] END WMNewTab: 20 +[16:54.18.700] [MobaSCP11] Using SCP1 +[16:54.18.700] BEGIN WMNewTab: 62 +[16:54.18.700] END WMNewTab: 62 +[16:54.18.700] [MobaSCP11] Connected to 192.168.127.10 +[16:54.19.050] BEGIN WMNewTab: 20 +[16:54.19.050] END WMNewTab: 20 +[16:54.19.340] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.19.832] BEGIN TFormXterm.FormResize +[16:54.19.832] TFormXterm.FormResize: CenterBtnReattachTab +[16:54.19.832] TFormXterm.FormResize: SplitModeResize +[16:54.19.832] TFormXterm.FormResize: BtnSplitNo.Down +[16:54.19.832] TFormXterm.FormResize: ResizeTerminal(Indice,Panel1); +[16:54.19.832] BEGIN ResizeTerminal +[16:54.19.832] END ResizeTerminal +[16:54.19.832] TFormXterm.FormResize: AdaptSidebarArrows; +[16:54.19.832] BEGIN AdaptSidebarArrows +[16:54.19.832] END AdaptSidebarArrows +[16:54.19.832] TFormXterm.FormResize: AdaptTV2; +[16:54.19.832] END TFormXterm.FormResize +[16:54.19.891] BEGIN WMNewTab: 20 +[16:54.19.891] END WMNewTab: 20 +[16:54.20.014] BEGIN WMNewTab: 20 +[16:54.20.014] END WMNewTab: 20 +[16:54.20.014] BEGIN WMNewTab: 20 +[16:54.20.014] END WMNewTab: 20 +[16:54.20.028] BEGIN WMNewTab: 20 +[16:54.20.028] END WMNewTab: 20 +[16:54.20.028] BEGIN WMNewTab: 20 +[16:54.20.028] END WMNewTab: 20 +[16:54.20.028] BEGIN WMNewTab: 20 +[16:54.20.028] END WMNewTab: 20 +[16:54.20.119] BEGIN WMNewTab: 20 +[16:54.20.119] END WMNewTab: 20 +[16:54.20.471] BEGIN WMNewTab: 20 +[16:54.20.471] END WMNewTab: 20 + +[16:54.20.961] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.21.313] BEGIN WMNewTab: 20 +[16:54.21.313] END WMNewTab: 20 +[16:54.21.436] BEGIN WMNewTab: 20 +[16:54.21.436] END WMNewTab: 20 +[16:54.21.436] BEGIN WMNewTab: 20 +[16:54.21.436] END WMNewTab: 20 +[16:54.21.471] BEGIN WMNewTab: 20 +[16:54.21.471] END WMNewTab: 20 +[16:54.21.471] BEGIN WMNewTab: 20 +[16:54.21.471] END WMNewTab: 20 +[16:54.21.471] BEGIN WMNewTab: 20 +[16:54.21.471] END WMNewTab: 20 +[16:54.21.592] BEGIN WMNewTab: 20 +[16:54.21.592] END WMNewTab: 20 +[16:54.21.894] BEGIN WMNewTab: 20 +[16:54.21.894] END WMNewTab: 20 + +[16:54.22.562] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.22.734] BEGIN WMNewTab: 20 +[16:54.22.734] END WMNewTab: 20 +[16:54.22.856] BEGIN WMNewTab: 20 +[16:54.22.856] END WMNewTab: 20 +[16:54.22.856] BEGIN WMNewTab: 20 +[16:54.22.856] END WMNewTab: 20 +[16:54.22.887] BEGIN WMNewTab: 20 +[16:54.22.887] END WMNewTab: 20 +[16:54.22.887] BEGIN WMNewTab: 20 +[16:54.22.887] END WMNewTab: 20 +[16:54.22.887] BEGIN WMNewTab: 20 +[16:54.22.887] END WMNewTab: 20 +[16:54.23.008] BEGIN WMNewTab: 20 +[16:54.23.008] END WMNewTab: 20 +[16:54.23.311] BEGIN WMNewTab: 20 +[16:54.23.311] END WMNewTab: 20 + +[16:54.24.149] BEGIN WMNewTab: 20 +[16:54.24.149] END WMNewTab: 20 +[16:54.24.170] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.24.272] BEGIN WMNewTab: 20 +[16:54.24.272] END WMNewTab: 20 +[16:54.24.272] BEGIN WMNewTab: 20 +[16:54.24.272] END WMNewTab: 20 +[16:54.24.301] BEGIN WMNewTab: 20 +[16:54.24.301] END WMNewTab: 20 +[16:54.24.301] BEGIN WMNewTab: 20 +[16:54.24.302] END WMNewTab: 20 +[16:54.24.302] BEGIN WMNewTab: 20 +[16:54.24.302] END WMNewTab: 20 +[16:54.24.422] BEGIN WMNewTab: 20 +[16:54.24.422] END WMNewTab: 20 +[16:54.24.728] BEGIN WMNewTab: 20 +[16:54.24.728] END WMNewTab: 20 + +[16:54.25.570] BEGIN WMNewTab: 20 +[16:54.25.570] END WMNewTab: 20 +[16:54.25.692] BEGIN WMNewTab: 20 +[16:54.25.692] END WMNewTab: 20 +[16:54.25.693] BEGIN WMNewTab: 20 +[16:54.25.693] END WMNewTab: 20 +[16:54.25.723] BEGIN WMNewTab: 20 +[16:54.25.723] END WMNewTab: 20 +[16:54.25.723] BEGIN WMNewTab: 20 +[16:54.25.723] END WMNewTab: 20 +[16:54.25.723] BEGIN WMNewTab: 20 +[16:54.25.723] END WMNewTab: 20 +[16:54.25.784] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.25.880] BEGIN WMNewTab: 20 +[16:54.25.880] END WMNewTab: 20 +[16:54.26.150] BEGIN WMNewTab: 20 +[16:54.26.150] END WMNewTab: 20 + +[16:54.26.991] BEGIN WMNewTab: 20 +[16:54.26.991] END WMNewTab: 20 +[16:54.27.112] BEGIN WMNewTab: 20 +[16:54.27.112] END WMNewTab: 20 +[16:54.27.112] BEGIN WMNewTab: 20 +[16:54.27.112] END WMNewTab: 20 +[16:54.27.143] BEGIN WMNewTab: 20 +[16:54.27.143] END WMNewTab: 20 +[16:54.27.143] BEGIN WMNewTab: 20 +[16:54.27.143] END WMNewTab: 20 +[16:54.27.143] BEGIN WMNewTab: 20 +[16:54.27.143] END WMNewTab: 20 +[16:54.27.295] BEGIN WMNewTab: 20 +[16:54.27.295] END WMNewTab: 20 +[16:54.27.402] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.27.569] BEGIN WMNewTab: 20 +[16:54.27.569] END WMNewTab: 20 + +[16:54.28.406] BEGIN WMNewTab: 20 +[16:54.28.406] END WMNewTab: 20 +[16:54.28.529] BEGIN WMNewTab: 20 +[16:54.28.529] END WMNewTab: 20 +[16:54.28.529] BEGIN WMNewTab: 20 +[16:54.28.529] END WMNewTab: 20 +[16:54.28.560] BEGIN WMNewTab: 20 +[16:54.28.560] END WMNewTab: 20 +[16:54.28.560] BEGIN WMNewTab: 20 +[16:54.28.560] END WMNewTab: 20 +[16:54.28.560] BEGIN WMNewTab: 20 +[16:54.28.560] END WMNewTab: 20 +[16:54.28.712] BEGIN WMNewTab: 20 +[16:54.28.712] END WMNewTab: 20 +[16:54.28.987] BEGIN WMNewTab: 20 +[16:54.28.987] END WMNewTab: 20 +[16:54.29.002] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.29.824] BEGIN WMNewTab: 20 +[16:54.29.824] END WMNewTab: 20 +[16:54.29.971] BEGIN WMNewTab: 20 +[16:54.29.971] END WMNewTab: 20 +[16:54.29.972] BEGIN WMNewTab: 20 +[16:54.29.972] END WMNewTab: 20 +[16:54.29.975] BEGIN WMNewTab: 20 +[16:54.29.975] END WMNewTab: 20 +[16:54.29.975] BEGIN WMNewTab: 20 +[16:54.29.975] END WMNewTab: 20 +[16:54.29.975] BEGIN WMNewTab: 20 +[16:54.29.975] END WMNewTab: 20 +[16:54.30.128] BEGIN WMNewTab: 20 +[16:54.30.128] END WMNewTab: 20 +[16:54.30.402] BEGIN WMNewTab: 20 +[16:54.30.402] END WMNewTab: 20 +[16:54.30.615] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.31.239] BEGIN WMNewTab: 20 +[16:54.31.239] END WMNewTab: 20 +[16:54.31.376] BEGIN WMNewTab: 20 +[16:54.31.376] END WMNewTab: 20 +[16:54.31.376] BEGIN WMNewTab: 20 +[16:54.31.376] END WMNewTab: 20 +[16:54.31.391] BEGIN WMNewTab: 20 +[16:54.31.391] END WMNewTab: 20 +[16:54.31.391] BEGIN WMNewTab: 20 +[16:54.31.391] END WMNewTab: 20 +[16:54.31.391] BEGIN WMNewTab: 20 +[16:54.31.391] END WMNewTab: 20 +[16:54.31.545] BEGIN WMNewTab: 20 +[16:54.31.545] END WMNewTab: 20 +[16:54.31.820] BEGIN WMNewTab: 20 +[16:54.31.820] END WMNewTab: 20 + +[16:54.32.216] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.32.663] BEGIN WMNewTab: 20 +[16:54.32.663] END WMNewTab: 20 +[16:54.32.801] BEGIN WMNewTab: 20 +[16:54.32.801] END WMNewTab: 20 +[16:54.32.801] BEGIN WMNewTab: 20 +[16:54.32.801] END WMNewTab: 20 +[16:54.32.815] BEGIN WMNewTab: 20 +[16:54.32.815] END WMNewTab: 20 +[16:54.32.815] BEGIN WMNewTab: 20 +[16:54.32.815] END WMNewTab: 20 +[16:54.32.815] BEGIN WMNewTab: 20 +[16:54.32.815] END WMNewTab: 20 +[16:54.32.967] BEGIN WMNewTab: 20 +[16:54.32.967] END WMNewTab: 20 +[16:54.33.244] BEGIN WMNewTab: 20 +[16:54.33.244] END WMNewTab: 20 + +[16:54.33.842] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.34.085] BEGIN WMNewTab: 20 +[16:54.34.085] END WMNewTab: 20 +[16:54.34.222] BEGIN WMNewTab: 20 +[16:54.34.222] END WMNewTab: 20 +[16:54.34.222] BEGIN WMNewTab: 20 +[16:54.34.222] END WMNewTab: 20 +[16:54.34.237] BEGIN WMNewTab: 20 +[16:54.34.237] END WMNewTab: 20 +[16:54.34.237] BEGIN WMNewTab: 20 +[16:54.34.237] END WMNewTab: 20 +[16:54.34.238] BEGIN WMNewTab: 20 +[16:54.34.238] END WMNewTab: 20 +[16:54.34.390] BEGIN WMNewTab: 20 +[16:54.34.390] END WMNewTab: 20 +[16:54.34.664] BEGIN WMNewTab: 20 +[16:54.34.664] END WMNewTab: 20 + +[16:54.35.455] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.35.502] BEGIN WMNewTab: 20 +[16:54.35.502] END WMNewTab: 20 +[16:54.35.640] BEGIN WMNewTab: 20 +[16:54.35.640] END WMNewTab: 20 +[16:54.35.640] BEGIN WMNewTab: 20 +[16:54.35.640] END WMNewTab: 20 +[16:54.35.654] BEGIN WMNewTab: 20 +[16:54.35.654] END WMNewTab: 20 +[16:54.35.655] BEGIN WMNewTab: 20 +[16:54.35.655] END WMNewTab: 20 +[16:54.35.655] BEGIN WMNewTab: 20 +[16:54.35.655] END WMNewTab: 20 +[16:54.35.807] BEGIN WMNewTab: 20 +[16:54.35.807] END WMNewTab: 20 +[16:54.36.087] BEGIN WMNewTab: 20 +[16:54.36.087] END WMNewTab: 20 + +[16:54.36.919] BEGIN WMNewTab: 20 +[16:54.36.919] END WMNewTab: 20 +[16:54.37.055] BEGIN WMNewTab: 20 +[16:54.37.055] END WMNewTab: 20 +[16:54.37.055] BEGIN WMNewTab: 20 +[16:54.37.055] END WMNewTab: 20 +[16:54.37.112] BEGIN WMNewTab: 20 +[16:54.37.112] END WMNewTab: 20 +[16:54.37.112] BEGIN WMNewTab: 20 +[16:54.37.112] END WMNewTab: 20 +[16:54.37.112] BEGIN WMNewTab: 20 +[16:54.37.112] END WMNewTab: 20 +[16:54.37.119] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.37.222] BEGIN WMNewTab: 20 +[16:54.37.222] END WMNewTab: 20 +[16:54.37.498] BEGIN WMNewTab: 20 +[16:54.37.498] END WMNewTab: 20 + +[16:54.38.334] BEGIN WMNewTab: 20 +[16:54.38.334] END WMNewTab: 20 +[16:54.38.472] BEGIN WMNewTab: 20 +[16:54.38.472] END WMNewTab: 20 +[16:54.38.472] BEGIN WMNewTab: 20 +[16:54.38.472] END WMNewTab: 20 +[16:54.38.518] BEGIN WMNewTab: 20 +[16:54.38.518] END WMNewTab: 20 +[16:54.38.518] BEGIN WMNewTab: 20 +[16:54.38.518] END WMNewTab: 20 +[16:54.38.518] BEGIN WMNewTab: 20 +[16:54.38.518] END WMNewTab: 20 +[16:54.38.639] BEGIN WMNewTab: 20 +[16:54.38.639] END WMNewTab: 20 +[16:54.38.670] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.38.913] BEGIN WMNewTab: 20 +[16:54.38.913] END WMNewTab: 20 + +[16:54.39.750] BEGIN WMNewTab: 20 +[16:54.39.750] END WMNewTab: 20 +[16:54.39.888] BEGIN WMNewTab: 20 +[16:54.39.888] END WMNewTab: 20 +[16:54.39.888] BEGIN WMNewTab: 20 +[16:54.39.888] END WMNewTab: 20 +[16:54.39.932] BEGIN WMNewTab: 20 +[16:54.39.932] END WMNewTab: 20 +[16:54.39.933] BEGIN WMNewTab: 20 +[16:54.39.933] END WMNewTab: 20 +[16:54.39.933] BEGIN WMNewTab: 20 +[16:54.39.933] END WMNewTab: 20 +[16:54.40.053] BEGIN WMNewTab: 20 +[16:54.40.053] END WMNewTab: 20 +[16:54.40.280] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.40.327] BEGIN WMNewTab: 20 +[16:54.40.327] END WMNewTab: 20 + +[16:54.41.171] BEGIN WMNewTab: 20 +[16:54.41.171] END WMNewTab: 20 +[16:54.41.311] BEGIN WMNewTab: 20 +[16:54.41.311] END WMNewTab: 20 +[16:54.41.311] BEGIN WMNewTab: 20 +[16:54.41.311] END WMNewTab: 20 +[16:54.41.354] BEGIN WMNewTab: 20 +[16:54.41.354] END WMNewTab: 20 +[16:54.41.354] BEGIN WMNewTab: 20 +[16:54.41.354] END WMNewTab: 20 +[16:54.41.354] BEGIN WMNewTab: 20 +[16:54.41.354] END WMNewTab: 20 +[16:54.41.476] BEGIN WMNewTab: 20 +[16:54.41.476] END WMNewTab: 20 +[16:54.41.748] BEGIN WMNewTab: 20 +[16:54.41.748] END WMNewTab: 20 +[16:54.41.900] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.42.586] BEGIN WMNewTab: 20 +[16:54.42.586] END WMNewTab: 20 +[16:54.42.724] BEGIN WMNewTab: 20 +[16:54.42.724] END WMNewTab: 20 +[16:54.42.724] BEGIN WMNewTab: 20 +[16:54.42.724] END WMNewTab: 20 +[16:54.42.770] BEGIN WMNewTab: 20 +[16:54.42.770] END WMNewTab: 20 +[16:54.42.770] BEGIN WMNewTab: 20 +[16:54.42.770] END WMNewTab: 20 +[16:54.42.770] BEGIN WMNewTab: 20 +[16:54.42.770] END WMNewTab: 20 +[16:54.42.891] BEGIN WMNewTab: 20 +[16:54.42.891] END WMNewTab: 20 +[16:54.43.164] BEGIN WMNewTab: 20 +[16:54.43.164] END WMNewTab: 20 +[16:54.43.500] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.43.580] BEGIN WMNewTab: 0 +[16:54.43.580] WMNewTab: FormClick +[16:54.43.580] WMNewTab: LooseFocus +[16:54.43.583] END WMNewTab: 0 +[16:54.43.594] BEGIN WMNewTab: 0 +[16:54.43.594] WMNewTab: FormClick +[16:54.43.594] WMNewTab: LooseFocus +[16:54.43.597] END WMNewTab: 0 + +[16:54.44.003] BEGIN WMNewTab: 20 +[16:54.44.003] END WMNewTab: 20 +[16:54.44.137] BEGIN WMNewTab: 20 +[16:54.44.137] END WMNewTab: 20 +[16:54.44.137] BEGIN WMNewTab: 20 +[16:54.44.137] END WMNewTab: 20 +[16:54.44.184] BEGIN WMNewTab: 20 +[16:54.44.184] END WMNewTab: 20 +[16:54.44.184] BEGIN WMNewTab: 20 +[16:54.44.184] END WMNewTab: 20 +[16:54.44.184] BEGIN WMNewTab: 20 +[16:54.44.184] END WMNewTab: 20 +[16:54.44.308] BEGIN WMNewTab: 20 +[16:54.44.308] END WMNewTab: 20 +[16:54.44.583] BEGIN WMNewTab: 20 +[16:54.44.583] END WMNewTab: 20 + +[16:54.45.116] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.45.423] BEGIN WMNewTab: 20 +[16:54.45.423] END WMNewTab: 20 +[16:54.45.561] BEGIN WMNewTab: 20 +[16:54.45.561] END WMNewTab: 20 +[16:54.45.561] BEGIN WMNewTab: 20 +[16:54.45.561] END WMNewTab: 20 +[16:54.45.606] BEGIN WMNewTab: 20 +[16:54.45.606] END WMNewTab: 20 +[16:54.45.606] BEGIN WMNewTab: 20 +[16:54.45.606] END WMNewTab: 20 +[16:54.45.606] BEGIN WMNewTab: 20 +[16:54.45.606] END WMNewTab: 20 +[16:54.45.729] BEGIN WMNewTab: 20 +[16:54.45.729] END WMNewTab: 20 +[16:54.46.002] BEGIN WMNewTab: 20 +[16:54.46.002] END WMNewTab: 20 + +[16:54.46.715] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.46.837] BEGIN WMNewTab: 20 +[16:54.46.837] END WMNewTab: 20 +[16:54.46.975] BEGIN WMNewTab: 20 +[16:54.46.975] END WMNewTab: 20 +[16:54.46.975] BEGIN WMNewTab: 20 +[16:54.46.975] END WMNewTab: 20 +[16:54.47.020] BEGIN WMNewTab: 20 +[16:54.47.020] END WMNewTab: 20 +[16:54.47.020] BEGIN WMNewTab: 20 +[16:54.47.020] END WMNewTab: 20 +[16:54.47.020] BEGIN WMNewTab: 20 +[16:54.47.020] END WMNewTab: 20 +[16:54.47.141] BEGIN WMNewTab: 20 +[16:54.47.141] END WMNewTab: 20 +[16:54.47.413] BEGIN WMNewTab: 20 +[16:54.47.413] END WMNewTab: 20 + +[16:54.48.250] BEGIN WMNewTab: 20 +[16:54.48.250] END WMNewTab: 20 +[16:54.48.385] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.48.389] BEGIN WMNewTab: 20 +[16:54.48.389] END WMNewTab: 20 +[16:54.48.390] BEGIN WMNewTab: 20 +[16:54.48.390] END WMNewTab: 20 +[16:54.48.434] BEGIN WMNewTab: 20 +[16:54.48.434] END WMNewTab: 20 +[16:54.48.434] BEGIN WMNewTab: 20 +[16:54.48.434] END WMNewTab: 20 +[16:54.48.434] BEGIN WMNewTab: 20 +[16:54.48.434] END WMNewTab: 20 +[16:54.48.556] BEGIN WMNewTab: 20 +[16:54.48.556] END WMNewTab: 20 +[16:54.48.829] BEGIN WMNewTab: 20 +[16:54.48.829] END WMNewTab: 20 + +[16:54.49.672] BEGIN WMNewTab: 20 +[16:54.49.672] END WMNewTab: 20 +[16:54.49.804] BEGIN WMNewTab: 20 +[16:54.49.804] END WMNewTab: 20 +[16:54.49.804] BEGIN WMNewTab: 20 +[16:54.49.804] END WMNewTab: 20 +[16:54.49.850] BEGIN WMNewTab: 20 +[16:54.49.850] END WMNewTab: 20 +[16:54.49.850] BEGIN WMNewTab: 20 +[16:54.49.850] END WMNewTab: 20 +[16:54.49.850] BEGIN WMNewTab: 20 +[16:54.49.850] END WMNewTab: 20 +[16:54.49.941] (SSH-Browser) TDownUpForm.JvTimer1Timer +[16:54.49.991] BEGIN WMNewTab: 20 +[16:54.49.991] END WMNewTab: 20 +[16:54.50.259] BEGIN WMNewTab: 20 +[16:54.50.259] END WMNewTab: 20 + +[16:54.50.947] sListView1Click: FormClick +[16:54.51.053] (SSH-Browser) BEGIN OpenDir(6) +[16:54.51.053] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.51.053] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.51.053] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.51.053] (SSH-Browser) OpenDir(6): 列出远程文件夹 +[16:54.51.054] (SSH-Browser) OpenDir(6): SFTP.RequestAbsolutePath(/root/../); +[16:54.51.055] (SSH-Browser) END OpenDir(6) +[16:54.51.058] BEGIN WMNewTab: 20 +[16:54.51.058] END WMNewTab: 20 +[16:54.51.064] (SSH-Browser) ElSFTP1AbsolutePath(6) +[16:54.51.064] (SSH-Browser) ElSFTP1AbsolutePath(6): SFTP.OpenDirectory(/) +[16:54.51.085] BEGIN WMNewTab: 20 +[16:54.51.085] END WMNewTab: 20 +[16:54.51.094] (SSH-Browser) ElSFTP1OpenFile(6) +[16:54.51.094] (SSH-Browser) ElSFTP1OpenFile(6): SFTP.ReadDirectory +[16:54.51.154] (SSH-Browser) ElSFTP1Error(6): #1 - End of file +[16:54.51.154] (SSH-Browser) ElSFTP1Error(6): CloseCurrentHandle1 +[16:54.51.154] (SSH-Browser) BEGIN CloseCurrentHandle(6) +[16:54.51.154] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.51.154] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.51.154] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.51.154] (SSH-Browser) CloseCurrentHandle(6): SFTP.CloseHandle +[16:54.51.154] (SSH-Browser) END CloseCurrentHandle(6) +[16:54.51.154] (SSH-Browser) BEGIN CopySFTPFileListToListView(6) +[16:54.51.154] (SSH-Browser) CopySFTPFileListToListView(6): FileList.Count=28 +[16:54.51.154] (SSH-Browser) 对项目进行排序 +[16:54.51.154] (SSH-Browser) CopySFTPFileListToListView(6): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:54.51.165] (SSH-Browser) END CopySFTPFileListToListView(6) +[16:54.51.200] (SSH-Browser) ElSFTP1Success(6) +[16:54.51.215] BEGIN WMNewTab: 20 +[16:54.51.215] END WMNewTab: 20 +[16:54.51.262] BEGIN WMNewTab: 20 +[16:54.51.262] END WMNewTab: 20 +[16:54.51.262] BEGIN WMNewTab: 20 +[16:54.51.262] END WMNewTab: 20 +[16:54.51.263] BEGIN WMNewTab: 20 +[16:54.51.263] END WMNewTab: 20 +[16:54.51.427] BEGIN WMNewTab: 20 +[16:54.51.427] END WMNewTab: 20 +[16:54.51.704] BEGIN WMNewTab: 20 +[16:54.51.704] END WMNewTab: 20 +[16:54.51.770] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.52.500] BEGIN WMNewTab: 20 +[16:54.52.500] END WMNewTab: 20 +[16:54.52.633] BEGIN WMNewTab: 20 +[16:54.52.633] END WMNewTab: 20 +[16:54.52.633] BEGIN WMNewTab: 20 +[16:54.52.633] END WMNewTab: 20 +[16:54.52.682] BEGIN WMNewTab: 20 +[16:54.52.682] END WMNewTab: 20 +[16:54.52.682] BEGIN WMNewTab: 20 +[16:54.52.682] END WMNewTab: 20 +[16:54.52.682] BEGIN WMNewTab: 20 +[16:54.52.682] END WMNewTab: 20 +[16:54.52.841] BEGIN WMNewTab: 20 +[16:54.52.841] END WMNewTab: 20 +[16:54.52.853] sListView1Click: FormClick +[16:54.52.958] (SSH-Browser) BEGIN OpenDir(6) +[16:54.52.958] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.52.958] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.52.958] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.52.958] (SSH-Browser) OpenDir(6): 列出远程文件夹 +[16:54.52.959] (SSH-Browser) OpenDir(6): SFTP.RequestAbsolutePath(/userdata/); +[16:54.52.960] (SSH-Browser) END OpenDir(6) +[16:54.52.984] (SSH-Browser) ElSFTP1AbsolutePath(6) +[16:54.52.984] (SSH-Browser) ElSFTP1AbsolutePath(6): SFTP.OpenDirectory(/userdata) +[16:54.53.007] (SSH-Browser) ElSFTP1OpenFile(6) +[16:54.53.007] (SSH-Browser) ElSFTP1OpenFile(6): SFTP.ReadDirectory +[16:54.53.069] (SSH-Browser) ElSFTP1Error(6): #1 - End of file +[16:54.53.069] (SSH-Browser) ElSFTP1Error(6): CloseCurrentHandle1 +[16:54.53.069] (SSH-Browser) BEGIN CloseCurrentHandle(6) +[16:54.53.069] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.53.069] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.53.069] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.53.069] (SSH-Browser) CloseCurrentHandle(6): SFTP.CloseHandle +[16:54.53.069] (SSH-Browser) END CloseCurrentHandle(6) +[16:54.53.069] (SSH-Browser) BEGIN CopySFTPFileListToListView(6) +[16:54.53.069] (SSH-Browser) CopySFTPFileListToListView(6): FileList.Count=3 +[16:54.53.069] (SSH-Browser) 对项目进行排序 +[16:54.53.069] (SSH-Browser) CopySFTPFileListToListView(6): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:54.53.078] (SSH-Browser) END CopySFTPFileListToListView(6) +[16:54.53.100] (SSH-Browser) ElSFTP1Success(6) +[16:54.53.114] BEGIN WMNewTab: 20 +[16:54.53.114] END WMNewTab: 20 +[16:54.53.161] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.53.589] sListView1Click: FormClick +[16:54.53.662] (SSH-Browser) BEGIN OpenDir(6) +[16:54.53.662] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.53.662] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.53.662] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.53.662] (SSH-Browser) OpenDir(6): 列出远程文件夹 +[16:54.53.663] (SSH-Browser) OpenDir(6): SFTP.RequestAbsolutePath(/userdata/dev_ws/); +[16:54.53.663] (SSH-Browser) END OpenDir(6) +[16:54.53.685] (SSH-Browser) ElSFTP1AbsolutePath(6) +[16:54.53.685] (SSH-Browser) ElSFTP1AbsolutePath(6): SFTP.OpenDirectory(/userdata/dev_ws) +[16:54.53.712] (SSH-Browser) ElSFTP1OpenFile(6) +[16:54.53.712] (SSH-Browser) ElSFTP1OpenFile(6): SFTP.ReadDirectory +[16:54.53.774] (SSH-Browser) ElSFTP1Error(6): #1 - End of file +[16:54.53.774] (SSH-Browser) ElSFTP1Error(6): CloseCurrentHandle1 +[16:54.53.774] (SSH-Browser) BEGIN CloseCurrentHandle(6) +[16:54.53.774] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.53.774] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.53.774] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.53.774] (SSH-Browser) CloseCurrentHandle(6): SFTP.CloseHandle +[16:54.53.774] (SSH-Browser) END CloseCurrentHandle(6) +[16:54.53.774] (SSH-Browser) BEGIN CopySFTPFileListToListView(6) +[16:54.53.774] (SSH-Browser) CopySFTPFileListToListView(6): FileList.Count=8 +[16:54.53.774] (SSH-Browser) 对项目进行排序 +[16:54.53.774] (SSH-Browser) CopySFTPFileListToListView(6): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:54.53.784] (SSH-Browser) END CopySFTPFileListToListView(6) +[16:54.53.804] (SSH-Browser) ElSFTP1Success(6) +[16:54.53.910] BEGIN WMNewTab: 20 +[16:54.53.910] END WMNewTab: 20 +[16:54.54.048] BEGIN WMNewTab: 20 +[16:54.54.048] END WMNewTab: 20 +[16:54.54.094] BEGIN WMNewTab: 20 +[16:54.54.094] END WMNewTab: 20 +[16:54.54.094] BEGIN WMNewTab: 20 +[16:54.54.094] END WMNewTab: 20 +[16:54.54.094] BEGIN WMNewTab: 20 +[16:54.54.094] END WMNewTab: 20 +[16:54.54.244] sListView1Click: FormClick +[16:54.54.262] BEGIN WMNewTab: 20 +[16:54.54.262] END WMNewTab: 20 +[16:54.54.278] BEGIN WMNewTab: 20 +[16:54.54.278] END WMNewTab: 20 +[16:54.54.326] (SSH-Browser) BEGIN OpenDir(6) +[16:54.54.326] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.54.326] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.54.326] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.54.326] (SSH-Browser) OpenDir(6): 列出远程文件夹 +[16:54.54.327] (SSH-Browser) OpenDir(6): SFTP.RequestAbsolutePath(/userdata/dev_ws/src/); +[16:54.54.327] (SSH-Browser) END OpenDir(6) +[16:54.54.336] (SSH-Browser) ElSFTP1AbsolutePath(6) +[16:54.54.336] (SSH-Browser) ElSFTP1AbsolutePath(6): SFTP.OpenDirectory(/userdata/dev_ws/src) +[16:54.54.368] (SSH-Browser) ElSFTP1OpenFile(6) +[16:54.54.368] (SSH-Browser) ElSFTP1OpenFile(6): SFTP.ReadDirectory +[16:54.54.427] (SSH-Browser) ElSFTP1Error(6): #1 - End of file +[16:54.54.427] (SSH-Browser) ElSFTP1Error(6): CloseCurrentHandle1 +[16:54.54.427] (SSH-Browser) BEGIN CloseCurrentHandle(6) +[16:54.54.427] (SSH-Browser) BEGIN VerifySFTPConnection(6) +[16:54.54.427] (SSH-Browser) VerifySFTPConnection(6): result=true (Sftp 连接) +[16:54.54.427] (SSH-Browser) END VerifySFTPConnection(6) +[16:54.54.427] (SSH-Browser) CloseCurrentHandle(6): SFTP.CloseHandle +[16:54.54.427] (SSH-Browser) END CloseCurrentHandle(6) +[16:54.54.427] (SSH-Browser) BEGIN CopySFTPFileListToListView(6) +[16:54.54.427] (SSH-Browser) CopySFTPFileListToListView(6): FileList.Count=10 +[16:54.54.427] (SSH-Browser) 对项目进行排序 +[16:54.54.427] (SSH-Browser) CopySFTPFileListToListView(6): i=Indice --> 将 Remlist 复制到 sListView1 (显示项目) +[16:54.54.436] (SSH-Browser) END CopySFTPFileListToListView(6) +[16:54.54.503] (SSH-Browser) ElSFTP1Success(6) +[16:54.54.536] BEGIN WMNewTab: 20 +[16:54.54.536] END WMNewTab: 20 +[16:54.54.763] (SSH-Browser) TDownUpForm.JvTimer1Timer + +[16:54.55.333] BEGIN WMNewTab: 20 +[16:54.55.333] END WMNewTab: 20 +[16:54.55.462] BEGIN WMNewTab: 20 +[16:54.55.462] END WMNewTab: 20 +[16:54.55.527] BEGIN WMNewTab: 20 +[16:54.55.527] END WMNewTab: 20 +[16:54.55.527] BEGIN WMNewTab: 20 +[16:54.55.527] END WMNewTab: 20 +[16:54.55.527] BEGIN WMNewTab: 20 +[16:54.55.527] END WMNewTab: 20 +[16:54.55.675] BEGIN WMNewTab: 20 + + +[9:45:31] 收到主机密钥存储请求: ssh-ed25519@22:192.168.127.10|0x375d1796bb113c10bdb35b32081ed46dd897e3df77dc0681dde7b6db9a7ffb6d,0x649881426de5a5e61932ab6e824b2fd0eda5c410fe89f72029cd4e68ee9cf62 + + + + + + + + + + + + + + + + + +--------------------------------------------------------------------+ + | Windows 事件查看器: "应用程序" | + +--------------------------------------------------------------------+ + + + + + + + + +Info | 2025-10-30 07:06:33 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:06:33 | BrYNSvc | | Bad service request +Info | 2025-10-30 07:05:49 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:05:49 | BrYNSvc | | Bad service request +Info | 2025-10-30 07:05:19 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:05:19 | BrYNSvc | | Bad service request +Info | 2025-10-30 07:04:33 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:04:33 | BrYNSvc | | Bad service request +Info | 2025-10-30 07:03:19 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:03:19 | BrYNSvc | | Bad service request +Info | 2025-10-30 07:02:33 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:02:33 | BrYNSvc | | Bad service request +Info | 2025-10-30 07:02:18 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:02:18 | BrYNSvc | | Bad service request +Info | 2025-10-30 07:01:49 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:01:49 | BrYNSvc | | Bad service request +Info | 2025-10-30 07:01:19 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 07:01:19 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:55:47 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:55:47 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:54:33 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:54:33 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:54:18 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:54:18 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:52:33 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:52:33 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:52:18 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:52:18 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:51:19 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:51:19 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:48:48 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:48:48 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:48:18 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:48:18 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:46:33 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:46:33 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:45:19 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:45:19 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:45:03 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:45:03 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:44:33 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:44:33 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:41:46 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:41:46 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:41:16 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:41:16 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:40:46 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:40:46 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:40:18 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:40:18 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:39:49 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:39:49 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:39:19 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:39:19 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:39:03 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:39:03 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:38:33 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:38:33 | BrYNSvc | | Bad service request +Info | 2025-10-30 06:37:49 | SenaryAudioAppService | | 该服务已成功处理 PowerEvent。 +Info | 2025-10-30 06:37:49 | BrYNSvc | | Bad service request + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------------------------------------------------------+ + | Windows 事件查看器: "系统" | + +--------------------------------------------------------------------+ + + + + + + + + +Info | 2025-10-30 06:13:37 | Microsoft-Windows-Kernel-General | | 2025-10-30T06:13:37.2474215Z | 2025-10-30T06:13:37.2467829Z | 0 | 1 | \Device\HarddiskVolume3\Windows\System32\svchost.exe | 39476 | 2025-10-30T14:13:37.2474215Z | -480 | false | false +Info | 2025-10-30 06:13:37 | Microsoft-Windows-Kernel-General | | 0 | -480 | 0 | 0 | 0 +Info | 2025-10-30 06:13:37 | Microsoft-Windows-Kernel-General | | 2025-10-30T06:13:37.2462640Z | 2025-10-30T06:13:37.2455929Z | 0 | 1 | \Device\HarddiskVolume3\Windows\System32\svchost.exe | 39476 | 2025-10-30T14:13:37.2462640Z | -480 | false | false +Info | 2025-10-30 06:13:37 | Microsoft-Windows-Kernel-General | | 0 | -480 | 0 | 0 | 0 +Info | 2025-10-30 06:13:37 | Microsoft-Windows-Kernel-General | | 2025-10-30T06:13:37.2445141Z | 2025-10-30T06:13:39.2820111Z | -2037 | 1 | \Device\HarddiskVolume3\Windows\System32\svchost.exe | 39476 | 2025-10-30T14:13:37.2445141Z | -480 | false | false +Info | 2025-10-30 06:13:37 | Microsoft-Windows-Kernel-General | | 0 | -480 | 0 | 0 | 0 +Info | 2025-10-30 06:13:23 | Microsoft-Windows-Time-Service | | time.windows.com,0x9 (ntp.m|0x9|0.0.0.0:123->20.189.79.72:123) +Info | 2025-10-30 06:10:21 | Microsoft-Windows-WindowsUpdateClient | | 9PCFS5B6T72H-Microsoft.Paint | {9546ad9e-8740-4172-9a7f-8bf8c6c05c75} | 1 | {855e8a7c-ecb4-4ca3-b045-1dfa50104289} +Error | 2025-10-30 06:10:20 | Microsoft-Windows-WindowsUpdateClient | | 0x80073d02 | 9WZDNCRD29V9-MICROSOFT.MICROSOFTOFFICEHUB | {9ea649a4-20e3-475f-8e78-479ff5d25eb4} | 1 | {855e8a7c-ecb4-4ca3-b045-1dfa50104289} +Info | 2025-10-30 06:10:20 | Microsoft-Windows-Kernel-General | | 93 | \??\C:\Users\31554\AppData\Local\Packages\Microsoft.Paint_8wekyb3d8bbwe\Settings\settings.dat | 1 | 1 +Info | 2025-10-30 06:10:19 | Microsoft-Windows-WindowsUpdateClient | | 9WZDNCRD29V9-MICROSOFT.MICROSOFTOFFICEHUB | {9ea649a4-20e3-475f-8e78-479ff5d25eb4} | 1 +Info | 2025-10-30 06:10:19 | Microsoft-Windows-WindowsUpdateClient | | 9PCFS5B6T72H-Microsoft.Paint | {9546ad9e-8740-4172-9a7f-8bf8c6c05c75} | 1 +Info | 2025-10-30 06:09:59 | Microsoft-Windows-Kernel-General | | 143 | \??\C:\ProgramData\Microsoft\Windows\AppRepository\Packages\Microsoft.MicrosoftOfficeHub_19.2510.59081.0_x64__8wekyb3d8bbwe\ActivationStore.dat | 0 | 0 +Info | 2025-10-30 06:09:57 | Microsoft-Windows-Kernel-General | | 128 | \??\C:\ProgramData\Microsoft\Windows\AppRepository\Packages\Microsoft.Paint_11.2509.441.0_x64__8wekyb3d8bbwe\ActivationStore.dat | 0 | 0 +Error | 2025-10-30 06:09:51 | Microsoft-Windows-WindowsUpdateClient | | 0x80073d02 | 9NBLGGH4NNS1-Microsoft.DesktopAppInstaller | {da6142af-32f4-4b7b-9e7c-d303be69441f} | 1 | {855e8a7c-ecb4-4ca3-b045-1dfa50104289} +Info | 2025-10-30 06:09:51 | Microsoft-Windows-WindowsUpdateClient | | 9NBLGGH4NNS1-Microsoft.DesktopAppInstaller | {da6142af-32f4-4b7b-9e7c-d303be69441f} | 1 +Info | 2025-10-30 06:09:48 | Microsoft-Windows-WindowsUpdateClient | | 9WZDNCRD29V9-MICROSOFT.MICROSOFTOFFICEHUB | {9ea649a4-20e3-475f-8e78-479ff5d25eb4} | 1 +Info | 2025-10-30 06:09:48 | Microsoft-Windows-WindowsUpdateClient | | 9PCFS5B6T72H-Microsoft.Paint | {9546ad9e-8740-4172-9a7f-8bf8c6c05c75} | 1 +Info | 2025-10-30 06:09:48 | Microsoft-Windows-WindowsUpdateClient | | 9NBLGGH4NNS1-Microsoft.DesktopAppInstaller | {da6142af-32f4-4b7b-9e7c-d303be69441f} | 1 +Info | 2025-10-30 06:09:01 | Microsoft-Windows-Kernel-General | | 35 | \SystemRoot\System32\config\DRIVERS | 48034 | 2349 +Info | 2025-10-30 05:24:21 | Service Control Manager | | Background Intelligent Transfer Service | 自动启动 | 按需启动 | BITS +Info | 2025-10-30 05:22:30 | Microsoft-Windows-Kernel-General | | 100 | \??\C:\Users\31554\AppData\Local\Packages\Microsoft.WindowsStore_8wekyb3d8bbwe\Settings\settings.dat | 17 | 4 +Info | 2025-10-30 05:06:46 | Service Control Manager | | Background Intelligent Transfer Service | 按需启动 | 自动启动 | BITS +Info | 2025-10-30 04:16:05 | Service Control Manager | | Background Intelligent Transfer Service | 自动启动 | 按需启动 | BITS +Info | 2025-10-30 04:14:00 | Service Control Manager | | Background Intelligent Transfer Service | 按需启动 | 自动启动 | BITS +Info | 2025-10-30 04:00:00 | EventLog | | ? | ? | ? | ? | 417737 | 60 | -480 中国标准时间 +Info | 2025-10-30 03:44:13 | Microsoft-Windows-WindowsUpdateClient | | Microsoft Defender Antivirus 的安全智能更新 - KB2267602(版本 1.439.556.0)- 当前频道(广泛) | {03b7319b-371b-4274-b0c8-832d5784f19c} | 200 | {9482f4b4-e343-43b6-b170-9a65bc822c77} +Info | 2025-10-30 03:44:04 | Microsoft-Windows-WindowsUpdateClient | | Microsoft Defender Antivirus 的安全智能更新 - KB2267602(版本 1.439.556.0)- 当前频道(广泛) | {03b7319b-371b-4274-b0c8-832d5784f19c} | 200 +Info | 2025-10-30 03:44:03 | Microsoft-Windows-WindowsUpdateClient | | Microsoft Defender Antivirus 的安全智能更新 - KB2267602(版本 1.439.556.0)- 当前频道(广泛) | {03b7319b-371b-4274-b0c8-832d5784f19c} | 200 +Info | 2025-10-30 03:39:47 | Service Control Manager | | Background Intelligent Transfer Service | 自动启动 | 按需启动 | BITS +Info | 2025-10-30 03:36:52 | Service Control Manager | | Background Intelligent Transfer Service | 按需启动 | 自动启动 | BITS +Info | 2025-10-30 03:32:01 | Microsoft-Windows-Kernel-General | | 115 | \??\C:\Users\31554\AppData\Local\Packages\Microsoft.Windows.ShellExperienceHost_cw5n1h2txyewy\Settings\settings.dat | 2 | 1 +Info | 2025-10-30 03:26:45 | Service Control Manager | | Background Intelligent Transfer Service | 自动启动 | 按需启动 | BITS +Info | 2025-10-30 03:25:51 | Microsoft-Windows-Kernel-General | | 164 | \??\C:\ProgramData\Packages\3AD8A913.49937325EFC59_j4r74wbqry4cc\S-1-5-21-766103436-3213567576-2828573686-1001\SystemAppData\Helium\Cache\f9b8dc9c2e8be963_COM15.dat | 1 | 1 +Info | 2025-10-30 03:25:51 | Microsoft-Windows-Kernel-General | | 115 | \??\C:\Users\31554\AppData\Local\Packages\3AD8A913.49937325EFC59_j4r74wbqry4cc\SystemAppData\Helium\UserClasses.dat | 1 | 1 +Info | 2025-10-30 03:25:51 | Microsoft-Windows-Kernel-General | | 108 | \??\C:\Users\31554\AppData\Local\Packages\3AD8A913.49937325EFC59_j4r74wbqry4cc\SystemAppData\Helium\User.dat | 1 | 1 +Info | 2025-10-30 03:25:51 | Microsoft-Windows-Kernel-General | | 100 | \??\C:\Users\31554\AppData\Local\Packages\3AD8A913.49937325EFC59_j4r74wbqry4cc\Settings\settings.dat | 2 | 1 +Info | 2025-10-30 03:24:40 | Service Control Manager | | Background Intelligent Transfer Service | 按需启动 | 自动启动 | BITS +Info | 2025-10-30 02:46:03 | Service Control Manager | | Background Intelligent Transfer Service | 自动启动 | 按需启动 | BITS +Info | 2025-10-30 02:43:35 | Service Control Manager | | Background Intelligent Transfer Service | 按需启动 | 自动启动 | BITS +Warning | 2025-10-30 02:42:50 | DCOM | | 应用程序-特定 | 本地 | 激活 | {2593F8B9-4EAF-457C-B68A-50F6B8EA6B54} | {15C20B67-12E7-4BB6-92BB-7AFF07997402} | Huang | 31554 | S-1-5-21-766103436-3213567576-2828573686-1001 | LocalHost (使用 LRPC) | 不可用 | 不可用 +Info | 2025-10-30 02:42:34 | Microsoft-Windows-IsolatedUserMode | | 0 | 0 | 0 | NULL +Info | 2025-10-30 02:42:34 | Microsoft-Windows-IsolatedUserMode | | 0 | 0 | 0 +Info | 2025-10-30 02:26:50 | Service Control Manager | | Background Intelligent Transfer Service | 自动启动 | 按需启动 | BITS +Info | 2025-10-30 02:24:45 | Microsoft-Windows-Kernel-General | | 118 | \??\C:\Users\31554\AppData\Local\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\Settings\settings.dat | 328 | 28 +Info | 2025-10-30 02:16:43 | Service Control Manager | | Background Intelligent Transfer Service | 按需启动 | 自动启动 | BITS +Info | 2025-10-30 01:48:13 | Service Control Manager | | Background Intelligent Transfer Service | 自动启动 | 按需启动 | BITS +Info | 2025-10-30 01:44:45 | Service Control Manager | | Background Intelligent Transfer Service | 按需启动 | 自动启动 | BITS +Info | 2025-10-30 01:42:31 | Service Control Manager | | Background Intelligent Transfer Service | 自动启动 | 按需启动 | BITS +Info | 2025-10-30 01:40:20 | Microsoft-Windows-Kernel-General | | 104 | \??\C:\Users\31554\AppData\Local\Packages\Microsoft.AAD.BrokerPlugin_cw5n1h2txyewy\Settings\settings.dat | 5 | 1 +Info | 2025-10-30 01:40:20 | Service Control Manager | | Background Intelligent Transfer Service | 按需启动 | 自动启动 | BITS +Info | 2025-10-30 01:40:19 | Microsoft-Windows-Kernel-Power | | 19 | 15 | 170 | 2 | 23888725582 | 59721 | 59721 | 59721 | 59721 | 171 | 0 | true | 15 +Info | 2025-10-30 01:40:19 | Microsoft-Windows-Kernel-Power | | 0 | 3879549851 | 216183926203 | 76887600 | 20011392211 | 23890942062 | 312 | 82 | false | 15 | 0 | 1226425935 | true | 19856979226 | 476577 | false | true | 542693323 | 7 | 4 | true | false | 171 | false | 59721 | 59721 | 169 | 19 | 1 | 18446743858769919868 | 20011392211 | 19856979226 | 0 | 0 | 133135 | true | 59721 | 59721 | 2219982 | 59721 | 59721 | 23888725582 | 59721 | 59721 | 59721 | 59721 | 4 | 1 | 0 | 0 | 20011392211 | 19856979226 +Info | 2025-10-30 01:40:19 | Microsoft-Windows-Time-Service | | time.windows.com,0x9 (ntp.m|0x9|0.0.0.0:123->20.189.79.72:123) +Warning | 2025-10-30 01:40:18 | Win32k | | ? +Warning | 2025-10-30 01:40:18 | Win32k | | ? +Error | 2025-10-29 19:38:33 | DCOM | | {FD06603A-2BDF-4BB1-B7DF-5DC68F353601} +Error | 2025-10-29 19:29:33 | DCOM | | {FD06603A-2BDF-4BB1-B7DF-5DC68F353601} +Error | 2025-10-29 19:17:33 | DCOM | | {FD06603A-2BDF-4BB1-B7DF-5DC68F353601} +Error | 2025-10-29 19:05:54 | DCOM | | {FD06603A-2BDF-4BB1-B7DF-5DC68F353601} + + + + + + + + + + + + + + + + + +[15:06.38.979] !!!! EXCEPTION Exception: 重命名为 失败 diff --git a/MobaXterm_25.2_CN/MobaXterm_25.2_CN.exe b/MobaXterm_25.2_CN/MobaXterm_25.2_CN.exe new file mode 100644 index 0000000..1625b88 Binary files /dev/null and b/MobaXterm_25.2_CN/MobaXterm_25.2_CN.exe differ diff --git a/MobaXterm_25.2_CN/MobaXterm_backup.zip b/MobaXterm_25.2_CN/MobaXterm_backup.zip new file mode 100644 index 0000000..1ff3e20 Binary files /dev/null and b/MobaXterm_25.2_CN/MobaXterm_backup.zip differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..42806dc --- /dev/null +++ b/README.md @@ -0,0 +1,884 @@ +# RDK X5 + Gemini 2 + 鏈烘鑷傛姄鍙栧伐绋嬭鏄� + +- 浣跨敤 **RDK X5 + ROS 2 Humble** +- 浣跨敤 **Orbbec Gemini 2** 娣卞害鐩告満 +- 浣跨敤涓�濂� **鏅�� USB 鐩告満 + 娣卞害鐩告満 + 搴曠洏 + 鏈烘鑷�** 鐨勬瘮璧�/婕旂ず绯荤粺 +- 闇�瑕佸仛 **妗岄潰骞抽潰鎶撳彇鏍囧畾**銆�**娣卞害鐐规姄鍙�**銆�**鏁磋溅浠诲姟鑱斿姩** + +--- + +## 1. 宸ョ▼鏁翠綋缁撴瀯 + +### 1.1 鐩綍璇存槑 + +```bash +鈹溾攢鈹� arm_plane_calib/ +鈹� 鈹溾攢鈹� biaodi.png # 鏍囧畾鐐圭ず鎰忓浘/鍙傝�冨浘 +鈹� 鈹溾攢鈹� collect_plane_calib.py # 骞抽潰閲囨牱鑴氭湰 +鈹� 鈹溾攢鈹� fit_plane_calib.py # 鎷熷悎鑴氭湰 +鈹� 鈹溾攢鈹� predict_plane_cmd.py # 鐐瑰嚮鍍忕礌棰勬祴鑸垫満鍛戒护鑴氭湰锛堝彧棰勬祴銆佷笉鐩存帴鍙戜覆鍙o級 +鈹� 鈹溾攢鈹� depth_click_to_learm_cmd_node.py # 鐐瑰嚮鍍忕礌鍚庣洿鎺ラ娴嬪苟涓嬪彂涓插彛鍛戒护 +鈹� 鈹溾攢鈹� model.yaml # 鎷熷悎寰楀埌鐨勬ā鍨嬪弬鏁� +鈹� 鈹溾攢鈹� samples.yaml # 閲囨牱寰楀埌鐨勬牱鏈暟鎹� +鈹� 鈹斺攢鈹� readme.md # 鍘熷璇存槑 +鈹� +鈹斺攢鈹� dev_ws/ + 鈹溾攢鈹� README_RDK_X5.md # 鍘熷璇存槑 + 鈹溾攢鈹� scripts/ + 鈹� 鈹斺攢鈹� setup_orbbec_udev.sh # 瀹夎 Orbbec udev 瑙勫垯 + 鈹斺攢鈹� src/ + 鈹溾攢鈹� depth_target_detector # 娣卞害鐩爣妫�娴� + 鈹溾攢鈹� lerobot_arm_controller # 鏈烘鑷傛帶鍒� + 鈹溾攢鈹� mission_manager # 浠诲姟鐘舵�佹満 + 鈹溾攢鈹� orbbec_camera # Gemini 2 椹卞姩 + 鈹溾攢鈹� orbbec_camera_msgs # Orbbec 娑堟伅瀹氫箟 + 鈹溾攢鈹� origintank_base # 搴曠洏椹卞姩 + 鈹溾攢鈹� origintank_bringup # 鎬诲惎鍔ㄥ叆鍙� + 鈹斺攢鈹� signal_board_detector # 鏅�氱浉鏈鸿瘑鍒俊鍙风墝 +``` + +### 1.2 鍔熻兘鍒嗗眰 + +鏁村宸ョ▼鍙互鍒嗘垚涓ゅぇ閮ㄥ垎锛� + +1. **鏁磋溅/鏁寸郴缁熻繍琛岄儴鍒�**锛氫綅浜� `dev_ws` + - 搴曠洏杩愬姩 + - 鏅�� USB 鐩告満璇嗗埆淇″彿鐗� + - Gemini 2 娣卞害鐐规娴� + - 鏈烘鑷備覆鍙f姄鍙栨帶鍒� + - mission_manager 缁熶竴璋冨害 + +2. **妗岄潰鎶撳彇骞抽潰鏍囧畾閮ㄥ垎**锛氫綅浜� `arm_plane_calib` + - 榧犳爣鐐瑰嚮鍥惧儚涓殑妗岄潰鐐� + - 鍒╃敤娣卞害鍥惧拰鐩告満鍐呭弬鍙嶇畻 `x_cam/y_cam/z_cam` + - 鎵嬪姩璁板綍璇ョ偣瀵瑰簲鐨勬満姊拌噦鍛戒护鍚戦噺 + - 鐢ㄤ簩娆″椤瑰紡寤虹珛鈥滅浉鏈哄钩闈㈢偣 -> 鑸垫満鍛戒护鈥濈殑鏄犲皠 + - 杩愯鏃剁偣鍑讳换鎰忕洰鏍囩偣锛屽嵆鍙娴嬫満姊拌噦鑸垫満鍛戒护 + +--- + +## 2. ROS 2 鍔熻兘鍖� + +### 2.1 `origintank_base` + +搴曠洏椹卞姩鍖咃紝璐熻矗搴曠洏鎺у埗鍜屽熀纭�浼犳劅鍣ㄦ暟鎹彂甯冿細 + +- `/odom` +- `/imu` +- `/ultrasonic/front/range` + +### 2.2 `origintank_bringup` + +鎬诲惎鍔ㄥ叆鍙o紝璐熻矗鎶婂簳鐩樸�佹櫘閫� USB 鐩告満銆丱rbbec 鐩告満銆佹繁搴︽娴嬨�佹満姊拌噦鎺у埗鍜屼换鍔$姸鎬佹満涓茶捣鏉ャ�� + +### 2.3 `signal_board_detector` + +鏅�� USB 鐩告満璇嗗埆淇″彿鐗岋紝杈撳叆閫氬父涓猴細 + +- `/image` + +杈撳嚭璇嗗埆缁撴灉缁欎换鍔$姸鎬佹満銆� + +### 2.4 `depth_target_detector` + +鍩轰簬娣卞害鍥炬彁鍙栨渶杩戠洰鏍囷紝鍙戝竷锛� + +- `/depth_target/point` +- `/depth_target/point3d` +- `/depth_target/debug_image` + +鍏朵腑锛� + +- `/depth_target/point` 琛ㄧず鐩爣璺濈鍜屽綊涓�鍖栧亸绉� +- `/depth_target/point3d` 琛ㄧず鐩爣鍦ㄧ浉鏈哄潗鏍囩郴涓嬬殑涓夌淮鐐� `(x_cam, y_cam, z_cam)` + +### 2.5 `lerobot_arm_controller` + +鏈烘鑷備覆鍙f帶鍒朵笌鎶撳彇娴佺▼鎵ц鑺傜偣銆� + +涓昏璁㈤槄锛� + +- `/arm_command` +- `/depth_target/point3d` + +涓昏鍙戝竷锛� + +- `/arm/status` +- `/arm/debug_target` + +### 2.6 `mission_manager` + +浠诲姟鐘舵�佹満锛岀粺涓�璋冨害搴曠洏銆佽瘑鍒�佹姄鍙栫瓑娴佺▼銆� + +榛樿閰嶇疆涓� `autostart: false`锛屽洜姝や竴鑸渶瑕佹墜鍔ㄥ彂閫佸惎鍔ㄥ懡浠ゃ�� + +### 2.7 `orbbec_camera` 涓� `orbbec_camera_msgs` + +浠� Orbbec SDK ROS2 宸ョ▼涓鍓嚭鏉ョ殑 Gemini 2 椹卞姩涓庢秷鎭畾涔夛紝涓嶅啀渚濊禆绯荤粺棰濆瀹夎鐨� `ros-humble-orbbec-camera`銆� +- `gemini2.launch.py` +- Gemini 2 閰嶇疆鏂囦欢 +- 蹇呰 SDK 婧愮爜 +- 娑堟伅涓庢湇鍔″畾涔� +- udev 瑙勫垯 `99-obsensor-libusb.rules` + +--- + +## 3. 纭欢涓庢帶鍒堕摼璺� + +### 3.1 褰撳墠鏈哄櫒宸茬‘璁ょ殑璁惧鏄犲皠 + +鎸変綘鐜板満鎻愪緵鐨勬灇涓剧粨鏋滐細 + +- `lsusb` + - Orbbec Gemini 2锛歚2bc5:0670` + - 鏅�� USB 鎽勫儚澶达細`0c45:6341` + - 涓や釜 CH340 涓插彛锛歚1a86:7523` +- `ls /dev/ttyUSB*` + - `/dev/ttyUSB0` + - `/dev/ttyUSB1` + +缁撳悎浣犵殑瀹為檯鎺ョ嚎锛屽綋鍓嶈澶囨槧灏勫缓璁浐瀹氬啓鎴愶細 + +| 璁惧 | 褰撳墠鎺ュ彛 | +|---|---| +| 搴曠洏鎺у埗鏉� | `/dev/ttyUSB0` | +| 鏈烘鑷傛帶鍒舵澘 | `/dev/ttyUSB1` | +| 鏅�� USB 鐩告満 | `/dev/video0` | +| 娣卞害鐩告満 | `/dev/video1` | + +鍏朵腑锛� + +- 鏈烘鑷傞粯璁ゆ尝鐗圭巼锛�**9600** +- 搴曠洏涓插彛浠嶆寜搴曠洏椹卞姩閰嶇疆澶勭悊锛堝綋鍓� launch 榛樿 `B115200`锛� + +鏁翠綋閾捐矾濡備笅锛� + +- 搴曠洏杩愬姩銆佺紪鐮佸櫒銆両MU銆佽秴澹版尝 -> `origintank_base` +- 鏅�� USB 鐩告満 -> `signal_board_detector` +- Gemini 2 娣卞害鐩告満 -> `orbbec_camera` +- 娣卞害鐩爣鐐� `/depth_target/point3d` -> `lerobot_arm_controller` +- `mission_manager` 缁熶竴璋冨害搴曠洏銆佽瘑鍒拰鎶撳彇 + +--- + +## 4. 鐜涓庝緷璧� + +### 4.1 绯荤粺鐜 + +寤鸿鐜锛� + +- Ubuntu 22.04 +- ROS 2 Humble +- Python 3 + +### 4.2 Python/ROS 渚濊禆 + +浠庡綋鍓嶄唬鐮佸拰 `package.xml` 鐪嬶紝鑷冲皯娑夊強浠ヤ笅渚濊禆锛� + +- `rclpy` +- `rclcpp` +- `sensor_msgs` +- `geometry_msgs` +- `nav_msgs` +- `std_msgs` +- `tf2_ros` +- `cv_bridge` +- `python3-opencv` +- `python3-numpy` +- `python3-serial` +- `yaml` + +濡傛灉鏄崟鐙繍琛� `arm_plane_calib` 鐩綍涓嬭剼鏈紝閲嶇偣瑕佷繚璇侊細 + +- `cv_bridge` +- `opencv-python` 鎴栫郴缁� OpenCV +- `numpy` +- `PyYAML` +- `pyserial`锛堜粎 `depth_click_to_learm_cmd_node.py` 闇�瑕侊級 + +--- + +## 5. 缂栬瘧鍓嶅噯澶� + +### 5.1 瀹夎 Orbbec 鐨� udev 瑙勫垯 + +鍦� `dev_ws` 鏍圭洰褰曚笅鎵ц锛� + +```bash +cd ~/dev_ws +chmod +x scripts/setup_orbbec_udev.sh +./scripts/setup_orbbec_udev.sh +``` + +濡傛灉浣犵殑宸ヤ綔鐩綍涓嶆槸 `~/dev_ws`锛岃鍒囨崲鍒板疄闄呯殑 `dev_ws` 鏍圭洰褰曞啀鎵ц銆� + +鑴氭湰鏈川涓婁細鎶婏細 + +- `src/orbbec_camera/scripts/99-obsensor-libusb.rules` + +澶嶅埗鍒帮細 + +- `/etc/udev/rules.d/99-obsensor-libusb.rules` + +鐒跺悗鍒锋柊 udev 瑙勫垯銆� + +濡傛灉 Gemini 2 宸叉彃涓婏紝寤鸿閲嶆柊鎻掓嫈涓�娆°�� + +### 5.2 缂栬瘧宸ヤ綔绌洪棿 + +```bash +cd ~/dev_ws +source /opt/ros/humble/setup.bash +colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release +source install/setup.bash +``` + +### 5.3 鍐呭瓨涓嶈冻鏃跺鍔犱复鏃� swap + +Orbbec 鐩稿叧鍖呬綋绉緝澶э紝鍐呭瓨涓嶈冻鏃跺彲浠ヤ复鏃跺姞 8G swap锛� + +```bash +free -h +swapon --show + +fallocate -l 8G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=8192 +chmod 600 /swapfile +mkswap /swapfile +swapon /swapfile + +free -h +swapon --show +``` + +缂栬瘧瀹屾垚鍚庡彲鍏抽棴锛� + +```bash +swapoff /swapfile +rm -f /swapfile +``` + +--- + +## 6. 鏁村绯荤粺鍚姩鏂瑰紡 + +### 6.1 鍚姩鏁磋溅浠诲姟绯荤粺 + +```bash +ros2 launch origintank_bringup rdk_x5_auto_mission.launch.py \ + cmd_port:=/dev/ttyUSB0 \ + arm_port:=/dev/ttyUSB1 \ + usb_video_device:=/dev/video0 +``` + +杩欓噷闇�瑕佹妸鈥滀唬鐮侀粯璁ゅ�尖�濆拰鈥滃綋鍓嶆満鍣ㄥ疄闄呮帴绾库�濆垎寮�鐪嬶細 + +- **褰撳墠鏈哄櫒瀹為檯鎺ョ嚎/鏋氫妇**锛堟寜浣犳彁渚涚殑 `ls /dev/ttyUSB*` 涓� `lsusb`锛� + - 搴曠洏鎺у埗鍙o細**`/dev/ttyUSB0`** + - 鏈烘鑷傛帶鍒跺彛锛�**`/dev/ttyUSB1`** + - 鏅�� USB 鐩告満锛�**`/dev/video0`** + - 娣卞害鐩告満锛�**`/dev/video1`** +- **褰撳墠浠g爜榛樿鍊�** + - `rdk_x5_auto_mission.launch.py` 閲� `arm_port` 榛樿鍊艰繕鏄� **`/dev/ttyUSB2`** + - `lerobot_arm_controller/config/lerobot_arm_controller.yaml` 閲� `port` 榛樿鍊间篃鏄� **`/dev/ttyUSB2`** + + +### 6.2 榛樿浼氬惎鍔ㄥ摢浜涘唴瀹� + +榛樿鍙傛暟涓嬩細鍚姩锛� + +- 搴曠洏椹卞姩 +- 鏅�� USB 鐩告満 +- Gemini 2 +- 娣卞害鐩爣妫�娴� +- 鏈烘鑷傛帶鍒� +- 浠诲姟鐘舵�佹満 + +瀵瑰簲寮�鍏冲弬鏁帮細 + +- `use_usb_camera` +- `use_orbbec_camera` +- `use_depth_detector` +- `use_arm_controller` +- `use_hobot_usb_cam` + +濡傛灉鍙兂灞�閮ㄨ皟璇曪紝鍙互鍦� launch 鍙傛暟閲屽叧闂搴旀ā鍧椼�� + +--- + +## 7. 鍗曠嫭娴嬭瘯 Gemini 2 + +### 7.1 鍚姩 Gemini 2 + +```bash +ros2 launch origintank_bringup orbbec_gemini2.launch.py +``` + +杩欎釜 launch 鏈川涓婃槸瀵� `orbbec_camera/launch/gemini2.launch.py` 鐨勫皝瑁呫�� + +榛樿浼犻�掔殑鍏稿瀷鍙傛暟鍖呮嫭锛� + +- `camera_name:=camera` +- `enable_point_cloud:=false` +- `enable_colored_point_cloud:=false` +- `depth_registration:=true` + +### 7.2 鏌ョ湅璁惧 + +```bash +ros2 run orbbec_camera list_devices_node +``` + +### 7.3 鏌ョ湅娣卞害宸ヤ綔妯″紡 + +```bash +ros2 run orbbec_camera list_depth_work_mode_node +``` + +--- + +## 8. 浠诲姟鎺у埗涓庡叧閿瘽棰� + +### 8.1 鎵嬪姩鍚姩/鍋滄浠诲姟 + +鍚姩锛� + +```bash +ros2 topic pub --once /mission/start std_msgs/msg/Bool "{data: true}" +``` + +鍋滄锛� + +```bash +ros2 topic pub --once /mission/start std_msgs/msg/Bool "{data: false}" +``` + +### 8.2 鍏抽敭璇濋鎬昏〃 + +搴曠洏涓庡熀纭�浼犳劅鍣細 + +- `/odom` +- `/imu` +- `/ultrasonic/front/range` + +鏅�氱浉鏈轰笌璇嗗埆锛� + +- `/image_raw` +- `/signal_board/result` + +Gemini 2 娣卞害鐩稿叧锛� + +- `/camera/color/image_raw` +- `/camera/depth/image_raw` +- `/camera/depth/camera_info` +- `/depth_target/debug_image` +- `/depth_target/point` +- `/depth_target/point3d` + +鏈烘鑷傜浉鍏筹細 + +- `/arm_command` +- `/arm/status` +- `/arm/debug_target` + +浠诲姟鐘舵�佹満锛� + +- `/mission/start` +- `/mission_manager/state` + +### 8.3 鍙厛妫�鏌ョ殑璇濋 + +```bash +ros2 topic list +ros2 topic echo /camera/depth/camera_info +ros2 topic echo /depth_target/point3d +ros2 topic echo /arm/status +``` + +--- + +## 9. 闇�瑕佺幇鍦烘爣瀹�/淇敼鐨勫叧閿厤缃� + +### 9.1 娣卞害鐩爣妫�娴嬪弬鏁� + +鏂囦欢锛� + +- `src/depth_target_detector/config/depth_target_detector.yaml` + +褰撳墠涓昏鍙傛暟锛� + +- `min_depth_m: 0.10` +- `max_depth_m: 1.20` +- `roi_x_ratio: 0.25` +- `roi_y_ratio: 0.25` +- `roi_w_ratio: 0.50` +- `roi_h_ratio: 0.50` +- `nearest_band_m: 0.03` +- `min_cluster_pixels: 80` + +鍚箟琛ュ厖锛� + +- `roi_*`锛氬彧鍦ㄥ浘鍍忎腑澶煇涓尯鍩熷鎵剧洰鏍囷紝鍑忓皯杈圭紭骞叉壈 +- `nearest_band_m`锛氫互鏈�杩戞繁搴︿负鍩哄噯锛屽彇涓�涓帤搴﹀甫鍋氳繛閫氬煙鎻愬彇 +- `min_cluster_pixels`锛氳繃婊ゅお灏忕殑鍣0鍖哄煙 + +### 9.2 鏈烘鑷傛帶鍒跺弬鏁� + +鏂囦欢锛� + +- `src/lerobot_arm_controller/config/lerobot_arm_controller.yaml` + +褰撳墠閲嶇偣鍙傛暟锛� + +- 涓插彛锛歚port`銆乣baud_rate` +- 鎶撳彇鍔ㄤ綔锛歚move_time_ms`銆乣settle_sec` +- 瀹夊叏浣嶄笌 home 浣嶏細`safe_z_cm`銆乣home_x_cm`銆乣home_y_cm`銆乣home_z_cm` +- 鎶撳彇鍓�/鏈�缁堥珮搴﹀亸绉伙細`grasp_pre_z_offset_cm`銆乣grasp_final_z_offset_cm` +- 澶圭埅寮�鍚堣锛歚gripper_open_angle_deg`銆乣gripper_close_angle_deg` +- 鐩告満鍒版満姊拌噦澶栧弬锛� + - `camera_to_arm_x_m` + - `camera_to_arm_y_m` + - `camera_to_arm_z_m` +- 鎶撳彇琛ュ伩锛� + - `grasp_forward_extra_m` + - `grasp_lateral_extra_m` + - `grasp_height_extra_m` +- 骞冲彴鍜岃壊鍧楁斁缃偣锛� + - `platform_left_*` + - `platform_right_*` + - `blue_zone_*` + - `green_zone_*` + +### 9.3 mission_manager 鍙傛暟 + +鏂囦欢锛� + +- `src/mission_manager/config/mission_manager.yaml` + +褰撳墠閲嶇偣鍙傛暟锛� + +- `autostart: false` +- `approach_speed_mps` +- `slope_speed_mps` +- `lateral_speed_mps` +- `turn_speed_radps` +- `yaw_tolerance_deg` +- `ultrasonic_stop_distance_m` +- `signboard_stop_distance_m` +- `board_hold_sec` +- `alignment_tolerance` +- `max_wait_signal_board_sec` + +--- + +## 10. `arm_plane_calib` 鐨勪綔鐢ㄤ笌閫傜敤鍦烘櫙 + +杩欎釜鐩綍涓嶆槸鏁磋溅杩愯蹇呴』鐨� ROS 鍖咃紝鑰屾槸涓�缁�**鐢ㄤ簬妗岄潰骞抽潰鎶撳彇蹇�熸爣瀹氫笌楠岃瘉鐨勭嫭绔嬭剼鏈�**銆� +鍚庣画鍙牴鎹甡arm_plane_calib`鏉ュ垱寤轰竴涓彲姝e父浣跨敤鐨凴OS2鍔熻兘鍖� +--- + +## 11. `arm_plane_calib` 鍚勮剼鏈鏄� + +### 11.1 `collect_plane_calib.py` + +浣滅敤锛� + +- 璁㈤槄褰╄壊鍥俱�佹繁搴﹀浘銆佺浉鏈哄唴鍙� +- 榧犳爣鐐瑰嚮鍥惧儚涓殑鏍囧畾鐐� +- 鑷姩璁$畻鐐瑰嚮鐐圭殑鐩告満鍧愭爣 `X_cam, Y_cam, Z_cam` +- 缁堢鎵嬪姩杈撳叆璇ョ偣瀵瑰簲鐨勬満姊拌噦鍛戒护鍚戦噺 +- 鑷姩淇濆瓨鍒� `samples.yaml` + +榛樿鍙傛暟锛� + +- `color_topic: /camera/color/image_raw` +- `depth_topic: /camera/depth/image_raw` +- `camera_info_topic: /camera/depth/camera_info` +- `save_path: samples.yaml` +- `depth_scale: 0.001` +- `min_depth_m: 0.05` +- `max_depth_m: 1.50` +- `median_kernel: 5` +- `target_count: 9` + + +### 11.2 `fit_plane_calib.py` + +浣滅敤锛� + +- 璇诲彇 `samples.yaml` +- 鐢ㄤ簩娆″椤瑰紡鏈�灏忎簩涔樻嫙鍚� +- 鐢熸垚 `model.yaml` + +鐗瑰緛鍚戦噺鍥哄畾涓猴細 + +```text +[1, x, y, x虏, x*y, y虏] +``` + +杈撳嚭妯″瀷鍖呭惈锛� + +- `feature_order` +- `weights` +- `cmd_dim` +- `sample_count` +- `mae_per_dim` +- `rmse_per_dim` +- `z_ref_median` + +琛ュ厖璇存槑锛� + +- 鑴氭湰瑕佹眰鑷冲皯 **6 涓牱鏈�** 鎵嶈兘鎷熷悎 +- 瀹為檯寤鸿 **9~16 涓牱鏈�** +- `mae_per_dim` 鍜� `rmse_per_dim` 鍙互鐩存帴鐢ㄦ潵鍒ゆ柇姣忎釜鑸垫満缁村害鎷熷悎寰楀ソ涓嶅ソ +- `z_ref_median` 鏄噰鏍风偣娣卞害涓綅鏁帮紝鍙綔涓哄弬鑰冨钩闈㈤珮搴� + +### 11.3 `predict_plane_cmd.py` + +浣滅敤锛� + +- 杩愯鏃剁偣鍑诲浘鍍忎腑鐨勪换鎰忕洰鏍囩偣 +- 鑷姩鍙栨繁搴︺�佸弽绠楃浉鏈哄潗鏍� +- 鐢� `model.yaml` 棰勬祴鏈烘鑷傚懡浠ゅ悜閲� +- 鍦ㄧ粓绔墦鍗扮粨鏋� + +琛ュ厖璇存槑锛� + +- 杩欎釜鑴氭湰**鍙娴嬨�佷笉鐩存帴鍙戜覆鍙�** +- 褰撳墠浠g爜涓紝妯″瀷杈撳嚭椤哄簭鍥哄畾鎸夛細 + +```text +6, 5, 4, 3 +``` + +- 浣嗘墦鍗版椂浼氭寜浣犳洿瀹规槗璇荤殑椤哄簭杈撳嚭锛� + +```text +3, 4, 5, 6 +``` + +- 褰撳墠鍙 3/4/5/6 鍙疯埖鏈哄仛澶勭悊锛屼笖缁熶竴闄愬箙锛� + +```text +servo_min = 125 +servo_max = 875 +``` + +鎵�浠ュ鏋滀綘鐨勬満姊拌噦鑸垫満椤哄簭鎴栭檺浣嶄笉鏄繖鏍凤紝闇�瑕佸悓姝ユ敼浠g爜銆� + +### 11.4 `depth_click_to_learm_cmd_node.py` + +浣滅敤锛� + +- 鐐瑰嚮鍥惧儚涓殑鐩爣鐐� +- 鑷姩鍙栨繁搴︺�侀娴嬪懡浠ゅ悜閲� +- 鐩存帴閫氳繃涓插彛涓嬪彂鏈烘鑷傚鑸垫満杩愬姩鍛戒护 + +瀹冪浉褰撲簬鎶娾�滈娴嬧�濆拰鈥滃彂鍛戒护鈥濆悎鎴愪竴姝ワ紝閫傚悎蹇�熻仈璋冦�� + +琛ュ厖璇存槑锛� + +- **褰撳墠浠g爜榛樿涓插彛鍙傛暟**锛� + - `serial_port: /dev/ttyUSB0` + - `baud_rate: 9600` +- **褰撳墠鏈哄櫒瀹為檯寤鸿鍙傛暟**锛堟寜浣犵幇鍦烘帴绾匡級锛� + - `serial_port: /dev/ttyUSB1` + - `baud_rate: 9600` +- 榛樿杩愬姩鏃堕棿锛� + - `move_time_ms: 800` +- 榛樿 `auto_send: true`锛岀偣鍑诲悗浼�**绔嬪埢鍙戦��** +- 榛樿鑸垫満椤哄簭锛� + +```text +servo_ids = [6, 5, 4, 3] +``` + +- 榛樿鑸垫満闄愪綅锛� + +```text +servo_min = [125, 125, 125, 125] +servo_max = [875, 875, 875, 875] +``` + +- 鎸夐敭琛屼负锛� + - `q`锛氶��鍑� + - `s`锛氬涓婃缁撴灉鍐嶆鍙戦�佷竴娆� + - `c`锛氭竻闄や笂娆$偣鍑绘樉绀� + +杩欓噷杩樿鐗瑰埆琛ヤ竴涓鏄撴贩娣嗙殑鐐癸細 + +- 浠� `arm_plane_calib` 鐩綍鑴氭湰鐪嬶紝鏈烘鑷備覆鍙f帶鍒堕粯璁ゆ寜 **9600** 澶勭悊 +- 浣� `dev_ws/src/lerobot_arm_controller` 褰撳墠浠g爜鍙傛暟閲屽啓鐨勬槸 **115200** +- 浣犵幇鍦虹‘璁ょ殑鏈烘鑷傞粯璁ゆ尝鐗圭巼鏄� **9600** + +鍥犳锛屽綋鍓嶆枃妗d互浣犵殑**瀹為檯纭欢**涓哄噯锛氭満姊拌噦榛樿娉㈢壒鐜囨寜 **9600** 浣跨敤銆傝嫢缁х画浣跨敤 `lerobot_arm_controller`锛屽缓璁妸瀹冪殑 `baud_rate` 鍙傛暟鍚屾鏀规垚 9600锛岄伩鍏嶁�滄爣瀹氳剼鏈兘閫氥�佷换鍔$郴缁熶笉閫氣�濈殑鎯呭喌銆� + +--- + +## 12. 骞抽潰鏍囧畾鎺ㄨ崘娴佺▼ + +### 12.1 鍑嗗鏍囧畾鐐� + +寤鸿鍦ㄦ闈㈣创 9 涓偣锛岀粍鎴� 3x3锛� + +```text +1 2 3 +4 5 6 +7 8 9 +``` + +瑕佹眰锛� + +- 灏介噺閾烘弧鏈烘鑷傚疄闄呮姄鍙栧尯鍩� +- 鐐逛綅涓嶈澶尋 +- 灏介噺浣嶄簬鍚屼竴骞抽潰 + +### 12.2 鍚姩 Gemini 2 + +```bash +source /opt/ros/humble/setup.bash +source ~/dev_ws/install/setup.bash +ros2 launch origintank_bringup orbbec_gemini2.launch.py +``` + +### 12.3 杩愯閲囨牱鑴氭湰 + +```bash +cd ~/arm_plane_calib +python3 collect_plane_calib.py +``` + +### 12.4 閫愮偣閲囨牱 + +姣忎釜鐐规墽琛屼竴娆★細 + +1. 榧犳爣鐐瑰嚮鍥惧儚閲岀殑妗岄潰鐐� +2. 缁堢浼氭墦鍗拌鐐圭殑 `X/Y/Z` +3. 鎵嬪姩鎶婃満姊拌噦鏈绉诲姩鍒拌鐐规涓婃柟 +4. 杈撳叆璇ョ偣瀵瑰簲鐨勫懡浠ゅ悜閲� + +渚嬪杈撳叆锛� + +```text +520,610,430,500 +``` + +褰撳墠鏍蜂緥璇箟鏄細 + +```text +鎸夋ā鍨嬮『搴忥細6杞�, 5杞�, 4杞�, 3杞� +``` + +澶圭埅寮�鍚堥�氬父涓嶅弬涓庡钩闈㈡嫙鍚堬紝鎶撳彇鏃跺啀棰濆澶勭悊銆� + +### 12.5 鑷姩淇濆瓨鏍锋湰 + +鑴氭湰姣忚褰曚竴涓牱鏈兘浼氳嚜鍔ㄥ啓鍏� `samples.yaml`銆� + +閲囨弧 9 涓偣鍚庝細鑷姩閫�鍑恒�� + +### 12.6 鎵ц鎷熷悎 + +```bash +python3 fit_plane_calib.py samples.yaml model.yaml +``` + +鎴愬姛鍚庝細杈撳嚭姣忕淮鐨� MAE / RMSE銆� + +### 12.7 娴嬭瘯棰勬祴 + +```bash +python3 predict_plane_cmd.py +``` + +鐐瑰嚮鍥惧儚浠绘剰浣嶇疆锛屼細鎵撳嵃绫讳技锛� + +```text +鐐瑰嚮鍍忕礌: (694, 230) +鐩告満鍧愭爣: X=0.0267, Y=-0.0681, Z=0.3600 +棰勬祴鏈烘鑷傚懡浠ゅ悜閲�(鎸夋ā鍨嬮『搴� 6,5,4,3): 501, 874, 385, 393 +鑸垫満鍒楄〃: 3:393,4:385,5:874,6:501 +``` + +### 12.8 娴嬭瘯鈥滅偣鍑诲嵆鍙戝懡浠も�� + +```bash +python3 depth_click_to_learm_cmd_node.py +``` + +濡傛灉涓插彛銆佹尝鐗圭巼銆佽埖鏈洪『搴忛兘姝g‘锛岀偣鍑诲悗灏变細鐩存帴涓嬪彂澶氳埖鏈鸿繍鍔ㄥ懡浠ゃ�� + +--- + +## 13. 鏍锋湰鏂囦欢涓庢ā鍨嬫枃浠舵牸寮忚鏄� + +### 13.1 `samples.yaml` + +姣忎釜鏍锋湰鍖呭惈锛� + +- `u`, `v`锛氱偣鍑诲儚绱犲潗鏍� +- `x_cam`, `y_cam`, `z_cam`锛氱浉鏈哄潗鏍囩郴涓嬩笁缁寸偣 +- `arm_cmd`锛氳鐐瑰搴旂殑鏈烘鑷傚懡浠ゅ悜閲� + +椤跺眰杩樺寘鍚細 + +- `cmd_dim` + +### 13.2 `model.yaml` + +褰撳墠妯″瀷鏂囦欢涓褰曪細 + +- 鐗瑰緛椤哄簭 `['1', 'x', 'y', 'x2', 'xy', 'y2']` +- 鏉冮噸鐭╅樀 `weights` +- 杈撳嚭缁村害 `cmd_dim` +- 鏍锋湰鏁� `sample_count` +- `mae_per_dim` +- `rmse_per_dim` +- `z_ref_median` + +杩欐剰鍛崇潃褰撳墠骞抽潰鎷熷悎瀹為檯涓婃槸锛� + +```text +cmd = [1, x, y, x虏, x*y, y虏] @ W +``` + +--- + +## 14. 鏈烘鑷備覆鍙f帶鍒惰ˉ鍏呰鏄� + +### 14.1 `depth_click_to_learm_cmd_node.py` 涓殑涓插彛鍗忚 + +浠g爜涓瀯閫犵殑甯ф牸寮忎负锛� + +```text +55 55 Length CMD Params... +``` + +澶氳埖鏈烘帶鍒朵娇鐢細 + +- `CMD = 0x03` + +鍙傛暟鏍煎紡鍖呭惈锛� + +- 鑸垫満鏁伴噺 +- 杩愬姩鏃堕棿浣庨珮瀛楄妭 +- 姣忎釜鑸垫満鐨� `id + pulse浣庡瓧鑺� + pulse楂樺瓧鑺俙 + +### 14.2 涓轰粈涔堥渶瑕佹敞鎰忚埖鏈洪『搴� + +骞抽潰鎷熷悎寰楀埌鐨勫彧鏄�滃懡浠ゅ悜閲忊�濓紝瀹冩湰韬苟涓嶇煡閬撳摢涓�缁村搴斿摢涓�涓埖鏈恒�� + +鎵�浠ヤ綘蹇呴』淇濊瘉浠ヤ笅涓夎�呬竴鑷达細 + +1. 閲囨牱鏃朵綘杈撳叆 `arm_cmd` 鐨勯『搴� +2. `model.yaml` 鐨勮緭鍑虹淮搴﹂『搴� +3. 瀹為檯鍙戦�佷覆鍙f椂鐨� `servo_ids` 椤哄簭 + +鍙杩欎笁鑰呮湁涓�澶勪笉涓�鑷达紝灏变細鍑虹幇鈥滈娴嬬湅璧锋潵鏈夊�硷紝浣嗘満姊拌噦鍔ㄤ綔瀹屽叏涓嶅鈥濈殑鎯呭喌銆� + +--- + + +## 16. 甯歌妫�鏌ラ」 + +### 16.1 鐩告満鏈夌敾闈絾鐐逛笉鍒版湁鏁堟繁搴� + +浼樺厛妫�鏌ワ細 + +- `/camera/depth/image_raw` 鏄惁姝e父 +- `/camera/depth/camera_info` 鏄惁姝e父 +- 鐐瑰嚮浣嶇疆鏄惁瓒呭嚭鏈夋晥娣卞害鑼冨洿 +- `depth_scale` 鏄惁姝g‘ +- `min_depth_m / max_depth_m` 鏄惁璁剧疆杩囩獎 + +### 16.2 鐐瑰嚮鍚庢湁棰勬祴鍊硷紝浣嗘満姊拌噦鍔ㄤ綔涓嶅 + +浼樺厛妫�鏌ワ細 + +- `servo_ids` 椤哄簭鏄惁鍜岄噰鏍锋椂杈撳叆椤哄簭涓�鑷� +- `servo_min / servo_max` 鏄惁闄愬箙杩囨 +- 娉㈢壒鐜囨槸鍚﹀尮閰� +- 涓插彛鏄惁鎺ュ +- 鍙戦�佸崗璁槸鍚﹀拰鎺у埗鏉夸竴鑷� + +### 16.3 鏁磋溅鑳借窇锛屼絾鏈烘鑷備笉鍔� + +浼樺厛妫�鏌ワ細 + +- `lerobot_arm_controller` 鐨� `port` 鏄惁姝g‘ +- 褰撳墠杩愯鍙傛暟鏄惁宸茬粡鏀规垚 `/dev/ttyUSB1`锛堜笉瑕佹部鐢ㄤ唬鐮侀噷鐨勬棫榛樿鍊� `/dev/ttyUSB2`锛� +- `/depth_target/point3d` 鏄惁鐪熺殑鏈夋暟鎹� +- `/arm/status` 鏄惁涓�鐩村仠鍦� `busy` 鎴栨病鏈夊彉鍖� + +### 16.4 缂栬瘧 Orbbec 鍖呮姤鍐呭瓨涓嶈冻 + +鐩存帴鍏堝姞 swap锛屽啀缂栬瘧銆� + +### 16.5 鏍囧畾鏁堟灉宸� + +鍙紭鍏堜粠杩欏嚑涓柟鍚戜紭鍖栵細 + +- 閲囨牱鐐逛粠 9 鐐瑰鍔犲埌 12~16 鐐� +- 閲囨牱鍖哄煙灏介噺閾烘弧宸ヤ綔鍖� +- 鐐瑰嚮鐐瑰敖閲忓噯纭� +- 杈撳叆鐨勬満姊拌噦鍛戒护鍊间繚鎸佷竴鑷寸殑濮挎�佸熀鍑� +- 淇濊瘉鐩爣骞抽潰楂樺害鍩烘湰涓�鑷� + +--- + +## 17. 褰撳墠宸ョ▼閲岄渶瑕佹敞鎰忕殑涓嶄竴鑷寸偣 + +杩欓噷鎶婃垜鍦ㄥ悎骞舵椂鍙戠幇鐨勫嚑涓鏄撹俯鍧戠殑鍦版柟鍗曠嫭鍒楀嚭鏉ワ細 + +### 17.1 涓插彛鍙e悕瑕佹寜褰撳墠鏈哄櫒鏋氫妇锛屼笉瑕佸彧鐪嬫棫鏂囨。 + +浣犲綋鍓嶆満鍣ㄧ幇鍦烘灇涓惧凡缁忕‘璁わ細 + +- 搴曠洏锛歚/dev/ttyUSB0` +- 鏈烘鑷傦細`/dev/ttyUSB1` + +浣� `dev_ws` 閲岀殑閮ㄥ垎 launch/config 浠嶄繚鐣欑潃 `/dev/ttyUSB2`銆傚洜姝わ細 + +- 鐩存帴杩愯鏃讹紝瑕佷箞鏄惧紡浼� `arm_port:=/dev/ttyUSB1` +- 瑕佷箞鎶婃簮鐮侀粯璁ゅ�肩粺涓�鏀规垚 `/dev/ttyUSB1` + +### 17.2 鏈烘鑷傛尝鐗圭巼瑕佺粺涓�鍒� 9600 + +- `arm_plane_calib/depth_click_to_learm_cmd_node.py`锛氶粯璁� `9600` +- `arm_plane_calib/learm_test.py`锛氶粯璁� `9600` +- `lerobot_arm_controller` 褰撳墠浠g爜鍙傛暟锛歚115200` +- 浣犵幇鍦虹‘璁ょ殑鏈烘鑷傞粯璁ゆ尝鐗圭巼锛歚9600` + +鎵�浠ョ幇闃舵鎺ㄨ崘缁熶竴鎸� **9600** 閰嶇疆鏈烘鑷傜浉鍏宠妭鐐广�� + +### 17.3 鐩告満璁惧鍙锋寜褰撳墠鏈哄櫒鍐欐硶 + +浣犲綋鍓嶆満鍣ㄧ幇鍦轰俊鎭负锛� + +- 鏅�� USB 鐩告満锛歚/dev/video0` +- 娣卞害鐩告満锛歚/dev/video1` + +涓嶈繃鍦� ROS 2 瀹為檯杩愯涓紝Gemini 2 涓昏杩樻槸閫氳繃 `orbbec_camera` 椹卞姩鎺ョ锛屼笉涓�瀹氱洿鎺ヤ緷璧� `/dev/video1` 鍋氬浘鍍忛噰闆嗗叆鍙o紱`/dev/video1` 鏇撮�傚悎浣滀负璁惧鏋氫妇鍜屾帓闅滃弬鑰冦�� + +### 17.4 `learm_test.py` 瀹為檯瀛樺湪 + +涔嬪墠鏃ц鏄庨噷杩欎釜鏂囦欢瀹规槗琚拷鐣ワ紝浣嗕綘褰撳墠鍘嬬缉鍖呴噷**瀹為檯鏈�**锛� + +- `arm_plane_calib/learm_test.py` + +瀹冮�傚悎鐢ㄦ潵鍋氭渶鍩虹鐨勪覆鍙i摼璺笌鑸垫満鍔ㄤ綔鑱旇皟銆� +--- + +## 18. 鎺ㄨ崘鐨勬渶灏忚仈璋冮『搴� + +濡傛灉浣犺浠庨浂寮�濮嬪揩閫熸墦閫氾紝寤鸿鎸変笅闈㈤『搴忥細 + +1. 鍗曠嫭鍚姩 Gemini 2锛岀‘璁ゅ僵鑹插浘/娣卞害鍥�/鐩告満鍐呭弬姝e父 +2. 璺� `collect_plane_calib.py` 閲� 9~16 涓偣 +3. 璺� `fit_plane_calib.py` 鐢熸垚 `model.yaml` +4. 璺� `predict_plane_cmd.py` 鐪嬮娴嬪�兼槸鍚﹀悎鐞� +5. 璺� `depth_click_to_learm_cmd_node.py` 楠岃瘉鐐瑰嚮鍚庢槸鍚﹁兘鐩磋揪鐩爣闄勮繎 +6. 鍐嶆帴鍏� `lerobot_arm_controller` +7. 鏈�鍚庡啀鎺ュ叆 `mission_manager` 鍋氭暣杞﹁仈璋� + +杩欐牱鎺掓煡鏈�蹇紝涔熸渶瀹规槗鎶婇棶棰樺垏鍒嗘竻妤氥�� + diff --git a/arm_plane_calib/biaodi.png b/arm_plane_calib/biaodi.png new file mode 100644 index 0000000..1d778e9 Binary files /dev/null and b/arm_plane_calib/biaodi.png differ diff --git a/arm_plane_calib/collect_plane_calib.py b/arm_plane_calib/collect_plane_calib.py new file mode 100644 index 0000000..e6cad91 --- /dev/null +++ b/arm_plane_calib/collect_plane_calib.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import yaml +import cv2 +import numpy as np + +import rclpy +from rclpy.node import Node +from sensor_msgs.msg import Image, CameraInfo +from cv_bridge import CvBridge + + +class PlaneCalibCollector(Node): + def __init__(self): + super().__init__('plane_calib_collector') + + self.declare_parameter('color_topic', '/camera/color/image_raw') + self.declare_parameter('depth_topic', '/camera/depth/image_raw') + self.declare_parameter('camera_info_topic', '/camera/depth/camera_info') + self.declare_parameter('save_path', 'samples.yaml') + self.declare_parameter('depth_scale', 0.001) # 娣卞害鍗曚綅杞背锛屽父瑙� mm -> m + self.declare_parameter('min_depth_m', 0.05) + self.declare_parameter('max_depth_m', 1.50) + self.declare_parameter('median_kernel', 5) + self.declare_parameter('target_count', 9) # 閲囨弧澶氬皯涓偣鑷姩閫�鍑� + + self.color_topic = self.get_parameter('color_topic').value + self.depth_topic = self.get_parameter('depth_topic').value + self.camera_info_topic = self.get_parameter('camera_info_topic').value + self.save_path = self.get_parameter('save_path').value + self.depth_scale = float(self.get_parameter('depth_scale').value) + self.min_depth_m = float(self.get_parameter('min_depth_m').value) + self.max_depth_m = float(self.get_parameter('max_depth_m').value) + self.median_kernel = int(self.get_parameter('median_kernel').value) + self.target_count = int(self.get_parameter('target_count').value) + + self.bridge = CvBridge() + self.color_img = None + self.depth_img = None + self.K = None + self.samples = [] + self.should_exit = False + + self.create_subscription(Image, self.color_topic, self.on_color, 10) + self.create_subscription(Image, self.depth_topic, self.on_depth, 10) + self.create_subscription(CameraInfo, self.camera_info_topic, self.on_info, 10) + + self.window_name = 'plane_calib_click' + cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL) + cv2.setMouseCallback(self.window_name, self.on_mouse) + + self.get_logger().info('宸﹂敭鐐瑰嚮鏍囧畾鐐癸紝缁堢杈撳叆鏈烘鑷傚懡浠ゅ悜閲忥紝渚嬪: 500,620,410,530') + self.get_logger().info(f'姣忚褰� 1 涓牱鏈嚜鍔ㄤ繚瀛橈紝閲囨弧 {self.target_count} 涓牱鏈嚜鍔ㄩ��鍑�') + self.get_logger().info('鎸� q 鍙墜鍔ㄩ��鍑�') + + def on_color(self, msg: Image): + self.color_img = self.bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8') + + def on_depth(self, msg: Image): + if msg.encoding in ('16UC1', 'mono16'): + self.depth_img = self.bridge.imgmsg_to_cv2(msg, desired_encoding='passthrough') + else: + self.get_logger().warn(f'涓嶆敮鎸佺殑娣卞害缂栫爜: {msg.encoding}') + + def on_info(self, msg: CameraInfo): + self.K = np.array(msg.k, dtype=np.float64).reshape(3, 3) + + def get_xyz_from_pixel(self, u: int, v: int): + if self.depth_img is None or self.K is None: + return None + + h, w = self.depth_img.shape[:2] + if not (0 <= u < w and 0 <= v < h): + return None + + k = self.median_kernel + r = k // 2 + u0, u1 = max(0, u - r), min(w, u + r + 1) + v0, v1 = max(0, v - r), min(h, v + r + 1) + patch = self.depth_img[v0:v1, u0:u1].astype(np.float32) + + valid = patch[patch > 0] + if valid.size == 0: + return None + + z = np.median(valid) * self.depth_scale + if z < self.min_depth_m or z > self.max_depth_m: + return None + + fx = self.K[0, 0] + fy = self.K[1, 1] + cx = self.K[0, 2] + cy = self.K[1, 2] + + x = (u - cx) * z / fx + y = (v - cy) * z / fy + return float(x), float(y), float(z) + + def save_samples(self): + data = { + 'samples': self.samples, + 'cmd_dim': len(self.samples[0]['arm_cmd']) if self.samples else 0 + } + with open(self.save_path, 'w', encoding='utf-8') as f: + yaml.safe_dump(data, f, allow_unicode=True, sort_keys=False) + print(f'[SAVE] 宸蹭繚瀛樺埌 {self.save_path}') + + def on_mouse(self, event, x, y, flags, param): + if event != cv2.EVENT_LBUTTONDOWN: + return + + xyz = self.get_xyz_from_pixel(x, y) + if xyz is None: + print(f'[WARN] 鐐瑰嚮鐐� ({x}, {y}) 鏃犳湁鏁堟繁搴�') + return + + X, Y, Z = xyz + print(f'\n鐐瑰嚮鍍忕礌: ({x}, {y})') + print(f'鐩告満鍧愭爣: X={X:.4f} m, Y={Y:.4f} m, Z={Z:.4f} m') + print('璇锋墜鍔ㄦ妸鏈烘鑷傛湯绔Щ鍒拌繖涓偣姝d笂鏂癸紝鐒跺悗杈撳叆鍛戒护鍚戦噺锛屼緥濡� 500,620,410,530') + cmd_str = input('arm_cmd> ').strip() + if not cmd_str: + print('[SKIP] 鏈緭鍏ワ紝璺宠繃') + return + + try: + arm_cmd = [float(s) for s in cmd_str.split(',')] + except Exception: + print('[ERR] 杈撳叆鏍煎紡閿欒锛屽簲绫讳技 500,620,410,530') + return + + item = { + 'u': int(x), + 'v': int(y), + 'x_cam': X, + 'y_cam': Y, + 'z_cam': Z, + 'arm_cmd': arm_cmd + } + self.samples.append(item) + print(f'[OK] 宸茶褰曠 {len(self.samples)} 涓牱鏈�') + + # 鑷姩淇濆瓨 + self.save_samples() + + # 閲囨弧鑷姩閫�鍑� + if len(self.samples) >= self.target_count: + print(f'[DONE] 宸查噰婊� {self.target_count} 涓牱鏈紝鑷姩淇濆瓨骞堕��鍑�') + self.should_exit = True + + def spin_loop(self): + while rclpy.ok() and not self.should_exit: + rclpy.spin_once(self, timeout_sec=0.03) + + if self.color_img is not None: + show = self.color_img.copy() + for i, s in enumerate(self.samples): + cv2.circle(show, (s['u'], s['v']), 4, (0, 255, 0), -1) + cv2.putText( + show, str(i + 1), (s['u'] + 6, s['v'] - 6), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1 + ) + cv2.imshow(self.window_name, show) + + key = cv2.waitKey(1) & 0xFF + if key == ord('q'): + print('[EXIT] 鐢ㄦ埛閫�鍑�') + break + + cv2.destroyAllWindows() + + +def main(): + rclpy.init() + node = PlaneCalibCollector() + try: + node.spin_loop() + finally: + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/arm_plane_calib/depth_click_to_learm_cmd_node.py b/arm_plane_calib/depth_click_to_learm_cmd_node.py new file mode 100644 index 0000000..4ae0b35 --- /dev/null +++ b/arm_plane_calib/depth_click_to_learm_cmd_node.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import time +import yaml +import cv2 +import numpy as np +import serial + +import rclpy +from rclpy.node import Node +from sensor_msgs.msg import Image, CameraInfo +from cv_bridge import CvBridge + + +class LeArmSerial: + def __init__(self, port="/dev/ttyUSB0", baudrate=9600): + self.port = port + self.baudrate = baudrate + self.ser = None + + def open(self): + self.ser = serial.Serial() + self.ser.port = self.port + self.ser.baudrate = self.baudrate + self.ser.bytesize = serial.EIGHTBITS + self.ser.parity = serial.PARITY_NONE + self.ser.stopbits = serial.STOPBITS_ONE + self.ser.timeout = 0.1 + self.ser.xonxoff = False + self.ser.rtscts = False + self.ser.dsrdtr = False + self.ser.dtr = False + self.ser.rts = False + self.ser.open() + + print(f"[INFO] 涓插彛宸叉墦寮�: {self.port} @ {self.baudrate}") + print("[INFO] 绛夊緟鎺у埗鏉跨ǔ瀹�...") + time.sleep(3.0) + + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + + def close(self): + if self.ser and self.ser.is_open: + self.ser.close() + print("[INFO] 涓插彛宸插叧闂�") + + @staticmethod + def build_frame(cmd: int, params: bytes = b"") -> bytes: + # 鍗忚: 55 55 Length CMD Params... + # Length = CMD(1) + Params闀垮害 + length = 1 + len(params) + return bytes([0x55, 0x55, length, cmd]) + params + + def move_servos(self, servo_pairs, move_time_ms=800): + """ + servo_pairs: [(servo_id, pulse), ...] + CMD=3 澶氳埖鏈烘帶鍒� + """ + if not servo_pairs: + print("[WARN] 绌鸿埖鏈哄垪琛�") + return + + params = bytearray() + params.append(len(servo_pairs)) + params.append(move_time_ms & 0xFF) + params.append((move_time_ms >> 8) & 0xFF) + + for sid, pulse in servo_pairs: + sid = int(sid) + pulse = int(pulse) + params.append(sid & 0xFF) + params.append(pulse & 0xFF) + params.append((pulse >> 8) & 0xFF) + + frame = self.build_frame(0x03, bytes(params)) + print("TX:", frame.hex(" ")) + self.ser.write(frame) + self.ser.flush() + + +class DepthClickToLeArm(Node): + def __init__(self): + super().__init__("depth_click_to_learm_cmd") + + # 鐩告満璇濋 + self.declare_parameter("depth_topic", "/camera/depth/image_raw") + self.declare_parameter("camera_info_topic", "/camera/depth/camera_info") + self.declare_parameter("color_topic", "/camera/color/image_raw") + + # 妯″瀷 + self.declare_parameter("model_path", "model.yaml") + + # 娣卞害鍙傛暟 + self.declare_parameter("depth_scale", 0.001) # 16UC1 甯歌 mm->m + self.declare_parameter("min_depth_m", 0.05) + self.declare_parameter("max_depth_m", 1.20) + self.declare_parameter("median_kernel", 5) + + # 涓插彛 + self.declare_parameter("serial_port", "/dev/ttyUSB0") + self.declare_parameter("baud_rate", 9600) + self.declare_parameter("move_time_ms", 800) + + # 瑙嗗浘 + self.declare_parameter("show_color_view", True) + self.declare_parameter("draw_text", True) + + # 鍛戒护鍚戦噺 -> 鑸垫満ID鏄犲皠 + # 杩欓噷鐨勯『搴忓繀椤诲拰 model.yaml 杈撳嚭鐨勫懡浠ゅ悜閲忛『搴忎竴鑷� + # 榛樿缁欎竴缁勫父瑙侀『搴忥紝浣犲悗闈㈡寜鑷繁鏈烘鑷傚疄闄呮敼 + self.declare_parameter("servo_ids", [6, 5, 4, 3]) + + # 姣忎釜鑸垫満鑼冨洿锛屾寜浣犵粰鍑虹殑鑼冨洿璁剧疆 + self.declare_parameter("servo_min", [125, 125, 125, 125]) + self.declare_parameter("servo_max", [875, 875, 875, 875]) + + # 濡傛灉鎯虫妸澶圭埅鍔犲叆鎶撳彇鍔ㄤ綔锛屽彲鍦ㄧ偣鍑诲悗鑷繁鍐嶅姞鍥哄畾鍔ㄤ綔 + self.declare_parameter("auto_send", True) + + self.depth_topic = self.get_parameter("depth_topic").value + self.camera_info_topic = self.get_parameter("camera_info_topic").value + self.color_topic = self.get_parameter("color_topic").value + + self.model_path = self.get_parameter("model_path").value + + self.depth_scale = float(self.get_parameter("depth_scale").value) + self.min_depth_m = float(self.get_parameter("min_depth_m").value) + self.max_depth_m = float(self.get_parameter("max_depth_m").value) + self.median_kernel = int(self.get_parameter("median_kernel").value) + + self.serial_port = self.get_parameter("serial_port").value + self.baud_rate = int(self.get_parameter("baud_rate").value) + self.move_time_ms = int(self.get_parameter("move_time_ms").value) + + self.show_color_view = bool(self.get_parameter("show_color_view").value) + self.draw_text = bool(self.get_parameter("draw_text").value) + + self.servo_ids = list(self.get_parameter("servo_ids").value) + self.servo_min = list(self.get_parameter("servo_min").value) + self.servo_max = list(self.get_parameter("servo_max").value) + self.auto_send = bool(self.get_parameter("auto_send").value) + + # 璇诲彇妯″瀷 + with open(self.model_path, "r", encoding="utf-8") as f: + model = yaml.safe_load(f) + + self.W = np.array(model["weights"], dtype=np.float64) # [6, cmd_dim] + self.cmd_dim = int(model["cmd_dim"]) + if self.cmd_dim != len(self.servo_ids): + raise RuntimeError( + f"model cmd_dim={self.cmd_dim} 涓� servo_ids 鏁伴噺={len(self.servo_ids)} 涓嶄竴鑷�" + ) + + self.bridge = CvBridge() + self.depth_img = None + self.color_img = None + self.K = None + + self.last_click = None + self.window_name = "depth_click_to_learm_cmd" + + self.arm = LeArmSerial(self.serial_port, self.baud_rate) + self.arm.open() + + self.create_subscription(Image, self.depth_topic, self.on_depth, 10) + self.create_subscription(CameraInfo, self.camera_info_topic, self.on_info, 10) + self.create_subscription(Image, self.color_topic, self.on_color, 10) + + cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL) + cv2.setMouseCallback(self.window_name, self.on_mouse) + + self.get_logger().info("鑺傜偣宸插惎鍔紝宸﹂敭鐐瑰嚮鐩爣鐐瑰嵆鍙娴嬪苟鍙戦�� CMD=3銆�") + + def destroy_node(self): + try: + self.arm.close() + except Exception: + pass + super().destroy_node() + + def on_depth(self, msg: Image): + self.depth_img = self.bridge.imgmsg_to_cv2(msg, desired_encoding="passthrough") + + def on_color(self, msg: Image): + try: + self.color_img = self.bridge.imgmsg_to_cv2(msg, desired_encoding="bgr8") + except Exception: + self.color_img = None + + def on_info(self, msg: CameraInfo): + self.K = np.array(msg.k, dtype=np.float64).reshape(3, 3) + + @staticmethod + def features(x, y): + return np.array([1.0, x, y, x * x, x * y, y * y], dtype=np.float64) + + def pixel_to_xyz(self, u, v): + if self.depth_img is None or self.K is None: + return None + + h, w = self.depth_img.shape[:2] + if not (0 <= u < w and 0 <= v < h): + return None + + r = self.median_kernel // 2 + u0, u1 = max(0, u - r), min(w, u + r + 1) + v0, v1 = max(0, v - r), min(h, v + r + 1) + patch = self.depth_img[v0:v1, u0:u1].astype(np.float32) + + valid = patch[patch > 0] + if valid.size == 0: + return None + + z = float(np.median(valid) * self.depth_scale) + if z < self.min_depth_m or z > self.max_depth_m: + return None + + fx = self.K[0, 0] + fy = self.K[1, 1] + cx = self.K[0, 2] + cy = self.K[1, 2] + + x = float((u - cx) * z / fx) + y = float((v - cy) * z / fy) + return x, y, z + + def predict_cmd(self, x_cam, y_cam): + feat = self.features(x_cam, y_cam) # [6] + cmd = feat @ self.W # [cmd_dim] + return cmd + + def clamp_cmd(self, cmd): + out = [] + for i, v in enumerate(cmd): + lo = float(self.servo_min[i]) + hi = float(self.servo_max[i]) + out.append(int(round(max(lo, min(hi, v))))) + return out + + def send_cmd_vector(self, cmd_vec): + servo_pairs = list(zip(self.servo_ids, cmd_vec)) + self.arm.move_servos(servo_pairs, move_time_ms=self.move_time_ms) + + def on_mouse(self, event, x, y, flags, param): + if event != cv2.EVENT_LBUTTONDOWN: + return + + xyz = self.pixel_to_xyz(x, y) + if xyz is None: + print(f"[WARN] 鐐瑰嚮鐐� ({x}, {y}) 鏃犳湁鏁堟繁搴�") + return + + x_cam, y_cam, z_cam = xyz + pred = self.predict_cmd(x_cam, y_cam) + pred_clamped = self.clamp_cmd(pred) + + self.last_click = { + "u": int(x), + "v": int(y), + "x_cam": x_cam, + "y_cam": y_cam, + "z_cam": z_cam, + "pred_raw": pred.tolist(), + "pred_cmd": pred_clamped, + } + + print("\n========== 鐐瑰嚮鐩爣鐐� ==========") + print(f"鍍忕礌: ({x}, {y})") + print(f"鐩告満鍧愭爣: X={x_cam:.4f} m, Y={y_cam:.4f} m, Z={z_cam:.4f} m") + print("棰勬祴鍘熷鍛戒护鍚戦噺:", ", ".join([f"{v:.2f}" for v in pred.tolist()])) + print("闄愬箙鍚庡懡浠ゅ悜閲�:", pred_clamped) + print("鑸垫満鏄犲皠:", list(zip(self.servo_ids, pred_clamped))) + + if self.auto_send: + self.send_cmd_vector(pred_clamped) + print("[OK] 宸茬洿鎺ュ彂閫� CMD=3") + + def make_depth_vis(self): + if self.depth_img is None: + return None + + depth = self.depth_img.astype(np.float32) * self.depth_scale + depth = np.clip(depth, self.min_depth_m, self.max_depth_m) + + norm = (depth - self.min_depth_m) / max(1e-6, (self.max_depth_m - self.min_depth_m)) + norm = (norm * 255.0).astype(np.uint8) + vis = cv2.applyColorMap(255 - norm, cv2.COLORMAP_JET) + return vis + + def spin_loop(self): + while rclpy.ok(): + rclpy.spin_once(self, timeout_sec=0.03) + + show = None + if self.show_color_view and self.color_img is not None: + show = self.color_img.copy() + else: + vis = self.make_depth_vis() + if vis is not None: + show = vis + + if show is not None and self.last_click is not None: + u = self.last_click["u"] + v = self.last_click["v"] + cv2.circle(show, (u, v), 6, (0, 255, 0), -1) + if self.draw_text: + txt1 = f"({u},{v})" + txt2 = f"X={self.last_click['x_cam']:.3f} Y={self.last_click['y_cam']:.3f} Z={self.last_click['z_cam']:.3f}" + txt3 = "CMD=" + ",".join([str(v) for v in self.last_click["pred_cmd"]]) + cv2.putText(show, txt1, (u + 8, v - 24), cv2.FONT_HERSHEY_SIMPLEX, 0.55, (0, 255, 0), 1) + cv2.putText(show, txt2, (u + 8, v - 8), cv2.FONT_HERSHEY_SIMPLEX, 0.50, (0, 255, 0), 1) + cv2.putText(show, txt3, (u + 8, v + 10), cv2.FONT_HERSHEY_SIMPLEX, 0.50, (0, 255, 0), 1) + + cv2.imshow(self.window_name, show) + elif show is not None: + cv2.imshow(self.window_name, show) + + key = cv2.waitKey(1) & 0xFF + if key == ord("q"): + break + elif key == ord("s") and self.last_click is not None: + # 鎵嬪姩鍐嶅彂閫佷竴娆� + self.send_cmd_vector(self.last_click["pred_cmd"]) + print("[OK] 鎵嬪姩鍐嶆鍙戦�� CMD=3") + elif key == ord("c"): + self.last_click = None + + cv2.destroyAllWindows() + + +def main(): + rclpy.init() + node = DepthClickToLeArm() + try: + node.spin_loop() + finally: + node.destroy_node() + rclpy.shutdown() + + +if __name__ == "__main__": + main() diff --git a/arm_plane_calib/fit_plane_calib.py b/arm_plane_calib/fit_plane_calib.py new file mode 100644 index 0000000..4c8f9a0 --- /dev/null +++ b/arm_plane_calib/fit_plane_calib.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +import yaml +import numpy as np +import sys + + +def features(x, y): + return np.array([1.0, x, y, x * x, x * y, y * y], dtype=np.float64) + + +def main(): + sample_path = sys.argv[1] if len(sys.argv) > 1 else 'samples.yaml' + model_path = sys.argv[2] if len(sys.argv) > 2 else 'model.yaml' + + with open(sample_path, 'r', encoding='utf-8') as f: + data = yaml.safe_load(f) + + samples = data['samples'] + if len(samples) < 6: + print('鏍锋湰澶皯锛岃嚦灏戦渶瑕� 6 涓紝寤鸿 9~16 涓�') + return + + X = [] + Y = [] + + for s in samples: + X.append(features(s['x_cam'], s['y_cam'])) + Y.append(s['arm_cmd']) + + X = np.array(X, dtype=np.float64) # [N, 6] + Y = np.array(Y, dtype=np.float64) # [N, cmd_dim] + + # 鏈�灏忎簩涔� + W, _, _, _ = np.linalg.lstsq(X, Y, rcond=None) # [6, cmd_dim] + Y_pred = X @ W + err = Y_pred - Y + mae = np.mean(np.abs(err), axis=0) + rmse = np.sqrt(np.mean(err ** 2, axis=0)) + + model = { + 'feature_order': ['1', 'x', 'y', 'x2', 'xy', 'y2'], + 'weights': W.tolist(), + 'cmd_dim': int(Y.shape[1]), + 'sample_count': int(len(samples)), + 'mae_per_dim': mae.tolist(), + 'rmse_per_dim': rmse.tolist(), + 'z_ref_median': float(np.median([s['z_cam'] for s in samples])) + } + + with open(model_path, 'w', encoding='utf-8') as f: + yaml.safe_dump(model, f, allow_unicode=True, sort_keys=False) + + print(f'妯″瀷宸蹭繚瀛樺埌: {model_path}') + print('姣忕淮 MAE:', mae) + print('姣忕淮 RMSE:', rmse) + + +if __name__ == '__main__': + main() + diff --git a/arm_plane_calib/learm_test.py b/arm_plane_calib/learm_test.py new file mode 100644 index 0000000..3a77922 --- /dev/null +++ b/arm_plane_calib/learm_test.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import time +import serial + + +class LeArmSerial: + def __init__(self, port="/dev/ttyUSB0", baudrate=9600): + self.port = port + self.baudrate = baudrate + self.ser = None + + def open(self): + self.ser = serial.Serial() + self.ser.port = self.port + self.ser.baudrate = self.baudrate + self.ser.bytesize = serial.EIGHTBITS + self.ser.parity = serial.PARITY_NONE + self.ser.stopbits = serial.STOPBITS_ONE + self.ser.timeout = 0.1 + self.ser.xonxoff = False + self.ser.rtscts = False + self.ser.dsrdtr = False + + self.ser.dtr = False + self.ser.rts = False + self.ser.open() + + print(f"[INFO] 涓插彛宸叉墦寮�: {self.port} @ {self.baudrate}") + print("[INFO] 绛夊緟鎺у埗鏉跨ǔ瀹�...") + time.sleep(3.0) + + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + + def close(self): + if self.ser and self.ser.is_open: + self.ser.close() + print("[INFO] 涓插彛宸插叧闂�") + + @staticmethod + def build_frame(cmd: int, params: bytes = b"") -> bytes: + length = 2 + len(params) + return bytes([0x55, 0x55, length, cmd]) + params + + def send_frame(self, cmd: int, params: bytes = b""): + frame = self.build_frame(cmd, params) + print("TX:", frame.hex(" ")) + self.ser.write(frame) + self.ser.flush() + + def read_frames(self, wait_s: float = 1.0): + deadline = time.time() + wait_s + buf = bytearray() + + while time.time() < deadline: + n = self.ser.in_waiting + if n > 0: + buf.extend(self.ser.read(n)) + time.sleep(0.01) + + print("RAW RX:", bytes(buf).hex(" ")) + return self.split_frames(bytes(buf)) + + @staticmethod + def split_frames(buf: bytes): + frames = [] + i = 0 + while i <= len(buf) - 3: + if buf[i] == 0x55 and buf[i + 1] == 0x55: + length = buf[i + 2] + frame_len = 2 + length + if i + frame_len <= len(buf): + frames.append(buf[i:i + frame_len]) + i += frame_len + continue + i += 1 + return frames + + @staticmethod + def parse_fw_query(frame: bytes): + if len(frame) != 6 or frame[:4] != b"\x55\x55\x04\x01": + return None + servo_type = frame[4] + fw_ver = frame[5] + return { + "servo_type": servo_type, + "servo_type_text": {1: "PWM鑸垫満", 2: "鎬荤嚎鑸垫満"}.get(servo_type, f"鏈煡({servo_type})"), + "firmware_version": fw_ver, + } + + @staticmethod + def parse_servo_readback(frame: bytes): + if len(frame) < 6 or frame[0] != 0x55 or frame[1] != 0x55 or frame[3] != 0x0D: + return None + + payload = frame[4:] + items = [] + if len(payload) % 3 != 0: + usable = len(payload) - (len(payload) % 3) + payload = payload[:usable] + + for i in range(0, len(payload), 3): + sid = payload[i] + pulse = payload[i + 1] | (payload[i + 2] << 8) + items.append({"id": sid, "pulse": pulse}) + return items + + def query_firmware(self): + self.ser.reset_input_buffer() + self.send_frame(0x01) + frames = self.read_frames(wait_s=1.0) + + ok = False + for f in frames: + print("FRAME:", f.hex(" ")) + info = self.parse_fw_query(f) + if info: + ok = True + print("[OK] 鍥轰欢鏌ヨ鎴愬姛") + print("鑸垫満绫诲瀷:", info["servo_type_text"]) + print("鍥轰欢鐗堟湰鍙�:", info["firmware_version"]) + if not ok: + print("[WARN] 鏈В鏋愬埌鏈夋晥鍥轰欢鏌ヨ杩斿洖") + + def read_servo_angles(self): + self.ser.reset_input_buffer() + self.send_frame(0x0D) + frames = self.read_frames(wait_s=1.0) + + ok = False + for f in frames: + print("FRAME:", f.hex(" ")) + items = self.parse_servo_readback(f) + if items is not None: + ok = True + print("[OK] 鑸垫満瑙掑害鍥炶鎴愬姛") + for item in items: + print(f" 鑸垫満ID={item['id']}, 鑴夊={item['pulse']}") + if not ok: + print("[WARN] 鏈В鏋愬埌鏈夋晥鑸垫満瑙掑害鍥炶杩斿洖") + + def set_init_pose(self): + self.ser.reset_input_buffer() + self.send_frame(0x0C) + time.sleep(1.5) + print("[OK] 宸插彂閫佸垵濮嬩綅濮胯缃懡浠�") + + def move_servos(self, servo_pairs, move_time_ms=800): + """ + servo_pairs: [(servo_id, pulse), ...] + 鍗忚: + 闀垮害 = 鑸垫満涓暟*3 + 5 + params: + 涓暟(1B), time_low(1B), time_high(1B), + [id, pulse_low, pulse_high] * N + """ + if not servo_pairs: + print("[WARN] 绌鸿埖鏈哄垪琛�") + return + + params = bytearray() + params.append(len(servo_pairs)) + params.append(move_time_ms & 0xFF) + params.append((move_time_ms >> 8) & 0xFF) + + for sid, pulse in servo_pairs: + pulse = int(pulse) + params.append(int(sid) & 0xFF) + params.append(pulse & 0xFF) + params.append((pulse >> 8) & 0xFF) + + self.ser.reset_input_buffer() + self.send_frame(0x03, bytes(params)) + time.sleep(max(move_time_ms / 1000.0, 0.5)) + print("[OK] 宸插彂閫佸鑸垫満鎺у埗鍛戒护") + + def interactive(self): + menu = """ +================ LeArm 涓插彛娴嬭瘯 ================= +1. 鍥轰欢鏌ヨ +2. 鑸垫満瑙掑害鍥炶 +3. 鍒濆浣嶅Э璁剧疆 +4. 鎺у埗鍗曚釜鑸垫満 +5. 鎺у埗澶氫釜鑸垫満 +q. 閫�鍑� + 鑸垫満鑼冨洿 +(1澶圭埅,200-700;2鑵曢儴,125-875;) +(3鍙�,125-875;4鍙�,125-875;) +(5鍙�,125-875;6鏃嬭浆,125-875;) +================================================= +""" + while True: + print(menu) + choice = input("璇烽�夋嫨: ").strip().lower() + + if choice == "1": + self.query_firmware() + + elif choice == "2": + self.read_servo_angles() + + elif choice == "3": + self.set_init_pose() + + elif choice == "4": + sid = int(input("鑸垫満ID: ").strip()) + pulse = int(input("鐩爣浣嶇疆(渚嬪 500): ").strip()) + t = int(input("杩愯鏃堕棿ms(渚嬪 800): ").strip() or "800") + self.move_servos([(sid, pulse)], move_time_ms=t) + + elif choice == "5": + print("杈撳叆鏍煎紡绀轰緥: 1:500,2:600,3:450") + raw = input("鑸垫満鍒楄〃: ").strip() + t = int(input("杩愯鏃堕棿ms(渚嬪 800): ").strip() or "800") + + pairs = [] + for item in raw.split(","): + sid_s, pulse_s = item.split(":") + pairs.append((int(sid_s), int(pulse_s))) + + self.move_servos(pairs, move_time_ms=t) + + elif choice == "q": + break + + else: + print("[WARN] 鏃犳晥閫夐」") + + +def main(): + arm = LeArmSerial(port="/dev/ttyUSB0", baudrate=9600) + try: + arm.open() + arm.interactive() + finally: + arm.close() + + +if __name__ == "__main__": + main() diff --git a/arm_plane_calib/model.yaml b/arm_plane_calib/model.yaml new file mode 100644 index 0000000..89a18bc --- /dev/null +++ b/arm_plane_calib/model.yaml @@ -0,0 +1,45 @@ +feature_order: +- '1' +- x +- y +- x2 +- xy +- y2 +weights: +- - 511.28515454089643 + - 821.2615901131778 + - 265.21874233385535 + - 398.5549181928104 +- - -771.8329814607213 + - 52.76710377195036 + - 237.64443893556836 + - -114.8132656337159 +- - 362.52663422740244 + - -580.4727764870705 + - -26.751203474622418 + - -1877.4142059960259 +- - 680.0875101829623 + - 7153.497267194028 + - 5925.331927860114 + - 1758.558407685675 +- - -4993.565252238856 + - 4809.674284044076 + - 17834.265848385203 + - -12695.665144123212 +- - 5570.783049089005 + - 3393.015647299803 + - 30196.06155860567 + - -33269.65533447665 +cmd_dim: 4 +sample_count: 9 +mae_per_dim: +- 17.308270436659697 +- 9.353204865258602 +- 23.274954237277775 +- 26.493102071291403 +rmse_per_dim: +- 20.835859382625955 +- 12.3444244473184 +- 28.89964968573881 +- 35.21007477027654 +z_ref_median: 0.34400000000000003 diff --git a/arm_plane_calib/predict_plane_cmd.py b/arm_plane_calib/predict_plane_cmd.py new file mode 100644 index 0000000..7832b47 --- /dev/null +++ b/arm_plane_calib/predict_plane_cmd.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +import yaml +import cv2 +import numpy as np + +import rclpy +from rclpy.node import Node +from sensor_msgs.msg import Image, CameraInfo +from cv_bridge import CvBridge + + +def features(x, y): + return np.array([1.0, x, y, x * x, x * y, y * y], dtype=np.float64) + + +class PlaneCmdPredictor(Node): + def __init__(self): + super().__init__('plane_cmd_predictor') + + self.declare_parameter('color_topic', '/camera/color/image_raw') + self.declare_parameter('depth_topic', '/camera/depth/image_raw') + self.declare_parameter('camera_info_topic', '/camera/depth/camera_info') + self.declare_parameter('model_path', 'model.yaml') + self.declare_parameter('depth_scale', 0.001) + + self.color_topic = self.get_parameter('color_topic').value + self.depth_topic = self.get_parameter('depth_topic').value + self.camera_info_topic = self.get_parameter('camera_info_topic').value + self.model_path = self.get_parameter('model_path').value + self.depth_scale = float(self.get_parameter('depth_scale').value) + + with open(self.model_path, 'r', encoding='utf-8') as f: + model = yaml.safe_load(f) + + self.W = np.array(model['weights'], dtype=np.float64) # [6, cmd_dim] + self.bridge = CvBridge() + self.color_img = None + self.depth_img = None + self.K = None + + # 浣犵殑妯″瀷杈撳嚭椤哄簭鍥哄畾涓猴細6鍙枫��5鍙枫��4鍙枫��3鍙� + self.model_servo_order = [6, 5, 4, 3] + + # 浣犳兂鎵撳嵃鎴愶細3鍙枫��4鍙枫��5鍙枫��6鍙� + self.print_servo_order = [3, 4, 5, 6] + + # 褰撳墠鍙鐞� 3/4/5/6 鍙疯埖鏈猴紝鑼冨洿閮戒竴鑷� + self.servo_min = 125 + self.servo_max = 875 + + self.create_subscription(Image, self.color_topic, self.on_color, 10) + self.create_subscription(Image, self.depth_topic, self.on_depth, 10) + self.create_subscription(CameraInfo, self.camera_info_topic, self.on_info, 10) + + self.window_name = 'predict_plane_cmd' + cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL) + cv2.setMouseCallback(self.window_name, self.on_mouse) + + def on_color(self, msg): + self.color_img = self.bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8') + + def on_depth(self, msg): + self.depth_img = self.bridge.imgmsg_to_cv2(msg, desired_encoding='passthrough') + + def on_info(self, msg): + self.K = np.array(msg.k, dtype=np.float64).reshape(3, 3) + + def pixel_to_xyz(self, u, v): + if self.depth_img is None or self.K is None: + return None + + h, w = self.depth_img.shape[:2] + if not (0 <= u < w and 0 <= v < h): + return None + + patch = self.depth_img[max(0, v - 2):min(h, v + 3), max(0, u - 2):min(w, u + 3)].astype(np.float32) + valid = patch[patch > 0] + if valid.size == 0: + return None + + z = np.median(valid) * self.depth_scale + fx = self.K[0, 0] + fy = self.K[1, 1] + cx = self.K[0, 2] + cy = self.K[1, 2] + + x = (u - cx) * z / fx + y = (v - cy) * z / fy + return float(x), float(y), float(z) + + def clamp_servo(self, value): + value = int(round(value)) + if value < self.servo_min: + value = self.servo_min + if value > self.servo_max: + value = self.servo_max + return value + + def on_mouse(self, event, x, y, flags, param): + if event != cv2.EVENT_LBUTTONDOWN: + return + + xyz = self.pixel_to_xyz(x, y) + if xyz is None: + print('[WARN] 鏃犳湁鏁堟繁搴�') + return + + X, Y, Z = xyz + + # 妯″瀷杈撳嚭椤哄簭锛�6,5,4,3 + cmd_raw = features(X, Y) @ self.W + cmd_raw = cmd_raw.tolist() + + # 鍏堝彇鏁村苟闄愬箙 + cmd_int = [self.clamp_servo(v) for v in cmd_raw] + + # 杞垚 {鑸垫満ID: 鍊紏 + servo_map = {} + for sid, val in zip(self.model_servo_order, cmd_int): + servo_map[sid] = val + + # 鎸変綘甯屾湜鐨勯『搴忔墦鍗帮細3,4,5,6 + ordered_pairs = [(sid, servo_map[sid]) for sid in self.print_servo_order] + + print(f'\n鐐瑰嚮鍍忕礌: ({x}, {y})') + print(f'鐩告満鍧愭爣: X={X:.4f}, Y={Y:.4f}, Z={Z:.4f}') + print('棰勬祴鏈烘鑷傚懡浠ゅ悜閲�(鎸夋ā鍨嬮『搴� 6,5,4,3):', + ', '.join([str(servo_map[sid]) for sid in self.model_servo_order])) + print('鑸垫満鍒楄〃:', ','.join([f'{sid}:{val}' for sid, val in ordered_pairs])) + + def spin_loop(self): + while rclpy.ok(): + rclpy.spin_once(self, timeout_sec=0.03) + if self.color_img is not None: + cv2.imshow(self.window_name, self.color_img) + if (cv2.waitKey(1) & 0xFF) == ord('q'): + break + cv2.destroyAllWindows() + + +def main(): + rclpy.init() + node = PlaneCmdPredictor() + try: + node.spin_loop() + finally: + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/arm_plane_calib/readme.md b/arm_plane_calib/readme.md new file mode 100644 index 0000000..c4c9220 --- /dev/null +++ b/arm_plane_calib/readme.md @@ -0,0 +1,310 @@ +# arm_plane_calib 浣跨敤璇存槑 + + +## 1. 褰撳墠鏈哄櫒鐨勫疄闄呰澶囨槧灏� + +鏍规嵁鐜板満鏋氫妇缁撴灉锛屽綋鍓嶆満鍣ㄥ缓璁寜涓嬮潰鐨勬槧灏勭悊瑙e拰浣跨敤锛� + +### 1.1 涓插彛璁惧 + +- **鏈烘鑷傛帶鍒跺彛**锛歚/dev/ttyUSB1` +- **鏈烘鑷傞粯璁ゆ尝鐗圭巼**锛歚9600` + +鐜板満涓插彛鏋氫妇锛� + +```bash +root@ubuntu:~# ls /dev/ttyUSB* +/dev/ttyUSB0 /dev/ttyUSB1 +``` + +璇存槑锛� + +- `ttyUSB0` 褰撳墠鐢ㄤ簬搴曠洏 +- `ttyUSB1` 褰撳墠鐢ㄤ簬鏈烘鑷� + +### 1.2 娣卞害鐩告満 + +- **娣卞害鐩告満鍨嬪彿**锛歄rbbec Gemini 2 +- **绯荤粺鑺傜偣**锛歚/dev/video1` + +浣嗘湰宸ョ▼閲岀殑娣卞害鏁版嵁 **涓嶆槸鐩存帴鎸夋櫘閫� UVC 鎽勫儚澶村幓璇� `/dev/video1`**锛岃�屾槸閫氳繃 `orbbec_camera` 椹卞姩鍙戝竷 ROS 2 璇濋锛� + +- `/camera/color/image_raw` +- `/camera/depth/image_raw` +- `/camera/depth/camera_info` + +鎵�浠ュ湪鍋氭爣瀹氬墠锛岄渶瑕佸厛鎶� Gemini 2 鐨� ROS 璇濋璺戣捣鏉ャ�� + +--- + +## 2. 鐩綍璇存槑 + +```bash +~/arm_plane_calib +鈹溾攢鈹� biaodi.png # 鏍囧畾绀烘剰鍥� +鈹溾攢鈹� collect_plane_calib.py # 閲囨牱鑴氭湰 +鈹溾攢鈹� depth_click_to_learm_cmd_node.py # 鐐瑰嚮娣卞害鍥� -> 棰勬祴鑸垫満鍊� -> 鍙�夎嚜鍔ㄥ彂閫� +鈹溾攢鈹� fit_plane_calib.py # 鎷熷悎鑴氭湰 +鈹溾攢鈹� learm_test.py # 鏈烘鑷備覆鍙f祴璇曡剼鏈� +鈹溾攢鈹� model.yaml # 鎷熷悎鍚庣殑妯″瀷鍙傛暟 +鈹溾攢鈹� predict_plane_cmd.py # 鐐瑰嚮鍥惧儚棰勬祴鑸垫満鍛戒护 +鈹溾攢鈹� readme.md # 鍘熷璇存槑 +鈹斺攢鈹� samples.yaml # 閲囨牱鏁版嵁 +``` + +--- + +## 3. 骞抽潰鏍囧畾鐨勭洰鐨� + +骞抽潰鏍囧畾鐨勬牳蹇冪洰鐨勬槸锛� + +> 褰撲綘鍦ㄧ浉鏈虹敾闈腑鐐瑰嚮涓�涓闈㈢洰鏍囩偣鏃讹紝绯荤粺鑳藉鏍规嵁娣卞害鐩告満娴嬪緱鐨勪笁缁翠俊鎭紝棰勬祴鍑轰竴缁勬満姊拌噦鑸垫満鎺у埗鍊硷紝浣挎満姊拌噦鏈杩愬姩鍒拌鐩爣鐐逛笂鏂广�� + +褰撳墠杩欏鏍囧畾浣跨敤鐨勬槸锛� + +- 杈撳叆鐗瑰緛锛歚x_cam`, `y_cam` +- 鎷熷悎妯″瀷锛氫簩娆″椤瑰紡 +- 鐗瑰緛椤哄簭锛歚[1, x, y, x虏, x*y, y虏]` + +娉ㄦ剰锛氬綋鍓嶆嫙鍚� **涓嶇洿鎺ヤ娇鐢� `z_cam` 鍋氬缓妯�**锛屼絾浼氳褰� `z_cam`锛屽苟鍦� `model.yaml` 涓粰鍑� `z_ref_median` 浣滀负鍙傝�冦�� + +--- + +## 4. 鏍囧畾鍓嶅噯澶� + +### 4.1 鍏堝惎鍔� Gemini 2 + +```bash +cd ~/dev_ws +source /opt/ros/humble/setup.bash +source install/setup.bash +ros2 launch origintank_bringup orbbec_gemini2.launch.py +``` + +### 4.2 鍐嶈繘鍏ユ爣瀹氱洰褰� + +```bash +cd ~/arm_plane_calib +``` + +--- + +## 5. 鑴氭湰璇存槑 + +### 5.1 `collect_plane_calib.py` 鈥斺�� 閲囨牱鑴氭湰 + +浣滅敤锛� + +- 璁㈤槄锛� + - `/camera/color/image_raw` + - `/camera/depth/image_raw` + - `/camera/depth/camera_info` +- 榧犳爣鐐瑰嚮鍥惧儚涓殑鏍囧畾鐐� +- 鑷姩璁$畻璇ョ偣鐨勭浉鏈哄潗鏍� `X_cam, Y_cam, Z_cam` +- 缁堢鎵嬪姩杈撳叆瀵瑰簲鐨勬満姊拌噦鍛戒护鍚戦噺 +- 鑷姩淇濆瓨鍒� `samples.yaml` +- 閲囨弧璁惧畾鏁伴噺鍚庤嚜鍔ㄩ��鍑� + +榛樿鍙傛暟瑕佺偣锛� + +- `save_path = samples.yaml` +- `depth_scale = 0.001` +- `min_depth_m = 0.05` +- `max_depth_m = 1.50` +- `median_kernel = 5` +- `target_count = 9` + +杩愯锛� + +```bash +cd ~/arm_plane_calib +python3 collect_plane_calib.py +``` + +閲囨牱鏃剁粓绔緭鍏ョず渚嬶細 + +```bash +520,610,430,500 +``` + +杩� 4 缁村懡浠ゅ悜閲忕殑鍏蜂綋鍚箟锛岄渶瑕佷笌浣犵殑妯″瀷杈撳嚭椤哄簭淇濇寔涓�鑷淬�� + +--- + +### 5.2 `fit_plane_calib.py` 鈥斺�� 鎷熷悎鑴氭湰 + +浣滅敤锛� + +- 璇诲彇 `samples.yaml` +- 鏋勯�犱簩娆″椤瑰紡鐗瑰緛 +- 瀵规満姊拌噦鍛戒护鍚戦噺鍋氭渶灏忎簩涔樻嫙鍚� +- 杈撳嚭 `model.yaml` +- 鍚屾椂鎵撳嵃姣忎竴缁寸殑 `MAE` 鍜� `RMSE` + +杩愯锛� + +```bash +cd ~/arm_plane_calib +python3 fit_plane_calib.py samples.yaml model.yaml +``` + +瑕佹眰锛� + +- 鑷冲皯闇�瑕� `6` 涓牱鏈偣鎵嶈兘鎷熷悎 +- 瀹為檯寤鸿 `9~16` 涓偣 +- 鐐逛綅灏介噺閾烘弧宸ヤ綔鍖猴紝涓嶈鍙泦涓湪涓棿 + +--- + +### 5.3 `predict_plane_cmd.py` 鈥斺�� 鐐瑰嚮鍥惧儚棰勬祴鑸垫満鍊� + +浣滅敤锛� + +- 杩愯鏃剁偣鍑诲浘鍍忎换鎰忎綅缃� +- 鑷姩姹傚彇璇ュ儚绱犵偣瀵瑰簲鐨勭浉鏈轰笁缁村潗鏍� +- 璋冪敤 `model.yaml` 棰勬祴鏈烘鑷傚懡浠ゅ悜閲� +- 鍦ㄧ粓绔緭鍑洪娴嬬粨鏋� + +杩愯锛� + +```bash +cd ~/arm_plane_calib +python3 predict_plane_cmd.py +``` + +褰撳墠鑴氭湰涓殑鍏抽敭绾﹀畾锛� + +- 妯″瀷杈撳嚭椤哄簭鍥哄畾涓猴細**6銆�5銆�4銆�3** +- 缁堢鎵撳嵃鏃朵細鏁寸悊涓猴細**3銆�4銆�5銆�6** +- 褰撳墠榛樿鑸垫満闄愬箙鑼冨洿锛歚125 ~ 875` + +绀轰緥杈撳嚭锛� + +```text +鐐瑰嚮鍍忕礌: (694, 230) +鐩告満鍧愭爣: X=0.0267, Y=-0.0681, Z=0.3600 +棰勬祴鏈烘鑷傚懡浠ゅ悜閲�(鎸夋ā鍨嬮『搴� 6,5,4,3): 501, 874, 385, 393 +鑸垫満鍒楄〃: 3:393,4:385,5:874,6:501 +``` + +--- + +### 5.4 `depth_click_to_learm_cmd_node.py` 鈥斺�� 鐐瑰嚮娣卞害鍥惧悗鍙洿鎺ュ彂閫佹帶鍒� + +浣滅敤锛� + +- 璁㈤槄娣卞害鍥俱�佸僵鑹插浘鍜岀浉鏈哄唴鍙� +- 鐐瑰嚮鍥惧儚鍚庤嚜鍔ㄩ娴嬫満姊拌噦鍛戒护鍚戦噺 +- 鍙寜鍙傛暟鍐冲畾鏄惁鑷姩閫氳繃涓插彛鍙戦�佺粰鏈烘鑷� + +鍏抽敭榛樿鍙傛暟锛� + +- `serial_port = /dev/ttyUSB0` +- `baud_rate = 9600` +- `move_time_ms = 800` +- `servo_ids = [6, 5, 4, 3]` +- `servo_min = [125, 125, 125, 125]` +- `servo_max = [875, 875, 875, 875]` +- `auto_send = True` + +**娉ㄦ剰锛氳繖涓剼鏈簮鐮侀粯璁や覆鍙d粛鐒跺啓鐨勬槸 `/dev/ttyUSB0`锛屼笌浣犲綋鍓嶆満鍣ㄧ殑鏈烘鑷傚疄闄呭彛 `/dev/ttyUSB1` 涓嶄竴鑷淬��** + +鍥犳褰撳墠鏈哄櫒浣跨敤鏃讹紝寤鸿鏄惧紡浼犲弬锛� + +```bash +cd ~/arm_plane_calib +python3 depth_click_to_learm_cmd_node.py --ros-args -p serial_port:=/dev/ttyUSB1 -p baud_rate:=9600 +``` + +--- + +### 5.5 `learm_test.py` 鈥斺�� 鏈烘鑷備覆鍙f祴璇曡剼鏈� + +浣滅敤锛� + +- 娴嬭瘯涓插彛鏄惁鑳借繛涓婃満姊拌噦 +- 鏌ヨ鍥轰欢 +- 鍥炶鑸垫満浣嶇疆 +- 鍙戝垵濮嬩綅濮垮懡浠� +- 鎺у埗鍗曚釜鎴栧涓埖鏈� + +褰撳墠鑴氭湰 `main()` 閲岄粯璁ゅ啓鐨勬槸锛� + +- `port = /dev/ttyUSB0` +- `baudrate = 9600` + +浣嗕綘褰撳墠鏈哄櫒鐨勬満姊拌噦瀹為檯杩炴帴涓� **`/dev/ttyUSB1`**锛屽洜姝や娇鐢ㄥ墠寤鸿鍏堟妸婧愮爜鏈�鍚庝竴琛屾敼鎴愶細 + +```python +arm = LeArmSerial(port="/dev/ttyUSB1", baudrate=9600) +``` + +鍐嶈繍琛岋細 + +```bash +cd ~/arm_plane_calib +python3 learm_test.py +``` + +--- + +## 6. 涔濈偣鏍囧畾鎺ㄨ崘娴佺▼ + +### 6.1 甯冪偣寤鸿 + +寤鸿鐢� 3脳3 鍏� 9 涓偣锛屽敖閲忛摵婊℃満姊拌噦瀹為檯鎶撳彇鍖哄煙锛� + +```text +1 2 3 +4 5 6 +7 8 9 +``` + +### 6.2 鍚姩 Gemini 2 + +```bash +cd ~/dev_ws +source /opt/ros/humble/setup.bash +source install/setup.bash +ros2 launch origintank_bringup orbbec_gemini2.launch.py +``` + +### 6.3 杩愯閲囨牱鑴氭湰 + +```bash +cd ~/arm_plane_calib +python3 collect_plane_calib.py +``` + +### 6.4 瀵规瘡涓偣閲嶅浠ヤ笅鍔ㄤ綔 + +1. 榧犳爣鐐瑰嚮鍥惧儚涓殑妗岄潰鏍囧畾鐐� +2. 鎵嬪姩鎶婃満姊拌噦鏈绉诲姩鍒拌鐐规涓婃柟 +3. 鍦ㄧ粓绔緭鍏ヨ繖涓�鐐圭殑鏈烘鑷傚懡浠ゅ悜閲� +4. 鑴氭湰鑷姩淇濆瓨鍒� `samples.yaml` + +渚嬪杈撳叆锛� + +```bash +520,610,430,500 +``` + +璇存槑锛� + +- 褰撳墠鏍囧畾榛樿浠� **4 缁村懡浠ゅ悜閲�** 涓轰緥 +- 澶圭埅寮�鍚堥�氬父涓嶅弬涓庡钩闈㈡爣瀹� +- 鎶撳彇鏃跺啀鍗曠嫭闄勫姞澶圭埅鍔ㄤ綔鍗冲彲 + +### 6.5 瀹屾垚鍚庢嫙鍚堟ā鍨� + +```bash +cd ~/arm_plane_calib +python3 fit_plane_calib.py samples.yaml model.yaml +``` + +### 6.6 棰勬祴娴嬭瘯 + +```bash +cd ~/arm_plane_calib +python3 predict_plane_cmd.py +``` diff --git a/arm_plane_calib/samples.yaml b/arm_plane_calib/samples.yaml new file mode 100644 index 0000000..38b5e3b --- /dev/null +++ b/arm_plane_calib/samples.yaml @@ -0,0 +1,92 @@ +samples: +- u: 582 + v: 240 + x_cam: -0.03145534404311617 + y_cam: -0.0625876597787623 + z_cam: 0.358 + arm_cmd: + - 540.0 + - 885.0 + - 421.0 + - 375.0 +- u: 681 + v: 233 + x_cam: 0.01995364206116322 + y_cam: -0.06658371695309058 + z_cam: 0.36 + arm_cmd: + - 505.0 + - 884.0 + - 369.0 + - 401.0 +- u: 771 + v: 243 + x_cam: 0.06592038079659751 + y_cam: -0.060522141786992736 + z_cam: 0.355 + arm_cmd: + - 467.0 + - 872.0 + - 363.0 + - 422.0 +- u: 566 + v: 316 + x_cam: -0.03830266258671575 + y_cam: -0.022374943079671503 + z_cam: 0.34500000000000003 + arm_cmd: + - 514.0 + - 847.0 + - 284.0 + - 419.0 +- u: 681 + v: 323 + x_cam: 0.019066813525111522 + y_cam: -0.018825745192638882 + z_cam: 0.34400000000000003 + arm_cmd: + - 468.0 + - 815.0 + - 332.0 + - 363.0 +- u: 761 + v: 329 + x_cam: 0.05855634668063165 + y_cam: -0.015747077324389527 + z_cam: 0.342 + arm_cmd: + - 513.0 + - 879.0 + - 242.0 + - 498.0 +- u: 566 + v: 412 + x_cam: -0.03674835164116786 + y_cam: 0.024512461886783923 + z_cam: 0.331 + arm_cmd: + - 566.0 + - 816.0 + - 274.0 + - 347.0 +- u: 681 + v: 419 + x_cam: 0.018179984989059823 + y_cam: 0.027612575073894863 + z_cam: 0.328 + arm_cmd: + - 518.0 + - 816.0 + - 274.0 + - 347.0 +- u: 780 + v: 419 + x_cam: 0.06517939133605848 + y_cam: 0.027612575073894863 + z_cam: 0.328 + arm_cmd: + - 450.0 + - 843.0 + - 384.0 + - 265.0 +cmd_dim: 4 diff --git a/dev_ws/README.md b/dev_ws/README.md new file mode 100644 index 0000000..751a524 --- /dev/null +++ b/dev_ws/README.md @@ -0,0 +1,210 @@ +# README_RDK_X5 浣跨敤璇存槑 + + +## 1. 褰撳墠鏈哄櫒鐨勫疄闄呰澶囨槧灏� + +鏍规嵁鐜板満鏋氫妇缁撴灉锛屽綋鍓嶆満鍣ㄥ缓璁寜涓嬮潰鐨勬槧灏勭悊瑙e拰浣跨敤锛� + +### 1.1 涓插彛璁惧 + +- **搴曠洏鎺у埗鍙�**锛歚/dev/ttyUSB0` +- **鏈烘鑷傛帶鍒跺彛**锛歚/dev/ttyUSB1` +- **鏈烘鑷傞粯璁ゆ尝鐗圭巼**锛歚9600` + +鐜板満涓插彛鏋氫妇锛� + +```bash +root@ubuntu:~# ls /dev/ttyUSB* +/dev/ttyUSB0 /dev/ttyUSB1 +``` + +### 1.2 鎽勫儚澶磋澶� + +- **鏅�� USB 鎽勫儚澶�**锛歚/dev/video0` +- **娣卞害鎽勫儚澶磋澶囪妭鐐�**锛歚/dev/video1` +- **娣卞害鐩告満鍨嬪彿**锛歄rbbec Gemini 2 + +鐜板満 USB 鏋氫妇锛� + +```bash +root@ubuntu:~# lsusb +Bus 002 Device 003: ID 2bc5:0670 Orbbec 3D Technology International, Inc Orbbec(R) Gemini(TM) +Bus 001 Device 008: ID 0c45:6341 Microdia Defender G-Lens 2577 HD720p Camera +Bus 001 Device 004: ID 1a86:7523 QinHeng Electronics CH340 serial converter +Bus 001 Device 003: ID 1a86:7523 QinHeng Electronics CH340 serial converter +``` + +### 1.3 涓�涓緢閲嶈鐨勮鏄� + +铏界劧绯荤粺閲岃兘鐪嬪埌 `/dev/video1`锛屼絾杩欏宸ョ▼涓殑 **Gemini 2 娣卞害鏁版嵁骞朵笉鏄寜鏅�� UVC 鎽勫儚澶存柟寮忕洿鎺ヨ鍙� `/dev/video1`**锛岃�屾槸閫氳繃 `orbbec_camera` 椹卞姩鍙戝竷 ROS 2 璇濋锛� + +- `/camera/color/image_raw` +- `/camera/depth/image_raw` +- `/camera/depth/camera_info` + +鎵�浠ワ細 + +- **鏅�� USB 鎽勫儚澶�** 璧� `usb_video_device:=/dev/video0` +- **Gemini 2** 璧� `orbbec_camera` 椹卞姩鍜屽搴� ROS 璇濋 + +涓嶈鎶婅繖涓ゅ閾捐矾娣峰湪涓�璧枫�� + +--- + +## 2. 宸ヤ綔绌洪棿鐩綍 + +```bash +~/dev_ws +鈹溾攢鈹� src +鈹� 鈹溾攢鈹� depth_target_detector +鈹� 鈹溾攢鈹� lerobot_arm_controller +鈹� 鈹溾攢鈹� mission_manager +鈹� 鈹溾攢鈹� orbbec_camera +鈹� 鈹溾攢鈹� orbbec_camera_msgs +鈹� 鈹溾攢鈹� origintank_base +鈹� 鈹溾攢鈹� origintank_bringup +鈹� 鈹斺攢鈹� signal_board_detector +``` + +--- + +## 3. 鍚勫姛鑳藉寘浣滅敤 + +- `origintank_base`锛氬簳鐩橀┍鍔紝璐熻矗搴曠洏鎺у埗涓庡熀纭�浼犳劅鍣ㄦ暟鎹彂甯� +- `origintank_bringup`锛氭暣鏈哄惎鍔ㄥ叆鍙� +- `mission_manager`锛氫换鍔$姸鎬佹満锛岀粺涓�璋冨害搴曠洏銆佽瘑鍒拰鏈烘鑷傚姩浣� +- `signal_board_detector`锛氭櫘閫� USB 鎽勫儚澶磋瘑鍒换鍔$洰鏍囨垨鏍囧織鐗� +- `depth_target_detector`锛氬熀浜� Gemini 2 杈撳嚭娣卞害鐩爣涓夌淮鐐� +- `lerobot_arm_controller`锛氭満姊拌噦涓插彛鎺у埗涓庢姄鍙栨祦绋� +- `orbbec_camera`锛欸emini 2 椹卞姩 +- `orbbec_camera_msgs`锛歄rbbec 鐩告満娑堟伅瀹氫箟 + +--- + +## 4. 鏁存満鎺у埗閾捐矾 + +鏁存満閾捐矾鍙互鐞嗚В涓猴細 + +1. **搴曠洏** 鐢� `origintank_base` 璐熻矗锛屽彂甯� `/odom`銆乣/imu`銆乣/ultrasonic/front/range` +2. **鏅�� USB 鎽勫儚澶�** 鐢辩浉鍏� launch 鎷夎捣锛屼緵 `signal_board_detector` 浣跨敤 +3. **Gemini 2** 鐢� `orbbec_camera` 鍚姩锛岃緭鍑哄僵鑹插浘銆佹繁搴﹀浘鍜岀浉鏈哄唴鍙� +4. `depth_target_detector` 灏嗙洰鏍囪浆鎹负涓夌淮鐐瑰苟鍙戝竷鍒� `/depth_target/point3d` +5. `lerobot_arm_controller` 璁㈤槄 `/depth_target/point3d`锛屾帶鍒舵満姊拌噦鎵ц鎶撳彇 +6. `mission_manager` 缁熶竴绠$悊寮�濮嬨�佸仠姝€�佺姸鎬佸垏鎹㈠拰浠诲姟娴佺▼ + +--- + +## 5. 缂栬瘧鍓嶅噯澶� + +### 5.1 鍔犺浇 ROS 鐜 + +```bash +source /opt/ros/humble/setup.bash +``` + +### 5.2 瀹夎 Orbbec udev 瑙勫垯 + +濡傛灉宸ョ▼閲屽甫鏈夊畨瑁呰剼鏈紝鍙厛鎵ц锛� + +```bash +cd ~/raico_rdk_x5_ws_minimal_gemini2 +chmod +x scripts/setup_orbbec_udev.sh +./scripts/setup_orbbec_udev.sh +``` + +濡傛灉浣犲疄闄呬娇鐢ㄧ殑鏄� `~/dev_ws` 杩欎竴濂楀伐绋嬶紝涔熻纭繚 `orbbec_camera/scripts/99-obsensor-libusb.rules` 宸叉纭畨瑁呭埌绯荤粺閲屻�� + +### 5.3 缂栬瘧宸ヤ綔绌洪棿 + +```bash +cd ~/dev_ws +source /opt/ros/humble/setup.bash +colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release +source install/setup.bash +``` + +--- + +## 6. 鍐呭瓨涓嶈冻鏃剁殑澶勭悊鏂规硶 + +Orbbec 鐩稿叧鍖呰緝澶э紝濡傛灉缂栬瘧鏃跺唴瀛樹笉瓒筹紝鍙互涓存椂寮� 8G swap锛� + +```bash +free -h +swapon --show + +fallocate -l 8G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=8192 +chmod 600 /swapfile +mkswap /swapfile +swapon /swapfile +free -h +swapon --show +``` + +缂栬瘧瀹屾垚鍚庡彲鍏抽棴锛� + +```bash +swapoff /swapfile +rm -f /swapfile +``` + +--- + +## 7. 鏁存満鍚姩鏂瑰紡 + +### 7.1 鎺ㄨ崘鍚姩鍛戒护锛堟寜褰撳墠鏈哄櫒瀹為檯杩炴帴锛� + +```bash +cd ~/dev_ws +source /opt/ros/humble/setup.bash +source install/setup.bash + +ros2 launch origintank_bringup rdk_x5_auto_mission.launch.py \ + cmd_port:=/dev/ttyUSB0 \ + arm_port:=/dev/ttyUSB1 \ + usb_video_device:=/dev/video0 +``` + +### 7.2 鍚姩鍚庨粯璁や細鎷夎捣鐨勬ā鍧� + +- 搴曠洏椹卞姩 +- 鏅�� USB 鎽勫儚澶磋瘑鍒� +- Gemini 2 椹卞姩 +- 娣卞害鐩爣妫�娴� +- 鏈烘鑷傛帶鍒� +- 浠诲姟鐘舵�佹満 + +--- + +## 8. 鍙祴璇� Gemini 2 + +```bash +cd ~/dev_ws +source /opt/ros/humble/setup.bash +source install/setup.bash + +ros2 launch origintank_bringup orbbec_gemini2.launch.py +``` + +鍙�夋鏌ワ細 + +```bash +ros2 run orbbec_camera list_devices_node +ros2 run orbbec_camera list_depth_work_mode_node +``` + +--- + +## 9. 鎵嬪姩鍚姩鍜屽仠姝换鍔� + +鍚姩浠诲姟锛� + +```bash +ros2 topic pub --once /mission/start std_msgs/msg/Bool "{data: true}" +``` + +鍋滄浠诲姟锛� + +```bash +ros2 topic pub --once /mission/start std_msgs/msg/Bool "{data: false}" +``` diff --git a/dev_ws/scripts/setup_orbbec_udev.sh b/dev_ws/scripts/setup_orbbec_udev.sh new file mode 100644 index 0000000..ce93c4a --- /dev/null +++ b/dev_ws/scripts/setup_orbbec_udev.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e +RULE_SRC="$(cd "$(dirname "$0")/.." && pwd)/src/orbbec_camera/scripts/99-obsensor-libusb.rules" +if [ ! -f "$RULE_SRC" ]; then + echo "udev rule not found: $RULE_SRC" >&2 + exit 1 +fi +sudo cp "$RULE_SRC" /etc/udev/rules.d/99-obsensor-libusb.rules +sudo udevadm control --reload-rules +sudo udevadm trigger +echo "Orbbec udev rules installed. Replug Gemini 2 if it is already connected." diff --git a/dev_ws/src/depth_target_detector/config/depth_target_detector.yaml b/dev_ws/src/depth_target_detector/config/depth_target_detector.yaml new file mode 100644 index 0000000..228e970 --- /dev/null +++ b/dev_ws/src/depth_target_detector/config/depth_target_detector.yaml @@ -0,0 +1,12 @@ +depth_target_detector: + ros__parameters: + depth_topic: "/camera/depth/image_raw" + camera_info_topic: "/camera/depth/camera_info" + min_depth_m: 0.10 + max_depth_m: 1.20 + roi_x_ratio: 0.25 + roi_y_ratio: 0.25 + roi_w_ratio: 0.50 + roi_h_ratio: 0.50 + nearest_band_m: 0.03 + min_cluster_pixels: 80 diff --git a/dev_ws/src/depth_target_detector/depth_target_detector/__init__.py b/dev_ws/src/depth_target_detector/depth_target_detector/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dev_ws/src/depth_target_detector/depth_target_detector/depth_target_detector_node.py b/dev_ws/src/depth_target_detector/depth_target_detector/depth_target_detector_node.py new file mode 100644 index 0000000..f1ce8b2 --- /dev/null +++ b/dev_ws/src/depth_target_detector/depth_target_detector/depth_target_detector_node.py @@ -0,0 +1,153 @@ +import cv2 +import numpy as np +import rclpy +from cv_bridge import CvBridge +from geometry_msgs.msg import PointStamped +from rclpy.node import Node +from sensor_msgs.msg import CameraInfo, Image + + +class DepthTargetDetector(Node): + def __init__(self) -> None: + super().__init__('depth_target_detector') + self.declare_parameter('depth_topic', '/camera/depth/image_raw') + self.declare_parameter('camera_info_topic', '/camera/depth/camera_info') + self.declare_parameter('min_depth_m', 0.10) + self.declare_parameter('max_depth_m', 1.20) + self.declare_parameter('roi_x_ratio', 0.25) + self.declare_parameter('roi_y_ratio', 0.25) + self.declare_parameter('roi_w_ratio', 0.50) + self.declare_parameter('roi_h_ratio', 0.50) + self.declare_parameter('nearest_band_m', 0.03) + self.declare_parameter('min_cluster_pixels', 80) + + self.depth_topic = str(self.get_parameter('depth_topic').value) + self.camera_info_topic = str(self.get_parameter('camera_info_topic').value) + self.min_depth_m = float(self.get_parameter('min_depth_m').value) + self.max_depth_m = float(self.get_parameter('max_depth_m').value) + self.roi_x_ratio = float(self.get_parameter('roi_x_ratio').value) + self.roi_y_ratio = float(self.get_parameter('roi_y_ratio').value) + self.roi_w_ratio = float(self.get_parameter('roi_w_ratio').value) + self.roi_h_ratio = float(self.get_parameter('roi_h_ratio').value) + self.nearest_band_m = float(self.get_parameter('nearest_band_m').value) + self.min_cluster_pixels = int(self.get_parameter('min_cluster_pixels').value) + + self.bridge = CvBridge() + self.point_pub = self.create_publisher(PointStamped, '/depth_target/point', 10) + self.point3d_pub = self.create_publisher(PointStamped, '/depth_target/point3d', 10) + self.debug_pub = self.create_publisher(Image, '/depth_target/debug_image', 10) + self.create_subscription(Image, self.depth_topic, self.on_depth_image, 10) + self.create_subscription(CameraInfo, self.camera_info_topic, self.on_camera_info, 10) + + self.fx = None + self.fy = None + self.cx = None + self.cy = None + + def on_camera_info(self, msg: CameraInfo) -> None: + if len(msg.k) >= 9: + self.fx = float(msg.k[0]) + self.fy = float(msg.k[4]) + self.cx = float(msg.k[2]) + self.cy = float(msg.k[5]) + + def normalize_depth(self, depth_image: np.ndarray) -> np.ndarray: + if depth_image.dtype == np.uint16: + return depth_image.astype(np.float32) / 1000.0 + return depth_image.astype(np.float32) + + def _extract_target(self, roi: np.ndarray): + valid_mask = np.logical_and(np.isfinite(roi), np.logical_and(roi > self.min_depth_m, roi < self.max_depth_m)) + if np.count_nonzero(valid_mask) < self.min_cluster_pixels: + return None + + valid_depths = np.where(valid_mask, roi, np.nan) + nearest = float(np.nanmin(valid_depths)) + band_mask = np.logical_and(valid_mask, roi <= nearest + self.nearest_band_m) + band_mask_u8 = (band_mask.astype(np.uint8) * 255) + band_mask_u8 = cv2.morphologyEx(band_mask_u8, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8)) + band_mask_u8 = cv2.morphologyEx(band_mask_u8, cv2.MORPH_CLOSE, np.ones((5, 5), np.uint8)) + + num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(band_mask_u8) + best = None + best_depth = None + for label in range(1, num_labels): + area = int(stats[label, cv2.CC_STAT_AREA]) + if area < self.min_cluster_pixels: + continue + ys, xs = np.where(labels == label) + depths = roi[ys, xs] + med_depth = float(np.median(depths)) + if best is None or med_depth < best_depth: + cx, cy = centroids[label] + best = (int(round(cx)), int(round(cy)), area, med_depth) + best_depth = med_depth + return best + + def on_depth_image(self, msg: Image) -> None: + depth_image = self.bridge.imgmsg_to_cv2(msg) + depth_m = self.normalize_depth(depth_image) + if depth_m.ndim != 2: + self.get_logger().warning('Depth image is not single channel, skip frame.') + return + + h, w = depth_m.shape[:2] + x0 = int(w * self.roi_x_ratio) + y0 = int(h * self.roi_y_ratio) + rw = int(w * self.roi_w_ratio) + rh = int(h * self.roi_h_ratio) + x1 = min(w, x0 + rw) + y1 = min(h, y0 + rh) + roi = depth_m[y0:y1, x0:x1] + + target = self._extract_target(roi) + if target is None: + return + + px_roi, py_roi, area, distance = target + global_x = x0 + px_roi + global_y = y0 + py_roi + offset_x = (global_x - (w / 2.0)) / (w / 2.0) + offset_y = (global_y - (h / 2.0)) / (h / 2.0) + + point = PointStamped() + point.header = msg.header + point.point.x = float(distance) + point.point.y = float(offset_x) + point.point.z = float(offset_y) + self.point_pub.publish(point) + + if all(v is not None for v in [self.fx, self.fy, self.cx, self.cy]): + x_cam = (global_x - self.cx) * distance / self.fx + y_cam = (global_y - self.cy) * distance / self.fy + z_cam = distance + point3d = PointStamped() + point3d.header = msg.header + point3d.point.x = float(x_cam) + point3d.point.y = float(y_cam) + point3d.point.z = float(z_cam) + self.point3d_pub.publish(point3d) + + roi_vis = np.nan_to_num(roi, nan=self.max_depth_m) + roi_vis = np.clip(roi_vis, self.min_depth_m, self.max_depth_m) + roi_vis = ((roi_vis - self.min_depth_m) / (self.max_depth_m - self.min_depth_m + 1e-6) * 255.0).astype(np.uint8) + roi_vis = cv2.applyColorMap(roi_vis, cv2.COLORMAP_JET) + cv2.circle(roi_vis, (px_roi, py_roi), 8, (255, 255, 255), 2) + cv2.putText(roi_vis, f'd={distance:.3f}m area={area}', (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2) + debug_msg = self.bridge.cv2_to_imgmsg(roi_vis, encoding='bgr8') + debug_msg.header = msg.header + self.debug_pub.publish(debug_msg) + + +def main() -> None: + rclpy.init() + node = DepthTargetDetector() + try: + rclpy.spin(node) + finally: + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/dev_ws/src/depth_target_detector/launch/depth_target_detector.launch.py b/dev_ws/src/depth_target_detector/launch/depth_target_detector.launch.py new file mode 100644 index 0000000..d7a8f66 --- /dev/null +++ b/dev_ws/src/depth_target_detector/launch/depth_target_detector.launch.py @@ -0,0 +1,20 @@ +from launch import LaunchDescription +from launch_ros.actions import Node +from ament_index_python.packages import get_package_share_directory +import os + + +def generate_launch_description(): + config = os.path.join( + get_package_share_directory('depth_target_detector'), + 'config', 'depth_target_detector.yaml' + ) + return LaunchDescription([ + Node( + package='depth_target_detector', + executable='depth_target_detector', + name='depth_target_detector', + output='screen', + parameters=[config], + ) + ]) diff --git a/dev_ws/src/depth_target_detector/package.xml b/dev_ws/src/depth_target_detector/package.xml new file mode 100644 index 0000000..0b6866e --- /dev/null +++ b/dev_ws/src/depth_target_detector/package.xml @@ -0,0 +1,23 @@ + + + + depth_target_detector + 0.1.0 + Simple depth target detector for sponge and floor block pickup. + OpenAI + Apache-2.0 + + + rclpy + geometry_msgs + sensor_msgs + cv_bridge + + python3-opencv + python3-numpy + ros2launch + + + ament_python + + diff --git a/dev_ws/src/depth_target_detector/resource/depth_target_detector b/dev_ws/src/depth_target_detector/resource/depth_target_detector new file mode 100644 index 0000000..e69de29 diff --git a/dev_ws/src/depth_target_detector/setup.cfg b/dev_ws/src/depth_target_detector/setup.cfg new file mode 100644 index 0000000..509a204 --- /dev/null +++ b/dev_ws/src/depth_target_detector/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/depth_target_detector +[install] +install_scripts=$base/lib/depth_target_detector diff --git a/dev_ws/src/depth_target_detector/setup.py b/dev_ws/src/depth_target_detector/setup.py new file mode 100644 index 0000000..e00ffa6 --- /dev/null +++ b/dev_ws/src/depth_target_detector/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup + +package_name = 'depth_target_detector' + +setup( + name=package_name, + version='0.1.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', ['launch/depth_target_detector.launch.py']), + ('share/' + package_name + '/config', ['config/depth_target_detector.yaml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='OpenAI', + maintainer_email='openai@example.com', + description='Simple depth target detector for sponge and floor block pickup', + license='Apache-2.0', + entry_points={ + 'console_scripts': [ + 'depth_target_detector = depth_target_detector.depth_target_detector_node:main', + ], + }, +) diff --git a/dev_ws/src/display_controller/config/display_controller.yaml b/dev_ws/src/display_controller/config/display_controller.yaml new file mode 100644 index 0000000..cc7967a --- /dev/null +++ b/dev_ws/src/display_controller/config/display_controller.yaml @@ -0,0 +1,13 @@ +display_controller: + ros__parameters: + width: 640 + height: 480 + square_size_px: 260 + publish_fps: 10.0 + minimum_hold_sec: 3.10 + show_window: false + window_name: "Logistics Challenge Display" + command_topic: "/display/command" + image_topic: "/display/image" + status_topic: "/display/status" + diff --git a/dev_ws/src/display_controller/display_controller/__init__.py b/dev_ws/src/display_controller/display_controller/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dev_ws/src/display_controller/display_controller/__init__.py @@ -0,0 +1 @@ + diff --git a/dev_ws/src/display_controller/display_controller/display_controller_node.py b/dev_ws/src/display_controller/display_controller/display_controller_node.py new file mode 100644 index 0000000..a81027c --- /dev/null +++ b/dev_ws/src/display_controller/display_controller/display_controller_node.py @@ -0,0 +1,168 @@ +import math +from typing import Optional + +import cv2 +import numpy as np +import rclpy +from cv_bridge import CvBridge +from rclpy.node import Node +from sensor_msgs.msg import Image +from std_msgs.msg import String + + +class DisplayController(Node): + def __init__(self) -> None: + super().__init__('display_controller') + self._declare_parameters() + self._load_parameters() + + self.bridge = CvBridge() + self.image_pub = self.create_publisher(Image, self.image_topic, 10) + self.status_pub = self.create_publisher(String, self.status_topic, 10) + self.create_subscription(String, self.command_topic, self.on_command, 10) + self.timer = self.create_timer(1.0 / max(self.publish_fps, 1.0), self.on_timer) + + self.current_command = 'clear' + self.command_start_time = self.get_clock().now() + self.done_sent = False + self.window_ready = False + self.last_frame: Optional[np.ndarray] = None + self.publish_status('ready:clear') + + def _declare_parameters(self) -> None: + defaults = { + 'width': 640, + 'height': 480, + 'square_size_px': 260, + 'publish_fps': 10.0, + 'minimum_hold_sec': 3.10, + 'show_window': False, + 'window_name': 'Logistics Challenge Display', + 'command_topic': '/display/command', + 'image_topic': '/display/image', + 'status_topic': '/display/status', + } + for name, value in defaults.items(): + self.declare_parameter(name, value) + + def _load_parameters(self) -> None: + get = self.get_parameter + self.width = max(64, int(get('width').value)) + self.height = max(64, int(get('height').value)) + self.square_size_px = max(10, int(get('square_size_px').value)) + self.publish_fps = float(get('publish_fps').value) + self.minimum_hold_sec = max(3.0, float(get('minimum_hold_sec').value)) + self.show_window = bool(get('show_window').value) + self.window_name = str(get('window_name').value) + self.command_topic = str(get('command_topic').value) + self.image_topic = str(get('image_topic').value) + self.status_topic = str(get('status_topic').value) + + def publish_status(self, text: str) -> None: + msg = String() + msg.data = text + self.status_pub.publish(msg) + self.get_logger().info(text) + + def on_command(self, msg: String) -> None: + command = msg.data.strip().lower() + supported = {'clear', 'blue_square', 'all_green', 'yellow_square', + 'yellow_triangle', 'yellow_star'} + if command not in supported: + self.publish_status(f'error:unsupported_command:{command}') + return + self.current_command = command + self.command_start_time = self.get_clock().now() + self.done_sent = False + self.publish_status(f'showing:{command}') + + def blank_frame(self, color=(255, 255, 255)) -> np.ndarray: + return np.full((self.height, self.width, 3), color, dtype=np.uint8) + + def render_frame(self) -> np.ndarray: + if self.current_command == 'all_green': + return self.blank_frame((0, 255, 0)) + if self.current_command == 'clear': + return self.blank_frame((255, 255, 255)) + + frame = self.blank_frame((255, 255, 255)) + centre = (self.width // 2, self.height // 2) + size = min(self.square_size_px, self.width - 20, self.height - 20) + half = size // 2 + if self.current_command == 'blue_square': + cv2.rectangle(frame, (centre[0] - half, centre[1] - half), + (centre[0] + half, centre[1] + half), (255, 0, 0), -1) + elif self.current_command == 'yellow_square': + cv2.rectangle(frame, (centre[0] - half, centre[1] - half), + (centre[0] + half, centre[1] + half), (0, 255, 255), -1) + elif self.current_command == 'yellow_triangle': + points = np.asarray([ + [centre[0], centre[1] - half], + [centre[0] - half, centre[1] + half], + [centre[0] + half, centre[1] + half], + ], dtype=np.int32) + cv2.fillPoly(frame, [points], (0, 255, 255)) + elif self.current_command == 'yellow_star': + points = [] + for index in range(10): + angle = -math.pi / 2.0 + index * math.pi / 5.0 + radius = half if index % 2 == 0 else half * 0.42 + points.append([ + int(round(centre[0] + radius * math.cos(angle))), + int(round(centre[1] + radius * math.sin(angle))), + ]) + cv2.fillPoly(frame, [np.asarray(points, dtype=np.int32)], (0, 255, 255)) + return frame + + def on_timer(self) -> None: + frame = self.render_frame() + self.last_frame = frame + image_msg = self.bridge.cv2_to_imgmsg(frame, encoding='bgr8') + image_msg.header.stamp = self.get_clock().now().to_msg() + image_msg.header.frame_id = 'competition_display' + self.image_pub.publish(image_msg) + + if self.show_window: + try: + if not self.window_ready: + cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL) + cv2.setWindowProperty( + self.window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN + ) + self.window_ready = True + cv2.imshow(self.window_name, frame) + cv2.waitKey(1) + except cv2.error as exc: + self.show_window = False + self.publish_status(f'error:display_window:{exc}') + + if self.current_command == 'clear' or self.done_sent: + return + elapsed = (self.get_clock().now() - self.command_start_time).nanoseconds / 1e9 + if elapsed >= self.minimum_hold_sec: + self.done_sent = True + self.publish_status(f'done:{self.current_command}') + + def destroy_node(self): + if self.window_ready: + try: + cv2.destroyWindow(self.window_name) + except cv2.error: + pass + return super().destroy_node() + + +def main() -> None: + rclpy.init() + node = DisplayController() + try: + rclpy.spin(node) + except KeyboardInterrupt: + pass + finally: + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/dev_ws/src/display_controller/launch/display_controller.launch.py b/dev_ws/src/display_controller/launch/display_controller.launch.py new file mode 100644 index 0000000..56ead6c --- /dev/null +++ b/dev_ws/src/display_controller/launch/display_controller.launch.py @@ -0,0 +1,35 @@ +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node +from launch_ros.parameter_descriptions import ParameterValue + + +def generate_launch_description(): + config = os.path.join( + get_package_share_directory('display_controller'), + 'config', + 'display_controller.yaml', + ) + return LaunchDescription([ + DeclareLaunchArgument('show_window', default_value='false'), + Node( + package='display_controller', + executable='display_controller', + name='display_controller', + output='screen', + parameters=[ + config, + { + 'show_window': ParameterValue( + LaunchConfiguration('show_window'), + value_type=bool, + ) + }, + ], + ) + ]) + diff --git a/dev_ws/src/display_controller/package.xml b/dev_ws/src/display_controller/package.xml new file mode 100644 index 0000000..0f5df12 --- /dev/null +++ b/dev_ws/src/display_controller/package.xml @@ -0,0 +1,22 @@ + + + + display_controller + 0.1.0 + Competition pattern display controller. + SK + Apache-2.0 + + rclpy + sensor_msgs + std_msgs + cv_bridge + python3-opencv + python3-numpy + ros2launch + + + ament_python + + + diff --git a/dev_ws/src/display_controller/resource/display_controller b/dev_ws/src/display_controller/resource/display_controller new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dev_ws/src/display_controller/resource/display_controller @@ -0,0 +1 @@ + diff --git a/dev_ws/src/display_controller/setup.cfg b/dev_ws/src/display_controller/setup.cfg new file mode 100644 index 0000000..368b0c2 --- /dev/null +++ b/dev_ws/src/display_controller/setup.cfg @@ -0,0 +1,5 @@ +[develop] +script_dir=$base/lib/display_controller +[install] +install_scripts=$base/lib/display_controller + diff --git a/dev_ws/src/display_controller/setup.py b/dev_ws/src/display_controller/setup.py new file mode 100644 index 0000000..05f6ba4 --- /dev/null +++ b/dev_ws/src/display_controller/setup.py @@ -0,0 +1,29 @@ +from setuptools import setup + + +package_name = 'display_controller' + + +setup( + name=package_name, + version='0.1.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', ['launch/display_controller.launch.py']), + ('share/' + package_name + '/config', ['config/display_controller.yaml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='SK', + maintainer_email='sk@example.com', + description='Competition display image and hold-time controller.', + license='Apache-2.0', + entry_points={ + 'console_scripts': [ + 'display_controller = display_controller.display_controller_node:main', + ], + }, +) + diff --git a/dev_ws/src/lerobot_arm_controller/config/lerobot_arm_controller.yaml b/dev_ws/src/lerobot_arm_controller/config/lerobot_arm_controller.yaml new file mode 100644 index 0000000..d73633b --- /dev/null +++ b/dev_ws/src/lerobot_arm_controller/config/lerobot_arm_controller.yaml @@ -0,0 +1,36 @@ +lerobot_arm_controller: + ros__parameters: + simulation: false + port: "/dev/ttyUSB2" + baud_rate: 115200 + serial_timeout_sec: 0.10 + latest_point_timeout_sec: 1.0 + move_time_ms: 500 + settle_sec: 0.20 + safe_z_cm: 18.0 + home_x_cm: 15.0 + home_y_cm: 0.0 + home_z_cm: 10.0 + grasp_pre_z_offset_cm: 4.0 + grasp_final_z_offset_cm: 1.0 + gripper_open_angle_deg: 90.0 + gripper_close_angle_deg: 18.0 + wrist_roll_angle_deg: 0.0 + camera_to_arm_x_m: 0.02 + camera_to_arm_y_m: 0.00 + camera_to_arm_z_m: 0.08 + grasp_forward_extra_m: 0.00 + grasp_lateral_extra_m: 0.00 + grasp_height_extra_m: 0.00 + platform_left_x_cm: 14.0 + platform_left_y_cm: 8.0 + platform_left_z_cm: 4.5 + platform_right_x_cm: 14.0 + platform_right_y_cm: -8.0 + platform_right_z_cm: 4.5 + blue_zone_x_cm: 18.0 + blue_zone_y_cm: 8.0 + blue_zone_z_cm: 4.0 + green_zone_x_cm: 18.0 + green_zone_y_cm: -8.0 + green_zone_z_cm: 4.0 diff --git a/dev_ws/src/lerobot_arm_controller/launch/lerobot_arm_controller.launch.py b/dev_ws/src/lerobot_arm_controller/launch/lerobot_arm_controller.launch.py new file mode 100644 index 0000000..a381e02 --- /dev/null +++ b/dev_ws/src/lerobot_arm_controller/launch/lerobot_arm_controller.launch.py @@ -0,0 +1,27 @@ +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node + + +def generate_launch_description(): + cfg = os.path.join( + get_package_share_directory('lerobot_arm_controller'), 'config', 'lerobot_arm_controller.yaml' + ) + return LaunchDescription([ + DeclareLaunchArgument('port', default_value='/dev/ttyUSB2'), + DeclareLaunchArgument('baud_rate', default_value='115200'), + Node( + package='lerobot_arm_controller', + executable='lerobot_arm_controller', + name='lerobot_arm_controller', + output='screen', + parameters=[cfg, { + 'port': LaunchConfiguration('port'), + 'baud_rate': LaunchConfiguration('baud_rate'), + }], + ) + ]) diff --git a/dev_ws/src/lerobot_arm_controller/lerobot_arm_controller/__init__.py b/dev_ws/src/lerobot_arm_controller/lerobot_arm_controller/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dev_ws/src/lerobot_arm_controller/lerobot_arm_controller/lerobot_arm_controller_node.py b/dev_ws/src/lerobot_arm_controller/lerobot_arm_controller/lerobot_arm_controller_node.py new file mode 100644 index 0000000..9a74ed7 --- /dev/null +++ b/dev_ws/src/lerobot_arm_controller/lerobot_arm_controller/lerobot_arm_controller_node.py @@ -0,0 +1,346 @@ +import math +import queue +import struct +import threading +import time +from typing import Optional, Tuple + +import rclpy +from geometry_msgs.msg import PointStamped +from rclpy.node import Node +from std_msgs.msg import String + +try: + import serial # type: ignore +except Exception: # pragma: no cover + serial = None + + +APP_PACKET_HEADER = 0x55 +CMD_MULT_SERVO_MOVE = 3 +CMD_COORDINATE_SET = 4 + +MIN_X_CM = 10.0 +MAX_X_CM = 20.0 +MIN_Y_CM = -10.0 +MAX_Y_CM = 10.0 +MIN_Z_CM = 0.0 +MAX_Z_CM = 25.0 + +SERIAL_ANGLE_FACTOR = 4.166666666666667 +SERIAL_CLAW_FACTOR = 5.555555555555556 + + +class LeRobotArmController(Node): + def __init__(self) -> None: + super().__init__('lerobot_arm_controller') + self._declare_parameters() + self._load_parameters() + + self.arm_status_pub = self.create_publisher(String, '/arm/status', 10) + self.arm_debug_target_pub = self.create_publisher(PointStamped, '/arm/debug_target', 10) + self.create_subscription(String, '/arm_command', self.on_arm_command, 10) + self.create_subscription(PointStamped, '/depth_target/point3d', self.on_depth_point, 10) + + self.latest_point3d: Optional[PointStamped] = None + self.current_xyz_cm = [self.home_x_cm, self.home_y_cm, self.home_z_cm] + self._cmd_queue: 'queue.Queue[str]' = queue.Queue() + self._worker = threading.Thread(target=self._worker_loop, daemon=True) + self._worker.start() + + self.ser = None + if not self.simulation: + self._open_serial() + + self.publish_status('idle') + + def _declare_parameters(self) -> None: + defaults = { + 'simulation': False, + 'port': '/dev/ttyUSB2', + 'baud_rate': 115200, + 'serial_timeout_sec': 0.10, + 'latest_point_timeout_sec': 1.0, + 'move_time_ms': 500, + 'settle_sec': 0.20, + 'safe_z_cm': 18.0, + 'home_x_cm': 15.0, + 'home_y_cm': 0.0, + 'home_z_cm': 10.0, + 'grasp_pre_z_offset_cm': 4.0, + 'grasp_final_z_offset_cm': 1.0, + 'gripper_open_angle_deg': 90.0, + 'gripper_close_angle_deg': 18.0, + 'wrist_roll_angle_deg': 0.0, + 'camera_to_arm_x_m': 0.02, + 'camera_to_arm_y_m': 0.0, + 'camera_to_arm_z_m': 0.08, + 'grasp_forward_extra_m': 0.0, + 'grasp_lateral_extra_m': 0.0, + 'grasp_height_extra_m': 0.0, + 'platform_left_x_cm': 14.0, + 'platform_left_y_cm': 8.0, + 'platform_left_z_cm': 4.5, + 'platform_right_x_cm': 14.0, + 'platform_right_y_cm': -8.0, + 'platform_right_z_cm': 4.5, + 'blue_zone_x_cm': 18.0, + 'blue_zone_y_cm': 8.0, + 'blue_zone_z_cm': 4.0, + 'green_zone_x_cm': 18.0, + 'green_zone_y_cm': -8.0, + 'green_zone_z_cm': 4.0, + } + for key, value in defaults.items(): + self.declare_parameter(key, value) + + def _load_parameters(self) -> None: + g = self.get_parameter + self.simulation = bool(g('simulation').value) + self.port = str(g('port').value) + self.baud_rate = int(g('baud_rate').value) + self.serial_timeout_sec = float(g('serial_timeout_sec').value) + self.latest_point_timeout_sec = float(g('latest_point_timeout_sec').value) + self.move_time_ms = int(g('move_time_ms').value) + self.settle_sec = float(g('settle_sec').value) + self.safe_z_cm = float(g('safe_z_cm').value) + self.home_x_cm = float(g('home_x_cm').value) + self.home_y_cm = float(g('home_y_cm').value) + self.home_z_cm = float(g('home_z_cm').value) + self.grasp_pre_z_offset_cm = float(g('grasp_pre_z_offset_cm').value) + self.grasp_final_z_offset_cm = float(g('grasp_final_z_offset_cm').value) + self.gripper_open_angle_deg = float(g('gripper_open_angle_deg').value) + self.gripper_close_angle_deg = float(g('gripper_close_angle_deg').value) + self.wrist_roll_angle_deg = float(g('wrist_roll_angle_deg').value) + self.camera_to_arm_x_m = float(g('camera_to_arm_x_m').value) + self.camera_to_arm_y_m = float(g('camera_to_arm_y_m').value) + self.camera_to_arm_z_m = float(g('camera_to_arm_z_m').value) + self.grasp_forward_extra_m = float(g('grasp_forward_extra_m').value) + self.grasp_lateral_extra_m = float(g('grasp_lateral_extra_m').value) + self.grasp_height_extra_m = float(g('grasp_height_extra_m').value) + self.platform_left = ( + float(g('platform_left_x_cm').value), + float(g('platform_left_y_cm').value), + float(g('platform_left_z_cm').value), + ) + self.platform_right = ( + float(g('platform_right_x_cm').value), + float(g('platform_right_y_cm').value), + float(g('platform_right_z_cm').value), + ) + self.blue_zone = ( + float(g('blue_zone_x_cm').value), + float(g('blue_zone_y_cm').value), + float(g('blue_zone_z_cm').value), + ) + self.green_zone = ( + float(g('green_zone_x_cm').value), + float(g('green_zone_y_cm').value), + float(g('green_zone_z_cm').value), + ) + + def _open_serial(self) -> None: + if serial is None: + raise RuntimeError('pyserial is not available, cannot control arm hardware.') + self.ser = serial.Serial(self.port, self.baud_rate, timeout=self.serial_timeout_sec) + self.get_logger().info(f'LeRobot arm serial opened: {self.port} @ {self.baud_rate}') + + def on_depth_point(self, msg: PointStamped) -> None: + self.latest_point3d = msg + + def on_arm_command(self, msg: String) -> None: + cmd = msg.data.strip() + if cmd: + self._cmd_queue.put(cmd) + + def publish_status(self, text: str) -> None: + msg = String() + msg.data = text + self.arm_status_pub.publish(msg) + + def _worker_loop(self) -> None: + while rclpy.ok(): + cmd = self._cmd_queue.get() + try: + self.publish_status('busy') + self._execute_command(cmd) + self.publish_status('done') + except Exception as exc: # pragma: no cover + self.get_logger().error(f'Arm command failed: {cmd}: {exc}') + self.publish_status('error') + + def _execute_command(self, cmd: str) -> None: + if cmd in {'home', 'move_home'}: + self.move_home() + return + if cmd == 'open_claw': + self.set_claw(self.gripper_open_angle_deg) + return + if cmd == 'close_claw': + self.set_claw(self.gripper_close_angle_deg) + return + if cmd.startswith('pick_and_place_platform:'): + side = cmd.split(':', 1)[1].strip().lower() + self.pick_from_latest_depth() + self.place_platform(side) + self.move_home() + return + if cmd.startswith('pick_block:'): + self.pick_from_latest_depth() + return + if cmd.startswith('place_block:'): + zone = cmd.split(':', 1)[1].strip().lower() + self.place_block(zone) + self.move_home() + return + if cmd in {'pick_from_depth', 'pick'}: + self.pick_from_latest_depth() + return + raise ValueError(f'Unsupported arm command: {cmd}') + + def _packet(self, cmd: int, payload: bytes) -> bytes: + return bytes([APP_PACKET_HEADER, APP_PACKET_HEADER, 2 + len(payload), cmd]) + payload + + def _write_packet(self, packet: bytes) -> None: + if self.simulation: + self.get_logger().info(f'[SIM] TX {packet.hex(" ")}') + return + assert self.ser is not None + self.ser.write(packet) + self.ser.flush() + + def send_coordinate_delta(self, dx_cm: float, dy_cm: float, dz_cm: float, move_time_ms: Optional[int] = None) -> None: + move_time_ms = int(move_time_ms or self.move_time_ms) + sx = int(max(-120, min(120, round(dx_cm * 10.0)))) + sy = int(max(-120, min(120, round(dy_cm * 10.0)))) + sz = int(max(-120, min(120, round(dz_cm * 10.0)))) + payload = struct.pack('bbb', sx, sy, sz) + self._write_packet(self._packet(CMD_COORDINATE_SET, payload)) + self.current_xyz_cm[0] += sx / 10.0 + self.current_xyz_cm[1] += sy / 10.0 + self.current_xyz_cm[2] += sz / 10.0 + time.sleep(max(move_time_ms / 1000.0, self.settle_sec)) + + def move_absolute_xyz(self, target_x_cm: float, target_y_cm: float, target_z_cm: float, move_time_ms: Optional[int] = None) -> None: + move_time_ms = int(move_time_ms or self.move_time_ms) + tx = max(MIN_X_CM, min(MAX_X_CM, target_x_cm)) + ty = max(MIN_Y_CM, min(MAX_Y_CM, target_y_cm)) + tz = max(MIN_Z_CM, min(MAX_Z_CM, target_z_cm)) + dx = tx - self.current_xyz_cm[0] + dy = ty - self.current_xyz_cm[1] + dz = tz - self.current_xyz_cm[2] + max_axis = max(abs(dx), abs(dy), abs(dz), 0.0) + steps = max(1, int(math.ceil(max_axis / 6.0))) + for i in range(1, steps + 1): + next_x = self.current_xyz_cm[0] + (tx - self.current_xyz_cm[0]) / (steps - i + 1) + next_y = self.current_xyz_cm[1] + (ty - self.current_xyz_cm[1]) / (steps - i + 1) + next_z = self.current_xyz_cm[2] + (tz - self.current_xyz_cm[2]) / (steps - i + 1) + self.send_coordinate_delta(next_x - self.current_xyz_cm[0], next_y - self.current_xyz_cm[1], next_z - self.current_xyz_cm[2], move_time_ms) + + def _send_multi_servo(self, pairs, move_time_ms: Optional[int] = None) -> None: + move_time_ms = int(move_time_ms or self.move_time_ms) + payload = bytearray() + payload.append(len(pairs)) + payload.append(move_time_ms & 0xFF) + payload.append((move_time_ms >> 8) & 0xFF) + for servo_id, duty in pairs: + payload.append(int(servo_id) & 0xFF) + payload.append(int(duty) & 0xFF) + payload.append((int(duty) >> 8) & 0xFF) + self._write_packet(self._packet(CMD_MULT_SERVO_MOVE, bytes(payload))) + time.sleep(max(move_time_ms / 1000.0, self.settle_sec)) + + def set_claw(self, open_angle_deg: float, move_time_ms: Optional[int] = None) -> None: + angle = max(0.0, min(90.0, open_angle_deg)) + duty = int(round(700.0 - SERIAL_CLAW_FACTOR * angle)) + duty = max(200, min(700, duty)) + self._send_multi_servo([(1, duty)], move_time_ms) + + def set_roll(self, rotation_angle_deg: float, move_time_ms: Optional[int] = None) -> None: + angle = max(-90.0, min(90.0, rotation_angle_deg)) + duty = int(round(500.0 - SERIAL_ANGLE_FACTOR * angle)) + duty = max(120, min(880, duty)) + self._send_multi_servo([(2, duty)], move_time_ms) + + def move_home(self) -> None: + self.move_absolute_xyz(self.current_xyz_cm[0], self.current_xyz_cm[1], max(self.current_xyz_cm[2], self.safe_z_cm)) + self.move_absolute_xyz(self.home_x_cm, self.home_y_cm, max(self.home_z_cm, self.safe_z_cm)) + self.move_absolute_xyz(self.home_x_cm, self.home_y_cm, self.home_z_cm) + self.set_roll(self.wrist_roll_angle_deg) + self.set_claw(self.gripper_open_angle_deg) + + def _latest_point_fresh(self) -> bool: + if self.latest_point3d is None: + return False + stamp = self.latest_point3d.header.stamp + point_time = float(stamp.sec) + float(stamp.nanosec) / 1e9 + now_time = self.get_clock().now().nanoseconds / 1e9 + return (now_time - point_time) <= self.latest_point_timeout_sec + + def camera_point_to_arm_xyz_cm(self, point: PointStamped) -> Tuple[float, float, float]: + x_cam = float(point.point.x) + y_cam = float(point.point.y) + z_cam = float(point.point.z) + arm_x_m = z_cam + self.camera_to_arm_x_m + self.grasp_forward_extra_m + arm_y_m = -x_cam + self.camera_to_arm_y_m + self.grasp_lateral_extra_m + arm_z_m = -y_cam + self.camera_to_arm_z_m + self.grasp_height_extra_m + debug = PointStamped() + debug.header = point.header + debug.point.x = arm_x_m + debug.point.y = arm_y_m + debug.point.z = arm_z_m + self.arm_debug_target_pub.publish(debug) + return arm_x_m * 100.0, arm_y_m * 100.0, arm_z_m * 100.0 + + def pick_from_latest_depth(self) -> None: + if not self._latest_point_fresh(): + raise RuntimeError('No fresh /depth_target/point3d available for grasping.') + assert self.latest_point3d is not None + target_x_cm, target_y_cm, target_z_cm = self.camera_point_to_arm_xyz_cm(self.latest_point3d) + pre_z = target_z_cm + self.grasp_pre_z_offset_cm + final_z = target_z_cm + self.grasp_final_z_offset_cm + + self.set_roll(self.wrist_roll_angle_deg) + self.set_claw(self.gripper_open_angle_deg) + self.move_absolute_xyz(self.current_xyz_cm[0], self.current_xyz_cm[1], max(self.current_xyz_cm[2], self.safe_z_cm)) + self.move_absolute_xyz(target_x_cm, target_y_cm, max(pre_z, self.safe_z_cm)) + self.move_absolute_xyz(target_x_cm, target_y_cm, pre_z) + self.move_absolute_xyz(target_x_cm, target_y_cm, final_z, move_time_ms=max(250, self.move_time_ms // 2)) + self.set_claw(self.gripper_close_angle_deg, move_time_ms=max(250, self.move_time_ms // 2)) + self.move_absolute_xyz(target_x_cm, target_y_cm, max(pre_z, self.safe_z_cm)) + + def place_platform(self, side: str) -> None: + target = self.platform_left if side == 'left' else self.platform_right + self._place_to_xyz(target) + + def place_block(self, zone: str) -> None: + if zone == 'blue': + self._place_to_xyz(self.blue_zone) + elif zone == 'green': + self._place_to_xyz(self.green_zone) + else: + raise ValueError(f'Unknown place zone: {zone}') + + def _place_to_xyz(self, target_xyz_cm: Tuple[float, float, float]) -> None: + tx, ty, tz = target_xyz_cm + pre_z = max(tz + 4.0, self.safe_z_cm) + self.move_absolute_xyz(self.current_xyz_cm[0], self.current_xyz_cm[1], max(self.current_xyz_cm[2], self.safe_z_cm)) + self.move_absolute_xyz(tx, ty, pre_z) + self.move_absolute_xyz(tx, ty, tz) + self.set_claw(self.gripper_open_angle_deg) + self.move_absolute_xyz(tx, ty, pre_z) + + +def main() -> None: + rclpy.init() + node = LeRobotArmController() + try: + rclpy.spin(node) + finally: + if getattr(node, 'ser', None) is not None: + try: + node.ser.close() + except Exception: + pass + node.destroy_node() + rclpy.shutdown() diff --git a/dev_ws/src/lerobot_arm_controller/package.xml b/dev_ws/src/lerobot_arm_controller/package.xml new file mode 100644 index 0000000..77cc86c --- /dev/null +++ b/dev_ws/src/lerobot_arm_controller/package.xml @@ -0,0 +1,23 @@ + + + lerobot_arm_controller + 0.1.0 + LeRobot mechanical arm controller with depth-guided grasping for ROS 2 Humble + OpenAI + Apache-2.0 + + + rclpy + std_msgs + geometry_msgs + builtin_interfaces + + python3-serial + + ament_lint_auto + ament_lint_common + + + ament_python + + diff --git a/dev_ws/src/lerobot_arm_controller/resource/lerobot_arm_controller b/dev_ws/src/lerobot_arm_controller/resource/lerobot_arm_controller new file mode 100644 index 0000000..e69de29 diff --git a/dev_ws/src/lerobot_arm_controller/setup.cfg b/dev_ws/src/lerobot_arm_controller/setup.cfg new file mode 100644 index 0000000..475e03a --- /dev/null +++ b/dev_ws/src/lerobot_arm_controller/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/lerobot_arm_controller +[install] +install_scripts=$base/lib/lerobot_arm_controller diff --git a/dev_ws/src/lerobot_arm_controller/setup.py b/dev_ws/src/lerobot_arm_controller/setup.py new file mode 100644 index 0000000..fd546e2 --- /dev/null +++ b/dev_ws/src/lerobot_arm_controller/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup + +package_name = 'lerobot_arm_controller' + +setup( + name=package_name, + version='0.1.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', ['launch/lerobot_arm_controller.launch.py']), + ('share/' + package_name + '/config', ['config/lerobot_arm_controller.yaml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='OpenAI', + maintainer_email='openai@example.com', + description='ROS 2 serial arm controller for LeRobot arm with depth-guided grasping', + license='Apache-2.0', + entry_points={ + 'console_scripts': [ + 'lerobot_arm_controller = lerobot_arm_controller.lerobot_arm_controller_node:main', + ], + }, +) diff --git a/dev_ws/src/mission_manager/config/mission_manager.yaml b/dev_ws/src/mission_manager/config/mission_manager.yaml new file mode 100644 index 0000000..0496b37 --- /dev/null +++ b/dev_ws/src/mission_manager/config/mission_manager.yaml @@ -0,0 +1,17 @@ +mission_manager: + ros__parameters: + autostart: false + auto_arm_complete_timeout_sec: 8.0 + platform_side: "left" + blue_zone_label: "blue" + green_zone_label: "green" + approach_speed_mps: 0.18 + slope_speed_mps: 0.32 + lateral_speed_mps: 0.12 + turn_speed_radps: 0.65 + yaw_tolerance_deg: 5.0 + ultrasonic_stop_distance_m: 0.35 + signboard_stop_distance_m: 0.70 + board_hold_sec: 3.0 + alignment_tolerance: 0.12 + max_wait_signal_board_sec: 30.0 diff --git a/dev_ws/src/mission_manager/launch/mission_manager.launch.py b/dev_ws/src/mission_manager/launch/mission_manager.launch.py new file mode 100644 index 0000000..05ff897 --- /dev/null +++ b/dev_ws/src/mission_manager/launch/mission_manager.launch.py @@ -0,0 +1,21 @@ +from launch import LaunchDescription +from launch_ros.actions import Node +from ament_index_python.packages import get_package_share_directory +import os + + +def generate_launch_description(): + config = os.path.join( + get_package_share_directory('mission_manager'), + 'config', + 'mission_manager.yaml' + ) + return LaunchDescription([ + Node( + package='mission_manager', + executable='mission_manager', + name='mission_manager', + output='screen', + parameters=[config], + ) + ]) diff --git a/dev_ws/src/mission_manager/mission_manager/__init__.py b/dev_ws/src/mission_manager/mission_manager/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dev_ws/src/mission_manager/mission_manager/mission_manager_node.py b/dev_ws/src/mission_manager/mission_manager/mission_manager_node.py new file mode 100644 index 0000000..35a2c3b --- /dev/null +++ b/dev_ws/src/mission_manager/mission_manager/mission_manager_node.py @@ -0,0 +1,310 @@ +import math +from enum import Enum, auto +from typing import Optional + +import rclpy +from geometry_msgs.msg import PointStamped, Twist +from nav_msgs.msg import Odometry +from rclpy.duration import Duration +from rclpy.node import Node +from sensor_msgs.msg import Imu, Range +from std_msgs.msg import Bool, String + + +class MissionState(Enum): + IDLE = auto() + APPROACH_SLOPE_ENTRY = auto() + PICK_AND_PLACE_SPONGE = auto() + TURN_LEFT_90 = auto() + RUSH_SLOPE = auto() + CHECK_SIGNAL_BOARD = auto() + MOVE_TO_BLOCK_1 = auto() + PICK_BLOCK_1 = auto() + PLACE_BLOCK_1 = auto() + MOVE_TO_BLOCK_2 = auto() + PICK_BLOCK_2 = auto() + PLACE_BLOCK_2 = auto() + FINISHED = auto() + + +class MissionManager(Node): + def __init__(self) -> None: + super().__init__('mission_manager') + + self.declare_parameter('autostart', False) + self.declare_parameter('auto_arm_complete_timeout_sec', 2.0) + self.declare_parameter('platform_side', 'left') + self.declare_parameter('blue_zone_label', 'blue') + self.declare_parameter('green_zone_label', 'green') + self.declare_parameter('approach_speed_mps', 0.18) + self.declare_parameter('slope_speed_mps', 0.32) + self.declare_parameter('lateral_speed_mps', 0.12) + self.declare_parameter('turn_speed_radps', 0.65) + self.declare_parameter('yaw_tolerance_deg', 5.0) + self.declare_parameter('ultrasonic_stop_distance_m', 0.35) + self.declare_parameter('signboard_stop_distance_m', 0.70) + self.declare_parameter('board_hold_sec', 3.0) + self.declare_parameter('alignment_tolerance', 0.12) + self.declare_parameter('max_wait_signal_board_sec', 30.0) + + self.autostart = self.get_parameter('autostart').value + self.auto_arm_complete_timeout_sec = float(self.get_parameter('auto_arm_complete_timeout_sec').value) + self.platform_side = str(self.get_parameter('platform_side').value) + self.blue_zone_label = str(self.get_parameter('blue_zone_label').value) + self.green_zone_label = str(self.get_parameter('green_zone_label').value) + self.approach_speed_mps = float(self.get_parameter('approach_speed_mps').value) + self.slope_speed_mps = float(self.get_parameter('slope_speed_mps').value) + self.lateral_speed_mps = float(self.get_parameter('lateral_speed_mps').value) + self.turn_speed_radps = float(self.get_parameter('turn_speed_radps').value) + self.yaw_tolerance_rad = math.radians(float(self.get_parameter('yaw_tolerance_deg').value)) + self.ultrasonic_stop_distance_m = float(self.get_parameter('ultrasonic_stop_distance_m').value) + self.signboard_stop_distance_m = float(self.get_parameter('signboard_stop_distance_m').value) + self.board_hold_sec = float(self.get_parameter('board_hold_sec').value) + self.alignment_tolerance = float(self.get_parameter('alignment_tolerance').value) + self.max_wait_signal_board_sec = float(self.get_parameter('max_wait_signal_board_sec').value) + + self.cmd_pub = self.create_publisher(Twist, '/cmd_vel', 10) + self.arm_cmd_pub = self.create_publisher(String, '/arm_command', 10) + self.state_pub = self.create_publisher(String, '/mission_manager/state', 10) + + self.create_subscription(Range, '/ultrasonic/front/range', self.on_range, 10) + self.create_subscription(Imu, '/imu', self.on_imu, 10) + self.create_subscription(Odometry, '/odom', self.on_odom, 10) + self.create_subscription(String, '/signal_board/result', self.on_signal_board, 10) + self.create_subscription(PointStamped, '/depth_target/point', self.on_depth_target, 10) + self.create_subscription(String, '/arm/status', self.on_arm_status, 10) + self.create_subscription(Bool, '/mission/start', self.on_start, 10) + + self.timer = self.create_timer(0.05, self.on_timer) + + self.state = MissionState.APPROACH_SLOPE_ENTRY if self.autostart else MissionState.IDLE + self.current_range_m: Optional[float] = None + self.current_yaw: Optional[float] = None + self.current_pose = None + self.signal_board_result = 'unknown' + self.depth_target: Optional[PointStamped] = None + self.arm_busy = False + self.pending_arm_done_deadline = None + self.turn_start_yaw: Optional[float] = None + self.state_enter_time = self.get_clock().now() + self.block_pick_count = 0 + self.sponge_done = False + self.signal_idle_seen = False + + self.publish_state('READY' if self.autostart else 'IDLE_WAIT_START') + + def on_range(self, msg: Range) -> None: + self.current_range_m = float(msg.range) + + def on_imu(self, msg: Imu) -> None: + q = msg.orientation + siny_cosp = 2.0 * (q.w * q.z + q.x * q.y) + cosy_cosp = 1.0 - 2.0 * (q.y * q.y + q.z * q.z) + self.current_yaw = math.atan2(siny_cosp, cosy_cosp) + + def on_odom(self, msg: Odometry) -> None: + self.current_pose = msg.pose.pose + + def on_signal_board(self, msg: String) -> None: + self.signal_board_result = msg.data.strip() + + def on_depth_target(self, msg: PointStamped) -> None: + self.depth_target = msg + + def on_arm_status(self, msg: String) -> None: + data = msg.data.strip().lower() + if data in {'busy', 'running'}: + self.arm_busy = True + elif data in {'done', 'idle', 'ok', 'success'}: + self.arm_busy = False + self.pending_arm_done_deadline = None + elif data in {'failed', 'error'}: + self.arm_busy = False + self.pending_arm_done_deadline = None + self.get_logger().warning('Arm reported failure, mission pauses at current state.') + + def on_start(self, msg: Bool) -> None: + if msg.data and self.state == MissionState.IDLE: + self.transition_to(MissionState.APPROACH_SLOPE_ENTRY, 'external start signal') + elif (not msg.data) and self.state != MissionState.IDLE: + self.stop_robot() + self.transition_to(MissionState.IDLE, 'external stop signal') + + def publish_state(self, detail: str) -> None: + msg = String() + msg.data = f'{self.state.name}:{detail}' + self.state_pub.publish(msg) + + def transition_to(self, new_state: MissionState, reason: str) -> None: + self.stop_robot() + self.state = new_state + self.state_enter_time = self.get_clock().now() + if new_state != MissionState.TURN_LEFT_90: + self.turn_start_yaw = None + self.publish_state(reason) + self.get_logger().info(f'Transition -> {new_state.name}: {reason}') + + def state_elapsed(self) -> float: + return (self.get_clock().now() - self.state_enter_time).nanoseconds / 1e9 + + def stop_robot(self) -> None: + self.cmd_pub.publish(Twist()) + + def send_cmd(self, linear_x: float = 0.0, linear_y: float = 0.0, angular_z: float = 0.0) -> None: + cmd = Twist() + cmd.linear.x = float(linear_x) + cmd.linear.y = float(linear_y) + cmd.angular.z = float(angular_z) + self.cmd_pub.publish(cmd) + + def send_arm_command(self, command: str) -> None: + msg = String() + msg.data = command + self.arm_cmd_pub.publish(msg) + self.arm_busy = True + self.pending_arm_done_deadline = self.get_clock().now() + Duration(seconds=self.auto_arm_complete_timeout_sec) + self.get_logger().info(f'Arm command -> {command}') + + def arm_action_finished(self) -> bool: + if not self.arm_busy: + return True + if self.pending_arm_done_deadline is not None and self.get_clock().now() >= self.pending_arm_done_deadline: + self.arm_busy = False + self.pending_arm_done_deadline = None + self.get_logger().warning('Arm timeout auto-completed for integration testing.') + return True + return False + + @staticmethod + def angle_wrap(angle: float) -> float: + while angle > math.pi: + angle -= 2.0 * math.pi + while angle < -math.pi: + angle += 2.0 * math.pi + return angle + + def depth_target_aligned(self) -> bool: + if self.depth_target is None: + return False + return abs(self.depth_target.point.y) <= self.alignment_tolerance + + def on_timer(self) -> None: + if self.state == MissionState.IDLE: + self.stop_robot() + return + + if self.state == MissionState.APPROACH_SLOPE_ENTRY: + if (not self.sponge_done) and self.depth_target is not None and self.depth_target.point.x <= 0.55: + self.stop_robot() + self.send_arm_command(f'pick_and_place_platform:{self.platform_side}') + self.sponge_done = True + self.transition_to(MissionState.PICK_AND_PLACE_SPONGE, 'depth target in pickup window') + return + + if self.current_range_m is not None and self.current_range_m <= self.ultrasonic_stop_distance_m: + self.transition_to(MissionState.TURN_LEFT_90, 'ultrasonic reached slope-entry stop line') + return + + self.send_cmd(linear_x=self.approach_speed_mps) + return + + if self.state == MissionState.PICK_AND_PLACE_SPONGE: + if self.arm_action_finished(): + self.transition_to(MissionState.APPROACH_SLOPE_ENTRY, 'sponge placed on side platform') + return + + if self.state == MissionState.TURN_LEFT_90: + if self.current_yaw is None: + self.stop_robot() + return + if self.turn_start_yaw is None: + self.turn_start_yaw = self.current_yaw + delta = self.angle_wrap(self.current_yaw - self.turn_start_yaw) + target = math.pi / 2.0 + if abs(target - abs(delta)) <= self.yaw_tolerance_rad: + self.transition_to(MissionState.RUSH_SLOPE, 'left turn completed') + return + self.send_cmd(angular_z=self.turn_speed_radps) + return + + if self.state == MissionState.RUSH_SLOPE: + if self.current_range_m is not None and self.current_range_m <= self.signboard_stop_distance_m: + self.transition_to(MissionState.CHECK_SIGNAL_BOARD, 'arrived at signboard check point') + return + self.send_cmd(linear_x=self.slope_speed_mps) + return + + if self.state == MissionState.CHECK_SIGNAL_BOARD: + self.stop_robot() + if self.signal_board_result.startswith('idle'): + if not self.signal_idle_seen: + self.signal_idle_seen = True + self.state_enter_time = self.get_clock().now() + self.publish_state(f'signal board idle confirmed: {self.signal_board_result}') + elif self.state_elapsed() >= self.board_hold_sec: + self.transition_to(MissionState.MOVE_TO_BLOCK_1, 'signal board display hold completed') + return + + if self.signal_board_result == 'busy' and self.state_elapsed() >= self.max_wait_signal_board_sec: + self.get_logger().warning('Signal board stayed busy too long, mission still waits for manual intervention.') + self.state_enter_time = self.get_clock().now() + return + + if self.state == MissionState.MOVE_TO_BLOCK_1: + if self.depth_target is not None and self.depth_target_aligned() and self.depth_target.point.x <= 0.45: + self.send_arm_command('pick_block:1') + self.transition_to(MissionState.PICK_BLOCK_1, 'first floor block aligned') + return + self.send_cmd(linear_y=self.lateral_speed_mps) + return + + if self.state == MissionState.PICK_BLOCK_1: + if self.arm_action_finished(): + self.send_arm_command(f'place_block:{self.blue_zone_label}') + self.transition_to(MissionState.PLACE_BLOCK_1, 'first pick completed') + return + + if self.state == MissionState.PLACE_BLOCK_1: + if self.arm_action_finished(): + self.block_pick_count = 1 + self.transition_to(MissionState.MOVE_TO_BLOCK_2, 'first block placed to blue zone') + return + + if self.state == MissionState.MOVE_TO_BLOCK_2: + if self.depth_target is not None and self.depth_target_aligned() and self.depth_target.point.x <= 0.45: + self.send_arm_command('pick_block:2') + self.transition_to(MissionState.PICK_BLOCK_2, 'second floor block aligned') + return + self.send_cmd(linear_y=self.lateral_speed_mps) + return + + if self.state == MissionState.PICK_BLOCK_2: + if self.arm_action_finished(): + self.send_arm_command(f'place_block:{self.green_zone_label}') + self.transition_to(MissionState.PLACE_BLOCK_2, 'second pick completed') + return + + if self.state == MissionState.PLACE_BLOCK_2: + if self.arm_action_finished(): + self.block_pick_count = 2 + self.transition_to(MissionState.FINISHED, 'all competition actions completed') + return + + if self.state == MissionState.FINISHED: + self.stop_robot() + return + + +def main() -> None: + rclpy.init() + node = MissionManager() + try: + rclpy.spin(node) + finally: + node.stop_robot() + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/dev_ws/src/mission_manager/package.xml b/dev_ws/src/mission_manager/package.xml new file mode 100644 index 0000000..667d983 --- /dev/null +++ b/dev_ws/src/mission_manager/package.xml @@ -0,0 +1,22 @@ + + + + mission_manager + 0.1.0 + Mission state machine for the RDK X5 logistics competition robot. + OpenAI + Apache-2.0 + + + rclpy + geometry_msgs + nav_msgs + sensor_msgs + std_msgs + + ros2launch + + + ament_python + + diff --git a/dev_ws/src/mission_manager/resource/mission_manager b/dev_ws/src/mission_manager/resource/mission_manager new file mode 100644 index 0000000..e69de29 diff --git a/dev_ws/src/mission_manager/setup.cfg b/dev_ws/src/mission_manager/setup.cfg new file mode 100644 index 0000000..acb2e8e --- /dev/null +++ b/dev_ws/src/mission_manager/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/mission_manager +[install] +install_scripts=$base/lib/mission_manager diff --git a/dev_ws/src/mission_manager/setup.py b/dev_ws/src/mission_manager/setup.py new file mode 100644 index 0000000..e6500ca --- /dev/null +++ b/dev_ws/src/mission_manager/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup + +package_name = 'mission_manager' + +setup( + name=package_name, + version='0.1.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', ['launch/mission_manager.launch.py']), + ('share/' + package_name + '/config', ['config/mission_manager.yaml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='OpenAI', + maintainer_email='openai@example.com', + description='Mission state machine for RDK X5 logistics robot', + license='Apache-2.0', + entry_points={ + 'console_scripts': [ + 'mission_manager = mission_manager.mission_manager_node:main', + ], + }, +) diff --git a/dev_ws/src/orbbec_camera/CMakeLists.txt b/dev_ws/src/orbbec_camera/CMakeLists.txt new file mode 100644 index 0000000..9eb8e2e --- /dev/null +++ b/dev_ws/src/orbbec_camera/CMakeLists.txt @@ -0,0 +1,204 @@ +cmake_minimum_required(VERSION 3.8) +project(orbbec_camera) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O1") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC -g3") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O1") +option(USE_RK_HW_DECODER "Use Rockchip hardware decoder" OFF) +option(USE_NV_HW_DECODER "Use Nvidia hardware decoder" OFF) +option(INSTALL_UDEV_RULES "Install udev rule for Orbbec cameras" ON) + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Werror -Wno-pedantic -Wno-array-bounds) +endif() + +set(dependencies + ament_cmake + ament_index_cpp + Eigen3 + builtin_interfaces + cv_bridge + backward_ros + camera_info_manager + image_transport + image_publisher + OpenCV + orbbec_camera_msgs + rclcpp + rclcpp_components + sensor_msgs + std_msgs + std_srvs + tf2 + tf2_msgs + tf2_ros + tf2_sensor_msgs + Threads + diagnostic_updater + diagnostic_msgs + statistics_msgs + yaml-cpp + camera_calibration_parsers +) + +foreach(dep IN LISTS dependencies) + find_package(${dep} REQUIRED) +endforeach() +find_package(PkgConfig REQUIRED) +find_package(OpenSSL REQUIRED) + +if(USE_RK_HW_DECODER) + pkg_search_module(RK_MPP REQUIRED rockchip_mpp) + if(NOT RK_MPP_FOUND) + message(FATAL_ERROR "rockchip_mpp is not found") + endif() + pkg_search_module(RGA librga) + if(NOT RGA_FOUND) + add_definitions(-DUSE_LIBYUV) + message("librga is not found, use libyuv instead") + endif() +endif() + +execute_process(COMMAND uname -m OUTPUT_VARIABLE MACHINES) +execute_process(COMMAND getconf LONG_BIT OUTPUT_VARIABLE MACHINES_BIT) +if((${MACHINES} MATCHES "x86_64") AND (${MACHINES_BIT} MATCHES "64")) + set(HOST_PLATFORM "x64") +elseif(${MACHINES} MATCHES "arm" OR (${MACHINES} MATCHES "aarch64" AND ${MACHINES_BIT} MATCHES "32")) + message(FATAL_ERROR "ORBBEC SDK does not support arm32") +elseif((${MACHINES} MATCHES "aarch64") AND (${MACHINES_BIT} MATCHES "64")) + set(HOST_PLATFORM "arm64") +endif() + +set(ORBBEC_LIBS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SDK/lib/${HOST_PLATFORM}) +set(ORBBEC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SDK/include/) +set(CMAKE_BUILD_RPATH "${CMAKE_BUILD_RPATH}:${ORBBEC_LIBS_DIR}") +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:${ORBBEC_LIBS_DIR}") + +if(USE_NV_HW_DECODER) + set(JETSON_MULTI_MEDIA_API_DIR /usr/src/jetson_multimedia_api) + set(JETSON_MULTI_MEDIA_API_CLASS_DIR ${JETSON_MULTI_MEDIA_API_DIR}/samples/common/classes) + set(JETSON_MULTI_MEDIA_API_INCLUDE_DIR ${JETSON_MULTI_MEDIA_API_DIR}/include/) + set(LIBJPEG8B_INCLUDE_DIR ${JETSON_MULTI_MEDIA_API_INCLUDE_DIR}/libjpeg-8b) + set(TEGRA_ARMABI /usr/lib/aarch64-linux-gnu/) + add_definitions(-DUSE_NV_HW_DECODER) + add_compile_options(-Wno-missing-field-initializers -Wno-unused-parameter) + set(NV_LIBRARIES -lnvjpeg -lnvbufsurface -lnvbufsurftransform -lyuv -lv4l2) + list(APPEND NV_LIBRARIES -L${TEGRA_ARMABI} -L${TEGRA_ARMABI}/tegra) +endif() + +set(COMMON_INCLUDE_DIRS + $ + $ + $ + ${ORBBEC_INCLUDE_DIR} + ${OpenCV_INCLUDED_DIRS} +) + +set(COMMON_LIBRARIES + ${OpenCV_LIBS} + Eigen3::Eigen + -lOrbbecSDK + -L${ORBBEC_LIBS_DIR} + Threads::Threads + -lrt + -ldw + yaml-cpp +) + +set(SOURCE_FILES + src/d2c_viewer.cpp + src/dynamic_params.cpp + src/image_publisher.cpp + src/ob_camera_node_driver.cpp + src/ob_camera_node.cpp + src/ob_lidar_node.cpp + src/ros_param_backend.cpp + src/ros_service.cpp + src/synced_imu_publisher.cpp + src/utils.cpp + src/jpeg_decoder.cpp +) + +if(USE_RK_HW_DECODER) + add_definitions(-DUSE_RK_HW_DECODER) + list(APPEND SOURCE_FILES src/rk_mpp_decoder.cpp) + list(APPEND COMMON_INCLUDE_DIRS ${RK_MPP_INCLUDE_DIRS} ${RGA_INCLUDE_DIRS}) + list(APPEND COMMON_LIBRARIES ${RGA_LIBRARIES} ${RK_MPP_LIBRARIES}) + if(NOT RGA_FOUND) + list(APPEND COMMON_LIBRARIES -lyuv) + endif() +endif() + +if(USE_NV_HW_DECODER) + list(APPEND SOURCE_FILES src/jetson_nv_decoder.cpp) + list(APPEND COMMON_INCLUDE_DIRS ${JETSON_MULTI_MEDIA_API_INCLUDE_DIR} ${LIBJPEG8B_INCLUDE_DIR}) + list(APPEND SOURCE_FILES + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvBuffer.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvElement.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvElementProfiler.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvJpegDecoder.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvJpegEncoder.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvLogging.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvUtils.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvV4l2Element.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvV4l2ElementPlane.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvVideoDecoder.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvVideoEncoder.cpp + ${JETSON_MULTI_MEDIA_API_CLASS_DIR}/NvBufSurface.cpp + ) + list(APPEND COMMON_LIBRARIES ${NV_LIBRARIES}) +endif() + +macro(add_orbbec_executable TARGET SOURCE) + add_executable(${TARGET} ${SOURCE}) + target_include_directories(${TARGET} PUBLIC ${COMMON_INCLUDE_DIRS}) + target_link_libraries(${TARGET} ${COMMON_LIBRARIES} ${PROJECT_NAME}) + ament_target_dependencies(${TARGET} ${dependencies}) +endmacro() + +add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES}) +ament_target_dependencies(${PROJECT_NAME} ${dependencies}) +target_include_directories(${PROJECT_NAME} PUBLIC ${COMMON_INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} ${COMMON_LIBRARIES}) + +rclcpp_components_register_node( + ${PROJECT_NAME} PLUGIN "orbbec_camera::OBCameraNodeDriver" EXECUTABLE orbbec_camera_node +) + +# add_orbbec_executable(list_devices_node tools/list_devices_node.cpp) +# add_orbbec_executable(list_depth_work_mode_node tools/list_depth_work_mode.cpp) + +install(TARGETS ${PROJECT_NAME} + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) +# install(TARGETS list_devices_node list_depth_work_mode_node DESTINATION lib/${PROJECT_NAME}/) +install(DIRECTORY include/ DESTINATION include) +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}/) +install(DIRECTORY config DESTINATION share/${PROJECT_NAME}/) +install(DIRECTORY ${ORBBEC_INCLUDE_DIR} DESTINATION include) +install(DIRECTORY ${ORBBEC_LIBS_DIR}/ DESTINATION lib/ FILES_MATCHING PATTERN "*.so*") +file(GLOB_RECURSE EXTENSION_FILES "${ORBBEC_LIBS_DIR}/extensions/*") +if(EXTENSION_FILES) + install(FILES ${EXTENSION_FILES} DESTINATION lib/extensions/) +endif() +if(INSTALL_UDEV_RULES) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/99-obsensor-libusb.rules + DESTINATION share/${PROJECT_NAME}/udev) +endif() +if(DEFINED ENV{BUILDING_PACKAGE}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/99-obsensor-libusb.rules DESTINATION /etc/udev/rules.d) +endif() + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + ament_lint_auto_find_test_dependencies() +endif() + +ament_export_include_directories(include) +ament_export_libraries(${PROJECT_NAME}) +ament_export_dependencies(${dependencies}) +ament_package() diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/ObSensor.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/ObSensor.h new file mode 100644 index 0000000..02b4be8 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/ObSensor.h @@ -0,0 +1,23 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * \file ObSensor.h + * \brief This file serves as the C entrance for the SDK library. + * It includes all necessary header files for SDK usage. + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/ObSensor.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/ObSensor.hpp new file mode 100644 index 0000000..fde4917 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/ObSensor.hpp @@ -0,0 +1,21 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * \file ObSensor.hpp + * \brief This is the main entry point for the SDK C++ library. + * It includes all necessary header files for using the library. + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Advanced.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Advanced.h new file mode 100644 index 0000000..0a7b95f --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Advanced.h @@ -0,0 +1,337 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Get the current depth work mode. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_depth_work_mode The current depth work mode. + */ +OB_EXPORT ob_depth_work_mode ob_device_get_current_depth_work_mode(const ob_device *device, ob_error **error); + +/** + * @brief Get current depth mode name + * @brief According the current preset name to return current depth mode name + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* return the current depth mode name. + */ +OB_EXPORT const char *ob_device_get_current_depth_work_mode_name(const ob_device *device, ob_error **error); + +/** + * @brief Switch the depth work mode by ob_depth_work_mode. + * Prefer to use ob_device_switch_depth_work_mode_by_name to switch depth mode when the complete name of the depth work mode is known. + * + * @param[in] device The device object. + * @param[in] work_mode The depth work mode from ob_depth_work_mode_list which is returned by ob_device_get_depth_work_mode_list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_status The switch result. OB_STATUS_OK: success, other failed. + */ +OB_EXPORT ob_status ob_device_switch_depth_work_mode(ob_device *device, const ob_depth_work_mode *work_mode, ob_error **error); + +/** + * @brief Switch the depth work mode by work mode name. + * + * @param[in] device The device object. + * @param[in] mode_name The depth work mode name which is equal to ob_depth_work_mode.name. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_status The switch result. OB_STATUS_OK: success, other failed. + */ +OB_EXPORT ob_status ob_device_switch_depth_work_mode_by_name(ob_device *device, const char *mode_name, ob_error **error); + +/** + * @brief Request the list of supported depth work modes. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_depth_work_mode_list The list of ob_depth_work_mode. + */ +OB_EXPORT ob_depth_work_mode_list *ob_device_get_depth_work_mode_list(const ob_device *device, ob_error **error); + +/** + * @brief Get the depth work mode count that ob_depth_work_mode_list hold + * + * @param[in] work_mode_list Data structure containing a list of ob_depth_work_mode + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The total number contained in ob_depth_work_mode_list + */ +OB_EXPORT uint32_t ob_depth_work_mode_list_get_count(const ob_depth_work_mode_list *work_mode_list, ob_error **error); + +/** + * @brief Get the index target of ob_depth_work_mode from work_mode_list + * + * @param[in] work_mode_list Data structure containing a list of ob_depth_work_mode + * @param[in] index Index of the target ob_depth_work_mode + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_depth_work_mode + */ +OB_EXPORT ob_depth_work_mode ob_depth_work_mode_list_get_item(const ob_depth_work_mode_list *work_mode_list, uint32_t index, ob_error **error); + +/** + * @brief Free the resources of ob_depth_work_mode_list + * + * @param[in] work_mode_list Data structure containing a list of ob_depth_work_mode + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_depth_work_mode_list(ob_depth_work_mode_list *work_mode_list, ob_error **error); + +/** + * @brief Get the current preset name. + * @brief The preset mean a set of parameters or configurations that can be applied to the device to achieve a specific effect or function. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The current preset name, it should be one of the preset names returned by @ref ob_device_get_available_preset_list. + */ +OB_EXPORT const char *ob_device_get_current_preset_name(const ob_device *device, ob_error **error); + +/** + * @brief Get the available preset list. + * @attention After loading the preset, the settings in the preset will set to the device immediately. Therefore, it is recommended to re-read the device + * settings to update the user program temporarily. + * + * @param[in] device The device object. + * @param[in] preset_name Pointer to an error object that will be set if an error occurs. The name should be one of the preset names returned by @ref + * ob_device_get_available_preset_list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_load_preset(ob_device *device, const char *preset_name, ob_error **error); + +/** + * @brief Load preset from json string. + * @brief After loading the custom preset, the settings in the custom preset will set to the device immediately. + * @brief After loading the custom preset, the available preset list will be appended with the custom preset and named as the file name. + * + * @param[in] device The device object. + * @param[in] json_file_path The json file path. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_load_preset_from_json_file(ob_device *device, const char *json_file_path, ob_error **error); + +/** + * @brief Load custom preset from data. + * @brief After loading the custom preset, the settings in the custom preset will set to the device immediately. + * @brief After loading the custom preset, the available preset list will be appended with the custom preset and named as the @p presetName. + * + * @attention The user should ensure that the custom preset data is adapted to the device and the settings in the data are valid. + * @attention It is recommended to re-read the device settings to update the user program temporarily after successfully loading the custom preset. + * + * @param[in] device The device object. + * @param[in] presetName The name of the custome preset. + * @param[in] data The custom preset data. + * @param[in] size The size of the custom preset data. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_load_preset_from_json_data(ob_device *device, const char *presetName, const uint8_t *data, uint32_t size, ob_error **error); + +/** + * @brief Export current settings as a preset json file. + * @brief After exporting the custom preset, the available preset list will be appended with the custom preset and named as the file name. + * + * @param[in] device The device object. + * @param[in] json_file_path The json file path. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_export_current_settings_as_preset_json_file(ob_device *device, const char *json_file_path, ob_error **error); + +/** + * @brief Export current device settings as a preset json data. + * @brief After exporting the preset, a new preset named as the @p presetName will be added to the available preset list. + * + * @attention The memory of the data is allocated by the SDK, and will automatically be released by the SDK. + * @attention The memory of the data will be reused by the SDK on the next call, so the user should copy the data to a new buffer if it needs to be + * preserved. + * + * @param[in] device The device object. + * @param[in] presetName The name of the custome preset. + * @param[out] data Return the preset json data. + * @param[out] dataSize Return the size of the preset json data. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_export_current_settings_as_preset_json_data(ob_device *device, const char *presetName, const uint8_t **data, uint32_t *dataSize, + ob_error **error); + +/** + * @brief Get the available preset list. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The available preset list. + */ +OB_EXPORT ob_device_preset_list *ob_device_get_available_preset_list(const ob_device *device, ob_error **error); + +/** + * @brief Delete the available preset list. + * + * @param[in] preset_list The available preset list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_preset_list(ob_device_preset_list *preset_list, ob_error **error); + +/** + * @brief Get the number of preset in the preset list. + * + * @param[in] preset_list The available preset list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The number of preset in the preset list. + */ +OB_EXPORT uint32_t ob_device_preset_list_get_count(const ob_device_preset_list *preset_list, ob_error **error); + +/** + * @brief Get the name of the preset in the preset list. + * + * @param[in] preset_list The available preset list. + * @param[in] index The index of the preset in the preset list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The name of the preset in the preset list. + */ +OB_EXPORT const char *ob_device_preset_list_get_name(const ob_device_preset_list *preset_list, uint32_t index, ob_error **error); + +/** + * @brief Check if the preset list has the preset. + * + * @param[in] preset_list The available preset list. + * @param[in] preset_name The name of the preset. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return Whether the preset list has the preset. If true, the preset list has the preset. If false, the preset list does not have the preset. + */ +OB_EXPORT bool ob_device_preset_list_has_preset(const ob_device_preset_list *preset_list, const char *preset_name, ob_error **error); + +/** + * @brief Check if the device supports the frame interleave feature. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool Returns true if the device supports the frame interleave feature. + */ +OB_EXPORT bool ob_device_is_frame_interleave_supported(const ob_device *device, ob_error **error); +/** + * + * @brief load the frame interleave mode according to frame interleavee name. + * + * @param[in] device The device object. + * @param[in] frame_interleave_name The name should be one of the frame interleave names returned by @ref ob_device_get_available_frame_interleave_list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_load_frame_interleave(ob_device *device, const char *frame_interleave_name, ob_error **error); + +/** + * @brief Get the available frame interleave list. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The available frame interleave list. + */ +OB_EXPORT ob_device_frame_interleave_list *ob_device_get_available_frame_interleave_list(ob_device *device, ob_error **error); + +/** + * @brief Delete the available frame interleave list. + * + * @param[in] frame_interleave_list The available frame interleave list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_frame_interleave_list(ob_device_frame_interleave_list *frame_interleave_list, ob_error **error); + +/** + * @brief Get the number of frame interleave in the frame interleave list. + * + * @param[in] frame_interleave_list The available frame interleave list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The number of frame interleave in the frame interleave list. + */ +OB_EXPORT uint32_t ob_device_frame_interleave_list_get_count(ob_device_frame_interleave_list *frame_interleave_list, ob_error **error); + +/** + * @brief Get the name of frame interleave in the frame interleave list. + * + * @param[in] frame_interleave_list The available frame interleave list. + * @param[in] index The index of frame interleave in the frame interleave list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The name of frame interleave in the frame interleave list.. + */ +OB_EXPORT const char *ob_device_frame_interleave_list_get_name(ob_device_frame_interleave_list *frame_interleave_list, uint32_t index, ob_error **error); + +/** + * @brief Check if the interleave ae list has the interleave ae. + * + * @param[in] frame_interleave_list The available interleave ae list. + * @param[in] frame_interleave_name The name of the interleave ae. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return Whether the interleave ae list has the interleave ae. If true, the interleave ae list has the interleave ae. If false, the interleave ae list does + * not have the interleave ae. + */ +OB_EXPORT bool ob_device_frame_interleave_list_has_frame_interleave(ob_device_frame_interleave_list *frame_interleave_list, const char *frame_interleave_name, + ob_error **error); + +/** + * @brief Get the available preset resolution config list. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The available frame resolution config list. + */ +OB_EXPORT ob_preset_resolution_config_list *ob_device_get_available_preset_resolution_config_list(ob_device *device, ob_error **error); + +/** + * @brief Get the number of preset resolution in the preset resolution list. + * + * @param[in] ob_preset_resolution_config_list The available preset resolution list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The number of preset resolution in the preset resolution list. + */ +OB_EXPORT uint32_t ob_device_preset_resolution_config_get_count(ob_preset_resolution_config_list *ob_preset_resolution_config_list, ob_error **error); + +/** + * @brief Get the preset resolution in the preset resolution list. + * + * @param[in] ob_preset_resolution_config_list The available preset resolution list. + * @param[in] index The index of preset resolution in the preset resolution list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The preset resolution in the preset resolution list. + */ +OB_EXPORT OBPresetResolutionConfig ob_device_preset_resolution_config_list_get_item(const ob_preset_resolution_config_list *ob_preset_resolution_config_list, + uint32_t index, ob_error **error); + +/** + * @brief Delete the available preset resolution list. + * + * @param[in] ob_preset_resolution_config_list The available preset resolution list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_preset_resolution_config_list(ob_preset_resolution_config_list *ob_preset_resolution_config_list, ob_error **error); + +// The following interfaces are deprecated and are retained here for compatibility purposes. +#define ob_depth_work_mode_list_count ob_depth_work_mode_list_get_count +#define ob_device_preset_list_count ob_device_preset_list_get_count + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Context.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Context.h new file mode 100644 index 0000000..df39a41 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Context.h @@ -0,0 +1,268 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Context.h + * @brief Context is a management class that describes the runtime of the SDK and is responsible for resource allocation and release of the SDK. + * Context has the ability to manage multiple devices. It is responsible for enumerating devices, monitoring device callbacks, and enabling multi-device + * synchronization. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Create a context object with the default configuration file + * + * @param[out] error Pointer to an error object that will be populated if an error occurs during context creation + * + * @return Pointer to the created context object + */ +OB_EXPORT ob_context *ob_create_context(ob_error **error); + +/** + * @brief Create a context object with a specified configuration file + * + * @param[in] config_file_path Path to the configuration file. If NULL, the default configuration file will be used. + * @param[out] error Pointer to an error object that will be populated if an error occurs during context creation + * + * @return Pointer to the created context object + */ +OB_EXPORT ob_context *ob_create_context_with_config(const char *config_file_path, ob_error **error); + +/** + * @brief Delete a context object + * + * @param[in] context Pointer to the context object to be deleted + * @param[out] error Pointer to an error object that will be populated if an error occurs during context deletion + */ +OB_EXPORT void ob_delete_context(ob_context *context, ob_error **error); + +/** + * @brief Get a list of enumerated devices + * + * @param[in] context Pointer to the context object + * @param[out] error Pointer to an error object that will be populated if an error occurs during device enumeration + * + * @return Pointer to the device list object + */ +OB_EXPORT ob_device_list *ob_query_device_list(ob_context *context, ob_error **error); + +/** + * @brief Enable or disable network device enumeration + * @brief After enabling, the network device will be automatically discovered and can be retrieved through @ref ob_query_device_list. The default state can be + * set in the configuration file. + * + * @attention Network device enumeration is performed through the GVCP protocol. If the device is not in the same subnet as the host, it will be discovered but + * cannot be connected. + * + * @param[in] context Pointer to the context object + * @param[in] enable true to enable, false to disable + * @param[out] error Pointer to an error object that will be populated if an error occurs. + */ +OB_EXPORT void ob_enable_net_device_enumeration(ob_context *context, bool enable, ob_error **error); + +/** + * @brief "Force" a static IP address configuration in a device identified by its MAC Address. + * + * @param[in] macAddress MAC address of the network device. + * You can obtain it from @ref ob_device_info_get_uid, or specify it manually + * in the format xx:xx:xx:xx:xx:xx, where each xx is a two-digit hexadecimal value. + * @param[in] config The new IP configuration. + * @param[out] error Pointer to an error object that will be populated if an error occurs. + * + * @return bool true if the configuration command was processed successfully, false otherwise. + * + * @note This applies to all GigE Vision devices + */ +OB_EXPORT bool ob_force_ip_config(const char *macAddress, ob_net_ip_config config, ob_error **error); + +/** + * @brief Create a network device object + * + * @param[in] context Pointer to the context object + * @param[in] address IP address of the device + * @param[in] port Port number of the device + * @param[out] error Pointer to an error object that will be populated if an error occurs during device creation + * + * @return Pointer to the created device object + */ +OB_EXPORT ob_device *ob_create_net_device(ob_context *context, const char *address, uint16_t port, ob_error **error); + +/** + * @brief Create a network device object + * + * @param[in] context Pointer to the context object + * @param[in] address IP address of the device + * @param[in] port Port number of the device + * @param[in] accessMode Device access mode. @ref ob_device_access_mode. + * If the device does not support setting the Access Mode, the default OB_DEVICE_DEFAULT_ACCESS is used. + * Applies only on first device creation or after release and re-creation; subsequent calls ignore it. + * @param[out] error Pointer to an error object that will be populated if an error occurs during device creation + * + * @return Pointer to the created device object + */ +OB_EXPORT ob_device *ob_create_net_device_ex(ob_context *context, const char *address, uint16_t port, ob_device_access_mode accessMode, ob_error **error); + +/** + * @brief Set a device plug-in callback function + * + * @deprecated This function is deprecated. Please use ob_register_device_changed_callback() instead. + * + * @attention The added and removed device lists returned through the callback interface need to be released manually + * @attention This function supports multiple callbacks. Each call to this function adds a new callback to an internal list. + * + * @param[in] context Pointer to the context object + * @param[in] callback Pointer to the callback function triggered when a device is plugged or unplugged + * @param[in] user_data Pointer to user data that can be passed to and retrieved from the callback function + * @param[out] error Pointer to an error object that will be populated if an error occurs during callback function setting + */ +OB_EXPORT void ob_set_device_changed_callback(ob_context *context, ob_device_changed_callback callback, void *user_data, ob_error **error); + +/** + * @brief Register a device plug-in callback function. + * + * This function registers a callback that will be triggered whenever a device is plugged in or unplugged. + * + * @attention The added and removed device lists returned through the callback interface need to be released manually. + * @attention This function supports multiple callbacks. Each call to this function adds a new callback to an internal list. + * + * @param[in] context Pointer to the context object. + * @param[in] callback Pointer to the callback function triggered when a device is plugged or unplugged. + * @param[in] user_data Pointer to user data that can be passed to and retrieved from the callback function. + * @param[out] error Pointer to an error object that will be populated if an error occurs during callback function setting. + * + * @return A ob_callback_id that uniquely identifies the registered callback. + * This ID can be used later to unregister the callback with ob_unregister_device_changed_callback(). + * Returns INVALID_DEVICE_CHANGED_CALLBACK_ID if the registration fails. + */ +OB_EXPORT ob_callback_id ob_register_device_changed_callback(ob_context *context, ob_device_changed_callback callback, void *user_data, ob_error **error); + +/** + * @brief Unregister a previously registered device plug-in callback function. + * + * This function removes a callback that was registered by ob_register_device_changed_callback(). + * + * @param[in] context Pointer to the context object. + * @param[in] callback_id The callback ID returned by ob_register_device_changed_callback(). + * @param[out] error Pointer to an error object that will be populated if an error occurs during callback function setting. + */ +OB_EXPORT void ob_unregister_device_changed_callback(ob_context *context, ob_callback_id callback_id, ob_error **error); + +/** + * @brief Activates device clock synchronization to synchronize the clock of the host and all created devices (if supported). + * + * @param[in] context Pointer to the context object + * @param[in] repeat_interval_msec The interval for auto-repeated synchronization, in milliseconds. If the value is 0, synchronization is performed only once. + * @param[out] error Pointer to an error object that will be populated if an error occurs during execution + */ +OB_EXPORT void ob_enable_device_clock_sync(ob_context *context, uint64_t repeat_interval_msec, ob_error **error); + +/** + * @brief Free idle memory from the internal frame memory pool + * + * @param[in] context Pointer to the context object + * @param[out] error Pointer to an error object that will be populated if an error occurs during memory freeing + */ +OB_EXPORT void ob_free_idle_memory(ob_context *context, ob_error **error); + +/** + * @brief For linux, there are two ways to enable the UVC backend: libuvc and v4l2. This function is used to set the backend type. + * @brief It is effective when the new device is created. + * + * @attention This interface is only available for Linux. + * + * @param[in] context Pointer to the context object + * @param[in] backend_type The backend type to be used. + * @param[out] error Pointer to an error object that will be populated if an error occurs during backend type setting + */ +OB_EXPORT void ob_set_uvc_backend_type(ob_context *context, ob_uvc_backend_type backend_type, ob_error **error); + +/** + * @brief Set the global log level + * + * @attention This interface setting will affect the output level of all logs (terminal, file, callback) + * + * @param[in] severity Log level to set + * @param[out] error Pointer to an error object that will be populated if an error occurs during log level setting + */ +OB_EXPORT void ob_set_logger_severity(ob_log_severity severity, ob_error **error); + +/** + * @brief Set the log output to a file + * + * @param[in] severity Log level to output to file + * @param[in] directory Path to the log file output directory. + * If empty, the existing configuration is used; + * if the existing configuration is also empty, + * the value from the config file or the default configuration will be used. + * @param[out] error Pointer to an error object that will be populated if an error occurs during log output setting + * + * @note Other settings, such as log file name, remain unchanged. + */ +OB_EXPORT void ob_set_logger_to_file(ob_log_severity severity, const char *directory, ob_error **error); + +/** + * @brief Set the log file name for file output + * + * @param[in] file_name Log file name. Must not be empty. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @note Other settings, such as log level and output directory, remain unchanged. + */ +OB_EXPORT void ob_set_logger_file_name(const char *file_name, ob_error **error); + +/** + * @brief Set the log callback function + * + * @param[in] severity Log level to set for the callback function + * @param[in] callback Pointer to the callback function + * @param[in] user_data Pointer to user data that can be passed to and retrieved from the callback function + * @param[out] error Pointer to an error object that will be populated if an error occurs during log callback function setting + */ +OB_EXPORT void ob_set_logger_to_callback(ob_log_severity severity, ob_log_callback callback, void *user_data, ob_error **error); + +/** + * @brief Set the log output to the console + * + * @param[in] severity Log level to output to the console + * @param[out] error Pointer to an error object that will be populated if an error occurs during log output setting + */ +OB_EXPORT void ob_set_logger_to_console(ob_log_severity severity, ob_error **error); + +/** + * @brief Logs a message with severity, file, function, and line info. + * + * @param[in] severity Log level, see @ref ob_log_severity for details + * @param[in] module The module or component the log belongs to + * @param[in] message Message string to log + * @param[in] file Source file name, e.g., __FILE__ + * @param[in] func Function name, e.g., __func__ + * @param[in] line Line number, e.g., __LINE__ + * @param[out] error Pointer to an error object that will be populated if an error occurs during log output setting + */ +OB_EXPORT void ob_log_external_message(ob_log_severity severity, const char *module, const char *message, const char *file, const char *func, int line, + ob_error **error); + +/** + * @brief Set the extensions directory + * @brief The extensions directory is used to search for dynamic libraries that provide additional functionality to the SDK, such as the Frame filters. + * + * @attention Should be called before creating the context and pipeline, otherwise the default extensions directory (./extensions) will be used. + * + * @param[in] directory Path to the extensions directory. If the path is empty, extensions path will be set to the current working directory. + * @param[out] error Pointer to an error object that will be populated if an error occurs during extensions directory setting + */ +OB_EXPORT void ob_set_extensions_directory(const char *directory, ob_error **error); + +// The following interfaces are deprecated and are retained here for compatibility purposes. +#define ob_enable_multi_device_sync ob_enable_device_clock_sync +#define ob_set_logger_callback ob_set_logger_to_callback + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Device.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Device.h new file mode 100644 index 0000000..2b690ce --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Device.h @@ -0,0 +1,873 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Device.h + * @brief Device-related functions, including operations such as obtaining and creating a device, setting and obtaining device property, and obtaining sensors + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" +#include "Property.h" +#include "MultipleDevices.h" +#include "Advanced.h" + +/** + * @brief Delete a device. + * + * @param[in] device The device to be deleted. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_device(ob_device *device, ob_error **error); + +/** + * @brief List all sensors. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_sensor_list* The list of all sensors. + */ +OB_EXPORT ob_sensor_list *ob_device_get_sensor_list(const ob_device *device, ob_error **error); + +/** + * @brief Get a device's sensor. + * + * @param[in] device The device object. + * @param[in] type The type of sensor to get. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_sensor* The acquired sensor. + */ +OB_EXPORT ob_sensor *ob_device_get_sensor(ob_device *device, ob_sensor_type type, ob_error **error); + +/** + * @brief Set an integer type of device property. + * + * @param[in] device The device object. + * @param[in] property_id The ID of the property to be set. + * @param[in] value The property value to be set. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_set_int_property(ob_device *device, ob_property_id property_id, int32_t value, ob_error **error); + +/** + * @brief Get an integer type of device property. + * + * @param[in] device The device object. + * @param[in] property_id The property ID. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return int32_t The property value. + */ +OB_EXPORT int32_t ob_device_get_int_property(ob_device *device, ob_property_id property_id, ob_error **error); + +/** + * @brief Get the integer type of device property range. + * + * @param[in] device The device object. + * @param[in] property_id The property id. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The property range. + */ +OB_EXPORT ob_int_property_range ob_device_get_int_property_range(ob_device *device, ob_property_id property_id, ob_error **error); + +/** + * @brief Set a float type of device property. + * + * @param[in] device The device object. + * @param[in] property_id The ID of the property to be set. + * @param[in] value The property value to be set. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_set_float_property(ob_device *device, ob_property_id property_id, float value, ob_error **error); + +/** + * @brief Get a float type of device property. + * + * @param[in] device The device object. + * @param[in] property_id The property ID. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return float The property value. + */ +OB_EXPORT float ob_device_get_float_property(ob_device *device, ob_property_id property_id, ob_error **error); + +/** + * @brief Get the float type of device property range. + * + * @param[in] device The device object. + * @param[in] property_id The property id. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The property range. + */ +OB_EXPORT ob_float_property_range ob_device_get_float_property_range(ob_device *device, ob_property_id property_id, ob_error **error); + +/** + * @brief Set a boolean type of device property. + * + * @param[in] device The device object. + * @param[in] property_id The ID of the property to be set. + * @param[in] value The property value to be set. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_set_bool_property(ob_device *device, ob_property_id property_id, bool value, ob_error **error); + +/** + * @brief Get a boolean type of device property. + * + * @param[in] device The device object. + * @param[in] property_id The property ID. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool The property value. + */ +OB_EXPORT bool ob_device_get_bool_property(ob_device *device, ob_property_id property_id, ob_error **error); + +/** + * @brief Get the boolean type of device property range. + * + * @param[in] device The device object. + * @param[in] property_id The property id. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The property range. + */ +OB_EXPORT ob_bool_property_range ob_device_get_bool_property_range(ob_device *device, ob_property_id property_id, ob_error **error); + +/** + * @brief Set structured data. + * + * @param[in] device The device object. + * @param[in] property_id The ID of the property to be set. + * @param[in] data The property data to be set. + * @param[in] data_size The size of the property to be set. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_set_structured_data(ob_device *device, ob_property_id property_id, const uint8_t *data, uint32_t data_size, ob_error **error); + +/** + * @brief Get structured data of a device property. + * + * @param[in] device The device object. + * @param[in] property_id The ID of the property. + * @param[out] data The obtained property data. + * @param[out] data_size The size of the obtained property data. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_get_structured_data(ob_device *device, ob_property_id property_id, uint8_t *data, uint32_t *data_size, ob_error **error); + +/** + * @brief Get raw data of a device property. + * + * @param[in] device The device object. + * @param[in] property_id The ID of the property. + * @param[out] cb The get data callback. + * @param[out] user_data User-defined data that will be returned in the callback. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_get_raw_data(ob_device *device, ob_property_id property_id, ob_get_data_callback cb, void *user_data, ob_error **error); + +/** + * @brief Set customer data. + * + * @param[in] device The device object. + * @param[in] data The property data to be set. + * @param[in] data_size The size of the property to be set,the maximum length cannot exceed 65532 bytes. + * @param[out] error Log error messages. + */ +OB_EXPORT void ob_device_write_customer_data(ob_device *device, const void *data, uint32_t data_size, ob_error **error); + +/** + * @brief Get customer data of a device property. + * + * @param[in] device The device object. + * @param[out] data The obtained property data. + * @param[out] data_size The size of the obtained property data. + * @param[out] error Log error messages. + */ +OB_EXPORT void ob_device_read_customer_data(ob_device *device, void *data, uint32_t *data_size, ob_error **error); + +/** + * @brief Get the number of properties supported by the device. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The number of properties supported by the device. + */ +OB_EXPORT uint32_t ob_device_get_supported_property_count(const ob_device *device, ob_error **error); + +/** + * @brief Get the type of property supported by the device. + * + * @param[in] device The device object. + * @param[in] index The property index. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The type of property supported by the device. + */ +OB_EXPORT ob_property_item ob_device_get_supported_property_item(const ob_device *device, uint32_t index, ob_error **error); + +/** + * @brief Check if a device property permission is supported. + * + * @param[in] device The device object. + * @param[in] property_id The property id. + * @param[in] permission The type of permission that needs to be interpreted. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return Whether the property permission is supported. + */ +OB_EXPORT bool ob_device_is_property_supported(const ob_device *device, ob_property_id property_id, ob_permission_type permission, ob_error **error); + +/** + * @brief Check if the device supports global timestamp. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool Whether the device supports global timestamp. + */ +OB_EXPORT bool ob_device_is_global_timestamp_supported(const ob_device *device, ob_error **error); + +/** + * @brief Enable or disable global timestamp. + * + * @param[in] device The device object. + * @param[in] enable Whether to enable global timestamp. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_enable_global_timestamp(ob_device *device, bool enable, ob_error **error); + +/** + * @brief Update the device firmware. + * + * @param[in] device The device object. + * @param[in] path The firmware path. + * @param[in] callback The firmware upgrade progress callback. + * @param[in] async Whether to execute asynchronously. + * @param[in] user_data User-defined data that will be returned in the callback. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_update_firmware(ob_device *device, const char *path, ob_device_fw_update_callback callback, bool async, void *user_data, + ob_error **error); + +/** + * @brief Update the device firmware from data. + * + * @param[in] device The device object. + * @param[in] data The firmware file data. + * @param[in] data_size The firmware file size. + * @param[in] callback The firmware upgrade progress callback. + * @param[in] async Whether to execute asynchronously. + * @param[in] user_data User-defined data that will be returned in the callback. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_update_firmware_from_data(ob_device *device, const uint8_t *data, uint32_t data_size, ob_device_fw_update_callback callback, + bool async, void *user_data, ob_error **error); + +/** + * @brief Update the device optional depth presets. + * + * @param[in] device The device object. + * @param[in] file_path_list A list(2D array) of preset file paths, each up to OB_PATH_MAX characters. + * @param[in] path_count The number of the preset file paths. + * @param[in] callback The preset upgrade progress callback. + * @param[in] user_data User-defined data that will be returned in the callback. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_update_optional_depth_presets(ob_device *device, const char file_path_list[][OB_PATH_MAX], uint8_t path_count, + ob_device_fw_update_callback callback, void *user_data, ob_error **error); + +/** + * @brief Device reboot + * @attention The device will be disconnected and reconnected. After the device is disconnected, the interface access to the device handle may be abnormal. + * Please use the ob_delete_device interface to delete the handle directly. After the device is reconnected, it can be obtained again. + * + * @param[in] device Device object + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_reboot(ob_device *device, ob_error **error); + +/** + * @brief Get the current device status. + * + * @param[in] device The device object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device_state The device state information. + */ +OB_EXPORT ob_device_state ob_device_get_device_state(const ob_device *device, ob_error **error); + +/** + * @brief Set the device state changed callback. + * + * @param[in] device The device object. + * @param[in] callback The callback function to be called when the device status changes. + * @param[in] user_data User-defined data that will be returned in the callback. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_set_state_changed_callback(ob_device *device, ob_device_state_callback callback, void *user_data, ob_error **error); + +/** + * @brief Enable or disable the device heartbeat. + * @brief After enable the device heartbeat, the sdk will start a thread to send heartbeat signal to the device error every 3 seconds. + + * @attention If the device does not receive the heartbeat signal for a long time, it will be disconnected and rebooted. + * + * @param[in] device The device object. + * @param[in] enable Whether to enable the device heartbeat. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_enable_heartbeat(ob_device *device, bool enable, ob_error **error); + +/** + * @brief Send data to the device and receive data from the device. + * @brief This is a factory and debug function, which can be used to send and receive data from the device. The data format is secret and belongs to the device + * vendor. + * + * @param[in] device The device object. + * @param[in] send_data The data to be sent to the device. + * @param[in] send_data_size The size of the data to be sent to the device. + * @param[out] receive_data The data received from the device. + * @param[in,out] receive_data_size Pass in the expected size of the receive data, and return the actual size of the received data. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_send_and_receive_data(ob_device *device, const uint8_t *send_data, uint32_t send_data_size, uint8_t *receive_data, + uint32_t *receive_data_size, ob_error **error); + +/** + * @brief Get device information. + * + * @param[in] device The device to obtain information from. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device_info* The device information. + */ +OB_EXPORT ob_device_info *ob_device_get_device_info(const ob_device *device, ob_error **error); + +/** + * @brief Delete device information. + * + * @param[in] info The device information to be deleted. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_device_info(ob_device_info *info, ob_error **error); + +/** + * @brief Get device name + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* return the device name + */ +OB_EXPORT const char *ob_device_info_get_name(const ob_device_info *info, ob_error **error); + +/** +* @brief Get device pid + + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return int return the device pid +*/ +OB_EXPORT int ob_device_info_get_pid(const ob_device_info *info, ob_error **error); + +/** + * @brief Get device vid + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return int return device vid + */ +OB_EXPORT int ob_device_info_get_vid(const ob_device_info *info, ob_error **error); + +/** + * @brief Get device uid + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* return device uid + */ +OB_EXPORT const char *ob_device_info_get_uid(const ob_device_info *info, ob_error **error); + +/** + * @brief Get device serial number + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* return device serial number + */ +OB_EXPORT const char *ob_device_info_get_serial_number(const ob_device_info *info, ob_error **error); + +/** + * @brief Get the firmware version number + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return int return the firmware version number + */ +OB_EXPORT const char *ob_device_info_get_firmware_version(const ob_device_info *info, ob_error **error); + +/** + * @brief Get the device connection type + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The connection type, currently supports: "USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2", "Ethernet", "GMSL2" + */ +OB_EXPORT const char *ob_device_info_get_connection_type(const ob_device_info *info, ob_error **error); + +/** + * @brief Get the device IP address + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0" + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The IP address, such as "192.168.1.10" + */ +OB_EXPORT const char *ob_device_info_get_ip_address(const ob_device_info *info, ob_error **error); + +/** + * @brief Get the network device subnet mask + * + * @param[in] info Device information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * @return const char* The subnet mask, such as "255.255.255.0" + */ +OB_EXPORT const char *ob_device_info_get_subnet_mask(const ob_device_info *info, ob_error **error); + +/** + * @brief Get the network device gateway address + * + * @param[in] info Device information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The gateway address, such as "192.168.1.1" + */ +OB_EXPORT const char *ob_device_info_get_gateway(const ob_device_info *info, ob_error **error); + +/** + * @brief Get the hardware version number + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The hardware version number + */ +OB_EXPORT const char *ob_device_info_get_hardware_version(const ob_device_info *info, ob_error **error); + +/** + * @brief Check if the device extension information exists. + * + * @param[in] device The device object. + * @param[in] info_key The key of the device extension information. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool Whether the device extension information exists. + */ +OB_EXPORT bool ob_device_is_extension_info_exist(const ob_device *device, const char *info_key, ob_error **error); + +/** + * @brief Get the device extension information. + * @brief Extension information is a set of key-value pair of string, user cat get the information by the key. + * + * @param[in] device The device object. + * @param[in] info_key The key of the device extension information. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The device extension information + */ +OB_EXPORT const char *ob_device_get_extension_info(const ob_device *device, const char *info_key, ob_error **error); + +/** + * @brief Get the minimum SDK version number supported by the device + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The minimum SDK version number supported by the device + */ +OB_EXPORT const char *ob_device_info_get_supported_min_sdk_version(const ob_device_info *info, ob_error **error); + +/** + * @brief Get the chip name + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The ASIC name + */ +OB_EXPORT const char *ob_device_info_get_asicName(const ob_device_info *info, ob_error **error); + +/** + * @brief Get the device type + * + * @param[in] info Device Information + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device_type The device type + */ +OB_EXPORT ob_device_type ob_device_info_get_device_type(const ob_device_info *info, ob_error **error); + +/** + * @brief Delete a device list. + * + * @param[in] list The device list object to be deleted. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_device_list(ob_device_list *list, ob_error **error); + +/** + * @brief Get the number of devices + * + * @param[in] list Device list object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the number of devices + */ +OB_EXPORT uint32_t ob_device_list_get_count(const ob_device_list *list, ob_error **error); + +/** + * @brief Get device name + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* return device name + */ +OB_EXPORT const char *ob_device_list_get_device_name(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get the pid of the specified device + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return int return the device pid + */ +OB_EXPORT int ob_device_list_get_device_pid(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get the vid of the specified device + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return int return device vid + */ +OB_EXPORT int ob_device_list_get_device_vid(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get the uid of the specified device + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* return the device uid + */ +OB_EXPORT const char *ob_device_list_get_device_uid(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get the serial number of the specified device. + * + * @param[in] list Device list object. + * @param[in] index Device index. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The device UID. + */ +OB_EXPORT const char *ob_device_list_get_device_serial_number(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get device connection type + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* returns the device connection type, currently supports: "USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2", + * "Ethernet", "GMSL2" + */ +OB_EXPORT const char *ob_device_list_get_device_connection_type(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get device ip address + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* returns the device ip address, such as "192.168.1.10" + */ +OB_EXPORT const char *ob_device_list_get_device_ip_address(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get device subnet mask + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* returns the device subnet mask, such as "255.255.255.0" + */ +OB_EXPORT const char *ob_device_list_get_device_subnet_mask(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get device gateway + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* returns the device gateway, such as "192.168.1.1" + */ +OB_EXPORT const char *ob_device_list_get_device_gateway(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get the MAC address of the host network interface corresponding to the network device. + * + * @attention Only valid for network devices. Returns "0:0:0:0:0:0" for non-network devices. + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The MAC address of the host network interface associated with the device. + */ +OB_EXPORT const char *ob_device_list_get_device_local_mac(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get the IP address of the host network interface corresponding to the network device. + * + * @attention Only valid for network devices. Returns "0.0.0.0" for non-network devices. + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The IP address of the host network interface associated with the device. + */ +OB_EXPORT const char *ob_device_list_get_device_local_ip(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get the subnet length of the host network interface corresponding to the network device. + * + * @attention Only valid for network devices. Returns 0 for non-network devices. + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const uint8_t The subnet length (0~32) of the host network interface associated with the device. + */ +OB_EXPORT uint8_t ob_device_list_get_device_local_subnet_length(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Get the gateway of the host network interface corresponding to the network device. + * + * @attention Only valid for network devices. Returns "0.0.0.0" for non-network devices. + * + * @param[in] list Device list object + * @param[in] index Device index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* The gateway of the host network interface associated with the device. + */ +OB_EXPORT const char *ob_device_list_get_device_local_gateway(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Create a device. + * + * @attention If the device has already been acquired and created elsewhere, repeated acquisitions will return an error. + * + * @param[in] list Device list object. + * @param[in] index The index of the device to create. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device* The created device. + * + * @note Default access mode is OB_DEVICE_DEFAULT_ACCESS + */ +OB_EXPORT ob_device *ob_device_list_get_device(const ob_device_list *list, uint32_t index, ob_error **error); + +/** + * @brief Create a device. + * + * @attention If the device has already been acquired and created elsewhere, repeated acquisitions will return an error. + * + * @param[in] list Device list object. + * @param[in] index The index of the device to create. + * @param[in] accessMode Device access mode. @ref ob_device_access_mode. + * If the device does not support setting the Access Mode, the default OB_DEVICE_DEFAULT_ACCESS is used. + * Applies only on first device creation or after release and re-creation; subsequent calls ignore it. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device* The created device. + */ +OB_EXPORT ob_device *ob_device_list_get_device_ex(const ob_device_list *list, uint32_t index, ob_device_access_mode accessMode, ob_error **error); + +/** + * @brief Create a device. + * + * @attention If the device has already been acquired and created elsewhere, repeated acquisitions will return an error. + * + * @param[in] list Device list object. + * @param[in] serial_number The serial number of the device to create. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device* The created device. + * + * @note Default access mode is OB_DEVICE_DEFAULT_ACCESS + */ +OB_EXPORT ob_device *ob_device_list_get_device_by_serial_number(const ob_device_list *list, const char *serial_number, ob_error **error); + +/** + * @brief Create a device. + * + * @attention If the device has already been acquired and created elsewhere, repeated acquisitions will return an error. + * + * @param[in] list Device list object. + * @param[in] serial_number The serial number of the device to create. + * @param[in] accessMode Device access mode. @ref ob_device_access_mode. + * If the device does not support setting the Access Mode, the default OB_DEVICE_DEFAULT_ACCESS is used. + * Applies only on first device creation or after release and re-creation; subsequent calls ignore it. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device* The created device. + */ +OB_EXPORT ob_device *ob_device_list_get_device_by_serial_number_ex(const ob_device_list *list, const char *serial_number, ob_device_access_mode accessMode, + ob_error **error); + +/** + * @brief Create device by uid + * @brief On Linux platform, for usb device, the uid of the device is composed of bus-port-dev, for example 1-1.2-1. But the SDK will remove the dev number and + * only keep the bus-port as the uid to create the device, for example 1-1.2, so that we can create a device connected to the specified USB port. Similarly, + * users can also directly pass in bus-port as uid to create device. + * @brief For GMSL device, the uid is GMSL port with "gmsl2-" prefix, for example gmsl2-1. + * + * @attention If the device has already been acquired and created elsewhere, repeated acquisitions will return an error. + * + * @param[in] list Device list object. + * @param[in] uid The UID of the device to create. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device* The created device. + * + * @note Default access mode is OB_DEVICE_DEFAULT_ACCESS + */ +OB_EXPORT ob_device *ob_device_list_get_device_by_uid(const ob_device_list *list, const char *uid, ob_error **error); + +/** + * @brief Create device by uid + * @brief On Linux platform, for usb device, the uid of the device is composed of bus-port-dev, for example 1-1.2-1. But the SDK will remove the dev number and + * only keep the bus-port as the uid to create the device, for example 1-1.2, so that we can create a device connected to the specified USB port. Similarly, + * users can also directly pass in bus-port as uid to create device. + * @brief For GMSL device, the uid is GMSL port with "gmsl2-" prefix, for example gmsl2-1. + * + * @attention If the device has already been acquired and created elsewhere, repeated acquisitions will return an error. + * + * @param[in] list Device list object. + * @param[in] uid The UID of the device to create. + * @param[in] accessMode Device access mode. @ref ob_device_access_mode. + * If the device does not support setting the Access Mode, the default OB_DEVICE_DEFAULT_ACCESS is used. + * Applies only on first device creation or after release and re-creation; subsequent calls ignore it. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device* The created device. + */ +OB_EXPORT ob_device *ob_device_list_get_device_by_uid_ex(const ob_device_list *list, const char *uid, ob_device_access_mode accessMode, ob_error **error); + +/** + * @brief Get the original parameter list of camera calibration saved on the device. + * + * @attention The parameters in the list do not correspond to the current open-stream configuration.You need to select the parameters according to the actual + * situation, and may need to do scaling, mirroring and other processing. Non-professional users are recommended to use the ob_pipeline_get_camera_param() + * interface. + * + * @param[in] device The device object. + * @param[out] error Log error messages. + * + * @return ob_camera_param_list The camera parameter list. + */ +OB_EXPORT ob_camera_param_list *ob_device_get_calibration_camera_param_list(ob_device *device, ob_error **error); + +/** + * @brief Get the number of camera parameter lists + * + * @param[in] param_list Camera parameter list + * @param[out] error Log error messages + * + * @return uint32_t The number of lists + */ +OB_EXPORT uint32_t ob_camera_param_list_get_count(ob_camera_param_list *param_list, ob_error **error); + +/** + * @brief Get camera parameters from the camera parameter list + * + * @param[in] param_list Camera parameter list + * @param[in] index Parameter index + * @param[out] error Log error messages + * + * @return ob_camera_param The camera parameters. Since it returns the structure object directly, there is no need to provide a delete interface. + */ +OB_EXPORT ob_camera_param ob_camera_param_list_get_param(ob_camera_param_list *param_list, uint32_t index, ob_error **error); + +/** + * @brief Delete the camera parameter list + * + * @param[in] param_list Camera parameter list + * @param[out] error Log error messages + */ +OB_EXPORT void ob_delete_camera_param_list(ob_camera_param_list *param_list, ob_error **error); + +// The following interfaces are deprecated and are retained here for compatibility purposes. +#define ob_device_list_device_count ob_device_list_get_count +#define ob_device_list_get_extension_info ob_device_info_get_extension_info +#define ob_device_upgrade ob_device_update_firmware +#define ob_device_upgrade_from_data ob_device_update_firmware_from_data +#define ob_device_get_supported_property ob_device_get_supported_property_item +#define ob_device_state_changed ob_device_set_state_changed_callback +#define ob_device_info_name ob_device_info_get_name +#define ob_device_info_pid ob_device_info_get_pid +#define ob_device_info_vid ob_device_info_get_vid +#define ob_device_info_uid ob_device_info_get_uid +#define ob_device_info_serial_number ob_device_info_get_serial_number +#define ob_device_info_firmware_version ob_device_info_get_firmware_version +#define ob_device_info_connection_type ob_device_info_get_connection_type +#define ob_device_info_ip_address ob_device_info_get_ip_address +#define ob_device_info_hardware_version ob_device_info_get_hardware_version +#define ob_device_info_supported_min_sdk_version ob_device_info_get_supported_min_sdk_version +#define ob_device_info_asicName ob_device_info_get_asicName +#define ob_device_info_device_type ob_device_info_get_device_type +#define ob_device_list_get_device_count ob_device_list_get_count +#define ob_camera_param_list_count ob_camera_param_list_get_count + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Error.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Error.h new file mode 100644 index 0000000..79991b6 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Error.h @@ -0,0 +1,85 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Error.h + * @brief Functions for handling errors, mainly used for obtaining error messages. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Create a new error object. + * + * @param[in] status The error status. + * @param[in] message The error message. + * @param[in] function The name of the API function that caused the error. + * @param[in] args The error parameters. + * @param[in] exception_type The type of exception that caused the error. + * + * @return ob_error* The new error object. + */ +OB_EXPORT ob_error *ob_create_error(ob_status status, const char *message, const char *function, const char *args, ob_exception_type exception_type); + +/** + * @brief Get the error status. + * + * @param[in] error The error object. + * @return The error status. + */ +OB_EXPORT ob_status ob_error_get_status(const ob_error *error); + +/** + * @brief Get the error message. + * + * @param[in] error The error object. + * @return The error message. + */ +OB_EXPORT const char *ob_error_get_message(const ob_error *error); + +/** + * @brief Get the name of the API function that caused the error. + * + * @param[in] error The error object. + * @return The name of the API function. + */ +OB_EXPORT const char *ob_error_get_function(const ob_error *error); + +/** + * @brief Get the error parameters. + * + * @param[in] error The error object. + * @return The error parameters. + */ +OB_EXPORT const char *ob_error_get_args(const ob_error *error); + +/** + * @brief Get the type of exception that caused the error. + * + * @param[in] error The error object. + * @return The type of exception. + */ +OB_EXPORT ob_exception_type ob_error_get_exception_type(const ob_error *error); + +/** + * @brief Delete the error object. + * + * @param[in] error The error object to delete, you should set the pointer to NULL after calling this function. + */ +OB_EXPORT void ob_delete_error(ob_error *error); + +// The following interfaces are deprecated and are retained here for compatibility purposes. +#define ob_error_status ob_error_get_status +#define ob_error_message ob_error_get_message +#define ob_error_function ob_error_get_function +#define ob_error_args ob_error_get_args +#define ob_error_exception_type ob_error_get_exception_type + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Export.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Export.h new file mode 100644 index 0000000..a8fb41f --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Export.h @@ -0,0 +1,43 @@ + +#ifndef OB_EXPORT_H +#define OB_EXPORT_H + +#ifdef OB_STATIC_DEFINE +# define OB_EXPORT +# define OB_NO_EXPORT +#else +# ifndef OB_EXPORT +# ifdef OrbbecSDK_EXPORTS + /* We are building this library */ +# define OB_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define OB_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef OB_NO_EXPORT +# define OB_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef OB_DEPRECATED +# define OB_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef OB_DEPRECATED_EXPORT +# define OB_DEPRECATED_EXPORT OB_EXPORT OB_DEPRECATED +#endif + +#ifndef OB_DEPRECATED_NO_EXPORT +# define OB_DEPRECATED_NO_EXPORT OB_NO_EXPORT OB_DEPRECATED +#endif + +/* NOLINTNEXTLINE(readability-avoid-unconditional-preprocessor-if) */ +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef OB_NO_DEPRECATED +# define OB_NO_DEPRECATED +# endif +#endif + +#endif /* OB_EXPORT_H */ diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Filter.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Filter.h new file mode 100644 index 0000000..d718645 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Filter.h @@ -0,0 +1,273 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Filter.h + * @brief The processing unit of the SDK can perform point cloud generation, format conversion and other functions. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Create a Filter object. + * + * @attention If the filter of the specified name is a private filter, and the creator of the filter have not been activated, the function will return NULL. + * + * @param[in] name The name of the filter. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT ob_filter *ob_create_filter(const char *name, ob_error **error); + +/** + * @brief Get the name of ob_filter + * + * @param[in] filter ob_filter object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return char The filter of name + */ +OB_EXPORT const char *ob_filter_get_name(const ob_filter *filter, ob_error **error); + +/** + * @brief Get the vendor specific code of a filter by filter name. + * @brief A private filter can define its own vendor specific code for specific purposes. + * + * @param[in] name The name of the filter. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const char* Return the vendor specific code of the filter. + */ +OB_EXPORT const char *ob_filter_get_vendor_specific_code(const char *name, ob_error **error); + +/** + * @brief Create a private Filter object with activation key. + * @brief Some private filters require an activation key to be activated, its depends on the vendor of the filter. + * + * @param[in] name The name of the filter. + * @param[in] activation_key The activation key of the filter. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_filter* Return the private filter object. + */ +OB_EXPORT ob_filter *ob_create_private_filter(const char *name, const char *activation_key, ob_error **error); + +/** + * @brief Delete the filter. + * + * @param[in] filter The filter object to be deleted. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_filter(ob_filter *filter, ob_error **error); + +/** + * @brief Get config schema of the filter + * @brief The returned string is a csv format string representing the configuration schema of the filter. The format of the string is: + * ``, ``, ``, ``, ``, ``, + * `` + * + * @param[in] filter The filter object to get the configuration schema for + * @param[out] error Pointer to an error object that will be set if an error occurs + * + * @return A csv format string representing the configuration schema of the filter + */ +OB_EXPORT const char *ob_filter_get_config_schema(const ob_filter *filter, ob_error **error); + +/** + * @brief Get the filter config schema list of the filter + * @brief The returned string is a list of ob_config_schema_item representing the configuration schema of the filter. + * + * @attention The returned list should be deleted by calling @ref ob_delete_filter_config_schema_list when it is no longer needed. + * + * @param[in] filter The filter object to get the configuration schema for + * @param[out] error Pointer to an error object that will be set if an error occurs + * + * @return ob_filter_config_schema_list* Return the filter config schema list of the filter + */ +OB_EXPORT ob_filter_config_schema_list *ob_filter_get_config_schema_list(const ob_filter *filter, ob_error **error); + +/** + * @brief Delete a list of filter config schema items. + * + * @param[in] config_schema_list The list of filter config schema items to delete. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_filter_config_schema_list(ob_filter_config_schema_list *config_schema_list, ob_error **error); + +/** + * @brief Update config of the filter + * + * @attention The passed in argc and argv must match the configuration schema returned by the @ref ob_filter_get_config_schema function. + * + * @param[in] filter The filter object to update the configuration for + * @param[in] argc The number of arguments in the argv array + * @param[in] argv An array of strings representing the configuration values + * @param[out] error Pointer to an error object that will be set if an error occurs + */ +OB_EXPORT void ob_filter_update_config(ob_filter *filter, uint8_t argc, const char **argv, ob_error **error); + +/** + * @brief Get the filter config value by name and cast to double. + * + * @attention The returned value is cast to double, the actual type of the value depends on the filter config schema returned by @ref + * ob_filter_get_config_schema. + * + * @param[in] filter A filter object. + * @param[in] config_name config name + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return double The value of the config. + */ +OB_EXPORT double ob_filter_get_config_value(const ob_filter *filter, const char *config_name, ob_error **error); + +/** + * @brief Set the filter config value by name. + * + * @attention The pass into value type is double, witch will be cast to the actual type inside the filter. The actual type can be queried by the filter config + * schema returned by @ref ob_filter_get_config_schema. + * + * @param[in] filter A filter object. + * @param[in] config_name config name + * @param[in] value The value to set. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_filter_set_config_value(ob_filter *filter, const char *config_name, double value, ob_error **error); + +/** + * @brief Reset the filter, clears the cache, and resets the state. If the asynchronous interface is used, the processing thread will also be stopped and the + * pending cache frames will be cleared. + * + * @param[in] filter A filter object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_filter_reset(ob_filter *filter, ob_error **error); + +/** + * @brief Enable the frame post processing + * @brief The filter default is enable. + * + * @attention If the filter has been disabled by calling this function, processing will directly output a clone of the input frame. + * + * @param[in] filter A filter object. + * @param[in] enable enable status, true: enable; false: disable. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_filter_enable(ob_filter *filter, bool enable, ob_error **error); + +/** + * @brief Get the enable status of the frame post processing + * + * @attention If the filter is disabled, the processing will directly output a clone of the input frame. + * + * @param[in] filter A filter object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The post processing filter status. True: enable; False: disable. + */ +OB_EXPORT bool ob_filter_is_enabled(const ob_filter *filter, ob_error **error); + +/** + * @brief Process the frame (synchronous interface). + * + * @param[in] filter A filter object. + * @param[in] frame Pointer to the frame object to be processed. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The frame object processed by the filter. + */ +OB_EXPORT ob_frame *ob_filter_process(ob_filter *filter, const ob_frame *frame, ob_error **error); + +/** + * @brief Set the processing result callback function for the filter (asynchronous callback interface). + * + * @param[in] filter A filter object. + * @param[in] callback Callback function. + * @param[in] user_data Arbitrary user data pointer can be passed in and returned from the callback. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_filter_set_callback(ob_filter *filter, ob_filter_callback callback, void *user_data, ob_error **error); + +/** + * @brief Push the frame into the pending cache for the filter (asynchronous callback interface). + * @brief The frame will be processed by the filter when the processing thread is available and return a new processed frame to the callback function. + * + * @attention The frame object will be add reference count, so the user still need call @ref ob_delete_frame to release the frame after calling this function. + * + * @param[in] filter A filter object. + * @param[in] frame Pointer to the frame object to be processed. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_filter_push_frame(ob_filter *filter, const ob_frame *frame, ob_error **error); + +/** + * @brief Get the number of filter in the list + * + * @param[in] filter_list filter list + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t The number of list + */ +OB_EXPORT uint32_t ob_filter_list_get_count(const ob_filter_list *filter_list, ob_error **error); + +/** + * @brief Get the filter by index + * + * @param[in] filter_list Filter list + * @param[in] index Filter index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_filter The index of ob_filter + */ +OB_EXPORT ob_filter *ob_filter_list_get_filter(const ob_filter_list *filter_list, uint32_t index, ob_error **error); + +/** + * @brief Delete a list of ob_filter objects. + * + * @param[in] filter_list The list of ob_filter objects to delete. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_filter_list(ob_filter_list *filter_list, ob_error **error); + +/** + * @brief Get the number of config schema items in the config schema list + * + * @param[in] config_schema_list Filter config schema list + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t The number of config schema items in the filter list + */ +OB_EXPORT uint32_t ob_filter_config_schema_list_get_count(const ob_filter_config_schema_list *config_schema_list, ob_error **error); + +/** + * @brief Get the config schema item by index + * + * @param[in] config_schema_list Filter config schema list + * @param[in] index Config schema item index + * @param[out] error Pointer to an error object that will be set if an error occurs. + * @return ob_filter_config_schema_item* The config schema item by index + */ +OB_EXPORT ob_filter_config_schema_item ob_filter_config_schema_list_get_item(const ob_filter_config_schema_list *config_schema_list, uint32_t index, + ob_error **error); + +/** + * @brief Set the align to stream profile for the align filter. + * @brief It is useful when the align target stream dose not started (without any frame to get intrinsics and extrinsics). + * + * @param[in] filter A filter object. + * @param[in] align_to_stream_profile The align target stream profile. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_align_filter_set_align_to_stream_profile(ob_filter *filter, const ob_stream_profile *align_to_stream_profile, ob_error **error); + +// The following interfaces are deprecated and are retained here for compatibility purposes. +#define ob_get_filter ob_filter_list_get_filter +#define ob_get_filter_name ob_filter_get_name + +#ifdef __cplusplus +} +#endif + diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Frame.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Frame.h new file mode 100644 index 0000000..15f87d7 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Frame.h @@ -0,0 +1,686 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Frame.h + * @brief Frame related function is mainly used to obtain frame data and frame information + * + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Crate a frame object based on the specified parameters. + * + * @attention The frame object is created with a reference count of 1, and the reference count should be decreased by calling @ref ob_delete_frame() when it is + * no longer needed. + * + * @param[in] frame_type The frame object type. + * @param[in] format The frame object format. + * @param[in] data_size The size of the frame object data. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the frame object. + */ +OB_EXPORT ob_frame *ob_create_frame(ob_frame_type frame_type, ob_format format, uint32_t data_size, ob_error **error); + +/** + * @brief Create (clone) a frame object based on the specified other frame object. + * @brief The new frame object will have the same properties as the other frame object, but the data buffer is newly allocated. + * + * @attention The frame object is created with a reference count of 1, and the reference count should be decreased by calling @ref ob_delete_frame() when it is + * no longer needed. + * + * @param[in] other_frame The frame object to create the new frame object according to. + * @param[in] should_copy_data If true, the data of the source frame object will be copied to the new frame object. If false, the new frame object will + * have a data buffer with random data. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the new frame object. + */ +OB_EXPORT ob_frame *ob_create_frame_from_other_frame(const ob_frame *other_frame, bool should_copy_data, ob_error **error); + +/** + * @brief Create a frame object according to the specified stream profile. + * + * @attention The frame object is created with a reference count of 1, and the reference count should be decreased by calling @ref ob_delete_frame() when it is + * no logger needed. + * + * @param[in] stream_profile The stream profile to create the new frame object according to. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the new frame object. + */ +OB_EXPORT ob_frame *ob_create_frame_from_stream_profile(const ob_stream_profile *stream_profile, ob_error **error); + +/** + * @brief Create an video frame object based on the specified parameters. + * + * @attention The frame object is created with a reference count of 1, and the reference count should be decreased by calling @ref ob_delete_frame() when it is + * no longer needed. + * + * @param[in] frame_type Frame object type. + * @param[in] format Frame object format. + * @param[in] width Frame object width. + * @param[in] height Frame object height. + * @param[in] stride_bytes Row span in bytes. If 0, the stride is calculated based on the width and format. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return an empty frame object. + */ +OB_EXPORT ob_frame *ob_create_video_frame(ob_frame_type frame_type, ob_format format, uint32_t width, uint32_t height, uint32_t stride_bytes, ob_error **error); + +/** + * @brief Create a frame object based on an externally created buffer. + * + * @attention The buffer is owned by the user and will not be destroyed by the frame object. The user should ensure that the buffer is valid and not modified. + * @attention The frame object is created with a reference count of 1, and the reference count should be decreased by calling @ref ob_delete_frame() when it is + * no longer needed. + * + * @param[in] frame_type Frame object type. + * @param[in] format Frame object format. + * @param[in] buffer Frame object buffer. + * @param[in] buffer_size Frame object buffer size. + * @param[in] buffer_destroy_cb Destroy callback, will be called when the frame object is destroyed. + * @param[in] buffer_destroy_context Destroy context, user-defined context to be passed to the destroy callback. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the frame object. + */ +OB_EXPORT ob_frame *ob_create_frame_from_buffer(ob_frame_type frame_type, ob_format format, uint8_t *buffer, uint32_t buffer_size, + ob_frame_destroy_callback *buffer_destroy_cb, void *buffer_destroy_context, ob_error **error); + +/** + * @brief Create a video frame object based on an externally created buffer. + * + * @attention The buffer is owned by the user and will not be destroyed by the frame object. The user should ensure that the buffer is valid and not modified. + * @attention The frame object is created with a reference count of 1, and the reference count should be decreased by calling @ref ob_delete_frame() when it is + * no longer needed. + * + * @param[in] frame_type Frame object type. + * @param[in] format Frame object format. + * @param[in] width Frame object width. + * @param[in] height Frame object height. + * @param[in] stride_bytes Row span in bytes. If 0, the stride is calculated based on the width and format. + * @param[in] buffer Frame object buffer. + * @param[in] buffer_size Frame object buffer size. + * @param[in] buffer_destroy_cb Destroy callback, user-defined function to destroy the buffer. + * @param[in] buffer_destroy_context Destroy context, user-defined context to be passed to the destroy callback. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the frame object. + */ +OB_EXPORT ob_frame *ob_create_video_frame_from_buffer(ob_frame_type frame_type, ob_format format, uint32_t width, uint32_t height, uint32_t stride_bytes, + uint8_t *buffer, uint32_t buffer_size, ob_frame_destroy_callback *buffer_destroy_cb, + void *buffer_destroy_context, ob_error **error); + +/** + * @brief Create an empty frameset object. + * @brief A frameset object is a special type of frame object that can be used to store multiple frames. + * + * @attention The frameset object is created with a reference count of 1, and the reference count should be decreased by calling @ref ob_delete_frame() when it + * is no longer needed. + * + * @param[out] error Pointer to an error object that will be set if an error occurs. + * @return ob_frame* Return the frameset object. + */ +OB_EXPORT ob_frame *ob_create_frameset(ob_error **error); + +/** + * @brief Increase the reference count of a frame object. + * @brief The reference count is used to manage the lifetime of the frame object. + * + * @attention When calling this function, the reference count of the frame object is + * increased and requires to be decreased by calling @ref ob_delete_frame(). + * + * @param[in] frame Frame object to increase the reference count. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_frame_add_ref(const ob_frame *frame, ob_error **error); + +/** + * @brief Delete a frame object + * @brief This function will decrease the reference count of the frame object and release the memory if the reference count becomes 0. + * + * @param[in] frame The frame object to delete. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_frame(const ob_frame *frame, ob_error **error); + +/** + * @brief Copy the information of the source frame object to the destination frame object. + * @brief Including the index, timestamp, system timestamp, global timestamp and metadata will be copied. + * + * @param[in] src_frame Source frame object to copy the information from. + * @param[in] dst_frame Destination frame object to copy the information to. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_frame_copy_info(const ob_frame *src_frame, ob_frame *dst_frame, ob_error **error); + +/** + * @brief Get the frame index + * + * @param[in] frame Frame object + * @param[out] error Log wrong message + * + * @return uint64_t return the frame index + */ +OB_EXPORT uint64_t ob_frame_get_index(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the frame format + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_format return the frame format + */ +OB_EXPORT ob_format ob_frame_get_format(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the frame type + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame_type return the frame type + */ +OB_EXPORT ob_frame_type ob_frame_get_type(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the frame timestamp (also known as device timestamp, hardware timestamp) of the frame in microseconds. + * @brief The hardware timestamp is the time point when the frame was captured by the device (Typically in the mid-exposure, unless otherwise stated), on device + * clock domain. + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint64_t return the frame hardware timestamp in microseconds + */ +OB_EXPORT uint64_t ob_frame_get_timestamp_us(const ob_frame *frame, ob_error **error); + +/** + * @brief Set the frame timestamp (also known as the device timestamp, hardware timestamp) of a frame object. + * + * @param[in] frame Frame object to set the timestamp. + * @param[in] timestamp_us frame timestamp to set in microseconds. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_frame_set_timestamp_us(ob_frame *frame, uint64_t timestamp_us, ob_error **error); + +/** + * @brief Get the system timestamp of the frame in microseconds. + * @brief The system timestamp is the time point when the frame was received by the host, on host clock domain. + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint64_t return the frame system timestamp in microseconds + */ +OB_EXPORT uint64_t ob_frame_get_system_timestamp_us(const ob_frame *frame, ob_error **error); + +/** + * @brief Set the system timestamp of the frame in microseconds. + * + * @param[in] frame Frame object + * @param[in] system_timestamp_us frame system timestamp to set in microseconds. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_frame_set_system_timestamp_us(ob_frame *frame, uint64_t system_timestamp_us, ob_error **error); + +/** + * @brief Get the global timestamp of the frame in microseconds. + * @brief The global timestamp is the time point when the frame was captured by the device, and has been converted to the host clock domain. The + * conversion process base on the frame timestamp and can eliminate the timer drift of the device + * + * @attention The global timestamp is disabled by default. If global timestamp is not enabled, the function will return 0. To enable it, call @ref + * ob_device_enable_global_timestamp() function. + * @attention Only some models of device support getting the global timestamp. Check the device support status by @ref + * ob_device_is_global_timestamp_supported() function. + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint64_t The global timestamp of the frame in microseconds. + */ +OB_EXPORT uint64_t ob_frame_get_global_timestamp_us(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the data buffer of a frame. + * + * @attention The returned data buffer is mutable, but it is not recommended to modify it directly. Modifying the data directly may cause issues if the frame is + * being used in other threads or future use. If you need to modify the data, it is recommended to create a new frame object. + * + * @param[in] frame The frame object from which to retrieve the data. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint8_t* Pointer to the frame data buffer. + */ +OB_EXPORT uint8_t *ob_frame_get_data(const ob_frame *frame, ob_error **error); + +/** + * @brief Update the data of a frame. + * @brief The data will be memcpy to the frame data buffer. + * @brief The frame data size will be also updated as the input data size. + * + * @attention It is not recommended to update the frame data if the frame was not created by the user. If you must update it, ensure that the frame is not being + * used in other threads. + * @attention The size of the new data should be equal to or less than the current data size of the frame. Exceeding the original size may cause memory + * exceptions. + * + * @param[in] frame The frame object to update. + * @param[in] data The new data to update the frame with. + * @param[in] data_size The size of the new data. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_frame_update_data(ob_frame *frame, const uint8_t *data, uint32_t data_size, ob_error **error); + +/** + * @brief Get the frame data size + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the frame data size + * If it is point cloud data, it return the number of bytes occupied by all point sets. If you need to find the number of points, you need to divide dataSize + * by the structure size of the corresponding point type. + */ +OB_EXPORT uint32_t ob_frame_get_data_size(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the metadata of the frame + * + * @attention The returned metadata is mutable, but it is not recommended to modify it directly. Modifying the metadata directly may cause issues if the frame + * is being used in other threads or future use. If you need to modify the metadata, it is recommended to create a new frame object. + * + * @param[in] frame frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return const uint8_t * return the metadata pointer of the frame + */ +OB_EXPORT uint8_t *ob_frame_get_metadata(const ob_frame *frame, ob_error **error); +#define ob_video_frame_metadata ob_frame_get_metadata // for compatibility + +/** + * @brief Get the metadata size of the frame + * + * @param[in] frame frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the metadata size of the frame + */ +OB_EXPORT uint32_t ob_frame_get_metadata_size(const ob_frame *frame, ob_error **error); +#define ob_video_frame_metadata_size ob_frame_get_metadata_size // for compatibility + +/** + * @brief Update the metadata of the frame + * @brief The metadata will be memcpy to the frame metadata buffer. + * @brief The frame metadata size will be also updated as the input metadata size. + * + * @attention It is not recommended to update the frame metadata if the frame was not created by the user. If you must update it, ensure that the frame is not + * being used in other threads or future use. + * @attention The metadata size should be equal to or less than 256 bytes, otherwise it will cause memory exception. + * + * @param[in] frame frame object + * @param[in] metadata The new metadata to update. + * @param[in] metadata_size The size of the new metadata. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_frame_update_metadata(ob_frame *frame, const uint8_t *metadata, uint32_t metadata_size, ob_error **error); + +/** + * @brief check if the frame contains the specified metadata + * + * @param[in] frame frame object + * @param[in] type metadata type, refer to @ref ob_frame_metadata_type + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT bool ob_frame_has_metadata(const ob_frame *frame, ob_frame_metadata_type type, ob_error **error); + +/** + * @brief Get the metadata value of the frame + * + * @param[in] frame frame object + * @param[in] type metadata type, refer to @ref ob_frame_metadata_type + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return int64_t return the metadata value of the frame + */ +OB_EXPORT int64_t ob_frame_get_metadata_value(const ob_frame *frame, ob_frame_metadata_type type, ob_error **error); + +/** + * @brief Get the stream profile of the frame + * + * @attention Require @ref ob_delete_stream_profile() to release the return stream profile. + * + * @param[in] frame frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * @return ob_stream_profile* Return the stream profile of the frame, if the frame is not captured by a sensor stream, it will return NULL + */ +OB_EXPORT ob_stream_profile *ob_frame_get_stream_profile(const ob_frame *frame, ob_error **error); + +/** + * @brief Set (override) the stream profile of the frame + * + * @param[in] frame frame object + * @param[in] stream_profile The stream profile to set for the frame. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_frame_set_stream_profile(ob_frame *frame, const ob_stream_profile *stream_profile, ob_error **error); + +/** + * @brief Get the sensor of the frame + * + * @attention Require @ref ob_delete_sensor() to release the return sensor. + * + * @param[in] frame frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_sensor* return the sensor of the frame, if the frame is not captured by a sensor or the sensor stream has been destroyed, it will return NULL + */ +OB_EXPORT ob_sensor *ob_frame_get_sensor(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the device of the frame + * + * @attention Require @ref ob_delete_device() to release the return device. + * + * @param[in] frame frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device* return the device of the frame, if the frame is not captured by a sensor stream or the device has been destroyed, it will return NULL + */ +OB_EXPORT ob_device *ob_frame_get_device(const ob_frame *frame, ob_error **error); + +/** + * @brief Get video frame width + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the frame width + */ +OB_EXPORT uint32_t ob_video_frame_get_width(const ob_frame *frame, ob_error **error); + +/** + * @brief Get video frame height + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the frame height + */ +OB_EXPORT uint32_t ob_video_frame_get_height(const ob_frame *frame, ob_error **error); + +/** + * @brief Get video frame pixel format + * @brief Usually used to determine the pixel type of depth frame (depth, disparity, raw phase, etc.) + * + * @attention Always return OB_PIXEL_UNKNOWN for non-depth frame currently if user has not set the pixel type by @ref ob_video_frame_set_pixel_type() + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_pixel_type return the pixel format of the frame. + */ +OB_EXPORT ob_pixel_type ob_video_frame_get_pixel_type(const ob_frame *frame, ob_error **error); + +/** + * @brief Set video frame pixel format + * + * @param[in] frame Frame object + * @param[in] pixel_type the pixel format of the frame + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_video_frame_set_pixel_type(ob_frame *frame, ob_pixel_type pixel_type, ob_error **error); + +/** + * @brief Get the effective number of pixels (such as Y16 format frame, but only the lower 10 bits are effective bits, and the upper 6 bits are filled with 0) + * @attention Only valid for Y8/Y10/Y11/Y12/Y14/Y16 format + * + * @param[in] frame video frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint8_t return the effective number of pixels in the pixel, or 0 if it is an unsupported format + */ +OB_EXPORT uint8_t ob_video_frame_get_pixel_available_bit_size(const ob_frame *frame, ob_error **error); + +/** + * @brief Set the effective number of pixels (such as Y16 format frame, but only the lower 10 bits are effective bits, and the upper 6 bits are filled with 0) + * @attention Only valid for Y8/Y10/Y11/Y12/Y14/Y16 format + * + * @param[in] frame video frame object + * @param[in] bit_size the effective number of pixels in the pixel, or 0 if it is an unsupported format + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_video_frame_set_pixel_available_bit_size(ob_frame *frame, uint8_t bit_size, ob_error **error); + +/** + * @brief Get the value scale of the depth frame. The pixel value of the depth frame is multiplied by the scale to give a depth value in millimeters. + * For example, if valueScale=0.1 and a certain coordinate pixel value is pixelValue=10000, then the depth value = pixelValue*valueScale = 10000*0.1=1000mm. + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return float The value scale of the depth frame + */ +OB_EXPORT float ob_depth_frame_get_value_scale(const ob_frame *frame, ob_error **error); + +/** + * @brief Set the value scale of the depth frame. The pixel value of the depth frame is multiplied by the scale to give a depth value in millimeters. + * For example, if valueScale=0.1 and a certain coordinate pixel value is pixelValue=10000, then the depth value = pixelValue*valueScale = 10000*0.1=1000mm. + * + * @param[in] frame Frame object + * @param[in] value_scale The value scale of the depth frame + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_depth_frame_set_value_scale(ob_frame *frame, float value_scale, ob_error **error); + +/** + * @brief Get the point coordinate value scale of the points frame. The point position value of the points frame is multiplied by the scale to give a position + * value in millimeters. For example, if scale=0.1, the x-coordinate value of a point is x = 10000, which means that the actual x-coordinate value = x*scale = + * 10000*0.1 = 1000mm. + * + * @param[in] frame Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return float The coordinate value scale of the points frame + */ +OB_EXPORT float ob_points_frame_get_coordinate_value_scale(const ob_frame *frame, ob_error **error); + +/** + * @brief Get accelerometer frame data. + * + * @param[in] frame Accelerometer frame. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_accel_value Return the accelerometer data. + */ +OB_EXPORT ob_accel_value ob_accel_frame_get_value(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the temperature when acquiring the accelerometer frame. + * + * @param[in] frame Accelerometer frame. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return float Return the temperature value. + */ +OB_EXPORT float ob_accel_frame_get_temperature(const ob_frame *frame, ob_error **error); + +/** + * @brief Get gyroscope frame data. + * + * @param[in] frame Gyroscope frame. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_gyro_value Return the gyroscope data. + */ +OB_EXPORT ob_gyro_value ob_gyro_frame_get_value(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the temperature when acquiring the gyroscope frame. + * + * @param[in] frame Gyroscope frame. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return float Return the temperature value. + */ +OB_EXPORT float ob_gyro_frame_get_temperature(const ob_frame *frame, ob_error **error); + +/** + * @brief Get the number of frames contained in the frameset + * + * @attention The frame returned by this function should call @ref ob_delete_frame() to decrease the reference count when it is no longer needed. + * + * @param[in] frameset frameset object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the number of frames + */ +OB_EXPORT uint32_t ob_frameset_get_count(const ob_frame *frameset, ob_error **error); + +/** + * @brief Get the depth frame from the frameset. + * + * @attention The frame returned by this function should call @ref ob_delete_frame() to decrease the reference count when it is no longer needed. + * + * @param[in] frameset Frameset object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the depth frame. + */ +OB_EXPORT ob_frame *ob_frameset_get_depth_frame(const ob_frame *frameset, ob_error **error); + +/** + * @brief Get the color frame from the frameset. + * + * @attention The frame returned by this function should call @ref ob_delete_frame() to decrease the reference count when it is no longer needed. + * + * @param[in] frameset Frameset object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the color frame. + */ +OB_EXPORT ob_frame *ob_frameset_get_color_frame(const ob_frame *frameset, ob_error **error); + +/** + * @brief Get the infrared frame from the frameset. + * + * @attention The frame returned by this function should call @ref ob_delete_frame() to decrease the reference count when it is no longer needed. + * + * @param[in] frameset Frameset object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the infrared frame. + */ +OB_EXPORT ob_frame *ob_frameset_get_ir_frame(const ob_frame *frameset, ob_error **error); + +/** + * @brief Get point cloud frame from the frameset. + * + * @attention The frame returned by this function should call @ref ob_delete_frame() to decrease the reference count when it is no longer needed. + * + * @param[in] frameset Frameset object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the point cloud frame. + */ +OB_EXPORT ob_frame *ob_frameset_get_points_frame(const ob_frame *frameset, ob_error **error); + +/** + * @brief Get a frame of a specific type from the frameset. + * + * @attention The frame returned by this function should call @ref ob_delete_frame() to decrease the reference count when it is no longer needed. + * + * @param[in] frameset Frameset object. + * @param[in] frame_type Frame type. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the frame of the specified type, or nullptr if it does not exist. + */ +OB_EXPORT ob_frame *ob_frameset_get_frame(const ob_frame *frameset, ob_frame_type frame_type, ob_error **error); + +/** + * @brief Get a frame at a specific index from the FrameSet + * + * @param[in] frameset Frameset object. + * @param[in] index The index of the frame. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* Return the frame at the specified index, or nullptr if it does not exist. + */ +OB_EXPORT ob_frame *ob_frameset_get_frame_by_index(const ob_frame *frameset, uint32_t index, ob_error **error); + +/** + * @brief Push a frame to the frameset + * + * @attention If a frame with same type already exists in the frameset, it will be replaced by the new frame. + * @attention The frame push to the frameset will be add reference count, so you still need to call @ref ob_delete_frame() to decrease the reference count when + * it is no longer needed. + * + * @param[in] frameset Frameset object. + * @param[in] frame Frame object to push. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_frameset_push_frame(ob_frame *frameset, const ob_frame *frame, ob_error **error); + +/** + * @brief Get point cloud frame width + * + * @param[in] frame point cloud Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the point cloud frame width + */ +OB_EXPORT uint32_t ob_point_cloud_frame_get_width(const ob_frame *frame, ob_error **error); + +/** + * @brief Get point cloud frame height + * + * @param[in] frame point cloud Frame object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the point cloud frame height + */ +OB_EXPORT uint32_t ob_point_cloud_frame_get_height(const ob_frame *frame, ob_error **error); + +// The following interfaces are deprecated and are retained here for compatibility purposes. +#define ob_frame_index ob_frame_get_index +#define ob_frame_format ob_frame_get_format +#define ob_frame_time_stamp_us ob_frame_get_timestamp_us +#define ob_frame_set_device_time_stamp_us ob_frame_set_timestamp_us +#define ob_frame_system_time_stamp_us ob_frame_get_system_timestamp_us +#define ob_frame_global_time_stamp_us ob_frame_get_global_timestamp_us +#define ob_frame_data ob_frame_get_data +#define ob_frame_data_size ob_frame_get_data_size +#define ob_frame_metadata ob_frame_get_metadata +#define ob_frame_metadata_size ob_frame_get_metadata_size +#define ob_video_frame_width ob_video_frame_get_width +#define ob_video_frame_height ob_video_frame_get_height +#define ob_video_frame_pixel_available_bit_size ob_video_frame_get_pixel_available_bit_size +#define ob_points_frame_get_position_value_scale ob_points_frame_get_coordinate_value_scale +#define ob_frameset_frame_count ob_frameset_get_count +#define ob_frameset_depth_frame ob_frameset_get_depth_frame +#define ob_frameset_color_frame ob_frameset_get_color_frame +#define ob_frameset_ir_frame ob_frameset_get_ir_frame +#define ob_frameset_points_frame ob_frameset_get_points_frame +#define ob_accel_frame_value ob_accel_frame_get_value +#define ob_accel_frame_temperature ob_accel_frame_get_temperature +#define ob_gyro_frame_value ob_gyro_frame_get_value +#define ob_gyro_frame_temperature ob_gyro_frame_get_temperature +#define ob_frameset_get_frame_count ob_frameset_get_count + +#define ob_frame_time_stamp(frame, err) (ob_frame_get_timestamp_us(frame, err) / 1000) +#define ob_frame_system_time_stamp(frame, err) (ob_frame_get_system_timestamp_us(frame, err)) +#define ob_frame_set_system_time_stamp(frame, system_timestamp, err) (ob_frame_set_system_timestamp_us(frame, system_timestamp * 1000, err)) +#define ob_frame_set_device_time_stamp(frame, device_timestamp, err) (ob_frame_set_timestamp_us(frame, device_timestamp * 1000, err)) + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/MultipleDevices.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/MultipleDevices.h new file mode 100644 index 0000000..0ea2e4e --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/MultipleDevices.h @@ -0,0 +1,131 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file MultipleDevices.h + * @brief This file contains the multiple devices related API witch is used to control the synchronization between multiple devices and the synchronization + * between different sensor within single device. + * @brief The synchronization between multiple devices is complex, and different models have different synchronization modes and limitations. please refer to + * the product manual for details. + * @brief As the Depth and Infrared are the same sensor physically, the behavior of the Infrared is same as the Depth in the synchronization mode. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" +#include "Device.h" + +/** + * @brief Get the supported multi device sync mode bitmap of the device. + * @brief For example, if the return value is 0b00001100, it means the device supports @ref OB_MULTI_DEVICE_SYNC_MODE_PRIMARY and @ref + * OB_MULTI_DEVICE_SYNC_MODE_SECONDARY. User can check the supported mode by the code: + * ```c + * if(supported_mode_bitmap & OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN){ + * //support OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN + * } + * if(supported_mode_bitmap & OB_MULTI_DEVICE_SYNC_MODE_STANDALONE){ + * //support OB_MULTI_DEVICE_SYNC_MODE_STANDALONE + * } + * // and so on + * ``` + * @param[in] device The device handle. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint16_t return the supported multi device sync mode bitmap of the device. + */ +OB_EXPORT uint16_t ob_device_get_supported_multi_device_sync_mode_bitmap(const ob_device *device, ob_error **error); + +/** + * @brief set the multi device sync configuration of the device. + * + * @param[in] device The device handle. + * @param[in] config The multi device sync configuration. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_set_multi_device_sync_config(ob_device *device, const ob_multi_device_sync_config *config, ob_error **error); + +/** + * @brief get the current multi device sync configuration of the device. + * + * @param[in] device The device handle. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_multi_device_sync_config return the multi device sync configuration of the device. + */ +OB_EXPORT ob_multi_device_sync_config ob_device_get_multi_device_sync_config(const ob_device *device, ob_error **error); + +/** + * @brief send the capture command to the device to trigger the capture. + * @brief The device will start one time capture after receiving the capture command when it is in the @ref OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING + * + * @attention The frequency of the user call this function multiplied by the number of frames per trigger should be less than the frame rate of the stream. The + * number of frames per trigger can be set by @ref ob_multi_device_sync_config::framesPerTrigger. + * @attention For some models, receive and execute the capture command will have a certain delay and performance consumption, so the frequency of calling this + * function should not be too high, please refer to the product manual for the specific supported frequency. + * @attention If the device is not in the @ref OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING mode, device will ignore the capture command. + * + * @param[in] device The device handle. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_trigger_capture(ob_device *device, ob_error **error); + +/** + * @brief set the timestamp reset configuration of the device. + * + * @param[in] device The device handle. + * @param[in] config The timestamp reset configuration. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_set_timestamp_reset_config(ob_device *device, const ob_device_timestamp_reset_config *config, ob_error **error); + +/** + * @brief get the timestamp reset configuration of the device. + * + * @param[in] device The device handle. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device_timestamp_reset_config return the timestamp reset configuration of the device. + */ +OB_EXPORT ob_device_timestamp_reset_config ob_device_get_timestamp_reset_config(ob_device *device, ob_error **error); + +/** + * @brief send the timestamp reset command to the device. + * @brief The device will reset the timer for calculating the timestamp for output frames to 0 after receiving the timestamp reset command when the timestamp + * reset function is enabled. The timestamp reset function can be enabled by call @ref ob_device_set_timestamp_reset_config. + * + * @attention If the stream of the device is started, the timestamp of the continuous frames output by the stream will jump once after the timestamp reset. + * @attention Due to the timer of device is not high-accuracy, the timestamp of the continuous frames output by the stream will drift after a long time. User + * can call this function periodically to reset the timer to avoid the timestamp drift, the recommended interval time is 60 minutes. + * + * @param[in] device The device handle. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_timestamp_reset(ob_device *device, ob_error **error); + +/** + * @brief Alias for @ref ob_device_timestamp_reset since it is more accurate. + */ +#define ob_device_timer_reset ob_device_timestamp_reset + +/** + * @brief synchronize the timer of the device with the host. + * @brief After calling this function, the timer of the device will be synchronized with the host. User can call this function to multiple devices to + * synchronize all timers of the devices. + * + * @attention If the stream of the device is started, the timestamp of the continuous frames output by the stream will may jump once after the timer sync. + * @attention Due to the timer of device is not high-accuracy, the timestamp of the continuous frames output by the stream will drift after a long time. User + * can call this function periodically to synchronize the timer to avoid the timestamp drift, the recommended interval time is 60 minutes. + * + * @param[in] device The device handle. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_device_timer_sync_with_host(ob_device *device, ob_error **error); + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/ObTypes.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/ObTypes.h new file mode 100644 index 0000000..889dc24 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/ObTypes.h @@ -0,0 +1,2058 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file ObTypes.h + * @brief Provide structs commonly used in the SDK, enumerating constant definitions. + */ + +#pragma once + +#include "Export.h" + +#include +#include + +#pragma pack(push, 1) // struct 1-byte align + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ob_context_t ob_context; +typedef struct ob_device_t ob_device; +typedef struct ob_device_info_t ob_device_info; +typedef struct ob_device_list_t ob_device_list; +typedef struct ob_record_device_t ob_record_device; +typedef struct ob_playback_device_t ob_playback_device; +typedef struct ob_camera_param_list_t ob_camera_param_list; +typedef struct ob_sensor_t ob_sensor; +typedef struct ob_sensor_list_t ob_sensor_list; +typedef struct ob_stream_profile_t ob_stream_profile; +typedef struct ob_stream_profile_list_t ob_stream_profile_list; +typedef struct ob_frame_t ob_frame; +typedef struct ob_filter_t ob_filter; +typedef struct ob_filter_list_t ob_filter_list; +typedef struct ob_pipeline_t ob_pipeline; +typedef struct ob_config_t ob_config; +typedef struct ob_depth_work_mode_list_t ob_depth_work_mode_list; +typedef struct ob_device_preset_list_t ob_device_preset_list; +typedef struct ob_filter_config_schema_list_t ob_filter_config_schema_list; +typedef struct ob_device_frame_interleave_list_t ob_device_frame_interleave_list; +typedef struct ob_preset_resolution_config_list_t ob_preset_resolution_config_list; + +#define OB_WIDTH_ANY 0 +#define OB_HEIGHT_ANY 0 +#define OB_FPS_ANY 0 +#define OB_FORMAT_ANY OB_FORMAT_UNKNOWN +#define OB_PROFILE_DEFAULT 0 +#define OB_DEFAULT_STRIDE_BYTES 0 +#define OB_ACCEL_FULL_SCALE_RANGE_ANY OB_ACCEL_FS_UNKNOWN +#define OB_ACCEL_SAMPLE_RATE_ANY OB_SAMPLE_RATE_UNKNOWN +#define OB_GYRO_FULL_SCALE_RANGE_ANY OB_GYRO_FS_UNKNOWN +#define OB_GYRO_SAMPLE_RATE_ANY OB_SAMPLE_RATE_UNKNOWN +#define OB_LIDAR_SCAN_ANY OB_LIDAR_SCAN_UNKNOWN + +/** + * @brief maximum path length + */ +#define OB_PATH_MAX (1024) + +/** + * @brief the permission type of api or property + */ +typedef enum { + OB_PERMISSION_DENY = 0, /**< no permission */ + OB_PERMISSION_READ = 1, /**< can read */ + OB_PERMISSION_WRITE = 2, /**< can write */ + OB_PERMISSION_READ_WRITE = 3, /**< can read and write */ + OB_PERMISSION_ANY = 255, /**< any situation above */ +} OBPermissionType, + ob_permission_type; + +/** + * @brief error code + */ +typedef enum { + OB_STATUS_OK = 0, /**< status ok */ + OB_STATUS_ERROR = 1, /**< status error */ +} OBStatus, + ob_status; + +/** + * @brief log level, the higher the level, the stronger the log filter + */ +typedef enum { + OB_LOG_SEVERITY_DEBUG, /**< debug */ + OB_LOG_SEVERITY_INFO, /**< information */ + OB_LOG_SEVERITY_WARN, /**< warning */ + OB_LOG_SEVERITY_ERROR, /**< error */ + OB_LOG_SEVERITY_FATAL, /**< fatal error */ + OB_LOG_SEVERITY_OFF /**< off (close LOG) */ +} OBLogSeverity, + ob_log_severity, DEVICE_LOG_SEVERITY_LEVEL, OBDeviceLogSeverityLevel, ob_device_log_severity_level; +#define OB_LOG_SEVERITY_NONE OB_LOG_SEVERITY_OFF + +/** + * @brief The exception types in the SDK, through the exception type, you can easily determine the specific type of error. + * For detailed error API interface functions and error logs, please refer to the information of ob_error + */ +typedef enum { + OB_EXCEPTION_TYPE_UNKNOWN, /**< Unknown error, an error not clearly defined by the SDK */ + OB_EXCEPTION_STD_EXCEPTION, /** < Standard exception, an error caused by the standard library */ + OB_EXCEPTION_TYPE_CAMERA_DISCONNECTED, /**< Camera/Device has been disconnected, the camera/device is not available */ + OB_EXCEPTION_TYPE_PLATFORM, /**< An error in the SDK adaptation platform layer, which means an error in the implementation of a specific system + platform */ + OB_EXCEPTION_TYPE_INVALID_VALUE, /**< Invalid parameter type exception, need to check input parameter */ + OB_EXCEPTION_TYPE_WRONG_API_CALL_SEQUENCE, /**< Wrong API call sequence, the API is called in the wrong order or the wrong parameter is passed */ + OB_EXCEPTION_TYPE_NOT_IMPLEMENTED, /**< SDK and firmware have not yet implemented this function or feature */ + OB_EXCEPTION_TYPE_IO, /**< SDK access IO exception error */ + OB_EXCEPTION_TYPE_MEMORY, /**< SDK access and use memory errors. For example, the frame fails to allocate memory */ + OB_EXCEPTION_TYPE_UNSUPPORTED_OPERATION, /**< Unsupported operation type error by SDK or device */ + OB_EXCEPTION_TYPE_ACCESS_DENIED, /**< Device access denied */ +} OBExceptionType, + ob_exception_type; + +/** + * @brief The error class exposed by the SDK, users can get detailed error information according to the error + */ +typedef struct ob_error { + ob_status status; ///< Describe the status code of the error, as compatible with previous customer status code requirements + char message[256]; ///< Describe the detailed error log + char function[256]; ///< Describe the name of the function where the error occurred + char args[256]; ///< Describes the parameters passed to the function when an error occurs. Used to check whether the parameter is wrong + ob_exception_type exception_type; ///< The description is the specific error type of the SDK +} ob_error; + +/** + * @brief Enumeration value describing the sensor type + */ +typedef enum { + OB_SENSOR_UNKNOWN = 0, /**< Unknown type sensor */ + OB_SENSOR_IR = 1, /**< IR */ + OB_SENSOR_COLOR = 2, /**< Color */ + OB_SENSOR_DEPTH = 3, /**< Depth */ + OB_SENSOR_ACCEL = 4, /**< Accel */ + OB_SENSOR_GYRO = 5, /**< Gyro */ + OB_SENSOR_IR_LEFT = 6, /**< left IR for stereo camera*/ + OB_SENSOR_IR_RIGHT = 7, /**< Right IR for stereo camera*/ + OB_SENSOR_RAW_PHASE = 8, /**< Raw Phase */ + OB_SENSOR_CONFIDENCE = 9, /**< Confidence */ + OB_SENSOR_LIDAR = 10, /**< LiDAR */ + OB_SENSOR_COLOR_LEFT = 11, /**< Left Color */ + OB_SENSOR_COLOR_RIGHT = 12, /**< Right Color */ + OB_SENSOR_TYPE_COUNT, /**The total number of sensor types, is not a valid sensor type */ +} OBSensorType, + ob_sensor_type; + +/** + * @brief Enumeration value describing the type of data stream + */ +typedef enum { + OB_STREAM_UNKNOWN = -1, /**< Unknown type stream */ + OB_STREAM_VIDEO = 0, /**< Video stream (infrared, color, depth streams are all video streams) */ + OB_STREAM_IR = 1, /**< IR stream */ + OB_STREAM_COLOR = 2, /**< color stream */ + OB_STREAM_DEPTH = 3, /**< depth stream */ + OB_STREAM_ACCEL = 4, /**< Accelerometer data stream */ + OB_STREAM_GYRO = 5, /**< Gyroscope data stream */ + OB_STREAM_IR_LEFT = 6, /**< Left IR stream for stereo camera */ + OB_STREAM_IR_RIGHT = 7, /**< Right IR stream for stereo camera */ + OB_STREAM_RAW_PHASE = 8, /**< RawPhase Stream */ + OB_STREAM_CONFIDENCE = 9, /**< Confidence Stream*/ + OB_STREAM_LIDAR = 10, /**< LiDAR Stream for LiDAR device*/ + OB_STREAM_COLOR_LEFT = 11, /**< Left Color stream */ + OB_STREAM_COLOR_RIGHT = 12, /**< Right Color stream */ + OB_STREAM_TYPE_COUNT, /**< The total number of stream type,is not a valid stream type */ +} OBStreamType, + ob_stream_type; + +/** + * @brief Enumeration value describing the type of frame + */ +typedef enum { + OB_FRAME_UNKNOWN = -1, /**< Unknown frame type */ + OB_FRAME_VIDEO = 0, /**< Video frame */ + OB_FRAME_IR = 1, /**< IR frame */ + OB_FRAME_COLOR = 2, /**< Color frame */ + OB_FRAME_DEPTH = 3, /**< Depth frame */ + OB_FRAME_ACCEL = 4, /**< Accelerometer data frame */ + OB_FRAME_SET = 5, /**< Frame collection (internally contains a variety of data frames) */ + OB_FRAME_POINTS = 6, /**< Point cloud frame */ + OB_FRAME_GYRO = 7, /**< Gyroscope data frame */ + OB_FRAME_IR_LEFT = 8, /**< Left IR frame for stereo camera */ + OB_FRAME_IR_RIGHT = 9, /**< Right IR frame for stereo camera */ + OB_FRAME_RAW_PHASE = 10, /**< Raw Phase frame*/ + OB_FRAME_CONFIDENCE = 11, /**< Confidence frame*/ + OB_FRAME_LIDAR_POINTS = 12, /**< LiDAR point3d cloud frame*/ + OB_FRAME_COLOR_LEFT = 13, /**< Left Color frame */ + OB_FRAME_COLOR_RIGHT = 14, /**< Right Color frame */ + OB_FRAME_TYPE_COUNT, /**< The total number of frame types, is not a valid frame type */ +} OBFrameType, + ob_frame_type; + +/** + * @brief Enumeration value describing the pixel type of frame (usually used for depth frame) + * + */ +typedef enum { + OB_PIXEL_UNKNOWN = -1, // Unknown pixel type, or undefined pixel type for current frame + OB_PIXEL_DEPTH = 0, // Depth pixel type, the value of the pixel is the distance from the camera to the object + OB_PIXEL_DISPARITY = 2, // Disparity for structured light camera + OB_PIXEL_RAW_PHASE = 3, // Raw phase for tof camera + OB_PIXEL_TOF_DEPTH = 4, // Depth for tof camera +} OBPixelType, + ob_pixel_type; + +/** + * @brief Enumeration value describing the pixel format + */ +typedef enum { + OB_FORMAT_UNKNOWN = -1, /**< unknown format */ + OB_FORMAT_YUYV = 0, /**< YUYV format */ + OB_FORMAT_YUY2 = 1, /**< YUY2 format (the actual format is the same as YUYV) */ + OB_FORMAT_UYVY = 2, /**< UYVY format */ + OB_FORMAT_NV12 = 3, /**< NV12 format */ + OB_FORMAT_NV21 = 4, /**< NV21 format */ + OB_FORMAT_MJPG = 5, /**< MJPEG encoding format */ + OB_FORMAT_H264 = 6, /**< H.264 encoding format */ + OB_FORMAT_H265 = 7, /**< H.265 encoding format */ + OB_FORMAT_Y16 = 8, /**< Y16 format, 16-bit per pixel, single-channel*/ + OB_FORMAT_Y8 = 9, /**< Y8 format, 8-bit per pixel, single-channel */ + OB_FORMAT_Y10 = 10, /**< Y10 format, 10-bit per pixel, single-channel(SDK will unpack into Y16 by default) */ + OB_FORMAT_Y11 = 11, /**< Y11 format, 11-bit per pixel, single-channel (SDK will unpack into Y16 by default) */ + OB_FORMAT_Y12 = 12, /**< Y12 format, 12-bit per pixel, single-channel(SDK will unpack into Y16 by default) */ + OB_FORMAT_GRAY = 13, /**< GRAY (the actual format is the same as YUYV) */ + OB_FORMAT_HEVC = 14, /**< HEVC encoding format (the actual format is the same as H265) */ + OB_FORMAT_I420 = 15, /**< I420 format */ + OB_FORMAT_ACCEL = 16, /**< Acceleration data format */ + OB_FORMAT_GYRO = 17, /**< Gyroscope data format */ + OB_FORMAT_POINT = 19, /**< XYZ 3D coordinate point format, @ref OBPoint */ + OB_FORMAT_RGB_POINT = 20, /**< XYZ 3D coordinate point format with RGB information, @ref OBColorPoint */ + OB_FORMAT_RLE = 21, /**< RLE pressure test format (SDK will be unpacked into Y16 by default) */ + OB_FORMAT_RGB = 22, /**< RGB format (actual RGB888) */ + OB_FORMAT_BGR = 23, /**< BGR format (actual BGR888) */ + OB_FORMAT_Y14 = 24, /**< Y14 format, 14-bit per pixel, single-channel (SDK will unpack into Y16 by default) */ + OB_FORMAT_BGRA = 25, /**< BGRA format */ + OB_FORMAT_COMPRESSED = 26, /**< Compression format */ + OB_FORMAT_RVL = 27, /**< RVL pressure test format (SDK will be unpacked into Y16 by default) */ + OB_FORMAT_Z16 = 28, /**< Is same as Y16*/ + OB_FORMAT_YV12 = 29, /**< Is same as Y12, using for right ir stream*/ + OB_FORMAT_BA81 = 30, /**< Is same as Y8, using for right ir stream*/ + OB_FORMAT_RGBA = 31, /**< RGBA format */ + OB_FORMAT_BYR2 = 32, /**< byr2 format */ + OB_FORMAT_RW16 = 33, /**< RAW16 format */ + OB_FORMAT_Y12C4 = 34, /**< Y12C4 format */ + OB_FORMAT_LIDAR_POINT = 35, /**< XYZ 3D coordinate point format with LiDAR information, @ref OBLiDARPoint */ + OB_FORMAT_LIDAR_SPHERE_POINT = 36, /**< Spherical coordinate point format with LiDAR information, @ref OBLiDARSpherePoint */ + OB_FORMAT_LIDAR_SCAN = 37, /**< LiDAR single-line scan mode data format, @ref OBLiDARScanPoint */ + OB_FORMAT_LIDAR_CALIBRATION = 38, /**< LiDAR calibration mode point format */ +} OBFormat, + ob_format; + +#define OB_FORMAT_RGB888 OB_FORMAT_RGB // Alias of OB_FORMAT_RGB for compatibility +#define OB_FORMAT_MJPEG OB_FORMAT_MJPG // Alias of OB_FORMAT_MJPG for compatibility + +// Check if the format is a fixed data size format +#define IS_FIXED_SIZE_FORMAT(format) \ + (format != OB_FORMAT_MJPG && format != OB_FORMAT_H264 && format != OB_FORMAT_H265 && format != OB_FORMAT_HEVC && format != OB_FORMAT_RLE \ + && format != OB_FORMAT_RVL) + +// Check if the format is a packed format, which means the data of pixels is not continuous or bytes aligned in memory +#define IS_PACKED_FORMAT(format) \ + (format == OB_FORMAT_Y10 || format == OB_FORMAT_Y11 || format == OB_FORMAT_Y12 || format == OB_FORMAT_Y14 || format == OB_FORMAT_RLE) + +/** + * @brief Enumeration value describing the firmware upgrade status + */ +typedef enum { + STAT_DONE_REBOOT_AND_REUPDATE = 7, /**< update completed and device requires manual reboot and a second update*/ + STAT_DONE_WITH_DUPLICATES = 6, /**< update completed, but some files were duplicated and ignored */ + STAT_VERIFY_SUCCESS = 5, /**< Image file verifify success */ + STAT_FILE_TRANSFER = 4, /**< file transfer */ + STAT_DONE = 3, /**< update completed */ + STAT_IN_PROGRESS = 2, /**< upgrade in process */ + STAT_START = 1, /**< start the upgrade */ + STAT_VERIFY_IMAGE = 0, /**< Image file verification */ + ERR_VERIFY = -1, /**< Verification failed */ + ERR_PROGRAM = -2, /**< Program execution failed */ + ERR_ERASE = -3, /**< Flash parameter failed */ + ERR_FLASH_TYPE = -4, /**< Flash type error */ + ERR_IMAGE_SIZE = -5, /**< Image file size error */ + ERR_OTHER = -6, /**< other errors */ + ERR_DDR = -7, /**< DDR access error */ + ERR_TIMEOUT = -8, /**< timeout error */ + ERR_MISMATCH = -9, /**< Mismatch firmware error */ + ERR_UNSUPPORT_DEV = -10, /**< Unsupported device error */ + ERR_INVALID_COUNT = -11, /**< invalid firmware/preset count */ + ERR_FILE_READ = -12, /**< Read image file error */ + ERR_TRANSFER = -13 /**< Transfer failed */ +} OBUpgradeState, + OBFwUpdateState, ob_upgrade_state, ob_fw_update_state; + +/** + * @brief Enumeration value describing the file transfer status + */ +typedef enum { + FILE_TRAN_STAT_TRANSFER = 2, /**< File transfer */ + FILE_TRAN_STAT_DONE = 1, /**< File transfer succeeded */ + FILE_TRAN_STAT_PREPAR = 0, /**< Preparing */ + FILE_TRAN_ERR_DDR = -1, /**< DDR access failed */ + FILE_TRAN_ERR_NOT_ENOUGH_SPACE = -2, /**< Insufficient target space error */ + FILE_TRAN_ERR_PATH_NOT_WRITABLE = -3, /**< Destination path is not writable */ + FILE_TRAN_ERR_MD5_ERROR = -4, /**< MD5 checksum error */ + FILE_TRAN_ERR_WRITE_FLASH_ERROR = -5, /**< Write flash error */ + FILE_TRAN_ERR_TIMEOUT = -6 /**< Timeout error */ +} OBFileTranState, + ob_file_tran_state; + +/** + * @brief Enumeration value describing the data transfer status + */ +typedef enum { + DATA_TRAN_STAT_VERIFY_DONE = 4, /**< data verify done */ + DATA_TRAN_STAT_STOPPED = 3, /**< data transfer stoped */ + DATA_TRAN_STAT_DONE = 2, /**< data transfer completed */ + DATA_TRAN_STAT_VERIFYING = 1, /**< data verifying */ + DATA_TRAN_STAT_TRANSFERRING = 0, /**< data transferring */ + DATA_TRAN_ERR_BUSY = -1, /**< Transmission is busy */ + DATA_TRAN_ERR_UNSUPPORTED = -2, /**< Not supported */ + DATA_TRAN_ERR_TRAN_FAILED = -3, /**< Transfer failed */ + DATA_TRAN_ERR_VERIFY_FAILED = -4, /**< Test failed */ + DATA_TRAN_ERR_OTHER = -5 /**< Other errors */ +} OBDataTranState, + ob_data_tran_state; + +/** + * @brief Structure for transmitting data blocks + */ +typedef struct { + uint8_t *data; ///< Pointer to current block data + uint32_t size; ///< Length of current block data + uint32_t offset; ///< Offset of current data block relative to complete data + uint32_t fullDataSize; ///< Size of full data +} OBDataChunk, ob_data_chunk; + +/** + * @brief Structure for integer range + */ +typedef struct { + int32_t cur; ///< Current value + int32_t max; ///< Maximum value + int32_t min; ///< Minimum value + int32_t step; ///< Step value + int32_t def; ///< Default value +} OBIntPropertyRange, ob_int_property_range; + +/** + * @brief Structure for float range + */ +typedef struct { + float cur; ///< Current value + float max; ///< Maximum value + float min; ///< Minimum value + float step; ///< Step value + float def; ///< Default value +} OBFloatPropertyRange, ob_float_property_range; + +/** + * @brief Structure for float range + */ +typedef struct { + uint16_t cur; ///< Current value + uint16_t max; ///< Maximum value + uint16_t min; ///< Minimum value + uint16_t step; ///< Step value + uint16_t def; ///< Default value +} OBUint16PropertyRange, ob_uint16_property_range; + +/** + * @brief Structure for float range + */ +typedef struct { + uint8_t cur; ///< Current value + uint8_t max; ///< Maximum value + uint8_t min; ///< Minimum value + uint8_t step; ///< Step value + uint8_t def; ///< Default value +} OBUint8PropertyRange, ob_uint8_property_range; + +/** + * @brief Structure for boolean range + */ +typedef struct { + bool cur; ///< Current value + bool max; ///< Maximum value + bool min; ///< Minimum value + bool step; ///< Step value + bool def; ///< Default value +} OBBoolPropertyRange, ob_bool_property_range; + +/** \brief Distortion model: defines how pixel coordinates should be mapped to sensor coordinates. */ +typedef enum { + OB_DISTORTION_NONE, /**< Rectilinear images. No distortion compensation required. */ + OB_DISTORTION_MODIFIED_BROWN_CONRADY, /**< Equivalent to Brown-Conrady distortion, except that tangential distortion is applied to radially distorted points + */ + OB_DISTORTION_INVERSE_BROWN_CONRADY, /**< Equivalent to Brown-Conrady distortion, except undistorts image instead of distorting it */ + OB_DISTORTION_BROWN_CONRADY, /**< Unmodified Brown-Conrady distortion model */ + OB_DISTORTION_BROWN_CONRADY_K6, /**< Unmodified Brown-Conrady distortion model with k6 supported */ + OB_DISTORTION_KANNALA_BRANDT4, /**< Kannala-Brandt distortion model */ +} OBCameraDistortionModel, + ob_camera_distortion_model; + +/** + * @brief Structure for camera intrinsic parameters + */ +typedef struct { + float fx; ///< Focal length in x direction + float fy; ///< Focal length in y direction + float cx; ///< Optical center abscissa + float cy; ///< Optical center ordinate + int16_t width; ///< Image width + int16_t height; ///< Image height +} OBCameraIntrinsic, ob_camera_intrinsic; + +/** + * @brief Structure for accelerometer intrinsic parameters + */ +typedef struct { + double noiseDensity; ///< In-run bias instability + double randomWalk; ///< random walk + double referenceTemp; ///< reference temperature + double bias[3]; ///< bias for x, y, z axis + double gravity[3]; ///< gravity direction for x, y, z axis + double scaleMisalignment[9]; ///< scale factor and three-axis non-orthogonal error + double tempSlope[9]; ///< linear temperature drift coefficient +} OBAccelIntrinsic, ob_accel_intrinsic; + +/** + * @brief Structure for gyroscope intrinsic parameters + */ +typedef struct { + double noiseDensity; ///< In-run bias instability + double randomWalk; ///< random walk + double referenceTemp; ///< reference temperature + double bias[3]; ///< bias for x, y, z axis + double scaleMisalignment[9]; ///< scale factor and three-axis non-orthogonal error + double tempSlope[9]; ///< linear temperature drift coefficient +} OBGyroIntrinsic, ob_gyro_intrinsic; + +/** + * @brief Structure for distortion parameters + */ +typedef struct { + float k1; ///< Radial distortion factor 1 + float k2; ///< Radial distortion factor 2 + float k3; ///< Radial distortion factor 3 + float k4; ///< Radial distortion factor 4 + float k5; ///< Radial distortion factor 5 + float k6; ///< Radial distortion factor 6 + float p1; ///< Tangential distortion factor 1 + float p2; ///< Tangential distortion factor 2 + OBCameraDistortionModel model; +} OBCameraDistortion, ob_camera_distortion; + +/** + * @brief Structure for rotation/transformation + */ +typedef struct { + float rot[9]; ///< Rotation matrix + float trans[3]; ///< Transformation matrix in millimeters +} OBD2CTransform, ob_d2c_transform, OBTransform, ob_transform, OBExtrinsic, ob_extrinsic; + +/** + * @brief Structure for camera parameters + */ +typedef struct { + OBCameraIntrinsic depthIntrinsic; ///< Depth camera internal parameters + OBCameraIntrinsic rgbIntrinsic; ///< Color camera internal parameters + OBCameraDistortion depthDistortion; ///< Depth camera distortion parameters + OBCameraDistortion rgbDistortion; ///< Color camera distortion parameters + OBD2CTransform transform; ///< Rotation/transformation matrix + bool isMirrored; ///< Whether the image frame corresponding to this group of parameters is mirrored +} OBCameraParam, ob_camera_param; + +typedef struct { + int16_t width; ///< width + int16_t height; ///< height + int irDecimationFactor; ///< ir decimation factor + int depthDecimationFactor; ///< depth decimation factor +} OBPresetResolutionConfig, ob_preset_resolution_ratio_config; + +/** + * @brief calibration parameters + */ +typedef struct { + OBCameraIntrinsic intrinsics[OB_SENSOR_TYPE_COUNT]; ///< Sensor internal parameters + OBCameraDistortion distortion[OB_SENSOR_TYPE_COUNT]; ///< Sensor distortion + OBExtrinsic extrinsics[OB_SENSOR_TYPE_COUNT] + [OB_SENSOR_TYPE_COUNT]; ///< The extrinsic parameters allow 3D coordinate conversions between sensor.To transform from a + ///< source to a target 3D coordinate system,under extrinsics[source][target]. +} OBCalibrationParam, ob_calibration_param; + +/** + * @brief Configuration for depth margin filter + */ +typedef struct { + int margin_x_th; ///< Horizontal threshold settings + int margin_y_th; ///< Vertical threshold settings + int limit_x_th; ///< Maximum horizontal threshold + int limit_y_th; ///< Maximum vertical threshold + uint32_t width; ///< Image width + uint32_t height; ///< Image height + bool enable_direction; ///< Set to true for horizontal and vertical, false for horizontal only +} ob_margin_filter_config, OBMarginFilterConfig; + +/** + * @brief Configuration for mgc filter + */ +typedef struct { + uint32_t width; + uint32_t height; + int max_width_left; + int max_width_right; + int max_radius; + int margin_x_th; + int margin_y_th; + int limit_x_th; + int limit_y_th; +} OBMGCFilterConfig, ob_mgc_filter_config; + +/** + * @brief Alignment mode + */ +typedef enum { + ALIGN_DISABLE, /**< Turn off alignment */ + ALIGN_D2C_HW_MODE, /**< Hardware D2C alignment mode */ + ALIGN_D2C_SW_MODE, /**< Software D2C alignment mode */ +} OBAlignMode, + ob_align_mode; + +/** + * @brief Camera performance mode + */ +typedef enum { + ADAPTIVE_PERFORMANCE_MODE, /**< Camera adaptive mode */ + HIGH_PERFORMANCE_MODE, /**< High Performance Mode */ +} OBCameraPerformanceMode, + ob_camera_performance_mode; + +/** + * @brief Rectangle + */ +typedef struct { + uint32_t x; ///< Origin coordinate x + uint32_t y; ///< Origin coordinate y + uint32_t width; ///< Rectangle width + uint32_t height; ///< Rectangle height +} OBRect, ob_rect; + +/** + * @brief Enumeration of format conversion types + */ +typedef enum { + FORMAT_YUYV_TO_RGB = 0, /**< YUYV to RGB */ + FORMAT_I420_TO_RGB, /**< I420 to RGB */ + FORMAT_NV21_TO_RGB, /**< NV21 to RGB */ + FORMAT_NV12_TO_RGB, /**< NV12 to RGB */ + FORMAT_MJPG_TO_I420, /**< MJPG to I420 */ + FORMAT_RGB_TO_BGR, /**< RGB888 to BGR */ + FORMAT_MJPG_TO_NV21, /**< MJPG to NV21 */ + FORMAT_MJPG_TO_RGB, /**< MJPG to RGB */ + FORMAT_MJPG_TO_BGR, /**< MJPG to BGR */ + FORMAT_MJPG_TO_BGRA, /**< MJPG to BGRA */ + FORMAT_UYVY_TO_RGB, /**< UYVY to RGB */ + FORMAT_BGR_TO_RGB, /**< BGR to RGB */ + FORMAT_MJPG_TO_NV12, /**< MJPG to NV12 */ + FORMAT_YUYV_TO_BGR, /**< YUYV to BGR */ + FORMAT_YUYV_TO_RGBA, /**< YUYV to RGBA */ + FORMAT_YUYV_TO_BGRA, /**< YUYV to BGRA */ + FORMAT_YUYV_TO_Y16, /**< YUYV to Y16 */ + FORMAT_YUYV_TO_Y8, /**< YUYV to Y8 */ + FORMAT_RGBA_TO_RGB, /**< RGBA to RGB */ + FORMAT_BGRA_TO_BGR, /**< BGRA to BGR */ + FORMAT_Y16_TO_RGB, /**< Y16 to RGB */ + FORMAT_Y8_TO_RGB, /**< Y8 to RGB */ +} OBConvertFormat, + ob_convert_format; + +// DEPRECATED: Only used for old version program compatibility, will be completely deleted in subsequent iterative versions +#define FORMAT_MJPEG_TO_I420 FORMAT_MJPG_TO_I420 +#define FORMAT_MJPEG_TO_NV21 FORMAT_MJPG_TO_NV21 +#define FORMAT_MJPEG_TO_BGRA FORMAT_MJPG_TO_BGRA +#define FORMAT_YUYV_TO_RGB888 FORMAT_YUYV_TO_RGB +#define FORMAT_I420_TO_RGB888 FORMAT_I420_TO_RGB +#define FORMAT_NV21_TO_RGB888 FORMAT_NV21_TO_RGB +#define FORMAT_NV12_TO_RGB888 FORMAT_NV12_TO_RGB +#define FORMAT_UYVY_TO_RGB888 FORMAT_UYVY_TO_RGB +#define FORMAT_MJPG_TO_RGB888 FORMAT_MJPG_TO_RGB +#define FORMAT_MJPG_TO_BGR888 FORMAT_MJPG_TO_BGR +#define FORMAT_MJPEG_TO_RGB888 FORMAT_MJPG_TO_RGB +#define FORMAT_MJPEG_TO_BGR888 FORMAT_MJPG_TO_BGR +#define FORMAT_RGB888_TO_BGR FORMAT_RGB_TO_BGR + +/** + * @brief Enumeration of IMU sample rate values (gyroscope or accelerometer) + */ +typedef enum { + OB_SAMPLE_RATE_UNKNOWN = 0, + OB_SAMPLE_RATE_1_5625_HZ = 1, /**< 1.5625Hz */ + OB_SAMPLE_RATE_3_125_HZ = 2, /**< 3.125Hz */ + OB_SAMPLE_RATE_6_25_HZ = 3, /**< 6.25Hz */ + OB_SAMPLE_RATE_12_5_HZ = 4, /**< 12.5Hz */ + OB_SAMPLE_RATE_25_HZ = 5, /**< 25Hz */ + OB_SAMPLE_RATE_50_HZ = 6, /**< 50Hz */ + OB_SAMPLE_RATE_100_HZ = 7, /**< 100Hz */ + OB_SAMPLE_RATE_200_HZ = 8, /**< 200Hz */ + OB_SAMPLE_RATE_500_HZ = 9, /**< 500Hz */ + OB_SAMPLE_RATE_1_KHZ = 10, /**< 1KHz */ + OB_SAMPLE_RATE_2_KHZ = 11, /**< 2KHz */ + OB_SAMPLE_RATE_4_KHZ = 12, /**< 4KHz */ + OB_SAMPLE_RATE_8_KHZ = 13, /**< 8KHz */ + OB_SAMPLE_RATE_16_KHZ = 14, /**< 16KHz */ + OB_SAMPLE_RATE_32_KHZ = 15, /**< 32Hz */ + OB_SAMPLE_RATE_400_HZ = 16, /**< 400Hz*/ + OB_SAMPLE_RATE_800_HZ = 17, /**< 800Hz*/ +} OBIMUSampleRate, + OBGyroSampleRate, ob_gyro_sample_rate, OBAccelSampleRate, ob_accel_sample_rate, OB_SAMPLE_RATE; + +/** + * @brief Enumeration of gyroscope ranges + */ +typedef enum { + OB_GYRO_FS_UNKNOWN = -1, + OB_GYRO_FS_16dps = 1, /**< 16 degrees per second */ + OB_GYRO_FS_31dps = 2, /**< 31 degrees per second */ + OB_GYRO_FS_62dps = 3, /**< 62 degrees per second */ + OB_GYRO_FS_125dps = 4, /**< 125 degrees per second */ + OB_GYRO_FS_250dps = 5, /**< 250 degrees per second */ + OB_GYRO_FS_500dps = 6, /**< 500 degrees per second */ + OB_GYRO_FS_1000dps = 7, /**< 1000 degrees per second */ + OB_GYRO_FS_2000dps = 8, /**< 2000 degrees per second */ + OB_GYRO_FS_400dps = 9, /**< 400 degrees per second */ + OB_GYRO_FS_800dps = 10, /**< 800 degrees per second */ +} OBGyroFullScaleRange, + ob_gyro_full_scale_range, OB_GYRO_FULL_SCALE_RANGE; + +/** + * @brief Enumeration of accelerometer ranges + */ +typedef enum { + OB_ACCEL_FS_UNKNOWN = -1, + OB_ACCEL_FS_2g = 1, /**< 1x the acceleration of gravity */ + OB_ACCEL_FS_4g = 2, /**< 4x the acceleration of gravity */ + OB_ACCEL_FS_8g = 3, /**< 8x the acceleration of gravity */ + OB_ACCEL_FS_16g = 4, /**< 16x the acceleration of gravity */ + OB_ACCEL_FS_3g = 5, /**< 3x the acceleration of gravity */ + OB_ACCEL_FS_6g = 6, /**< 6x the acceleration of gravity */ + OB_ACCEL_FS_12g = 7, /**< 12x the acceleration of gravity */ + OB_ACCEL_FS_24g = 8, /**< 24x the acceleration of gravity */ +} OBAccelFullScaleRange, + ob_accel_full_scale_range, OB_ACCEL_FULL_SCALE_RANGE; + +/** + * @brief Data structures for accelerometers and gyroscopes + */ +typedef struct { + float x; ///< X-direction component + float y; ///< Y-direction component + float z; ///< Z-direction component +} OBAccelValue, OBGyroValue, OBFloat3D, ob_accel_value, ob_gyro_value, ob_float_3d; + +/** + * @brief Data structures for LiDAR scan rate + */ +typedef enum { + OB_LIDAR_SCAN_UNKNOWN = 0, + OB_LIDAR_SCAN_5HZ = 1, + OB_LIDAR_SCAN_10HZ = 2, + OB_LIDAR_SCAN_15HZ = 3, + OB_LIDAR_SCAN_20HZ = 4, + OB_LIDAR_SCAN_25HZ = 5, + OB_LIDAR_SCAN_30HZ = 6, + OB_LIDAR_SCAN_40HZ = 7, +} OBLiDARScanRate, + ob_lidar_scan_rate, OB_LIDAR_SCAN_RATE; + +/** + * @brief Device state + */ +typedef uint64_t OBDeviceState, ob_device_state; + +/** + * @brief Temperature parameters of the device (unit: Celsius) + */ +typedef struct { + float cpuTemp; ///< CPU temperature + float irTemp; ///< IR temperature + float ldmTemp; ///< Laser temperature + float mainBoardTemp; ///< Motherboard temperature + float tecTemp; ///< TEC temperature + float imuTemp; ///< IMU temperature + float rgbTemp; ///< RGB temperature + float irLeftTemp; ///< Left IR temperature + float irRightTemp; ///< Right IR temperature + float chipTopTemp; ///< MX6600 top temperature + float chipBottomTemp; ///< MX6600 bottom temperature +} OBDeviceTemperature, ob_device_temperature, DEVICE_TEMPERATURE; + +/** + * @brief Enumeration for depth crop modes + */ +typedef enum { + DEPTH_CROPPING_MODE_AUTO = 0, /**< Automatic mode */ + DEPTH_CROPPING_MODE_CLOSE = 1, /**< Close crop */ + DEPTH_CROPPING_MODE_OPEN = 2, /**< Open crop */ +} OBDepthCroppingMode, + ob_depth_cropping_mode, OB_DEPTH_CROPPING_MODE; + +/** + * @brief Enumeration for device types + */ +typedef enum { + OB_DEVICE_TYPE_UNKNOWN = -1, /**< Unknown device type */ + OB_STRUCTURED_LIGHT_MONOCULAR_CAMERA = 0, /**< Monocular structured light camera */ + OB_STRUCTURED_LIGHT_BINOCULAR_CAMERA = 1, /**< Binocular structured light camera */ + OB_TOF_CAMERA = 2, /**< Time-of-flight camera */ +} OBDeviceType, + ob_device_type, OB_DEVICE_TYPE; + +/** + * @brief Enumeration for types of media to record or playback + */ +typedef enum { + OB_MEDIA_COLOR_STREAM = 1, /**< Color stream */ + OB_MEDIA_DEPTH_STREAM = 2, /**< Depth stream */ + OB_MEDIA_IR_STREAM = 4, /**< Infrared stream */ + OB_MEDIA_GYRO_STREAM = 8, /**< Gyroscope stream */ + OB_MEDIA_ACCEL_STREAM = 16, /**< Accelerometer stream */ + OB_MEDIA_CAMERA_PARAM = 32, /**< Camera parameter */ + OB_MEDIA_DEVICE_INFO = 64, /**< Device information */ + OB_MEDIA_STREAM_INFO = 128, /**< Stream information */ + OB_MEDIA_IR_LEFT_STREAM = 256, /**< Left infrared stream */ + OB_MEDIA_IR_RIGHT_STREAM = 512, /**< Right infrared stream */ + + OB_MEDIA_ALL = OB_MEDIA_COLOR_STREAM | OB_MEDIA_DEPTH_STREAM | OB_MEDIA_IR_STREAM | OB_MEDIA_GYRO_STREAM | OB_MEDIA_ACCEL_STREAM | OB_MEDIA_CAMERA_PARAM + | OB_MEDIA_DEVICE_INFO | OB_MEDIA_STREAM_INFO | OB_MEDIA_IR_LEFT_STREAM | OB_MEDIA_IR_RIGHT_STREAM, /**< All media data types */ +} OBMediaType, + ob_media_type, OB_MEDIA_TYPE; + +/** + * @brief Enumeration for record playback status + */ +typedef enum { + OB_MEDIA_BEGIN = 0, /**< Begin */ + OB_MEDIA_PAUSE, /**< Pause */ + OB_MEDIA_RESUME, /**< Resume */ + OB_MEDIA_END, /**< End */ +} OBMediaState, + ob_media_state, OB_MEDIA_STATE_EM; + +/** + * @brief Enumeration for depth precision levels + * @attention The depth precision level does not completely determine the depth unit and real precision, and the influence of the data packaging format needs to + * be considered. The specific unit can be obtained through getValueScale() of DepthFrame + */ +typedef enum { + OB_PRECISION_1MM, /**< 1mm */ + OB_PRECISION_0MM8, /**< 0.8mm */ + OB_PRECISION_0MM4, /**< 0.4mm */ + OB_PRECISION_0MM1, /**< 0.1mm */ + OB_PRECISION_0MM2, /**< 0.2mm */ + OB_PRECISION_0MM5, /**< 0.5mm */ + OB_PRECISION_0MM05, /**< 0.05mm */ + OB_PRECISION_UNKNOWN, + OB_PRECISION_COUNT, +} OBDepthPrecisionLevel, + ob_depth_precision_level, OB_DEPTH_PRECISION_LEVEL, OBDepthUnit, ob_depth_unit; + +/** + * @brief disparity parameters for disparity based camera + * + */ +typedef struct { + double zpd; // the distance to calib plane + double zpps; // zpps=z0/fx + float baseline; // baseline length, for monocular camera,it means the distance of laser to the center of IR-CMOS + double fx; // focus + uint8_t bitSize; // disparity bit size (raw disp bit size, for example: MX6000 is 12, MX6600 is 14) + float unit; // reference units: unit=10 denote 1cm; unit=1 denote 1mm; unit=0.5 denote 0.5mm; and so on + float minDisparity; // dual disparity coefficient + uint8_t packMode; // data pack mode + float dispOffset; // disparity offset, actual disp=chip disp + disp_offset + int32_t invalidDisp; // invalid disparity, usually is 0, dual IR add a auxiliary value. + int32_t dispIntPlace; // disp integer digits, default is 8, Gemini2 XL is 10 + uint8_t isDualCamera; // 0 monocular camera, 1 dual camera +} OBDisparityParam, ob_disparity_param; + +/** + * @brief Enumeration for TOF filter scene ranges + */ +typedef enum { + OB_TOF_FILTER_RANGE_CLOSE = 0, /**< Close range */ + OB_TOF_FILTER_RANGE_MIDDLE = 1, /**< Middle range */ + OB_TOF_FILTER_RANGE_LONG = 2, /**< Long range */ + OB_TOF_FILTER_RANGE_DEBUG = 100, /**< Debug range */ +} OBTofFilterRange, + ob_tof_filter_range, TOF_FILTER_RANGE; +/** + * @brief 3D point structure in the SDK + */ +typedef struct { + float x; ///< X coordinate + float y; ///< Y coordinate + float z; ///< Z coordinate +} OBPoint, ob_point, OBPoint3f, ob_point3f; + +/** + * @brief 2D point structure in the SDK + */ +typedef struct { + float x; ///< X coordinate + float y; ///< Y coordinate +} OBPoint2f, ob_point2f; + +typedef struct { + float *xTable; ///< table used to compute X coordinate + float *yTable; ///< table used to compute Y coordinate + int width; ///< width of x and y tables + int height; ///< height of x and y tables +} OBXYTables, ob_xy_tables; + +/** + * @brief 3D point structure with color information + */ +typedef struct { + float x; ///< X coordinate + float y; ///< Y coordinate + float z; ///< Z coordinate + float r; ///< Red channel component + float g; ///< Green channel component + float b; ///< Blue channel component +} OBColorPoint, ob_color_point; + +/** + * @brief 3D point structure with LiDAR information + */ +typedef struct { + float angle; ///< angle, unit: degrees + float distance; ///< distance, unit: mm + uint16_t intensity; ///< intensity, 0~2000 +} OBLiDARScanPoint, ob_lidar_scan_point; + +/** + * @brief 3D point structure with LiDAR information + */ +typedef struct { + float x; ///< X coordinate, unit mm + float y; ///< Y coordinate, unit mm + float z; ///< Z coordinate, unit mm + uint8_t reflectivity; ///< reflectivity + uint8_t tag; ///< point state +} OBLiDARPoint, ob_lidar_point; + +/** + * @brief 3D point structure with LiDAR information + */ +typedef struct { + float distance; ///< distance, unit: mm + float theta; ///< azimuth angle, unit: degrees + float phi; ///< zenith angle, unit: degrees + uint8_t reflectivity; ///< reflectivity + uint8_t tag; ///< tag +} OBLiDARSpherePoint, ob_lidar_sphere_point; + +/** + * @brief Compression mode + */ +typedef enum { + OB_COMPRESSION_LOSSLESS = 0, /**< Lossless compression mode */ + OB_COMPRESSION_LOSSY = 1, /**< Lossy compression mode */ +} OBCompressionMode, + ob_compression_mode, OB_COMPRESSION_MODE; + +/** + * Compression Params + */ +typedef struct { + /** + * Lossy compression threshold, range [0~255], recommended value is 9, the higher the threshold, the higher the compression ratio. + */ + int threshold; +} OBCompressionParams, ob_compression_params, OB_COMPRESSION_PARAMS; + +/** + * @brief TOF Exposure Threshold + */ +typedef struct { + int32_t upper; ///< Upper threshold, unit: ms + int32_t lower; ///< Lower threshold, unit: ms +} OBTofExposureThresholdControl, ob_tof_exposure_threshold_control, TOF_EXPOSURE_THRESHOLD_CONTROL; + +/** + * @brief Sync mode + * @deprecated This define is deprecated, please use @ref ob_multi_device_sync_mode instead + */ +typedef enum { + /** + * @brief Close synchronize mode + * @brief Single device, neither process input trigger signal nor output trigger signal + * @brief Each Sensor in a single device automatically triggers + */ + OB_SYNC_MODE_CLOSE = 0x00, + + /** + * @brief Standalone synchronize mode + * @brief Single device, neither process input trigger signal nor output trigger signal + * @brief Inside single device, RGB as Major sensor: RGB -> IR/Depth/TOF + */ + OB_SYNC_MODE_STANDALONE = 0x01, + + /** + * @brief Primary synchronize mode + * @brief Primary device. Ignore process input trigger signal, only output trigger signal to secondary devices. + * @brief Inside single device, RGB as Major sensor: RGB -> IR/Depth/TOF + */ + OB_SYNC_MODE_PRIMARY = 0x02, + + /** + * @brief Secondary synchronize mode + * @brief Secondary device. Both process input trigger signal and output trigger signal to other devices. + * @brief Different sensors in a single devices receive trigger signals respectively: ext trigger -> RGB && ext trigger -> IR/Depth/TOF + * + * @attention With the current Gemini 2 device set to this mode, each Sensor receives the first external trigger signal + * after the stream is turned on and starts timing self-triggering at the set frame rate until the stream is turned off + */ + OB_SYNC_MODE_SECONDARY = 0x03, + + /** + * @brief MCU Primary synchronize mode + * @brief Primary device. Ignore process input trigger signal, only output trigger signal to secondary devices. + * @brief Inside device, MCU is the primary signal source: MCU -> RGB && MCU -> IR/Depth/TOF + */ + OB_SYNC_MODE_PRIMARY_MCU_TRIGGER = 0x04, + + /** + * @brief IR Primary synchronize mode + * @brief Primary device. Ignore process input trigger signal, only output trigger signal to secondary devices. + * @brief Inside device, IR is the primary signal source: IR/Depth/TOF -> RGB + */ + OB_SYNC_MODE_PRIMARY_IR_TRIGGER = 0x05, + + /** + * @brief Software trigger synchronize mode + * @brief Host, triggered by software control (receive the upper computer command trigger), at the same time to the trunk output trigger signal + * @brief Different sensors in a single machine receive trigger signals respectively: soft trigger -> RGB && soft trigger -> IR/Depth/TOF + * + * @attention Support product: Gemini2 + */ + OB_SYNC_MODE_PRIMARY_SOFT_TRIGGER = 0x06, + + /** + * @brief Software trigger synchronize mode as secondary device + * @brief The slave receives the external trigger signal (the external trigger signal comes from the soft trigger host) and outputs the trigger signal to + * the external relay. + * @brief Different sensors in a single machine receive trigger signals respectively: ext trigger -> RGB && ext trigger -> IR/Depth/TOF + */ + OB_SYNC_MODE_SECONDARY_SOFT_TRIGGER = 0x07, + + /** + * @brief IR and IMU sync signal + */ + OB_SYNC_MODE_IR_IMU_SYNC = 0x08, + + /** + * @brief Unknown type + */ + OB_SYNC_MODE_UNKNOWN = 0xff, + +} OBSyncMode, + ob_sync_mode, OB_SYNC_MODE; + +/** + * @brief Device synchronization configuration + * @deprecated This structure is deprecated, please use @ref ob_multi_device_sync_config instead + */ +typedef struct { + /** + * @brief Device synchronize mode + */ + OBSyncMode syncMode; + + /** + * @brief IR Trigger signal input delay: Used to configure the delay between the IR/Depth/TOF Sensor receiving the trigger signal and starting exposure, + * Unit: microsecond + * + * @attention This parameter is invalid when the synchronization MODE is set to @ref OB_SYNC_MODE_PRIMARY_IR_TRIGGER + */ + uint16_t irTriggerSignalInDelay; + + /** + * @brief RGB trigger signal input delay is used to configure the delay from the time when an RGB Sensor receives the trigger signal to the time when the + * exposure starts. Unit: microsecond + * + * @attention This parameter is invalid when the synchronization MODE is set to @ref OB_SYNC_MODE_PRIMARY + */ + uint16_t rgbTriggerSignalInDelay; + + /** + * @brief Device trigger signal output delay, used to control the delay configuration of the host device to output trigger signals or the slave device to + * output trigger signals. Unit: microsecond + * + * @attention This parameter is invalid when the synchronization MODE is set to @ref OB_SYNC_MODE_CLOSE or @ref OB_SYNC_MODE_STANDALONE + */ + uint16_t deviceTriggerSignalOutDelay; + + /** + * @brief The device trigger signal output polarity is used to control the polarity configuration of the trigger signal output from the host device or the + * trigger signal output from the slave device + * @brief 0: forward pulse; 1: negative pulse + * + * @attention This parameter is invalid when the synchronization MODE is set to @ref OB_SYNC_MODE_CLOSE or @ref OB_SYNC_MODE_STANDALONE + */ + uint16_t deviceTriggerSignalOutPolarity; + + /** + * @brief MCU trigger frequency, used to configure the output frequency of MCU trigger signal in MCU master mode, unit: Hz + * @brief This configuration will directly affect the image output frame rate of the Sensor. Unit: FPS (frames per second) + * + * @attention This parameter is invalid only when the synchronization MODE is set to @ref OB_SYNC_MODE_PRIMARY_MCU_TRIGGER + */ + uint16_t mcuTriggerFrequency; + + /** + * @brief Device number. Users can mark the device with this number + */ + uint16_t deviceId; + +} OBDeviceSyncConfig, ob_device_sync_config, OB_DEVICE_SYNC_CONFIG; + +/** + * @brief Preset tag + */ +typedef enum { + OB_DEVICE_DEPTH_WORK_MODE = 0, + OB_CUSTOM_DEPTH_WORK_MODE = 1, +} OBDepthWorkModeTag, + ob_depth_work_mode_tag; + +/** + * @brief Depth work mode + */ +typedef struct { + /** + * @brief Checksum of work mode + */ + uint8_t checksum[16]; + + /** + * @brief Name of work mode + */ + char name[32]; + /** + * @brief Preset tag + */ + OBDepthWorkModeTag tag; + +} OBDepthWorkMode, ob_depth_work_mode; + +/** + * @brief SequenceId fliter list item + */ +typedef struct { + int sequenceSelectId; + char name[8]; +} OBSequenceIdItem, ob_sequence_id_item; + +/** + * @brief Hole fillig mode + */ +typedef enum { + OB_HOLE_FILL_TOP = 0, + OB_HOLE_FILL_NEAREST = 1, // "max" means farest for depth, and nearest for disparity; FILL_NEAREST + OB_HOLE_FILL_FAREST = 2, // FILL_FAREST +} OBHoleFillingMode, + ob_hole_filling_mode; + +typedef struct { + uint8_t radius; // window_size +} OBSpatialFastFilterParams, ob_spatial_fast_filter_params; + +typedef struct { + uint8_t radius; // window_size + uint8_t magnitude; // magnitude + uint16_t disp_diff; // smooth_delta +} OBSpatialModerateFilterParams, ob_spatial_moderate_filter_params; + +typedef struct { + uint8_t magnitude; // magnitude + float alpha; // smooth_alpha + uint16_t disp_diff; // smooth_delta + uint16_t radius; // hole_fill +} OBSpatialAdvancedFilterParams, ob_spatial_advanced_filter_params; + +typedef enum OB_EDGE_NOISE_REMOVAL_TYPE { + OB_MG_FILTER = 0, + OB_MGH_FILTER = 1, // horizontal MG + OB_MGA_FILTER = 2, // asym MG + OB_MGC_FILTER = 3, +} OBEdgeNoiseRemovalType, + ob_edge_noise_removal_type; + +typedef struct { + OBEdgeNoiseRemovalType type; + uint16_t marginLeftTh; + uint16_t marginRightTh; + uint16_t marginTopTh; + uint16_t marginBottomTh; +} OBEdgeNoiseRemovalFilterParams, ob_edge_noise_removal_filter_params; + +/** + * @brief Denoising method + */ +typedef enum OB_DDO_NOISE_REMOVAL_TYPE { + OB_NR_LUT = 0, // SPLIT + OB_NR_OVERALL = 1, // NON_SPLIT +} OBDDONoiseRemovalType, + ob_ddo_noise_removal_type; + +typedef struct { + uint16_t max_size; + uint16_t disp_diff; + OBDDONoiseRemovalType type; +} OBNoiseRemovalFilterParams, ob_noise_removal_filter_params; + +/** + * @brief Control command protocol version number + */ +typedef struct { + /** + * @brief Major version number + */ + uint8_t major; + + /** + * @brief Minor version number + */ + uint8_t minor; + + /** + * @brief Patch version number + */ + uint8_t patch; +} OBProtocolVersion, ob_protocol_version; + +/** + * @brief Command version associated with property id + */ +typedef enum { + OB_CMD_VERSION_V0 = (uint16_t)0, ///< Version 1.0 + OB_CMD_VERSION_V1 = (uint16_t)1, ///< Version 2.0 + OB_CMD_VERSION_V2 = (uint16_t)2, ///< Version 3.0 + OB_CMD_VERSION_V3 = (uint16_t)3, ///< Version 4.0 + + OB_CMD_VERSION_NOVERSION = (uint16_t)0xfffe, + OB_CMD_VERSION_INVALID = (uint16_t)0xffff, ///< Invalid version +} OB_CMD_VERSION, + OBCmdVersion, ob_cmd_version; + +/** + * @brief IP address configuration for network devices (IPv4) + */ +typedef struct { + /** + * @brief DHCP status + * + * @note 0: static IP; 1: DHCP + */ + uint16_t dhcp; + + /** + * @brief IP address (IPv4, big endian: 192.168.1.10, address[0] = 192, address[1] = 168, address[2] = 1, address[3] = 10) + */ + uint8_t address[4]; + + /** + * @brief Subnet mask (big endian) + */ + uint8_t mask[4]; + + /** + * @brief Gateway (big endian) + */ + uint8_t gateway[4]; +} OBNetIpConfig, ob_net_ip_config, DEVICE_IP_ADDR_CONFIG; + +#define OBDeviceIpAddrConfig OBNetIpConfig +#define ob_device_ip_addr_config OBNetIpConfig + +/** + * @brief Device communication mode + */ +typedef enum { + OB_COMM_USB = 0x00, ///< USB + OB_COMM_NET = 0x01, ///< Ethernet +} OBCommunicationType, + ob_communication_type, OB_COMMUNICATION_TYPE; + +/** + * @brief USB power status + */ +typedef enum { + OB_USB_POWER_NO_PLUGIN = 0, ///< No plugin + OB_USB_POWER_5V_0A9 = 1, ///< 5V/0.9A + OB_USB_POWER_5V_1A5 = 2, ///< 5V/1.5A + OB_USB_POWER_5V_3A0 = 3, ///< 5V/3.0A +} OBUSBPowerState, + ob_usb_power_state; + +/** + * @brief DC power status + */ +typedef enum { + OB_DC_POWER_NO_PLUGIN = 0, ///< No plugin + OB_DC_POWER_PLUGIN = 1, ///< Plugin +} OBDCPowerState, + ob_dc_power_state; + +/** + * @brief Rotate degree + */ +typedef enum { + OB_ROTATE_DEGREE_0 = 0, ///< Rotate 0 + OB_ROTATE_DEGREE_90 = 90, ///< Rotate 90 + OB_ROTATE_DEGREE_180 = 180, ///< Rotate 180 + OB_ROTATE_DEGREE_270 = 270, ///< Rotate 270 +} ob_rotate_degree_type, + OBRotateDegreeType; + +/** + * @brief Power line frequency mode, for color camera anti-flicker configuration + */ +typedef enum { + OB_POWER_LINE_FREQ_MODE_CLOSE = 0, ///< Close + OB_POWER_LINE_FREQ_MODE_50HZ = 1, ///< 50Hz + OB_POWER_LINE_FREQ_MODE_60HZ = 2, ///< 60Hz +} ob_power_line_freq_mode, + OBPowerLineFreqMode; + +/** + * @brief Frame aggregate output mode + */ +typedef enum { + /** + * @brief Only FrameSet that contains all types of data frames will be output + */ + OB_FRAME_AGGREGATE_OUTPUT_ALL_TYPE_FRAME_REQUIRE = 0, + + /** + * @brief Color Frame Require output mode + * @brief Suitable for Color using H264, H265 and other inter-frame encoding format open stream + * + * @attention In this mode, the user may return null when getting a non-Color type data frame from the acquired FrameSet + */ + OB_FRAME_AGGREGATE_OUTPUT_COLOR_FRAME_REQUIRE, + + /** + * @brief FrameSet for any case will be output + * + * @attention In this mode, the user may return null when getting the specified type of data frame from the acquired FrameSet + */ + OB_FRAME_AGGREGATE_OUTPUT_ANY_SITUATION, + /** + * @brief Disable Frame Aggreate + * + * @attention In this mode, All types of data frames will output independently. + */ + OB_FRAME_AGGREGATE_OUTPUT_DISABLE, +} OB_FRAME_AGGREGATE_OUTPUT_MODE, + OBFrameAggregateOutputMode, ob_frame_aggregate_output_mode; +#define OB_FRAME_AGGREGATE_OUTPUT_FULL_FRAME_REQUIRE OB_FRAME_AGGREGATE_OUTPUT_ALL_TYPE_FRAME_REQUIRE + +/** + * @brief Enumeration of point cloud coordinate system types + */ +typedef enum { + OB_LEFT_HAND_COORDINATE_SYSTEM = 0, + OB_RIGHT_HAND_COORDINATE_SYSTEM = 1, +} OB_COORDINATE_SYSTEM_TYPE, + OBCoordinateSystemType, ob_coordinate_system_type; + +/** + * @brief Enumeration of device development modes + */ +typedef enum { + /** + * @brief User mode (default mode), which provides full camera device functionality + */ + OB_USER_MODE = 0, + + /** + * @brief Developer mode, which allows developers to access the operating system and software/hardware resources on the device directly + */ + OB_DEVELOPER_MODE = 1, +} OB_DEVICE_DEVELOPMENT_MODE, + OBDeviceDevelopmentMode, ob_device_development_mode; + +/** + * @brief Color camera preset + */ +typedef enum { + /** + * @brief Suitable for standard single-color-temperature lighting environments (e.g., typical indoor white LED or office lighting). + * This strategy serves as the system's default mode to achieve a balanced and natural white balance effect. + */ + OB_DEFAULT = 0, + + /** + * @brief Warm Biased AWB for mixed lighting is designed for mixed illumination combining standard white light and low-CCT sources (warm/yellow/red). + * This profile applies a controlled warm bias after AWB convergence to reduce blue cast in white-lit regions and deliver a more consistent, + * warm-leaning appearance in mixed-light scenes. + */ + OB_WARM_BIASED_AWB = 1, +} OBColorPreset, + ob_color_preset; + +/** + * @brief The synchronization mode of the device. + */ +typedef enum { + + /** + * @brief free run mode + * @brief The device does not synchronize with other devices, + * @brief The Color and Depth can be set to different frame rates. + */ + OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN = 1 << 0, + + /** + * @brief standalone mode + * @brief The device does not synchronize with other devices. + * @brief The Color and Depth should be set to same frame rates, the Color and Depth will be synchronized. + */ + OB_MULTI_DEVICE_SYNC_MODE_STANDALONE = 1 << 1, + + /** + * @brief primary mode + * @brief The device is the primary device in the multi-device system, it will output the trigger signal via VSYNC_OUT pin on synchronization port by + * default. + * @brief The Color and Depth should be set to same frame rates, the Color and Depth will be synchronized and can be adjusted by @ref + * OBMultiDeviceSyncConfig::colorDelayUs, @ref OBMultiDeviceSyncConfig::depthDelayUs or @ref OBMultiDeviceSyncConfig::trigger2ImageDelayUs. + */ + OB_MULTI_DEVICE_SYNC_MODE_PRIMARY = 1 << 2, + + /** + * @brief secondary mode + * @brief The device is the secondary device in the multi-device system, it will receive the trigger signal via VSYNC_IN pin on synchronization port. It + * will out the trigger signal via VSYNC_OUT pin on synchronization port by default. + * @brief The Color and Depth should be set to same frame rates, the Color and Depth will be synchronized and can be adjusted by @ref + * OBMultiDeviceSyncConfig::colorDelayUs, @ref OBMultiDeviceSyncConfig::depthDelayUs or @ref OBMultiDeviceSyncConfig::trigger2ImageDelayUs. + * @brief After starting the stream, the device will wait for the trigger signal to start capturing images, and will stop capturing images when the trigger + * signal is stopped. + * + * @attention The frequency of the trigger signal should be same as the frame rate of the stream profile which is set when starting the stream. + */ + OB_MULTI_DEVICE_SYNC_MODE_SECONDARY = 1 << 3, + + /** + * @brief secondary synced mode + * @brief The device is the secondary device in the multi-device system, it will receive the trigger signal via VSYNC_IN pin on synchronization port. It + * will out the trigger signal via VSYNC_OUT pin on synchronization port by default. + * @brief The Color and Depth should be set to same frame rates, the Color and Depth will be synchronized and can be adjusted by @ref + * OBMultiDeviceSyncConfig::colorDelayUs, @ref OBMultiDeviceSyncConfig::depthDelayUs or @ref OBMultiDeviceSyncConfig::trigger2ImageDelayUs. + * @brief After starting the stream, the device will be immediately start capturing images, and will adjust the capture time when the trigger signal is + * received to synchronize with the primary device. If the trigger signal is stopped, the device will still capture images. + * + * @attention The frequency of the trigger signal should be same as the frame rate of the stream profile which is set when starting the stream. + */ + OB_MULTI_DEVICE_SYNC_MODE_SECONDARY_SYNCED = 1 << 4, + + /** + * @brief software triggering mode + * @brief The device will start one time image capture after receiving the capture command and will output the trigger signal via VSYNC_OUT pin by default. + * The capture command can be sent form host by call @ref ob_device_trigger_capture. The number of images captured each time can be set by @ref + * OBMultiDeviceSyncConfig::framesPerTrigger. + * @brief The Color and Depth should be set to same frame rates, the Color and Depth will be synchronized and can be adjusted by @ref + * OBMultiDeviceSyncConfig::colorDelayUs, @ref OBMultiDeviceSyncConfig::depthDelayUs or @ref OBMultiDeviceSyncConfig::trigger2ImageDelayUs. + * + * @brief The frequency of the user call @ref ob_device_trigger_capture to send the capture command multiplied by the number of frames per trigger should be + * less than the frame rate of the stream profile which is set when starting the stream. + */ + OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING = 1 << 5, + + /** + * @brief hardware triggering mode + * @brief The device will start one time image capture after receiving the trigger signal via VSYNC_IN pin on synchronization port and will output the + * trigger signal via VSYNC_OUT pin by default. The number of images captured each time can be set by @ref OBMultiDeviceSyncConfig::framesPerTrigger. + * @brief The Color and Depth should be set to same frame rates, the Color and Depth will be synchronized and can be adjusted by @ref + * OBMultiDeviceSyncConfig::colorDelayUs, @ref OBMultiDeviceSyncConfig::depthDelayUs or @ref OBMultiDeviceSyncConfig::trigger2ImageDelayUs. + * + * @attention The frequency of the trigger signal multiplied by the number of frames per trigger should be less than the frame rate of the stream profile + * which is set when starting the stream. + * @attention The trigger signal input via VSYNC_IN pin on synchronization port should be ouput by other device via VSYNC_OUT pin in hardware triggering + * mode or software triggering mode. + * @attention Due to different models may have different signal input requirements, please do not use different models to output trigger + * signal as input-trigger signal. + */ + OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING = 1 << 6, + + /** + * @brief IR and IMU sync mode + */ + OB_MULTI_DEVICE_SYNC_MODE_IR_IMU_SYNC = 1 << 7, + + /** + * @brief The device captures data in software synchronization mode, starting acquisition based on the system time. + */ + OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_SYNCED = 1 << 8, +} ob_multi_device_sync_mode, + OBMultiDeviceSyncMode; + +/** + * @brief The synchronization configuration of the device. + */ +typedef struct { + /** + * @brief The sync mode of the device. + */ + OBMultiDeviceSyncMode syncMode; + + /** + * @brief The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds. + * + * @attention This parameter is only valid for some models, please refer to the product manual for details. + */ + int depthDelayUs; + + /** + * @brief The delay time of the color image capture after receiving the capture command or trigger signal in microseconds. + * + * @attention This parameter is only valid for some models, please refer to the product manual for details. + */ + int colorDelayUs; + + /** + * @brief The delay time of the image capture after receiving the capture command or trigger signal in microseconds. + * @brief The depth and color images are captured synchronously as the product design and can not change the delay between the depth and color images. + * + * @attention For Orbbec Astra 2 device, this parameter is valid only when the @ref triggerOutDelayUs is set to 0. + * @attention This parameter is only valid for some models to replace @ref depthDelayUs and @ref colorDelayUs, please refer to the product manual for + * details. + */ + int trigger2ImageDelayUs; + + /** + * @brief Trigger signal output enable flag. + * @brief After the trigger signal output is enabled, the trigger signal will be output when the capture command or trigger signal is received. User can + * adjust the delay time of the trigger signal output by @ref triggerOutDelayUs. + * + * @attention For some models, the trigger signal output is always enabled and cannot be disabled. + * @attention If device is in the @ref OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN or @ref OB_MULTI_DEVICE_SYNC_MODE_STANDALONE mode, the trigger signal output is + * always disabled. Set this parameter to true will not take effect. + */ + bool triggerOutEnable; + + /** + * @brief The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds. + * + * @attention For Orbbec Astra 2 device, only supported -1 and 0. -1 means the trigger signal output delay is automatically adjusted by the device, 0 means + * the trigger signal output is disabled. + */ + int triggerOutDelayUs; + + /** + * @brief The frame number of each stream after each trigger in triggering mode. + * + * @attention This parameter is only valid when the triggering mode is set to @ref OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING or @ref + * OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING. + * @attention The trigger frequency multiplied by the number of frames per trigger cannot exceed the maximum frame rate of the stream profile which is set + * when starting the stream. + */ + int framesPerTrigger; +} ob_multi_device_sync_config, OBMultiDeviceSyncConfig; + +/** + * @brief The timestamp reset configuration of the device. + * + */ +typedef struct { + /** + * @brief Whether to enable the timestamp reset function. + * @brief If the timestamp reset function is enabled, the timer for calculating the timestamp for output frames will be reset to 0 when the timestamp reset + * command or timestamp reset signal is received, and one timestamp reset signal will be output via TIMER_SYNC_OUT pin on synchronization port by default. + * The timestamp reset signal is input via TIMER_SYNC_IN pin on the synchronization port. + * + * @attention For some models, the timestamp reset function is always enabled and cannot be disabled. + */ + bool enable; + + /** + * @brief The delay time of executing the timestamp reset function after receiving the command or signal in microseconds. + */ + int timestamp_reset_delay_us; + + /** + * @brief the timestamp reset signal output enable flag. + * + * @attention For some models, the timestamp reset signal output is always enabled and cannot be disabled. + */ + bool timestamp_reset_signal_output_enable; +} ob_device_timestamp_reset_config, OBDeviceTimestampResetConfig; + +/** + * @brief Baseline calibration parameters + */ +typedef struct { + /** + * @brief Baseline length + */ + float baseline; + /** + * @brief Calibration distance + */ + float zpd; +} BASELINE_CALIBRATION_PARAM, ob_baseline_calibration_param, OBBaselineCalibrationParam; + +/** + * @brief HDR Configuration + */ +typedef struct { + + /** + * @brief Enable/disable HDR, after enabling HDR, the exposure_1 and gain_1 will be used as the first exposure and gain, and the exposure_2 and gain_2 will + * be used as the second exposure and gain. The output image will be alternately exposed and gain between the first and second + * exposure and gain. + * + * @attention After enabling HDR, the auto exposure will be disabled. + */ + uint8_t enable; + uint8_t sequence_name; ///< Sequence name + uint32_t exposure_1; ///< Exposure time 1 + uint32_t gain_1; ///< Gain 1 + uint32_t exposure_2; ///< Exposure time 2 + uint32_t gain_2; ///< Gain 2 +} HDR_CONFIG, ob_hdr_config, OBHdrConfig; + +/** + * @brief The rect of the region of interest + */ +typedef struct { + int16_t x0_left; + int16_t y0_top; + int16_t x1_right; + int16_t y1_bottom; +} AE_ROI, ob_region_of_interest, OBRegionOfInterest; + +typedef enum { + OB_FILTER_CONFIG_VALUE_TYPE_INVALID = -1, + OB_FILTER_CONFIG_VALUE_TYPE_INT = 0, + OB_FILTER_CONFIG_VALUE_TYPE_FLOAT = 1, + OB_FILTER_CONFIG_VALUE_TYPE_BOOLEAN = 2, +} OBFilterConfigValueType, + ob_filter_config_value_type; +/** + * @brief Configuration Item for the filter + */ +typedef struct { + const char *name; ///< Name of the configuration item + OBFilterConfigValueType type; ///< Value type of the configuration item + double min; ///< Minimum value casted to double + double max; ///< Maximum value casted to double + double step; ///< Step value casted to double + double def; ///< Default value casted to double + const char *desc; ///< Description of the configuration item +} OBFilterConfigSchemaItem, ob_filter_config_schema_item; + +/** + * @brief struct of serial number + */ +typedef struct { + char numberStr[16]; +} OBDeviceSerialNumber, ob_device_serial_number, OBSerialNumber, ob_serial_number; + +/** + * @brief Disparity offset interleaving configuration + */ +typedef struct { + uint8_t enable; + uint8_t offset0; + uint8_t offset1; + uint8_t reserved; +} OBDispOffsetConfig, ob_disp_offset_config; + +/** + * @details Defines the original resolution and hardware decimation factor. + */ +typedef struct { + uint32_t originWidth; ///< Origin width + uint32_t originHeight; ///< Origin height + uint32_t factor; ///< Decimation factor +} OBHardwareDecimationConfig, ob_hardware_decimation_config; + +/** + * @brief Frame metadata types + * @brief The frame metadata is a set of meta info generated by the device for current individual frame. + */ +typedef enum { + /** + * @brief Timestamp when the frame is captured. + * @attention Different device models may have different units. It is recommended to use the timestamp related functions to get the timestamp in the + * correct units. + */ + OB_FRAME_METADATA_TYPE_TIMESTAMP = 0, + + /** + * @brief Timestamp in the middle of the capture. + * @brief Usually is the middle of the exposure time. + * + * @attention Different device models may have different units. + */ + OB_FRAME_METADATA_TYPE_SENSOR_TIMESTAMP = 1, + + /** + * @brief The number of current frame. + */ + OB_FRAME_METADATA_TYPE_FRAME_NUMBER = 2, + + /** + * @brief Auto exposure status + * @brief If the value is 0, it means the auto exposure is disabled. Otherwise, it means the auto exposure is enabled. + */ + OB_FRAME_METADATA_TYPE_AUTO_EXPOSURE = 3, + + /** + * @brief Exposure time + * + * @attention Different sensor may have different units. Usually, it is 100us for color sensor and 1us for depth/infrared sensor. + */ + OB_FRAME_METADATA_TYPE_EXPOSURE = 4, + + /** + * @brief Gain + * + * @attention For some device models, the gain value represents the gain level, not the multiplier. + */ + OB_FRAME_METADATA_TYPE_GAIN = 5, + + /** + * @brief Auto white balance status + * @brief If the value is 0, it means the auto white balance is disabled. Otherwise, it means the auto white balance is enabled. + */ + OB_FRAME_METADATA_TYPE_AUTO_WHITE_BALANCE = 6, + + /** + * @brief White balance + */ + OB_FRAME_METADATA_TYPE_WHITE_BALANCE = 7, + + /** + * @brief Brightness + */ + OB_FRAME_METADATA_TYPE_BRIGHTNESS = 8, + + /** + * @brief Contrast + */ + OB_FRAME_METADATA_TYPE_CONTRAST = 9, + + /** + * @brief Saturation + */ + OB_FRAME_METADATA_TYPE_SATURATION = 10, + + /** + * @brief Sharpness + */ + OB_FRAME_METADATA_TYPE_SHARPNESS = 11, + + /** + * @brief Backlight compensation + */ + OB_FRAME_METADATA_TYPE_BACKLIGHT_COMPENSATION = 12, + + /** + * @brief Hue + */ + OB_FRAME_METADATA_TYPE_HUE = 13, + + /** + * @brief Gamma + */ + OB_FRAME_METADATA_TYPE_GAMMA = 14, + + /** + * @brief Power line frequency + * @brief For anti-flickering, 0: Close, 1: 50Hz, 2: 60Hz, 3: Auto + */ + OB_FRAME_METADATA_TYPE_POWER_LINE_FREQUENCY = 15, + + /** + * @brief Low light compensation + * + * @attention The low light compensation is a feature inside the device, and can not manually control it. + */ + OB_FRAME_METADATA_TYPE_LOW_LIGHT_COMPENSATION = 16, + + /** + * @brief Manual white balance setting + */ + OB_FRAME_METADATA_TYPE_MANUAL_WHITE_BALANCE = 17, + + /** + * @brief Actual frame rate + * @brief The actual frame rate will be calculated according to the exposure time and other parameters. + */ + OB_FRAME_METADATA_TYPE_ACTUAL_FRAME_RATE = 18, + + /** + * @brief Frame rate + */ + OB_FRAME_METADATA_TYPE_FRAME_RATE = 19, + + /** + * @brief Left region of interest for the auto exposure Algorithm. + */ + OB_FRAME_METADATA_TYPE_AE_ROI_LEFT = 20, + + /** + * @brief Top region of interest for the auto exposure Algorithm. + */ + OB_FRAME_METADATA_TYPE_AE_ROI_TOP = 21, + + /** + * @brief Right region of interest for the auto exposure Algorithm. + */ + OB_FRAME_METADATA_TYPE_AE_ROI_RIGHT = 22, + + /** + * @brief Bottom region of interest for the auto exposure Algorithm. + */ + OB_FRAME_METADATA_TYPE_AE_ROI_BOTTOM = 23, + + /** + * @brief Exposure priority + */ + OB_FRAME_METADATA_TYPE_EXPOSURE_PRIORITY = 24, + + /** + * @brief HDR sequence name + */ + OB_FRAME_METADATA_TYPE_HDR_SEQUENCE_NAME = 25, + + /** + * @brief HDR sequence size + */ + OB_FRAME_METADATA_TYPE_HDR_SEQUENCE_SIZE = 26, + + /** + * @brief HDR sequence index + */ + OB_FRAME_METADATA_TYPE_HDR_SEQUENCE_INDEX = 27, + + /** + * @brief Laser power value in mW + * + * @attention The laser power value is an approximate estimation. + */ + OB_FRAME_METADATA_TYPE_LASER_POWER = 28, + + /** + * @brief Laser power level + */ + OB_FRAME_METADATA_TYPE_LASER_POWER_LEVEL = 29, + + /** + * @brief Laser status + * @brief 0: Laser off, 1: Laser on + */ + OB_FRAME_METADATA_TYPE_LASER_STATUS = 30, + + /** + * @brief GPIO input data + */ + OB_FRAME_METADATA_TYPE_GPIO_INPUT_DATA = 31, + + /** + * @brief disparity search offset value + */ + OB_FRAME_METADATA_TYPE_DISPARITY_SEARCH_OFFSET = 32, + + /** + * @brief disparity search range + */ + OB_FRAME_METADATA_TYPE_DISPARITY_SEARCH_RANGE = 33, + + /** + * @brief The number of frame metadata types, using for types iterating + * @attention It is not a valid frame metadata type + */ + OB_FRAME_METADATA_TYPE_COUNT, +} ob_frame_metadata_type, + OBFrameMetadataType; + +/** + * @brief For Linux, there are two ways to access the UVC device, libuvc and v4l2. The backend type is used to select the backend to access the device. + * + */ +typedef enum { + /** + * @brief Auto detect system capabilities and device hint to select backend + * + */ + OB_UVC_BACKEND_TYPE_AUTO, + + /** + * @brief Use libuvc backend to access the UVC device + * + */ + OB_UVC_BACKEND_TYPE_LIBUVC, + + /** + * @brief Use v4l2 backend to access the UVC device + * + */ + OB_UVC_BACKEND_TYPE_V4L2, + + /** + * @brief Use MSMF backend to access the UVC device + */ + OB_UVC_BACKEND_TYPE_MSMF, +} ob_uvc_backend_type, + OBUvcBackendType; + +/** + * @brief The playback status of the media + */ +typedef enum { + OB_PLAYBACK_UNKNOWN, + OB_PLAYBACK_PLAYING, /**< The media is playing */ + OB_PLAYBACK_PAUSED, /**< The media is paused */ + OB_PLAYBACK_STOPPED, /**< The media is stopped */ + OB_PLAYBACK_COUNT, +} ob_playback_status, + OBPlaybackStatus; + +/** + * @brief Intra-camera Sync Reference based on the exposure start time, the exposure middle time, or the exposure end time. + */ +typedef enum { + OB_START_OF_EXPOSURE = 0, /**< start of exposure */ + OB_MIDDLE_OF_EXPOSURE, /**< middle of exposure */ + OB_END_OF_EXPOSURE, /**< end of exposure */ +} ob_intra_camera_sync_reference, + OBIntraCameraSyncReference; + +// For compatibility +#define OB_FRAME_METADATA_TYPE_LASER_POWER_MODE OB_FRAME_METADATA_TYPE_LASER_POWER_LEVEL +#define OB_FRAME_METADATA_TYPE_EMITTER_MODE OB_FRAME_METADATA_TYPE_LASER_STATUS +#define START_OF_EXPOSURE OB_START_OF_EXPOSURE +#define MIDDLE_OF_EXPOSURE OB_MIDDLE_OF_EXPOSURE +#define END_OF_EXPOSURE OB_END_OF_EXPOSURE + +/** + * @brief Device access mode for GigE network device + */ +typedef enum { + OB_DEVICE_ACCESS_DENIED = 0, ///< No access. This value is only used as a return value + OB_DEVICE_EXCLUSIVE_ACCESS = 1, ///< Exclusive access: full read/write, no other application allowed; can preempt existing monitor access + OB_DEVICE_CONTROL_ACCESS = 2, ///< Control access: read/write allowed; other applications permitted read-only monitor access + OB_DEVICE_MONITOR_ACCESS = 3, ///< Monitor access: read-only; no write or control privileges + OB_DEVICE_DEFAULT_ACCESS = 4, ///< Default access: control access for capable devices, ignored otherwise +} ob_device_access_mode, + OBDeviceAccessMode; + +/** + * @brief Callback for file transfer + * + * @param[in] state Transmission status + * @param[in] message Transfer status information + * @param[in] percent Transfer progress percentage + * @param[in] user_data User-defined data + */ +typedef void (*ob_file_send_callback)(ob_file_tran_state state, const char *message, uint8_t percent, void *user_data); + +/** + * @brief Callback for firmware upgrade + * + * @param[in] state Upgrade status + * @param[in] message Upgrade status information + * @param[in] percent Upgrade progress percentage + * @param[in] user_data User-defined data + */ +typedef void (*ob_device_fw_update_callback)(ob_fw_update_state state, const char *message, uint8_t percent, void *user_data); + +/** + * @brief Callback for device status + * + * @param[in] state Device status + * @param[in] message Device status information + * @param[in] user_data User-defined data + */ +typedef void (*ob_device_state_callback)(ob_device_state state, const char *message, void *user_data); + +/** + * @brief Callback for writing data + * + * @param[in] state Write data status + * @param[in] percent Write data percentage + * @param[in] user_data User-defined data + */ +typedef void (*ob_set_data_callback)(ob_data_tran_state state, uint8_t percent, void *user_data); + +/** + * @brief Callback for reading data + * + * @param[in] state Read data status + * @param[in] dataChunk Read the returned data block + * @param[in] user_data User-defined data + */ +typedef void (*ob_get_data_callback)(ob_data_tran_state state, ob_data_chunk *dataChunk, void *user_data); + +/** + * @brief Callback for media status (recording and playback) + * + * @param[in] state Condition + * @param[in] user_data User-defined data + */ +typedef void (*ob_media_state_callback)(ob_media_state state, void *user_data); + +/** + * @brief Callback for device change + * + * @param[in] removed List of deleted (dropped) devices + * @param[in] added List of added (online) devices + * @param[in] user_data User-defined data + */ +typedef void (*ob_device_changed_callback)(ob_device_list *removed, ob_device_list *added, void *user_data); + +// typedef void (*ob_net_device_added_callback)(const char *added, void *user_data); +// typedef void (*ob_net_device_removed_callback)(const char *removed, void *user_data); + +/** + * @brief Callback for frame + * + * @param[in] frame Frame object + * @param[in] user_data User-defined data + */ +typedef void (*ob_frame_callback)(ob_frame *frame, void *user_data); +#define ob_filter_callback ob_frame_callback +#define ob_playback_callback ob_frame_callback + +/** + * @brief Callback for frameset + * + * @param[in] frameset Frameset object + * @param[in] user_data User-defined data + */ +typedef void (*ob_frameset_callback)(ob_frame *frameset, void *user_data); + +/** + * @brief Customize the delete callback + * + * @param[in] buffer Data that needs to be deleted + * @param[in] user_data User-defined data + */ +typedef void(ob_frame_destroy_callback)(uint8_t *buffer, void *user_data); + +/** + * @brief Callback for receiving log + * + * @param[in] severity Current log level + * @param[in] message Log message + * @param[in] user_data User-defined data + */ +typedef void(ob_log_callback)(ob_log_severity severity, const char *message, void *user_data); + +typedef void (*ob_playback_status_changed_callback)(ob_playback_status status, void *user_data); + +/** + * @brief Callback Id + */ +typedef uint64_t OBCallbackId, ob_callback_id; +#define INVALID_CALLBACK_ID (0) + +/** + * @brief Check if the sensor_type is a video sensor + * + * @param[in] sensor_type Sensor type to check + * @return True if sensor_type is a video sensor, false otherwise + */ +#define ob_is_video_sensor_type(sensor_type) \ + (sensor_type == OB_SENSOR_COLOR || sensor_type == OB_SENSOR_COLOR_LEFT || sensor_type == OB_SENSOR_COLOR_RIGHT || sensor_type == OB_SENSOR_DEPTH \ + || sensor_type == OB_SENSOR_IR || sensor_type == OB_SENSOR_IR_LEFT || sensor_type == OB_SENSOR_IR_RIGHT || sensor_type == OB_SENSOR_CONFIDENCE) + +/** + * @brief check if the stream_type is a video stream + * + * @param[in] stream_type Stream type to check + * @return True if stream_type is a video stream, false otherwise + */ +#define ob_is_video_stream_type(stream_type) \ + (stream_type == OB_STREAM_COLOR || stream_type == OB_STREAM_COLOR_LEFT || stream_type == OB_STREAM_COLOR_RIGHT || stream_type == OB_STREAM_DEPTH \ + || stream_type == OB_STREAM_IR || stream_type == OB_STREAM_IR_LEFT || stream_type == OB_STREAM_IR_RIGHT || stream_type == OB_STREAM_VIDEO \ + || stream_type == OB_STREAM_CONFIDENCE) + +/** + * @brief Check if sensor_type is an IR sensor + * + * @param[in] sensor_type Sensor type to check + * @return True if sensor_type is an IR sensor, false otherwise + */ +#define is_ir_sensor(sensor_type) (sensor_type == OB_SENSOR_IR || sensor_type == OB_SENSOR_IR_LEFT || sensor_type == OB_SENSOR_IR_RIGHT) +#define isIRSensor is_ir_sensor + +/** + * @brief Check if sensor_type is an Color sensor + * + * @param sensor_type Sensor type to check + * @return True if sensor_type is an Color sensor, false otherwise + */ +#define is_color_sensor(sensor_type) (sensor_type == OB_SENSOR_COLOR || sensor_type == OB_SENSOR_COLOR_LEFT || sensor_type == OB_SENSOR_COLOR_RIGHT) +#define isColorSensor is_color_sensor + +/** + * @brief Check if stream_type is an IR stream + * + * @param[in] stream_type Stream type to check + * @return True if stream_type is an IR stream, false otherwise + */ +#define is_ir_stream(stream_type) (stream_type == OB_STREAM_IR || stream_type == OB_STREAM_IR_LEFT || stream_type == OB_STREAM_IR_RIGHT) +#define isIRStream is_ir_stream + +/** + * @brief Check if stream_type is an Color stream + * + * @param stream_type Stream type to check + * @return True if stream_type is an Color stream, false otherwise + */ +#define is_color_stream(stream_type) (stream_type == OB_STREAM_COLOR || stream_type == OB_STREAM_COLOR_LEFT || stream_type == OB_STREAM_COLOR_RIGHT) +#define isColorStream is_color_stream + +/** + * @brief Check if frame_type is an IR frame + * + * @param[in] frame_type Frame type to check + * @return True if frame_type is an IR frame, false otherwise + */ +#define is_ir_frame(frame_type) (frame_type == OB_FRAME_IR || frame_type == OB_FRAME_IR_LEFT || frame_type == OB_FRAME_IR_RIGHT) +#define isIRFrame is_ir_frame + +/** + * @brief Check if frame_type is an Color frame + * + * @param frame_type Frame type to check + * @return True if frame_type is an Color frame, false otherwise + */ +#define is_color_frame(frame_type) (frame_type == OB_FRAME_COLOR || frame_type == OB_FRAME_COLOR_LEFT || frame_type == OB_FRAME_COLOR_RIGHT) +#define isColorFrame is_color_frame + +/** + * @brief The default Decrypt Key + */ +#define OB_DEFAULT_DECRYPT_KEY (nullptr) + +#ifdef __cplusplus +} +#endif + +#pragma pack(pop) diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Pipeline.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Pipeline.h new file mode 100644 index 0000000..f7134ae --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Pipeline.h @@ -0,0 +1,372 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Pipeline.h + * @brief The SDK's advanced API can quickly implement functions such as switching streaming, frame synchronization, software filtering, etc., suitable for + * applications, and the algorithm focuses on rgbd data stream scenarios. If you are on real-time or need to handle synchronization separately, align the scene. + * Please use the interface of Device's Lower API. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Create a pipeline object + * + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_pipeline* return the pipeline object + */ +OB_EXPORT ob_pipeline *ob_create_pipeline(ob_error **error); + +/** + * @brief Using device objects to create pipeline objects + * + * @param[in] dev Device object used to create pipeline + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_pipeline* return the pipeline object + */ +OB_EXPORT ob_pipeline *ob_create_pipeline_with_device(const ob_device *dev, ob_error **error); + +/** + * @brief Delete pipeline objects + * + * @param[in] pipeline The pipeline object to be deleted + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_pipeline(ob_pipeline *pipeline, ob_error **error); + +/** + * @brief Start the pipeline with default parameters + * + * @param[in] pipeline pipeline object + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_pipeline_start(ob_pipeline *pipeline, ob_error **error); + +/** + * @brief Start the pipeline with configuration parameters + * + * @param[in] pipeline pipeline object + * @param[in] config Parameters to be configured + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_pipeline_start_with_config(ob_pipeline *pipeline, const ob_config *config, ob_error **error); + +/** + * @brief Start the pipeline and set the frame collection data callback + * + * @attention After start the pipeline with this interface, the frames will be output to the callback function and cannot be obtained frames by call + * @ref ob_pipeline_wait_for_frameset + * + * @param[in] pipeline pipeline object + * @param[in] config Parameters to be configured + * @param[in] callback Trigger a callback when all frame data in the frameset arrives + * @param[in] user_data Pass in any user data and get it from the callback + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_pipeline_start_with_callback(ob_pipeline *pipeline, const ob_config *config, ob_frameset_callback callback, void *user_data, + ob_error **error); + +/** + * @brief Stop pipeline + * + * @param[in] pipeline pipeline object + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_pipeline_stop(ob_pipeline *pipeline, ob_error **error); + +/** + * @brief Get the configuration object associated with the pipeline + * @brief Returns default configuration if the user has not configured + * + * @param[in] pipeline The pipeline object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_config* The configuration object + */ +OB_EXPORT ob_config *ob_pipeline_get_config(const ob_pipeline *pipeline, ob_error **error); + +/** + * @brief Switch the corresponding configuration + * + * @param[in] pipeline The pipeline object + * @param[in] config The pipeline configuration + * @param[out] error Log error messages + */ +OB_EXPORT void ob_pipeline_switch_config(ob_pipeline *pipeline, ob_config *config, ob_error **error); + +/** + * @brief Wait for a set of frames to be returned synchronously + * + * @param[in] pipeline The pipeline object + * @param[in] timeout_ms The timeout for waiting (in milliseconds) + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_frame* The frameset that was waited for. A frameset is a special frame that can be used to obtain independent frames from the set. + */ +OB_EXPORT ob_frame *ob_pipeline_wait_for_frameset(ob_pipeline *pipeline, uint32_t timeout_ms, ob_error **error); + +/** + * @brief Get the device object associated with the pipeline + * + * @param[in] pipeline The pipeline object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_device* The device object + */ +OB_EXPORT ob_device *ob_pipeline_get_device(const ob_pipeline *pipeline, ob_error **error); + +/** + * @brief Get the stream profile list associated with the pipeline + * + * @param[in] pipeline The pipeline object + * @param[in] sensorType The sensor type. The supported sensor types can be obtained through the ob_device_get_sensor_list() interface. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile_list* The stream profile list + */ +OB_EXPORT ob_stream_profile_list *ob_pipeline_get_stream_profile_list(const ob_pipeline *pipeline, ob_sensor_type sensorType, ob_error **error); + +/** + * @brief Enable frame synchronization + * @brief Synchronize the frames of different streams by using the timestamp information of the frames. + * @brief Dynamically (when pipeline is started) enable/disable frame synchronization is allowed. + * + * @param[in] pipeline The pipeline object + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_pipeline_enable_frame_sync(ob_pipeline *pipeline, ob_error **error); + +/** + * @brief Disable frame synchronization + * + * @param[in] pipeline The pipeline object + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_pipeline_disable_frame_sync(ob_pipeline *pipeline, ob_error **error); + +/** + * @brief Return a list of D2C-enabled depth sensor resolutions corresponding to the input color sensor resolution + * + * @param[in] pipeline The pipeline object + * @param[in] color_profile The input profile of the color sensor + * @param[in] align_mode The input align mode + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile_list* The list of D2C-enabled depth sensor resolutions + */ +OB_EXPORT ob_stream_profile_list *ob_get_d2c_depth_profile_list(const ob_pipeline *pipeline, const ob_stream_profile *color_profile, ob_align_mode align_mode, + ob_error **error); + +/** + * @brief Create the pipeline configuration + * + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_config* The configuration object + */ +OB_EXPORT ob_config *ob_create_config(ob_error **error); + +/** + * @brief Delete the pipeline configuration + * + * @param[in] config The configuration to be deleted + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_config(ob_config *config, ob_error **error); + +/** + * @brief Enable a stream with default profile + * + * @param[in] config The pipeline configuration object + * @param[in] stream_type The type of the stream to be enabled + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_enable_stream(ob_config *config, ob_stream_type stream_type, ob_error **error); + +/** + * @brief Enable all streams in the pipeline configuration + * + * @param[in] config The pipeline configuration + * @param[out] error Log error messages + */ +OB_EXPORT void ob_config_enable_all_stream(ob_config *config, ob_error **error); + +/** + * @brief Enable a stream according to the stream profile + * + * @param[in] config The pipeline configuration object + * @param[in] profile The stream profile to be enabled + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_enable_stream_with_stream_profile(ob_config *config, const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Enable video stream with specified parameters + * + * @attention The stream_type should be a video stream type, such as OB_STREAM_IR, OB_STREAM_COLOR, OB_STREAM_DEPTH, etc. + * + * @param[in] config The pipeline configuration object + * @param[in] stream_type The type of the stream to be enabled + * @param[in] width The width of the video stream + * @param[in] height The height of the video stream + * @param[in] fps The frame rate of the video stream + * @param[in] format The format of the video stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_enable_video_stream(ob_config *config, ob_stream_type stream_type, uint32_t width, uint32_t height, uint32_t fps, ob_format format, + ob_error **error); + +/** + * @brief Enable a video stream using a decimation configuration. + * + * @attention The stream_type should be a video stream type, such as OB_STREAM_IR, OB_STREAM_DEPTH, etc. + * + * @param[in] config The pipeline configuration object + * @param[in] stream_type The type of the stream to be enabled + * @param[in] decimation_config The decimation configuration for the stream + * @param[in] fps The frame rate of the video stream + * @param[in] format The format of the video stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_enable_video_stream_by_decimation_config(ob_config *config, ob_stream_type stream_type, + ob_hardware_decimation_config decimation_config, uint32_t fps, ob_format format, + ob_error **error); + +/** + * @brief Enable accelerometer stream with specified parameters + * + * @param[in] config The pipeline configuration object + * @param[in] full_scale_range The full scale range of the accelerometer + * @param[in] sample_rate The sample rate of the accelerometer + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_enable_accel_stream(ob_config *config, ob_accel_full_scale_range full_scale_range, ob_accel_sample_rate sample_rate, ob_error **error); + +/** + * @brief Enable gyroscope stream with specified parameters + * + * @param[in] config The pipeline configuration object + * @param[in] full_scale_range The full scale range of the gyroscope + * @param[in] sample_rate The sample rate of the gyroscope + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_enable_gyro_stream(ob_config *config, ob_gyro_full_scale_range full_scale_range, ob_gyro_sample_rate sample_rate, ob_error **error); + +/** + * @brief Enable LiDAR stream with specified parameters + * + * @param[in] config The pipeline configuration object + * @param[in] scan_rate The scan rate of LiDAR + * @param[in] format The format of the LiDAR stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_enable_lidar_stream(ob_config *config, ob_lidar_scan_rate scan_rate, ob_format format, ob_error **error); + +/** + * @brief Get the enabled stream profile list in the pipeline configuration + * + * @param[in] config The pipeline configuration object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile_list* The enabled stream profile list, should be released by @ref ob_delete_stream_profile_list after use + */ +OB_EXPORT ob_stream_profile_list *ob_config_get_enabled_stream_profile_list(const ob_config *config, ob_error **error); + +/** + * @brief Disable a specific stream in the pipeline configuration + * + * @param[in] config The pipeline configuration object + * @param[in] type The type of stream to be disabled + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_disable_stream(ob_config *config, ob_stream_type type, ob_error **error); + +/** + * @brief Disable all streams in the pipeline configuration + * + * @param[in] config The pipeline configuration object + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_disable_all_stream(ob_config *config, ob_error **error); + +/** + * @brief Set the alignment mode for the pipeline configuration + * + * @param[in] config The pipeline configuration object + * @param[in] mode The alignment mode to be set + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_set_align_mode(ob_config *config, ob_align_mode mode, ob_error **error); + +/** + * @brief Set whether depth scaling is required after enable depth to color alignment + * @brief After enabling depth to color alignment, the depth image may need to be scaled to match the color image size. + * + * @param[in] config The pipeline configuration object + * @param[in] enable Whether scaling is required + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_set_depth_scale_after_align_require(ob_config *config, bool enable, ob_error **error); + +/** + * @brief Set the frame aggregation output mode for the pipeline configuration + * @brief The processing strategy when the FrameSet generated by the frame aggregation function does not contain the frames of all opened streams (which + * can be caused by different frame rates of each stream, or by the loss of frames of one stream): drop directly or output to the user. + * + * @param[in] config The pipeline configuration object + * @param[in] mode The frame aggregation output mode to be set (default mode is @ref OB_FRAME_AGGREGATE_OUTPUT_ANY_SITUATION) + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_config_set_frame_aggregate_output_mode(ob_config *config, ob_frame_aggregate_output_mode mode, ob_error **error); + +/** + * @brief Get current camera parameters + * @attention If D2C is enabled, it will return the camera parameters after D2C, if not, it will return to the default parameters + * + * @param[in] pipeline pipeline object + * @param[out] error Log error messages + * + * @return ob_camera_param The camera internal parameters + */ +OB_EXPORT ob_camera_param ob_pipeline_get_camera_param(ob_pipeline *pipeline, ob_error **error); + +/** + * @brief Get the current camera parameters + * + * @param[in] pipeline pipeline object + * @param[in] colorWidth color width + * @param[in] colorHeight color height + * @param[in] depthWidth depth width + * @param[in] depthHeight depth height + * @param[out] error Log error messages + * + * @return ob_camera_param returns camera internal parameters + */ +OB_EXPORT ob_camera_param ob_pipeline_get_camera_param_with_profile(ob_pipeline *pipeline, uint32_t colorWidth, uint32_t colorHeight, uint32_t depthWidth, + uint32_t depthHeight, ob_error **error); + +/** + * @brief Get device calibration parameters with the specified configuration + * + * @param[in] pipeline pipeline object + * @param[in] config The pipeline configuration + * @param[out] error Log error messages + * + * @return ob_calibration_param The calibration parameters + */ +OB_EXPORT ob_calibration_param ob_pipeline_get_calibration_param(ob_pipeline *pipeline, ob_config *config, ob_error **error); + +// The following interfaces are deprecated and are retained here for compatibility purposes. +#define ob_config_set_depth_scale_require ob_config_set_depth_scale_after_align_require + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Property.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Property.h new file mode 100644 index 0000000..f436c7f --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Property.h @@ -0,0 +1,1073 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Property.h + * @brief Control command property list maintenance + */ + +#pragma once + +#include "ObTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Enumeration value describing all attribute control commands of the device + */ +typedef enum { + /** + * @brief LDP switch + */ + OB_PROP_LDP_BOOL = 2, + + /** + * @brief Laser switch + */ + OB_PROP_LASER_BOOL = 3, + + /** + * @brief laser pulse width + */ + OB_PROP_LASER_PULSE_WIDTH_INT = 4, + + /** + * @brief Laser current (uint: mA) + */ + OB_PROP_LASER_CURRENT_FLOAT = 5, + + /** + * @brief IR flood switch + */ + OB_PROP_FLOOD_BOOL = 6, + + /** + * @brief IR flood level + */ + OB_PROP_FLOOD_LEVEL_INT = 7, + + /** + * @brief Enable/disable temperature compensation + * + */ + OB_PROP_TEMPERATURE_COMPENSATION_BOOL = 8, + + /** + * @brief Depth mirror + */ + OB_PROP_DEPTH_MIRROR_BOOL = 14, + + /** + * @brief Depth flip + */ + OB_PROP_DEPTH_FLIP_BOOL = 15, + + /** + * @brief Depth Postfilter + */ + OB_PROP_DEPTH_POSTFILTER_BOOL = 16, + + /** + * @brief Depth Holefilter + */ + OB_PROP_DEPTH_HOLEFILTER_BOOL = 17, + + /** + * @brief IR mirror + */ + OB_PROP_IR_MIRROR_BOOL = 18, + + /** + * @brief IR flip + */ + OB_PROP_IR_FLIP_BOOL = 19, + + /** + * @brief Minimum depth threshold + */ + OB_PROP_MIN_DEPTH_INT = 22, + + /** + * @brief Maximum depth threshold + */ + OB_PROP_MAX_DEPTH_INT = 23, + + /** + * @brief Software filter switch + */ + OB_PROP_DEPTH_NOISE_REMOVAL_FILTER_BOOL = 24, + + /** + * @brief LDP status + */ + OB_PROP_LDP_STATUS_BOOL = 32, + + /** + * @brief maxdiff for depth noise removal filter + */ + OB_PROP_DEPTH_NOISE_REMOVAL_FILTER_MAX_DIFF_INT = 40, + + /** + * @brief maxSpeckleSize for depth noise removal filter + */ + OB_PROP_DEPTH_NOISE_REMOVAL_FILTER_MAX_SPECKLE_SIZE_INT = 41, + + /** + * @brief Hardware d2c is on + */ + OB_PROP_DEPTH_ALIGN_HARDWARE_BOOL = 42, + + /** + * @brief Timestamp adjustment + */ + OB_PROP_TIMESTAMP_OFFSET_INT = 43, + + /** + * @brief Hardware distortion switch Rectify + */ + OB_PROP_HARDWARE_DISTORTION_SWITCH_BOOL = 61, + + /** + * @brief Fan mode switch + */ + OB_PROP_FAN_WORK_MODE_INT = 62, + + /** + * @brief Multi-resolution D2C mode + */ + OB_PROP_DEPTH_ALIGN_HARDWARE_MODE_INT = 63, + + /** + * @brief Anti_collusion activation status + */ + OB_PROP_ANTI_COLLUSION_ACTIVATION_STATUS_BOOL = 64, + + /** + * @brief the depth precision level, which may change the depth frame data unit, needs to be confirmed through the ValueScale interface of + * DepthFrame + */ + OB_PROP_DEPTH_PRECISION_LEVEL_INT = 75, + + /** + * @brief tof filter range configuration + */ + OB_PROP_TOF_FILTER_RANGE_INT = 76, + + /** + * @brief laser mode, the firmware terminal currently only return 1: IR Drive, 2: Torch + */ + OB_PROP_LASER_MODE_INT = 79, + + /** + * @brief brt2r-rectify function switch (brt2r is a special module on mx6600), 0: Disable, 1: Rectify Enable + */ + OB_PROP_RECTIFY2_BOOL = 80, + + /** + * @brief Color mirror + */ + OB_PROP_COLOR_MIRROR_BOOL = 81, + + /** + * @brief Color flip + */ + OB_PROP_COLOR_FLIP_BOOL = 82, + + /** + * @brief Indicator switch, 0: Disable, 1: Enable + */ + OB_PROP_INDICATOR_LIGHT_BOOL = 83, + + /** + * @brief Disparity to depth switch, false: switch to software disparity convert to depth, true: switch to hardware disparity convert to depth + */ + OB_PROP_DISPARITY_TO_DEPTH_BOOL = 85, + + /** + * @brief BRT function switch (anti-background interference), 0: Disable, 1: Enable + */ + OB_PROP_BRT_BOOL = 86, + + /** + * @brief Watchdog function switch, 0: Disable, 1: Enable + */ + OB_PROP_WATCHDOG_BOOL = 87, + + /** + * @brief External signal trigger restart function switch, 0: Disable, 1: Enable + */ + OB_PROP_EXTERNAL_SIGNAL_RESET_BOOL = 88, + + /** + * @brief Heartbeat monitoring function switch, 0: Disable, 1: Enable + */ + OB_PROP_HEARTBEAT_BOOL = 89, + + /** + * @brief Depth cropping mode device: OB_DEPTH_CROPPING_MODE + */ + OB_PROP_DEPTH_CROPPING_MODE_INT = 90, + + /** + * @brief D2C preprocessing switch (such as RGB cropping), 0: off, 1: on + */ + OB_PROP_D2C_PREPROCESS_BOOL = 91, + + /** + * @brief Enable/disable GPM function + */ + OB_PROP_GPM_BOOL = 93, + + /** + * @brief Custom RGB cropping switch, 0 is off, 1 is on custom cropping, and the ROI cropping area is issued + */ + OB_PROP_RGB_CUSTOM_CROP_BOOL = 94, + + /** + * @brief Device operating mode (power consumption) + */ + OB_PROP_DEVICE_WORK_MODE_INT = 95, + + /** + * @brief Device communication type, 0: USB; 1: Ethernet(RTSP) + */ + OB_PROP_DEVICE_COMMUNICATION_TYPE_INT = 97, + + /** + * @brief Switch infrared imaging mode, 0: active IR mode, 1: passive IR mode + */ + OB_PROP_SWITCH_IR_MODE_INT = 98, + + /** + * @brief Laser power level + */ + OB_PROP_LASER_POWER_LEVEL_CONTROL_INT = 99, + + /** + * @brief LDP's measure distance, unit: mm + */ + OB_PROP_LDP_MEASURE_DISTANCE_INT = 100, + + /** + * @brief Reset device time to zero + */ + OB_PROP_TIMER_RESET_SIGNAL_BOOL = 104, + + /** + * @brief Enable send reset device time signal to other device. true: enable, false: disable + */ + OB_PROP_TIMER_RESET_TRIGGER_OUT_ENABLE_BOOL = 105, + + /** + * @brief Delay to reset device time, unit: us + */ + OB_PROP_TIMER_RESET_DELAY_US_INT = 106, + + /** + * @brief Signal to capture image + */ + OB_PROP_CAPTURE_IMAGE_SIGNAL_BOOL = 107, + + /** + * @brief Right IR sensor mirror state + */ + OB_PROP_IR_RIGHT_MIRROR_BOOL = 112, + + /** + * @brief Number frame to capture once a 'OB_PROP_CAPTURE_IMAGE_SIGNAL_BOOL' effect. range: [1, 255] + */ + OB_PROP_CAPTURE_IMAGE_FRAME_NUMBER_INT = 113, + + /** + * @brief Right IR sensor flip state. true: flip image, false: origin, default: false + */ + OB_PROP_IR_RIGHT_FLIP_BOOL = 114, + + /** + * @brief Color sensor rotation, angle{0, 90, 180, 270} + */ + OB_PROP_COLOR_ROTATE_INT = 115, + + /** + * @brief IR/Left-IR sensor rotation, angle{0, 90, 180, 270} + */ + OB_PROP_IR_ROTATE_INT = 116, + + /** + * @brief Right IR sensor rotation, angle{0, 90, 180, 270} + */ + OB_PROP_IR_RIGHT_ROTATE_INT = 117, + + /** + * @brief Depth sensor rotation, angle{0, 90, 180, 270} + */ + OB_PROP_DEPTH_ROTATE_INT = 118, + + /** + * @brief Get hardware laser power actual level which real state of laser element. OB_PROP_LASER_POWER_LEVEL_CONTROL_INT99 will effect this command + * which it setting and changed the hardware laser energy level. + */ + OB_PROP_LASER_POWER_ACTUAL_LEVEL_INT = 119, + + /** + * @brief USB's power state, enum type: OBUSBPowerState + */ + OB_PROP_USB_POWER_STATE_INT = 121, + + /** + * @brief DC's power state, enum type: OBDCPowerState + */ + OB_PROP_DC_POWER_STATE_INT = 122, + + /** + * @brief Device development mode switch, optional modes can refer to the definition in @ref OBDeviceDevelopmentMode,the default mode is + * @ref OB_USER_MODE + * @attention The device takes effect after rebooting when switching modes. + */ + OB_PROP_DEVICE_DEVELOPMENT_MODE_INT = 129, + + /** + * @brief Multi-DeviceSync synchronized signal trigger out is enable state. true: enable, false: disable + */ + OB_PROP_SYNC_SIGNAL_TRIGGER_OUT_BOOL = 130, + + /** + * @brief Restore factory settings and factory parameters + * @attention This command can only be written, and the parameter value must be true. The command takes effect after restarting the device. + */ + OB_PROP_RESTORE_FACTORY_SETTINGS_BOOL = 131, + + /** + * @brief Enter recovery mode (flashing mode) when boot the device + * @attention The device will take effect after rebooting with the enable option. After entering recovery mode, you can upgrade the device system. Upgrading + * the system may cause system damage, please use it with caution. + */ + OB_PROP_BOOT_INTO_RECOVERY_MODE_BOOL = 132, + + /** + * @brief Query whether the current device is running in recovery mode (read-only) + */ + OB_PROP_DEVICE_IN_RECOVERY_MODE_BOOL = 133, + + /** + * @brief Capture interval mode, 0:time interval, 1:number interval + */ + OB_PROP_CAPTURE_INTERVAL_MODE_INT = 134, + + /** + * @brief Capture time interval + */ + OB_PROP_CAPTURE_IMAGE_TIME_INTERVAL_INT = 135, + + /** + * @brief Capture number interval + */ + OB_PROP_CAPTURE_IMAGE_NUMBER_INTERVAL_INT = 136, + + /* + * @brief Timer reset function enable + */ + OB_PROP_TIMER_RESET_ENABLE_BOOL = 140, + + /** + * @brief Enable or disable the device to retry USB2.0 re-identification when the device is connected to a USB2.0 port. + * @brief This feature ensures that the device is not mistakenly identified as a USB 2.0 device when connected to a USB 3.0 port. + */ + OB_PROP_DEVICE_USB2_REPEAT_IDENTIFY_BOOL = 141, + + /** + * @brief Reboot device delay mode. Delay time unit: ms, range: [0, 8000). + */ + OB_PROP_DEVICE_REBOOT_DELAY_INT = 142, + + /** + * @brief Query the status of laser overcurrent protection (read-only) + */ + OB_PROP_LASER_OVERCURRENT_PROTECTION_STATUS_BOOL = 148, + + /** + * @brief Query the status of laser pulse width protection (read-only) + */ + OB_PROP_LASER_PULSE_WIDTH_PROTECTION_STATUS_BOOL = 149, + + /** + * @brief Laser always on, true: always on, false: off, laser will be turned off when out of exposure time + */ + OB_PROP_LASER_ALWAYS_ON_BOOL = 174, + + /** + * @brief Laser on/off alternate mode, 0: off, 1: on-off alternate, 2: off-on alternate + * @attention When turn on this mode, the laser will turn on and turn off alternately each frame. + */ + OB_PROP_LASER_ON_OFF_PATTERN_INT = 175, + + /** + * @brief Depth unit flexible adjustment\ + * @brief This property allows continuous adjustment of the depth unit, unlike @ref OB_PROP_DEPTH_PRECISION_LEVEL_INT must be set to some fixed value. + */ + OB_PROP_DEPTH_UNIT_FLEXIBLE_ADJUSTMENT_FLOAT = 176, + + /** + * @brief Laser control, 0: off, 1: on, 2: auto + * + */ + OB_PROP_LASER_CONTROL_INT = 182, + + /** + * @brief IR brightness + */ + OB_PROP_IR_BRIGHTNESS_INT = 184, + + /** + * @brief Slave/secondary device synchronization status (read-only) + */ + OB_PROP_SLAVE_DEVICE_SYNC_STATUS_BOOL = 188, + + /** + * @brief Color AE max exposure + */ + OB_PROP_COLOR_AE_MAX_EXPOSURE_INT = 189, + + /** + * @brief Max exposure time of IR auto exposure + */ + OB_PROP_IR_AE_MAX_EXPOSURE_INT = 190, + + /** + * @brief Disparity search range mode, 1: 128, 2: 256 + */ + OB_PROP_DISP_SEARCH_RANGE_MODE_INT = 191, + + /** + * @brief Laser high temperature protection + */ + OB_PROP_LASER_HIGH_TEMPERATURE_PROTECT_BOOL = 193, + + /** + * @brief low exposure laser control + * + * @brief Currently using for DabaiA device,if the exposure value is lower than a certain threshold, the laser is turned off; + * if it exceeds another threshold, the laser is turned on again. + */ + OB_PROP_LOW_EXPOSURE_LASER_CONTROL_BOOL = 194, + + /** + * @brief check pps sync in signal + */ + OB_PROP_CHECK_PPS_SYNC_IN_SIGNAL_BOOL = 195, + + /** + * @brief Disparity search range offset, range: [0, 127] + */ + OB_PROP_DISP_SEARCH_OFFSET_INT = 196, + + /** + * @brief cpu temperature correction . true: calibrate temperature + */ + OB_PROP_CPU_TEMPERATURE_CALIBRATION_BOOL = 199, + + /** + * @brief Repower device (cut off power and power on again) + * + * @brief Currently using for GMSL device, cut off power and power on again by GMSL host driver. + */ + OB_PROP_DEVICE_REPOWER_BOOL = 202, + + /** + * @brief frame interleave config index + */ + OB_PROP_FRAME_INTERLEAVE_CONFIG_INDEX_INT = 204, + + /** + * @brief frame interleave enable (true:enable,false:disable) + */ + OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL = 205, + /** + * @brief laser pattern sync with delay(us) + */ + OB_PROP_FRAME_INTERLEAVE_LASER_PATTERN_SYNC_DELAY_INT = 206, + /** + * @brief Get the health check result from device,range is [0.0f,1.5f] + */ + OB_PROP_ON_CHIP_CALIBRATION_HEALTH_CHECK_FLOAT = 209, + + /** + * @brief Enable or disable on-chip calibration + */ + OB_PROP_ON_CHIP_CALIBRATION_ENABLE_BOOL = 210, + + /** + * @brief hardware noise remove filter switch + */ + OB_PROP_HW_NOISE_REMOVE_FILTER_ENABLE_BOOL = 211, + /** + * @brief hardware noise remove filter threshold ,range [0.0 - 1.0] + */ + OB_PROP_HW_NOISE_REMOVE_FILTER_THRESHOLD_FLOAT = 212, + /** + * @brief soft trigger auto capture enable, use in OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING mode + */ + OB_DEVICE_AUTO_CAPTURE_ENABLE_BOOL = 216, + /** + * @brief soft trigger auto capture interval time, use in OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING mode + */ + OB_DEVICE_AUTO_CAPTURE_INTERVAL_TIME_INT = 217, + + /** + * @brief PTP time synchronization enable + */ + OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL = 223, + + /** + * @brief Depth with confidence stream enable + */ + OB_PROP_DEPTH_WITH_CONFIDENCE_STREAM_ENABLE_BOOL = 224, + + /** + * @brief Enable or disable confidence stream filter + */ + OB_PROP_CONFIDENCE_STREAM_FILTER_BOOL = 226, + + /** + * @brief Confidence stream filter threshold, range [0, 255] + */ + OB_PROP_CONFIDENCE_STREAM_FILTER_THRESHOLD_INT = 227, + + /** + * @brief Confidence stream mirror enable + */ + OB_PROP_CONFIDENCE_MIRROR_BOOL = 229, + + /** + * @brief Confidence stream flip enable + */ + OB_PROP_CONFIDENCE_FLIP_BOOL = 230, + + /** + * @brief Confidence stream rotate angle{0, 90, 180, 270} + */ + OB_PROP_CONFIDENCE_ROTATE_INT = 231, + + /** + * @brief Intra-camera Sync Reference based on the exposure start time, the exposure middle time, or the exposure end time. the definition in @ref + * OBIntraCameraSyncReference + */ + OB_PROP_INTRA_CAMERA_SYNC_REFERENCE_INT = 236, + + /** + * @brief Right Color sensor rotation, angle{0, 90, 180, 270} + */ + OB_PROP_COLOR_RIGHT_ROTATE_INT = 242, + + /** + * @brief Right Color mirror + */ + OB_PROP_COLOR_RIGHT_MIRROR_BOOL = 243, + + /** + * @brief Right Color flip + */ + OB_PROP_COLOR_RIGHT_FLIP_BOOL = 244, + + /** + * @brief Device AE reference source + * - 0: Depth based + * - 1: Color based + */ + OB_PROP_DEVICE_AE_REFERENCE_INT = 247, + + /** + * @brief Device AE strategy + * - 0: Default + * - 1: Motion + */ + OB_PROP_DEVICE_AE_STRATEGY_INT = 248, + + /** + * @brief Color camera ROI brightness adjustment + */ + OB_PROP_COLOR_ROI_BRIGHTNESS_INT = 249, + + /** + * @brief Left Color sensor rotation, angle{0, 90, 180, 270} + */ + OB_PROP_COLOR_LEFT_ROTATE_INT = 251, + + /** + * @brief Left Color mirror + */ + OB_PROP_COLOR_LEFT_MIRROR_BOOL = 252, + + /** + * @brief Left Color flip + */ + OB_PROP_COLOR_LEFT_FLIP_BOOL = 253, + + /** + * @brief Color camera preset priority + */ + OB_PROP_COLOR_PRESET_PRIORITY_INT = 255, + + /** + * @brief Baseline calibration parameters + */ + OB_STRUCT_BASELINE_CALIBRATION_PARAM = 1002, + + /** + * @brief Device temperature information + */ + OB_STRUCT_DEVICE_TEMPERATURE = 1003, + + /** + * @brief TOF exposure threshold range + */ + OB_STRUCT_TOF_EXPOSURE_THRESHOLD_CONTROL = 1024, + + /** + * @brief get/set serial number + */ + OB_STRUCT_DEVICE_SERIAL_NUMBER = 1035, + + /** + * @brief get/set device time + */ + OB_STRUCT_DEVICE_TIME = 1037, + + /** + * @brief Multi-device synchronization mode and parameter configuration + */ + OB_STRUCT_MULTI_DEVICE_SYNC_CONFIG = 1038, + + /** + * @brief RGB cropping ROI + */ + OB_STRUCT_RGB_CROP_ROI = 1040, + + /** + * @brief Device IP address configuration + */ + OB_STRUCT_DEVICE_IP_ADDR_CONFIG = 1041, + + /** + * @brief The current camera depth mode + */ + OB_STRUCT_CURRENT_DEPTH_ALG_MODE = 1043, + + /** + * @brief A list of depth accuracy levels, returning an array of uin16_t, corresponding to the enumeration + */ + OB_STRUCT_DEPTH_PRECISION_SUPPORT_LIST = 1045, + + /** + * @brief Device network static ip config record + * @brief Using for get last static ip config, witch is record in device flash when user set static ip config + * + * @attention read only + */ + OB_STRUCT_DEVICE_STATIC_IP_CONFIG_RECORD = 1053, + + /** + * @brief Using to configure the depth sensor's HDR mode + * @brief The Value type is @ref OBHdrConfig + * + * @attention After enable HDR mode, the depth sensor auto exposure will be disabled. + */ + OB_STRUCT_DEPTH_HDR_CONFIG = 1059, + + /** + * @brief Color Sensor AE ROI configuration + * @brief The Value type is @ref OBRegionOfInterest + */ + OB_STRUCT_COLOR_AE_ROI = 1060, + + /** + * @brief Depth Sensor AE ROI configuration + * @brief The Value type is @ref OBRegionOfInterest + * @brief Since the ir sensor is the same physical sensor as the depth sensor, this property will also effect the ir sensor. + */ + OB_STRUCT_DEPTH_AE_ROI = 1061, + + /** + * @brief ASIC serial number + */ + OB_STRUCT_ASIC_SERIAL_NUMBER = 1063, + + /** + * @brief Disparity offset interleaving + */ + OB_STRUCT_DISP_OFFSET_CONFIG = 1064, + + /** + * @brief Preset resolution ratio configuration + */ + OB_STRUCT_PRESET_RESOLUTION_CONFIG = 1069, + + /** + * @brief Color sensor synchronized exposure parameter structure + */ + OB_STRUCT_COLOR_SYNCED_EXPOSURE_PARAM = 1077, + + /** + * @brief Color camera auto exposure + */ + OB_PROP_COLOR_AUTO_EXPOSURE_BOOL = 2000, + + /** + * @brief Color camera exposure adjustment + */ + OB_PROP_COLOR_EXPOSURE_INT = 2001, + + /** + * @brief Color camera gain adjustment + */ + OB_PROP_COLOR_GAIN_INT = 2002, + + /** + * @brief Color camera automatic white balance + */ + OB_PROP_COLOR_AUTO_WHITE_BALANCE_BOOL = 2003, + + /** + * @brief Color camera white balance adjustment + */ + OB_PROP_COLOR_WHITE_BALANCE_INT = 2004, + + /** + * @brief Color camera brightness adjustment + */ + OB_PROP_COLOR_BRIGHTNESS_INT = 2005, + + /** + * @brief Color camera sharpness adjustment + */ + OB_PROP_COLOR_SHARPNESS_INT = 2006, + + /** + * @brief Color camera shutter adjustment + */ + OB_PROP_COLOR_SHUTTER_INT = 2007, + + /** + * @brief Color camera saturation adjustment + */ + OB_PROP_COLOR_SATURATION_INT = 2008, + + /** + * @brief Color camera contrast adjustment + */ + OB_PROP_COLOR_CONTRAST_INT = 2009, + + /** + * @brief Color camera gamma adjustment + */ + OB_PROP_COLOR_GAMMA_INT = 2010, + + /** + * @brief Color camera image rotation + */ + OB_PROP_COLOR_ROLL_INT = 2011, + + /** + * @brief Color camera auto exposure priority + */ + OB_PROP_COLOR_AUTO_EXPOSURE_PRIORITY_INT = 2012, + + /** + * @brief Color camera brightness compensation + */ + OB_PROP_COLOR_BACKLIGHT_COMPENSATION_INT = 2013, + + /** + * @brief Color camera color tint + */ + OB_PROP_COLOR_HUE_INT = 2014, + + /** + * @brief Color Camera Power Line Frequency + */ + OB_PROP_COLOR_POWER_LINE_FREQUENCY_INT = 2015, + + /** + * @brief Automatic exposure of depth camera (infrared camera will be set synchronously under some models of devices) + */ + OB_PROP_DEPTH_AUTO_EXPOSURE_BOOL = 2016, + + /** + * @brief Depth camera exposure adjustment (infrared cameras will be set synchronously under some models of devices) + */ + OB_PROP_DEPTH_EXPOSURE_INT = 2017, + + /** + * @brief Depth camera gain adjustment (infrared cameras will be set synchronously under some models of devices) + */ + OB_PROP_DEPTH_GAIN_INT = 2018, + + /** + * @brief Infrared camera auto exposure (depth camera will be set synchronously under some models of devices) + */ + OB_PROP_IR_AUTO_EXPOSURE_BOOL = 2025, + + /** + * @brief Infrared camera exposure adjustment (some models of devices will set the depth camera synchronously) + */ + OB_PROP_IR_EXPOSURE_INT = 2026, + + /** + * @brief Infrared camera gain adjustment (the depth camera will be set synchronously under some models of devices) + */ + OB_PROP_IR_GAIN_INT = 2027, + + /** + * @brief Select Infrared camera data source channel. If not support throw exception. 0 : IR stream from IR Left sensor; 1 : IR stream from IR Right sensor; + */ + OB_PROP_IR_CHANNEL_DATA_SOURCE_INT = 2028, + + /** + * @brief Depth effect dedistortion, true: on, false: off. mutually exclusive with D2C function, RM_Filter disable When hardware or software D2C is enabled. + */ + OB_PROP_DEPTH_RM_FILTER_BOOL = 2029, + + /** + * @brief Color camera maximal gain + */ + OB_PROP_COLOR_MAXIMAL_GAIN_INT = 2030, + + /** + * @brief Color camera shutter gain + */ + OB_PROP_COLOR_MAXIMAL_SHUTTER_INT = 2031, + + /** + * @brief The enable/disable switch for IR short exposure function, supported only by a few devices. + */ + OB_PROP_IR_SHORT_EXPOSURE_BOOL = 2032, + + /** + * @brief Color camera HDR + */ + OB_PROP_COLOR_HDR_BOOL = 2034, + + /** + * @brief IR long exposure mode switch read and write. + */ + OB_PROP_IR_LONG_EXPOSURE_BOOL = 2035, + + /** + * @brief Setting and getting the USB device frame skipping mode status, true: frame skipping mode, false: non-frame skipping mode. + */ + OB_PROP_SKIP_FRAME_BOOL = 2036, + + /** + * @brief Depth HDR merge, true: on, false: off. + */ + OB_PROP_HDR_MERGE_BOOL = 2037, + + /** + * @brief Color camera FOCUS + */ + OB_PROP_COLOR_FOCUS_INT = 2038, + /** + * @brief ir rectify status,true: ir rectify, false: no rectify + */ + OB_PROP_IR_RECTIFY_BOOL = 2040, + + /** + * @brief Depth camera priority + * + */ + OB_PROP_DEPTH_AUTO_EXPOSURE_PRIORITY_INT = 2052, + + /** + * @brief Software disparity to depth + */ + OB_PROP_SDK_DISPARITY_TO_DEPTH_BOOL = 3004, + + /** + * @brief Depth data unpacking function switch (each open stream will be turned on by default, support RLE/Y10/Y11/Y12/Y14 format) + */ + OB_PROP_SDK_DEPTH_FRAME_UNPACK_BOOL = 3007, + + /** + * @brief IR data unpacking function switch (each current will be turned on by default, support RLE/Y10/Y11/Y12/Y14 format) + */ + OB_PROP_SDK_IR_FRAME_UNPACK_BOOL = 3008, + + /** + * @brief Accel data conversion function switch (on by default) + */ + OB_PROP_SDK_ACCEL_FRAME_TRANSFORMED_BOOL = 3009, + + /** + * @brief Gyro data conversion function switch (on by default) + */ + OB_PROP_SDK_GYRO_FRAME_TRANSFORMED_BOOL = 3010, + + /** + * @brief Left IR frame data unpacking function switch (each current will be turned on by default, support RLE/Y10/Y11/Y12/Y14 format) + */ + OB_PROP_SDK_IR_LEFT_FRAME_UNPACK_BOOL = 3011, + + /** + * @brief Right IR frame data unpacking function switch (each current will be turned on by default, support RLE/Y10/Y11/Y12/Y14 format) + */ + OB_PROP_SDK_IR_RIGHT_FRAME_UNPACK_BOOL = 3012, + + /** + * @brief Depth Stream Industry Working Mode Settings, currently only supported by DCW2. + */ + OB_PROP_DEPTH_INDUSTRY_MODE_INT = 3024, + + /** + * @brief Read the current network bandwidth type of the network device, whether it is Gigabit Ethernet or Fast Ethernet, such as G335LE. + */ + OB_PROP_NETWORK_BANDWIDTH_TYPE_INT = 3027, + + /** + * @brief Switch device performance mode, currently available in Adaptive Mode and High Performance Mode, such as G335LE. + */ + OB_PROP_DEVICE_PERFORMANCE_MODE_INT = 3028, + + /** + * @brief Calibration JSON file read from device (Femto Mega, read only) + */ + OB_RAW_DATA_CAMERA_CALIB_JSON_FILE = 4029, + + /** + * @brief Confidence degree + */ + OB_PROP_DEBUG_ESGM_CONFIDENCE_FLOAT = 5013, + + /** + * @brief Color camera CCI denoising level. 0: Auto; 1-8: higher values indicate stronger denoising. + * @note This setting has no effect when AE (Auto Exposure) is disabled. + */ + OB_PROP_COLOR_DENOISING_LEVEL_INT = 5525, + + /* + * @brief LiDAR: set/get IP address + */ + OB_RAW_DATA_LIDAR_IP_ADDRESS = 8000, + + /** + * @brief LiDAR: set/get port + */ + OB_PROP_LIDAR_PORT_INT = 8001, + + /** + * @brief LiDAR: set/get MAC address + */ + OB_RAW_DATA_LIDAR_MAC_ADDRESS = 8002, + + /** + * @brief LiDAR: set/get subnet mask + */ + OB_RAW_DATA_LIDAR_SUBNET_MASK = 8003, + + /** + * @brief LiDAR: set/get work mode + */ + OB_PROP_LIDAR_WORK_MODE_INT = 8004, + + /** + * @brief LiDAR: apply configs + */ + OB_PROP_LIDAR_APPLY_CONFIGS_INT = 8005, + + /** + * @brief LiDAR: set/get tail filter level + */ + OB_PROP_LIDAR_TAIL_FILTER_LEVEL_INT = 8006, + + /** + * @brief LiDAR: set/get mems fov size + */ + OB_PROP_LIDAR_MEMS_FOV_SIZE_FLOAT = 8007, + + /** + * @brief LiDAR: set/get mems frequency + */ + OB_PROP_LIDAR_MEMS_FRENQUENCY_FLOAT = 8008, + + /** + * @brief LiDAR: get product model + */ + OB_RAW_DATA_LIDAR_PRODUCT_MODEL = 8009, + + /** + * @brief LiDAR: get firmware version + */ + OB_RAW_DATA_LIDAR_FIRMWARE_VERSION = 8010, + + /** + * @brief LiDAR: get fpga version + */ + OB_RAW_DATA_LIDAR_FPGA_VERSION = 8011, + + /** + * @brief LiDAR: get warning info + */ + OB_PROP_LIDAR_WARNING_INFO_INT = 8012, + + /** + * @brief LiDAR: get realtime motor spin speed, unit:0.01rpm + */ + OB_PROP_LIDAR_MOTOR_SPIN_SPEED_INT = 8013, + + /** + * @brief LiDAR: get mcu temperature, uint: 0.01degrees delsius + */ + OB_PROP_LIDAR_MCU_TEMPERATURE_INT = 8014, + + /** + * @brief LiDAR: get apd temperature, uint: 0.01degrees delsius + */ + OB_PROP_LIDAR_APD_TEMPERATURE_INT = 8015, + + /** + * @brief LiDAR: get/set specific mode + */ + OB_PROP_LIDAR_SPECIFIC_MODE_INT = 8016, + + /** + * @brief LiDAR: get/set repetitive scan mode + */ + OB_PROP_LIDAR_REPETITIVE_SCAN_MODE_INT = 8017 +} OBPropertyID, + ob_property_id; + +// For backward compatibility +#define OB_PROP_TIMER_RESET_TRIGGLE_OUT_ENABLE_BOOL OB_PROP_TIMER_RESET_TRIGGER_OUT_ENABLE_BOOL +#define OB_PROP_LASER_ON_OFF_MODE_INT OB_PROP_LASER_ON_OFF_PATTERN_INT +#define OB_PROP_LASER_ENERGY_LEVEL_INT OB_PROP_LASER_POWER_LEVEL_CONTROL_INT +#define OB_PROP_LASER_HW_ENERGY_LEVEL_INT OB_PROP_LASER_POWER_ACTUAL_LEVEL_INT +#define OB_PROP_DEVICE_USB3_REPEAT_IDENTIFY_BOOL OB_PROP_DEVICE_USB2_REPEAT_IDENTIFY_BOOL +#define OB_PROP_DEPTH_SOFT_FILTER_BOOL OB_PROP_DEPTH_NOISE_REMOVAL_FILTER_BOOL +#define OB_PROP_DEPTH_MAX_DIFF_INT OB_PROP_DEPTH_NOISE_REMOVAL_FILTER_MAX_DIFF_INT +#define OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT OB_PROP_DEPTH_NOISE_REMOVAL_FILTER_MAX_SPECKLE_SIZE_INT + +/** + * @brief The data type used to describe all property settings + */ +typedef enum OBPropertyType { + OB_BOOL_PROPERTY = 0, /**< Boolean property */ + OB_INT_PROPERTY = 1, /**< Integer property */ + OB_FLOAT_PROPERTY = 2, /**< Floating-point property */ + OB_STRUCT_PROPERTY = 3, /**< Struct property */ +} OBPropertyType, + ob_property_type; + +/** + * @brief Used to describe the characteristics of each property + */ +typedef struct OBPropertyItem { + OBPropertyID id; /**< Property ID */ + const char *name; /**< Property name */ + OBPropertyType type; /**< Property type */ + OBPermissionType permission; /**< Property read and write permission */ +} OBPropertyItem, ob_property_item; + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/RecordPlayback.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/RecordPlayback.h new file mode 100644 index 0000000..6102c2b --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/RecordPlayback.h @@ -0,0 +1,141 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file RecordPlayback.hpp + * @brief Record and playback device-related types, including interfaces to create recording and playback devices, + record and playback streaming data, etc. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Device.h" + +/** + * @brief Create a recording device for the specified device with a specified file path and compression enabled. + * + * @param[in] device The device to record. + * @param[in] file_path The file path to record to. + * @param[in] compression_enabled Whether to enable compression for the recording. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return A pointer to the newly created recording device, or NULL if an error occurred. + */ +OB_EXPORT ob_record_device *ob_create_record_device(ob_device *device, const char *file_path, bool compression_enabled, ob_error **error); + +/** + * @brief Delete a recording device. + * + * @param[in] recorder The recording device to delete. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_record_device(ob_record_device *recorder, ob_error **error); + +/** + * @brief Pause recording on the specified recording device. + * + * @param[in] recorder The recording device to pause. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_record_device_pause(ob_record_device *recorder, ob_error **error); + +/** + * @brief Resume recording on the specified recording device. + * + * @param[in] recorder The recording device to resume. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_record_device_resume(ob_record_device *recorder, ob_error **error); + +/** + * @brief Create a playback device for the specified file path. + * + * @param[in] file_path The file path to playback from. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return A pointer to the newly created playback device, or NULL if an error occurred. + */ +OB_EXPORT ob_device *ob_create_playback_device(const char *file_path, ob_error **error); + +/** + * @brief Pause playback on the specified playback device. + * + * @param[in] player The playback device to pause. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_playback_device_pause(ob_device *player, ob_error **error); + +/** + * @brief Resume playback on the specified playback device. + * + * @param[in] player The playback device to resume. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_playback_device_resume(ob_device *player, ob_error **error); + +/** + * @brief Set the playback to a specified time point of the played data. + * + * @param[in] player The playback device to set the position for. + * @param[in] timestamp The position to set the playback to, in milliseconds. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_playback_device_seek(ob_device *player, const uint64_t timestamp, ob_error **error); + +/** + * @brief Set the playback to a specified time point of the played data. + * + * @param[in] player The playback device to set the position for. + * @param[in] rate The playback rate to set. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_playback_device_set_playback_rate(ob_device *player, const float rate, ob_error **error); + +/** + * @brief Get the current playback status of the played data. + * + * @param[in] player The playback device to get the status for. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The current playback status of the played data. + */ +OB_EXPORT ob_playback_status ob_playback_device_get_current_playback_status(ob_device *player, ob_error **error); + +/** + * @brief Set a callback function to receive playback status updates. + * + * @param[in] player The playback device to set the callback for. + * @param[in] callback The callback function to receive playback status updates. + * @param[in] user_data Pointer to user data that can be passed to and retrieved from the callback function + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_playback_device_set_playback_status_changed_callback(ob_device *player, ob_playback_status_changed_callback callback, void *user_data, + ob_error **error); + +/** + * @brief Get the current playback position of the played data. + * + * @param[in] player The playback device to get the position for. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The current playback position of the played data, in milliseconds. + */ +OB_EXPORT uint64_t ob_playback_device_get_position(ob_device *player, ob_error **error); + +/** + * @brief Get the duration of the played data. + * + * @param[in] player The playback device to get the duration for. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The duration of the played data, in milliseconds. + */ +OB_EXPORT uint64_t ob_playback_device_get_duration(ob_device *player, ob_error **error); + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Sensor.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Sensor.h new file mode 100644 index 0000000..4e1fc1f --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Sensor.h @@ -0,0 +1,138 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Sensor.h + * @brief Defines types related to sensors, used for obtaining stream configurations, opening and closing streams, and setting and getting sensor properties. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Get the type of the sensor. + * + * @param[in] sensor The sensor object. + * @param[out] error Logs error messages. + * + * @return The sensor type. + */ +OB_EXPORT ob_sensor_type ob_sensor_get_type(const ob_sensor *sensor, ob_error **error); + +/** + * @brief Get a list of all supported stream profiles. + * + * @param[in] sensor The sensor object. + * @param[out] error Logs error messages. + * + * @return A list of stream profiles. + */ +OB_EXPORT ob_stream_profile_list *ob_sensor_get_stream_profile_list(const ob_sensor *sensor, ob_error **error); + +/** + * @brief Open the current sensor and set the callback data frame. + * + * @param[in] sensor The sensor object. + * @param[in] profile The stream configuration information. + * @param[in] callback The callback function triggered when frame data arrives. + * @param[in] user_data Any user data to pass in and get from the callback. + * @param[out] error Logs error messages. + */ +OB_EXPORT void ob_sensor_start(ob_sensor *sensor, const ob_stream_profile *profile, ob_frame_callback callback, void *user_data, ob_error **error); + +/** + * @brief Stop the sensor stream. + * + * @param[in] sensor The sensor object. + * @param[out] error Logs error messages. + */ +OB_EXPORT void ob_sensor_stop(ob_sensor *sensor, ob_error **error); + +/** + * @brief Switch resolutions. + * + * @param[in] sensor The sensor object. + * @param[in] profile The stream configuration information. + * @param[out] error Logs error messages. + */ +OB_EXPORT void ob_sensor_switch_profile(ob_sensor *sensor, ob_stream_profile *profile, ob_error **error); + +/** + * @brief Delete a sensor object. + * + * @param[in] sensor The sensor object to delete. + * @param[out] error Logs error messages. + */ +OB_EXPORT void ob_delete_sensor(ob_sensor *sensor, ob_error **error); + +/** + * @brief Create a list of recommended filters for the specified sensor. + * + * @param[in] sensor The ob_sensor object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_filter_list + */ +OB_EXPORT ob_filter_list *ob_sensor_create_recommended_filter_list(const ob_sensor *sensor, ob_error **error); + +/** + * @brief Get the number of sensors in the sensor list. + * + * @param[in] sensor_list The list of sensor objects. + * @param[out] error Logs error messages. + * + * @return The number of sensors in the list. + */ +OB_EXPORT uint32_t ob_sensor_list_get_count(const ob_sensor_list *sensor_list, ob_error **error); + +/** + * @brief Get the sensor type. + * + * @param[in] sensor_list The list of sensor objects. + * @param[in] index The index of the sensor on the list. + * @param[out] error Logs error messages. + * + * @return The sensor type. + */ +OB_EXPORT ob_sensor_type ob_sensor_list_get_sensor_type(const ob_sensor_list *sensor_list, uint32_t index, ob_error **error); + +/** + * @brief Get a sensor by sensor type. + * + * @param[in] sensor_list The list of sensor objects. + * @param[in] sensorType The sensor type to be obtained. + * @param[out] error Logs error messages. + * + * @return The sensor pointer. If the specified type of sensor does not exist, it will return null. + */ +OB_EXPORT ob_sensor *ob_sensor_list_get_sensor_by_type(const ob_sensor_list *sensor_list, ob_sensor_type sensorType, ob_error **error); + +/** + * @brief Get a sensor by index number. + * + * @param[in] sensor_list The list of sensor objects. + * @param[in] index The index of the sensor on the list. + * @param[out] error Logs error messages. + * + * @return The sensor object. + */ +OB_EXPORT ob_sensor *ob_sensor_list_get_sensor(const ob_sensor_list *sensor_list, uint32_t index, ob_error **error); + +/** + * @brief Delete a list of sensor objects. + * + * @param[in] sensor_list The list of sensor objects to delete. + * @param[out] error Logs error messages. + */ +OB_EXPORT void ob_delete_sensor_list(ob_sensor_list *sensor_list, ob_error **error); + +#define ob_sensor_list_get_sensor_count ob_sensor_list_get_count +#define ob_sensor_get_recommended_filter_list ob_sensor_create_recommended_filter_list + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/StreamProfile.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/StreamProfile.h new file mode 100644 index 0000000..e5a014c --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/StreamProfile.h @@ -0,0 +1,505 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file StreamProfile.h + * @brief The stream profile related type is used to get information such as the width, height, frame rate, and format of the stream. + * + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Create a stream profile object + * + * @param[in] type Stream type + * @param[in] format Stream format + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile* return the stream profile object + */ +OB_EXPORT ob_stream_profile *ob_create_stream_profile(ob_stream_type type, ob_format format, ob_error **error); + +/** + * @brief Create a video stream profile object + * + * @param[in] type Stream type + * @param[in] format Stream format + * @param[in] width Stream width + * @param[in] height Stream height + * @param[in] fps Stream frame rate + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile* return the video stream profile object + */ +OB_EXPORT ob_stream_profile *ob_create_video_stream_profile(ob_stream_type type, ob_format format, uint32_t width, uint32_t height, uint32_t fps, + ob_error **error); + +/** + * @brief Create a accel stream profile object + * + * @param[in] full_scale_range Accel full scale range + * @param[in] sample_rate Accel sample rate + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile* return the accel stream profile object + */ +OB_EXPORT ob_stream_profile *ob_create_accel_stream_profile(ob_accel_full_scale_range full_scale_range, ob_accel_sample_rate sample_rate, ob_error **error); + +/** + * @brief Create a gyro stream profile object + * + * @param[in] full_scale_range Gyro full scale range + * @param[in] sample_rate Gyro sample rate + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile* return the gyro stream profile object + */ +OB_EXPORT ob_stream_profile *ob_create_gyro_stream_profile(ob_gyro_full_scale_range full_scale_range, ob_gyro_sample_rate sample_rate, ob_error **error); + +/** + * @brief Create a LiDAR stream profile object + * + * @param[in] scan_rate The scan rate of LiDAR + * @param[in] format The format of the LiDAR stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + * @return ob_stream_profile* return the LiDAR stream profile object + */ +OB_EXPORT ob_stream_profile *ob_create_lidar_stream_profile(ob_lidar_scan_rate scan_rate, ob_format format, ob_error **error); + +/** + * @brief Copy the stream profile object from an other stream profile object + * + * @param[in] srcProfile Source stream profile object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile* return the new stream profile object + */ +OB_EXPORT ob_stream_profile *ob_create_stream_profile_from_other_stream_profile(const ob_stream_profile *srcProfile, ob_error **error); + +/** + * @brief Copy the stream profile object with a new format object + * + * @param[in] profile Stream profile object + * @param[in] new_format New format + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_profile* return the new stream profile object with the new format + */ +OB_EXPORT ob_stream_profile *ob_create_stream_profile_with_new_format(const ob_stream_profile *profile, ob_format new_format, ob_error **error); + +/** + * @brief Delete the stream configuration. + * + * @param[in] profile Stream profile object . + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_stream_profile(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Get stream profile format + * + * @param[in] profile Stream profile object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_format return the format of the stream + */ +OB_EXPORT ob_format ob_stream_profile_get_format(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set stream profile format + * + * @param[in] profile Stream profile object + * @param[in] format The format of the stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_stream_profile_set_format(ob_stream_profile *profile, ob_format format, ob_error **error); + +/** + * @brief Get stream profile type + * + * @param[in] profile Stream profile object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_stream_type stream type + */ +OB_EXPORT ob_stream_type ob_stream_profile_get_type(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set stream profile type + * + * @param[in] profile Stream profile object + * @param[in] type The type of the stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_stream_profile_set_type(const ob_stream_profile *profile, ob_stream_type type, ob_error **error); + +/** + * @brief Get the extrinsic for source stream to target stream + * + * @param[in] source Source stream profile + * @param[in] target Target stream profile + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_extrinsic The extrinsic + */ +OB_EXPORT ob_extrinsic ob_stream_profile_get_extrinsic_to(const ob_stream_profile *source, ob_stream_profile *target, ob_error **error); + +/** + * @brief Set the extrinsic for source stream to target stream + * + * @param[in] source Stream profile object + * @param[in] target Target stream type + * @param[in] extrinsic The extrinsic + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_stream_profile_set_extrinsic_to(ob_stream_profile *source, const ob_stream_profile *target, ob_extrinsic extrinsic, ob_error **error); + +/** + * @brief Set the extrinsic for source stream to target stream type + * + * @param[in] source Source stream profile + * @param[in] type Target stream type + * @param[in] extrinsic The extrinsic + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_stream_profile_set_extrinsic_to_type(ob_stream_profile *source, const ob_stream_type type, ob_extrinsic extrinsic, ob_error **error); + +/** + * @brief Get the frame rate of the video stream + * + * @param[in] profile Stream profile object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the frame rate of the stream + */ +OB_EXPORT uint32_t ob_video_stream_profile_get_fps(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Get the width of the video stream + * + * @param[in] profile Stream profile object , If the profile is not a video stream configuration, an error will be returned + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the width of the stream + */ +OB_EXPORT uint32_t ob_video_stream_profile_get_width(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set the width of the video stream + * + * @param[in] profile Stream profile object , If the profile is not a video stream configuration, an error will be returned + * @param[in] width The width of the stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_video_stream_profile_set_width(ob_stream_profile *profile, uint32_t width, ob_error **error); + +/** + * @brief Get the height of the video stream + * + * @param[in] profile Stream profile object , If the profile is not a video stream configuration, an error will be returned + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return uint32_t return the height of the stream + */ +OB_EXPORT uint32_t ob_video_stream_profile_get_height(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set the height of the video stream + * + * @param[in] profile Stream profile object , If the profile is not a video stream configuration, an error will be returned + * @param[in] height The height of the stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_video_stream_profile_set_height(ob_stream_profile *profile, uint32_t height, ob_error **error); + +/** + * @brief Get the intrinsic of the video stream profile + * + * @param[in] profile Stream profile object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_camera_intrinsic Return the intrinsic of the stream + */ +OB_EXPORT ob_camera_intrinsic ob_video_stream_profile_get_intrinsic(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set the intrinsic of the video stream profile + * + * @param[in] profile Stream profile object + * @param[in] intrinsic The intrinsic of the stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_video_stream_profile_set_intrinsic(ob_stream_profile *profile, ob_camera_intrinsic intrinsic, ob_error **error); + +/** + * @brief Get the distortion of the video stream profile + * + * @param[in] profile Stream profile object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_camera_distortion Return the distortion of the stream + */ +OB_EXPORT ob_camera_distortion ob_video_stream_profile_get_distortion(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Get the decimation configuration of the video stream profile. + * + * @param[in] profile Stream profile object. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_hardware_decimation_config Return the decimation configuration of the stream. + */ +OB_EXPORT ob_hardware_decimation_config ob_video_stream_profile_get_decimation_config(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set the distortion of the video stream profile + * + * @param[in] profile Stream profile object + * @param[in] distortion The distortion of the stream + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_video_stream_profile_set_distortion(ob_stream_profile *profile, ob_camera_distortion distortion, ob_error **error); + +/** + * @brief Get the process param of the disparity stream + * + * @param[in] profile Stream profile object + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_disparity_param Return the disparity process param of the stream + */ +OB_EXPORT ob_disparity_param ob_disparity_based_stream_profile_get_disparity_param(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set the disparity process param of the disparity stream. + * + * @param[in] profile Stream profile object. If the profile is not for the disparity stream, an error will be returned. + * @param[in] param The disparity process param of the disparity stream. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_disparity_based_stream_profile_set_disparity_param(ob_stream_profile *profile, ob_disparity_param param, ob_error **error); + +/** + * @brief Get the full-scale range of the accelerometer stream. + * + * @param[in] profile Stream profile object. If the profile is not for the accelerometer stream, an error will be returned. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The full-scale range of the accelerometer stream. + */ +OB_EXPORT ob_accel_full_scale_range ob_accel_stream_profile_get_full_scale_range(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Get the sampling frequency of the accelerometer frame. + * + * @param[in] profile Stream profile object. If the profile is not for the accelerometer stream, an error will be returned. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The sampling frequency of the accelerometer frame. + */ +OB_EXPORT ob_accel_sample_rate ob_accel_stream_profile_get_sample_rate(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Get the intrinsic of the accelerometer stream. + * + * @param[in] profile Stream profile object. If the profile is not for the accelerometer stream, an error will be returned. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_accel_intrinsic Return the intrinsic of the accelerometer stream. + */ +OB_EXPORT ob_accel_intrinsic ob_accel_stream_profile_get_intrinsic(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set the intrinsic of the accelerometer stream. + * + * @param[in] profile Stream profile object. If the profile is not for the accelerometer stream, an error will be returned. + * @param[in] intrinsic The intrinsic of the accelerometer stream. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_accel_stream_profile_set_intrinsic(ob_stream_profile *profile, ob_accel_intrinsic intrinsic, ob_error **error); + +/** + * @brief Get the full-scale range of the gyroscope stream. + * + * @param[in] profile Stream profile object. If the profile is not for the gyroscope stream, an error will be returned. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The full-scale range of the gyroscope stream. + */ +OB_EXPORT ob_gyro_full_scale_range ob_gyro_stream_profile_get_full_scale_range(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Get the sampling frequency of the gyroscope stream. + * + * @param[in] profile Stream profile object. If the profile is not for the gyroscope stream, an error will be returned. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The sampling frequency of the gyroscope stream. + */ +OB_EXPORT ob_gyro_sample_rate ob_gyro_stream_profile_get_sample_rate(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Get the intrinsic of the gyroscope stream. + * + * @param[in] profile Stream profile object. If the profile is not for the gyroscope stream, an error will be returned. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return ob_gyro_intrinsic Return the intrinsic of the gyroscope stream. + */ +OB_EXPORT ob_gyro_intrinsic ob_gyro_stream_get_intrinsic(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Set the intrinsic of the gyroscope stream. + * + * @param[in] profile Stream profile object. If the profile is not for the gyroscope stream, an error will be returned. + * @param[in] intrinsic The intrinsic of the gyroscope stream. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_gyro_stream_set_intrinsic(ob_stream_profile *profile, ob_gyro_intrinsic intrinsic, ob_error **error); + +/** + * @brief Get the scan rate of the LiDAR stream. + * + * @param[in] profile Stream profile object. If the profile is not for the LiDAR stream, an error will be returned. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * @return The scan rate of the LiDAR stream. + */ +OB_EXPORT ob_lidar_scan_rate ob_lidar_stream_profile_get_scan_rate(const ob_stream_profile *profile, ob_error **error); + +/** + * @brief Get the number of StreamProfile lists. + * + * @param[in] profile_list StreamProfile list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The number of StreamProfile lists. + */ +OB_EXPORT uint32_t ob_stream_profile_list_get_count(const ob_stream_profile_list *profile_list, ob_error **error); + +/** + * @brief Get the corresponding StreamProfile by subscripting. + * + * @attention The stream profile returned by this function should be deleted by calling @ref ob_delete_stream_profile() when it is no longer needed. + * + * @param[in] profile_list StreamProfile lists. + * @param[in] index Index. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The matching profile. + */ +OB_EXPORT ob_stream_profile *ob_stream_profile_list_get_profile(const ob_stream_profile_list *profile_list, int index, ob_error **error); + +/** + * @brief Match the corresponding ob_stream_profile through the passed parameters. If there are multiple matches, + * the first one in the list will be returned by default. If no matched profile is found, an error will be returned. + * + * @attention The stream profile returned by this function should be deleted by calling @ref ob_delete_stream_profile() when it is no longer needed. + * + * @param[in] profile_list Resolution list. + * @param[in] width Width. If you don't need to add matching conditions, you can pass OB_WIDTH_ANY. + * @param[in] height Height. If you don't need to add matching conditions, you can pass OB_HEIGHT_ANY. + * @param[in] format Format. If you don't need to add matching conditions, you can pass OB_FORMAT_ANY. + * @param[in] fps Frame rate. If you don't need to add matching conditions, you can pass OB_FPS_ANY. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The matching profile. + */ +OB_EXPORT ob_stream_profile *ob_stream_profile_list_get_video_stream_profile(const ob_stream_profile_list *profile_list, int width, int height, + ob_format format, int fps, ob_error **error); + +/** + * @brief Match the corresponding ob_stream_profile based on the provided decimation configuration. If multiple profiles match, the first profile in the list + * is returned by default. If no matched profile is found, an error will be returned. + * + * @attention The stream profile returned by this function should be released with @ref ob_delete_stream_profile() when it is no longer needed. + * + * @param[in] profile_list The list of stream profiles. + * @param[in] decimation_config Decimation configuration. The actual resolution is determined by original resolution and the scale factor. + * @param[in] format Stream format. If no matching condition is required, pass OB_FORMAT_ANY. + * @param[in] fps Frame rate. If no matching condition is required, pass OB_FPS_ANY. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The matched stream profile. + */ +OB_EXPORT ob_stream_profile *ob_stream_profile_list_get_video_stream_profile_by_decimation_config(const ob_stream_profile_list *profile_list, + ob_hardware_decimation_config decimation_config, + ob_format format, int fps, ob_error **error); + +/** + * @brief Match the corresponding ob_stream_profile through the passed parameters. If there are multiple matches, + * the first one in the list will be returned by default. If no matched profile is found, an error will be returned. + * + * @attention The stream profile returned by this function should be deleted by calling @ref ob_delete_stream_profile() when it is no longer needed. + * + * @param[in] profile_list Resolution list. + * @param[in] full_scale_range Full-scale range. If you don't need to add matching conditions, you can pass 0. + * @param[in] sample_rate Sample rate. If you don't need to add matching conditions, you can pass 0. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The matching profile. + */ +OB_EXPORT ob_stream_profile *ob_stream_profile_list_get_accel_stream_profile(const ob_stream_profile_list *profile_list, + ob_accel_full_scale_range full_scale_range, ob_accel_sample_rate sample_rate, + ob_error **error); + +/** + * @brief Match the corresponding ob_stream_profile through the passed parameters. If there are multiple matches, + * the first one in the list will be returned by default. If no matched profile is found, an error will be returned. + * + * @attention The stream profile returned by this function should be deleted by calling @ref ob_delete_stream_profile() when it is no longer needed. + * + * @param[in] profile_list Resolution list. + * @param[in] full_scale_range Full-scale range. If you don't need to add matching conditions, you can pass 0. + * @param[in] sample_rate Sample rate. If you don't need to add matching conditions, you can pass 0. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return The matching profile. + */ +OB_EXPORT ob_stream_profile *ob_stream_profile_list_get_gyro_stream_profile(const ob_stream_profile_list *profile_list, + ob_gyro_full_scale_range full_scale_range, ob_gyro_sample_rate sample_rate, + ob_error **error); + +/** + * @brief Match the corresponding ob_stream_profile through the passed parameters. If there are multiple matches, + * the first one in the list will be returned by default. If no matched profile is found, an error will be returned. + * + * @attention The stream profile returned by this function should be deleted by calling @ref ob_delete_stream_profile() when it is no longer needed. + * + * @param[in] profile_list Resolution list. + * @param[in] scan_rate The scan rate of LiDAR. If you don't need to add matching conditions, you can pass OB_LIDAR_SCAN_ANY. + * @param[in] format The format of the LiDAR stream. If you don't need to add matching conditions, you can pass OB_FORMAT_ANY. + * @param[out] error Pointer to an error object that will be set if an error occurs. + * @return The matching profile. + */ +OB_EXPORT ob_stream_profile *ob_stream_profile_list_get_lidar_stream_profile(const ob_stream_profile_list *profile_list, ob_lidar_scan_rate scan_rate, + ob_format format, ob_error **error); + +/** + * @brief Delete the stream profile list. + * + * @param[in] profile_list Stream configuration list. + * @param[out] error Pointer to an error object that will be set if an error occurs. + */ +OB_EXPORT void ob_delete_stream_profile_list(const ob_stream_profile_list *profile_list, ob_error **error); + +// The following interfaces are deprecated and are retained here for compatibility purposes. +#define ob_stream_profile_format ob_stream_profile_get_format +#define ob_stream_profile_type ob_stream_profile_get_type +#define ob_video_stream_profile_fps ob_video_stream_profile_get_fps +#define ob_video_stream_profile_width ob_video_stream_profile_get_width +#define ob_video_stream_profile_height ob_video_stream_profile_get_height +#define ob_accel_stream_profile_full_scale_range ob_accel_stream_profile_get_full_scale_range +#define ob_accel_stream_profile_sample_rate ob_accel_stream_profile_get_sample_rate +#define ob_gyro_stream_profile_full_scale_range ob_gyro_stream_profile_get_full_scale_range +#define ob_gyro_stream_profile_sample_rate ob_gyro_stream_profile_get_sample_rate +#define ob_stream_profile_list_count ob_stream_profile_list_get_count + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/TypeHelper.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/TypeHelper.h new file mode 100644 index 0000000..bcde022 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/TypeHelper.h @@ -0,0 +1,111 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Convert OBFormat to " char* " type and then return. + * + * @param[in] type OBFormat type. + * + * @return OBFormat of "char*" type. + */ +OB_EXPORT const char* ob_format_type_to_string(OBFormat type); + +/** + * @brief Convert OBFrameType to " char* " type and then return. + * + * @param[in] type OBFrameType type. + * + * @return OBFrameType of "char*" type. + */ +OB_EXPORT const char* ob_frame_type_to_string(OBFrameType type); + +/** + * @brief Convert OBStreamType to " char* " type and then return. + * + * @param[in] type OBStreamType type. + * + * @return OBStreamType of "char*" type. + */ +OB_EXPORT const char* ob_stream_type_to_string(OBStreamType type); + +/** + * @brief Convert OBSensorType to " char* " type and then return. + * + * @param[in] type OBSensorType type. + * + * @return OBSensorType of "char*" type. + */ +OB_EXPORT const char* ob_sensor_type_to_string(OBSensorType type); + +/** + * @brief Convert OBIMUSampleRate to " char* " type and then return. + * + * @param[in] type OBIMUSampleRate type. + * + * @return OBIMUSampleRate of "char*" type. + */ +OB_EXPORT const char* ob_imu_rate_type_to_string(OBIMUSampleRate type); + +/** + * @brief Convert OBGyroFullScaleRange to " char* " type and then return. + * + * @param[in] type OBGyroFullScaleRange type. + * + * @return OBGyroFullScaleRange of "char*" type. + */ +OB_EXPORT const char* ob_gyro_range_type_to_string(OBGyroFullScaleRange type); + +/** + * @brief Convert OBAccelFullScaleRange to " char* " type and then return. + * + * @param[in] type OBAccelFullScaleRange type. + * + * @return OBAccelFullScaleRange of "char*" type. + */ +OB_EXPORT const char* ob_accel_range_type_to_string(OBAccelFullScaleRange type); + +/** + * @brief Convert OBLiDARScanRate to " char* " type and then return. + * + * @param[in] type OBLiDARScanRate type. + * @return OBLiDARScanRate of "char*" type. + */ +OB_EXPORT const char *ob_lidar_scan_rate_type_to_string(OBLiDARScanRate type); + +/** + * @brief Convert OBFrameMetadataType to " char* " type and then return. + * + * @param[in] type OBFrameMetadataType type. + * + * @return OBFrameMetadataType of "char*" type. + */ +OB_EXPORT const char* ob_meta_data_type_to_string(OBFrameMetadataType type); + +/** + * @brief Convert OBStreamType to OBSensorType. + * + * @param[in] type The sensor type to convert. + * + * @return OBStreamType The corresponding stream type. + */ +OB_EXPORT OBStreamType ob_sensor_type_to_stream_type(OBSensorType type); + +/** + * @brief Convert OBFormat to " char* " type and then return. + * + * @param[in] format The OBFormat to convert. + * + * @return The string. + */ +OB_EXPORT const char *ob_format_to_string(OBFormat format); +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Utils.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Utils.h new file mode 100644 index 0000000..ae7f700 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Utils.h @@ -0,0 +1,136 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ObTypes.h" + +/** + * @brief Transform a 3d point of a source coordinate system into a 3d point of the target coordinate system. + * + * @param[in] source_point3f Source 3d point value + * @param[in] extrinsic Transformation matrix from source to target + * @param[out] target_point3f Target 3d point value + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool Transform result + */ +OB_EXPORT bool ob_transformation_3d_to_3d(const OBPoint3f source_point3f, OBExtrinsic extrinsic, OBPoint3f *target_point3f, ob_error **error); + +/** + * @brief Transform a 2d pixel coordinate with an associated depth value of the source camera into a 3d point of the target coordinate system. + * + * @param[in] source_point2f Source 2d point value + * @param[in] source_depth_pixel_value The depth of sourcePoint2f in millimeters + * @param[in] source_intrinsic Source intrinsic parameters + * @param[in] extrinsic Transformation matrix from source to target + * @param[out] target_point3f Target 3d point value + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool Transform result + */ +OB_EXPORT bool ob_transformation_2d_to_3d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic, + OBExtrinsic extrinsic, OBPoint3f *target_point3f, ob_error **error); + +/** + * @brief Transform a 3d point of a source coordinate system into a 2d pixel coordinate of the target camera. + * + * @param[in] source_point3f Source 3d point value + * @param[in] target_intrinsic Target intrinsic parameters + * @param[in] target_distortion Target distortion parameters + * @param[in] extrinsic Transformation matrix from source to target + * @param[out] target_point2f Target 2d point value + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool Transform result + */ +OB_EXPORT bool ob_transformation_3d_to_2d(const OBPoint3f source_point3f, const OBCameraIntrinsic target_intrinsic, const OBCameraDistortion target_distortion, + OBExtrinsic extrinsic, OBPoint2f *target_point2f, ob_error **error); + +/** + * @brief Transform a 2d pixel coordinate with an associated depth value of the source camera into a 2d pixel coordinate of the target camera + * + * @param[in] source_intrinsic Source intrinsic parameters + * @param[in] source_distortion Source distortion parameters + * @param[in] source_point2f Source 2d point value + * @param[in] source_depth_pixel_value The depth of sourcePoint2f in millimeters + * @param[in] target_intrinsic Target intrinsic parameters + * @param[in] target_distortion Target distortion parameters + * @param[in] extrinsic Transformation matrix from source to target + * @param[out] target_point2f Target 2d point value + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool Transform result + */ +OB_EXPORT bool ob_transformation_2d_to_2d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic, + const OBCameraDistortion source_distortion, const OBCameraIntrinsic target_intrinsic, + const OBCameraDistortion target_distortion, OBExtrinsic extrinsic, OBPoint2f *target_point2f, ob_error **error); + +// \deprecated This function is deprecated and will be removed in a future version. +OB_EXPORT ob_frame *transformation_depth_frame_to_color_camera(ob_device *device, ob_frame *depth_frame, uint32_t target_color_camera_width, + uint32_t target_color_camera_height, ob_error **error); + +// \deprecated This function is deprecated and will be removed in a future version. +OB_EXPORT bool transformation_init_xy_tables(const ob_calibration_param calibration_param, const ob_sensor_type sensor_type, float *data, uint32_t *data_size, + ob_xy_tables *xy_tables, ob_error **error); + +// \deprecated This function is deprecated and will be removed in a future version. +OB_EXPORT void transformation_depth_to_pointcloud(ob_xy_tables *xy_tables, const void *depth_image_data, void *pointcloud_data, ob_error **error); + +// \deprecated This function is deprecated and will be removed in a future version. +OB_EXPORT void transformation_depth_to_rgbd_pointcloud(ob_xy_tables *xy_tables, const void *depth_image_data, const void *color_image_data, + void *pointcloud_data, ob_error **error); + +// \deprecated This function is deprecated and will be removed in a future version. +// Use the ob_transformation_3d_to_3d instead. +OB_EXPORT bool ob_calibration_3d_to_3d(const ob_calibration_param calibration_param, const ob_point3f source_point3f, const ob_sensor_type source_sensor_type, + const ob_sensor_type target_sensor_type, ob_point3f *target_point3f, ob_error **error); + +// \deprecated This function is deprecated and will be removed in a future version. +// Use the ob_transformation_2d_to_3d instead. +OB_EXPORT bool ob_calibration_2d_to_3d(const ob_calibration_param calibration_param, const ob_point2f source_point2f, const float source_depth_pixel_value, + const ob_sensor_type source_sensor_type, const ob_sensor_type target_sensor_type, ob_point3f *target_point3f, + ob_error **error); + +// \deprecated This function is deprecated and will be removed in a future version. +// Use the ob_transformation_3d_to_2d instead. +OB_EXPORT bool ob_calibration_3d_to_2d(const ob_calibration_param calibration_param, const ob_point3f source_point3f, const ob_sensor_type source_sensor_type, + const ob_sensor_type target_sensor_type, ob_point2f *target_point2f, ob_error **error); + +// \deprecated This function is deprecated and will be removed in a future version. +// Use the ob_transformation_2d_to_2d instead. +OB_EXPORT bool ob_calibration_2d_to_2d(const ob_calibration_param calibration_param, const ob_point2f source_point2f, const float source_depth_pixel_value, + const ob_sensor_type source_sensor_type, const ob_sensor_type target_sensor_type, ob_point2f *target_point2f, + ob_error **error); +/** + * @brief save point cloud to ply file. + * + * @param[in] file_name Point cloud save path + * @param[in] frame Point cloud frame + * @param[in] save_binary Binary or textual,true: binary, false: textual + * @param[in] use_mesh Save mesh or not, true: save as mesh, false: not save as mesh + * @param[in] mesh_threshold Distance threshold for creating faces in point cloud,default value :50 + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool save point cloud result + */ +OB_EXPORT bool ob_save_pointcloud_to_ply(const char *file_name, ob_frame *frame, bool save_binary, bool use_mesh, float mesh_threshold, ob_error **error); + +/** + * @brief save LiDAR point cloud to ply file. + * + * @param[in] file_name Point cloud save path + * @param[in] frame LiDAR point cloud frame + * @param[in] save_binary Binary or textual,true: binary, false: textual + * @param[out] error Pointer to an error object that will be set if an error occurs. + * + * @return bool save LiDAR point cloud result + */ +OB_EXPORT bool ob_save_lidar_pointcloud_to_ply(const char *file_name, ob_frame *frame, bool save_binary, ob_error **error); +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Version.h b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Version.h new file mode 100644 index 0000000..c5e3dc8 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/h/Version.h @@ -0,0 +1,56 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Version.h + * @brief Functions for retrieving the SDK version number information. + * + */ +#pragma once + +#include "Export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get the SDK version number. + * + * @return int The SDK version number. + */ +OB_EXPORT int ob_get_version(void); + +/** + * @brief Get the SDK major version number. + * + * @return int The SDK major version number. + */ +OB_EXPORT int ob_get_major_version(void); + +/** + * @brief Get the SDK minor version number. + * + * @return int The SDK minor version number. + */ +OB_EXPORT int ob_get_minor_version(void); + +/** + * @brief Get the SDK patch version number. + * + * @return int The SDK patch version number. + */ +OB_EXPORT int ob_get_patch_version(void); + +/** + * @brief Get the SDK stage version. + * + * @attention The returned char* does not need to be freed. + * + * @return const char* The SDK stage version. + */ +OB_EXPORT const char *ob_get_stage_version(void); + +#ifdef __cplusplus +} +#endif diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Context.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Context.hpp new file mode 100644 index 0000000..5c65605 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Context.hpp @@ -0,0 +1,359 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Context.hpp + * @brief The SDK context class, which serves as the entry point to the underlying SDK. It is used to query device lists, handle device callbacks, and set the + * log level. + * + */ +#pragma once + +#include "libobsensor/h/Context.h" +#include "Types.hpp" +#include "Error.hpp" + +#include +#include +#include +#include +#include + +namespace ob { + +// forward declarations +class Device; +class DeviceInfo; +class DeviceList; + +class Context { +public: + /** + * @brief Type definition for the device changed callback function. + * + * @param[in] removedList The list of removed devices. + * @param[in] addedList The list of added devices. + */ + typedef std::function removedList, std::shared_ptr addedList)> DeviceChangedCallback; + + /** + * @brief Type definition for the log output callback function. + * + * @param[in] severity The current callback log level. + * @param[in] logMsg The log message. + */ + typedef std::function LogCallback; + + struct DeviceChangedCallbackContext { + Context *ctx; + uint64_t callbackId; + DeviceChangedCallback callback; + }; + +private: + ob_context *impl_ = nullptr; + std::mutex callbackMtx_; + + std::mutex legacyCallbackMtx_; + OBCallbackId legacyCallbackId_ = INVALID_CALLBACK_ID; + + std::unordered_map> devChangedCallbacks_; + // static LogCallback logCallback_; + +public: + /** + * @brief Context constructor. + * @brief The Context class is a management class that describes the runtime of the SDK. It is responsible for applying and releasing resources for the SDK. + * The context has the ability to manage multiple devices, enumerate devices, monitor device callbacks, and enable functions such as multi-device + * synchronization. + * + * @param[in] configPath The path to the configuration file. If the path is empty, the default configuration will be used. + */ + explicit Context(const char *configPath = "") { + ob_error *error = nullptr; + impl_ = ob_create_context_with_config(configPath, &error); + Error::handle(&error); + } + + /** + * @brief Context destructor. + */ + ~Context() noexcept { + // delete contex of C API, which will auto unregister all callbacks + ob_error *error = nullptr; + ob_delete_context(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Queries the enumerated device list. + * + * @return std::shared_ptr A pointer to the device list class. + */ + std::shared_ptr queryDeviceList() const { + ob_error *error = nullptr; + auto list = ob_query_device_list(impl_, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief enable or disable net device enumeration. + * @brief after enable, the net device will be discovered automatically and can be retrieved by @ref queryDeviceList. The default state can be set in the + * configuration file. + * + * @attention Net device enumeration by gvcp protocol, if the device is not in the same subnet as the host, it will be discovered but cannot be connected. + * + * @param[in] enable true to enable, false to disable + */ + void enableNetDeviceEnumeration(bool enable) const { + ob_error *error = nullptr; + ob_enable_net_device_enumeration(impl_, enable, &error); + Error::handle(&error); + } + + /** + * @brief "Force" a static IP address configuration in a device identified by its MAC Address. + * + * @param[in] macAddress MAC address of the network device. + * You can obtain it from @ref ob_device_info_get_uid, or specify it manually + * in the format xx:xx:xx:xx:xx:xx, where each xx is a two-digit hexadecimal value. + * @param[in] config The new IP configuration. + * @return bool true if the configuration command was processed successfully, false otherwise. + * + * @note This applies to all GigE Vision devices + */ + bool forceIp(const char *macAddress, const OBNetIpConfig &config) { + ob_error *error = nullptr; + auto res = ob_force_ip_config(macAddress, config, &error); + Error::handle(&error); + return res; + } + + /** + * @brief Creates a network device with the specified IP address and port. + * + * @param[in] address The IP address, ipv4 only. such as "192.168.1.10" + * @param[in] port The port number, currently only support 8090 + * @param[in] accessMode Device access mode. @ref ob_device_access_mode. + * If the device does not support setting the Access Mode, the default OB_DEVICE_DEFAULT_ACCESS is used. + * Applies only on first device creation or after release and re-creation; subsequent calls ignore it. + * + * @return std::shared_ptr The created device object. + */ + std::shared_ptr createNetDevice(const char *address, uint16_t port, OBDeviceAccessMode accessMode = OB_DEVICE_DEFAULT_ACCESS) const { + ob_error *error = nullptr; + auto device = ob_create_net_device_ex(impl_, address, port, accessMode, &error); + Error::handle(&error); + return std::make_shared(device); + } + + /** + * @brief Set the device plug-in callback function. + * + * @deprecated This function is deprecated. Please use registerDeviceChangedCallback() instead. + * + * @attention This function supports multiple callbacks. Each call to this function adds a new callback to an internal list. + * + * @param[in] callback The function triggered when the device is plugged and unplugged. + */ + void setDeviceChangedCallback(DeviceChangedCallback callback) { + std::lock_guard lock(legacyCallbackMtx_); + // remove the last callback first + if(legacyCallbackId_ != INVALID_CALLBACK_ID) { + unregisterDeviceChangedCallback(legacyCallbackId_); + } + // register the new callback + legacyCallbackId_ = registerDeviceChangedCallback(callback); + } + + OBCallbackId registerDeviceChangedCallback(DeviceChangedCallback callback) { + ob_error *error = nullptr; + auto cbCtxHolder = std::unique_ptr(new DeviceChangedCallbackContext({ this, 0, nullptr })); + auto id = ob_register_device_changed_callback(impl_, &Context::deviceChangedCallback, (void *)cbCtxHolder.get(), &error); + Error::handle(&error); + + cbCtxHolder->callbackId = id; + cbCtxHolder->callback = callback; + { + std::unique_lock lock(callbackMtx_); + devChangedCallbacks_[id] = std::move(cbCtxHolder); + } + return id; + } + + void unregisterDeviceChangedCallback(OBCallbackId id) { + ob_error *error = nullptr; + ob_unregister_device_changed_callback(impl_, id, &error); + { + std::unique_lock lock(callbackMtx_); + if(devChangedCallbacks_.count(id)) { + devChangedCallbacks_.erase(id); + } + } + Error::handle(&error); + } + + /** + * @brief Activates device clock synchronization to synchronize the clock of the host and all created devices (if supported). + * + * @param[in] repeatIntervalMsec The interval for auto-repeated synchronization, in milliseconds. If the value is 0, synchronization is performed only once. + */ + void enableDeviceClockSync(uint64_t repeatIntervalMsec) const { + ob_error *error = nullptr; + ob_enable_device_clock_sync(impl_, repeatIntervalMsec, &error); + Error::handle(&error); + } + + /** + * @brief Frees idle memory from the internal frame memory pool. + * @brief The SDK includes an internal frame memory pool that caches memory allocated for frames received from devices. + */ + void freeIdleMemory() const { + ob_error *error = nullptr; + ob_free_idle_memory(impl_, &error); + Error::handle(&error); + } + + /** + * @brief For linux, there are two ways to enable the UVC backend: libuvc and v4l2. This function is used to set the backend type. + * @brief It is effective when the new device is created. + * + * @attention This interface is only available for Linux. + * + * @param[in] type The backend type to be used. + */ + void setUvcBackendType(OBUvcBackendType type) const { + ob_error *error = nullptr; + ob_set_uvc_backend_type(impl_, type, &error); + Error::handle(&error); + } + + /** + * @brief Set the level of the global log, which affects both the log level output to the console, output to the file and output the user defined + * callback. + * + * @param[in] severity The log output level. + */ + static void setLoggerSeverity(OBLogSeverity severity) { + ob_error *error = nullptr; + ob_set_logger_severity(severity, &error); + Error::handle(&error); + } + + /** + * @brief Set log output to a file. + * + * @param[in] severity The log level output to the file. + * @param[in] directory The log file output path. If the path is empty, the existing settings will continue to be used (if the existing configuration is + * also empty, the log will not be output to the file). + */ + static void setLoggerToFile(OBLogSeverity severity, const char *directory) { + ob_error *error = nullptr; + ob_set_logger_to_file(severity, directory, &error); + Error::handle(&error); + } + + /** + * @brief Set the log file name for file output + * + * @param[in] fileName Log file name. Must not be empty. + * + * @note Other settings, such as log level and output directory, remain unchanged. + */ + static void setLoggerFileName(const std::string &fileName) { + ob_error *error = nullptr; + ob_set_logger_file_name(fileName.c_str(), &error); + Error::handle(&error); + } + + /** + * @brief Set log output to the console. + * + * @param[in] severity The log level output to the console. + */ + static void setLoggerToConsole(OBLogSeverity severity) { + ob_error *error = nullptr; + ob_set_logger_to_console(severity, &error); + Error::handle(&error); + } + + /** + * @brief Set the logger to callback. + * + * @param[in] severity The callback log level. + * @param[in] callback The callback function. + */ + static void setLoggerToCallback(OBLogSeverity severity, LogCallback callback) { + ob_error *error = nullptr; + Context::getLogCallback() = callback; + ob_set_logger_to_callback(severity, &Context::logCallback, &Context::getLogCallback(), &error); + Error::handle(&error); + } + + /** + * @brief Logs a message with severity, file, function, and line info. + * + * @param severity Log level, see @ref OBLogSeverity for details + * @param module The module or component the log belongs to + * @param message Message string to log + * @param file Source file name, e.g., __FILE__ + * @param func Function name, e.g., __func__ + * @param line Line number, e.g., __LINE__ + */ + static void logExternalMessage(OBLogSeverity severity, const std::string &module, const std::string &message, const std::string &file, + const std::string &func, int line) { + ob_error *error = nullptr; + ob_log_external_message(severity, module.c_str(), message.c_str(), file.c_str(), func.c_str(), line, &error); + Error::handle(&error); + } + + /** + * @brief Set the extensions directory + * @brief The extensions directory is used to search for dynamic libraries that provide additional functionality to the SDK, such as the Frame filters. + * + * @attention Should be called before creating the context and pipeline, otherwise the default extensions directory (./extensions) will be used. + * + * @param[in] directory Path to the extensions directory. If the path is empty, the existing settings will continue to be used (if the existing + */ + static void setExtensionsDirectory(const char *directory) { + ob_error *error = nullptr; + ob_set_extensions_directory(directory, &error); + Error::handle(&error); + } + +private: + static void deviceChangedCallback(ob_device_list *removedList, ob_device_list *addedList, void *userData) { + auto cbCtx = static_cast(userData); + if(cbCtx && cbCtx->ctx && cbCtx->callbackId != INVALID_CALLBACK_ID) { + DeviceChangedCallback callbackCopy; + { + // preventing the captured variables from being released. + std::unique_lock lock(cbCtx->ctx->callbackMtx_); + if(cbCtx->ctx->devChangedCallbacks_.count(cbCtx->callbackId)) { + callbackCopy = cbCtx->callback; + } + } + auto removed = std::make_shared(removedList); + auto added = std::make_shared(addedList); + callbackCopy(removed, added); + } + } + + static void logCallback(OBLogSeverity severity, const char *logMsg, void *userData) { + auto cb = static_cast(userData); + if(cb) { + (*cb)(severity, logMsg); + } + } + + // Lazy initialization of the logcallback_. The purpose is to initialize logcallback_ in .hpp + static LogCallback &getLogCallback() { + static LogCallback logCallback_ = nullptr; + return logCallback_; + } + +// for backward compatibility +#define enableMultiDeviceSync enableDeviceClockSync +}; +} // namespace ob diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Device.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Device.hpp new file mode 100644 index 0000000..a7000ca --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Device.hpp @@ -0,0 +1,1712 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Device.hpp + * @brief Device related types, including operations such as getting and creating a device, setting and obtaining device attributes, and obtaining sensors + * + */ +#pragma once +#include "Types.hpp" + +#include "libobsensor/h/Property.h" +#include "libobsensor/h/Device.h" +#include "libobsensor/h/Advanced.h" +#include "libobsensor/hpp/Filter.hpp" +#include "libobsensor/hpp/Sensor.hpp" + +#include "Error.hpp" +#include +#include +#include +#include +#include + +namespace ob { + +class DeviceInfo; +class SensorList; +class DevicePresetList; +class OBDepthWorkModeList; +class CameraParamList; +class DeviceFrameInterleaveList; +class PresetResolutionConfigList; + +class Device { +public: + /** + * @brief Callback function for device firmware update progress + * + * @param[in] state The device firmware update status. + * @param[in] message Status information. + * @param[in] percent The percentage of the update progress. + */ + typedef std::function DeviceFwUpdateCallback; + + /** + * @brief Callback function for device status updates. + * + * @param[in] state The device status. + * @param[in] message Status information. + */ + typedef std::function DeviceStateChangedCallback; + +protected: + ob_device *impl_ = nullptr; + DeviceStateChangedCallback deviceStateChangeCallback_; + DeviceFwUpdateCallback fwUpdateCallback_; + +public: + /** + * @brief Describe the entity of the RGBD camera, representing a specific model of RGBD camera + */ + explicit Device(ob_device_t *impl) : impl_(impl) {} + + Device(Device &&other) noexcept : impl_(other.impl_) { + other.impl_ = nullptr; + } + + Device &operator=(Device &&other) noexcept { + if(this != &other) { + ob_error *error = nullptr; + ob_delete_device(impl_, &error); + Error::handle(&error); + impl_ = other.impl_; + other.impl_ = nullptr; + } + return *this; + } + + Device(const Device &) = delete; + Device &operator=(const Device &) = delete; + + virtual ~Device() noexcept { + ob_error *error = nullptr; + ob_delete_device(impl_, &error); + Error::handle(&error, false); + } + + ob_device_t *getImpl() const { + return impl_; + } + + /** + * @brief Get device information + * + * @return std::shared_ptr return device information + */ + std::shared_ptr getDeviceInfo() const { + ob_error *error = nullptr; + auto info = ob_device_get_device_info(impl_, &error); + Error::handle(&error); + return std::make_shared(info); + } + + /** + * @brief Check if the extension information is exist + * + * @param[in] infoKey The key of the extension information + * + * @return bool Whether the extension information exists + */ + bool isExtensionInfoExist(const std::string &infoKey) const { + ob_error *error = nullptr; + auto exist = ob_device_is_extension_info_exist(impl_, infoKey.c_str(), &error); + Error::handle(&error); + return exist; + } + + /** + * @brief Get information about extensions obtained from SDK supported by the device + * + * @param[in] infoKey The key of the extension information + * + * @return const char* Returns extended information about the device + */ + const char *getExtensionInfo(const std::string &infoKey) const { + ob_error *error = nullptr; + const char *info = ob_device_get_extension_info(impl_, infoKey.c_str(), &error); + Error::handle(&error); + return info; + } + + /** + * @brief Get device sensor list + * + * @return std::shared_ptr return the sensor list + */ + std::shared_ptr getSensorList() const { + ob_error *error = nullptr; + auto list = ob_device_get_sensor_list(impl_, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief Get specific type of sensor + * if device not open, SDK will automatically open the connected device and return to the instance + * + * @return std::shared_ptr return the sensor example, if the device does not have the device,return nullptr + */ + std::shared_ptr getSensor(OBSensorType type) const { + ob_error *error = nullptr; + auto sensor = ob_device_get_sensor(impl_, type, &error); + Error::handle(&error); + return std::make_shared(sensor); + } + + /** + * @brief Set int type of device property + * + * @param[in] propertyId Property id + * @param[in] value Property value to be set + */ + void setIntProperty(OBPropertyID propertyId, int32_t value) const { + ob_error *error = nullptr; + ob_device_set_int_property(impl_, propertyId, value, &error); + Error::handle(&error); + } + + /** + * @brief Set float type of device property + * + * @param[in] propertyId Property id + * @param[in] value Property value to be set + */ + void setFloatProperty(OBPropertyID propertyId, float value) const { + ob_error *error = nullptr; + ob_device_set_float_property(impl_, propertyId, value, &error); + Error::handle(&error); + } + + /** + * @brief Set bool type of device property + * + * @param[in] propertyId Property id + * @param[in] value Property value to be set + */ + void setBoolProperty(OBPropertyID propertyId, bool value) const { + ob_error *error = nullptr; + ob_device_set_bool_property(impl_, propertyId, value, &error); + Error::handle(&error); + } + + /** + * @brief Get int type of device property + * + * @param[in] propertyId Property id + * + * @return int32_t Property to get + */ + int32_t getIntProperty(OBPropertyID propertyId) const { + ob_error *error = nullptr; + auto value = ob_device_get_int_property(impl_, propertyId, &error); + Error::handle(&error); + return value; + } + + /** + * @brief Get float type of device property + * + * @param[in] propertyId Property id + * + * @return float Property to get + */ + float getFloatProperty(OBPropertyID propertyId) const { + ob_error *error = nullptr; + auto value = ob_device_get_float_property(impl_, propertyId, &error); + Error::handle(&error); + return value; + } + + /** + * @brief Get bool type of device property + * + * @param[in] propertyId Property id + * + * @return bool Property to get + */ + bool getBoolProperty(OBPropertyID propertyId) const { + ob_error *error = nullptr; + auto value = ob_device_get_bool_property(impl_, propertyId, &error); + Error::handle(&error); + return value; + } + + /** + * @brief Get int type device property range (including current value and default value) + * + * @param[in] propertyId Property id + * + * @return OBIntPropertyRange Property range + */ + OBIntPropertyRange getIntPropertyRange(OBPropertyID propertyId) const { + ob_error *error = nullptr; + auto range = ob_device_get_int_property_range(impl_, propertyId, &error); + Error::handle(&error); + return range; + } + + /** + * @brief Get float type device property range((including current value and default value) + * + * @param[in] propertyId Property id + * + * @return OBFloatPropertyRange Property range + */ + OBFloatPropertyRange getFloatPropertyRange(OBPropertyID propertyId) const { + ob_error *error = nullptr; + auto range = ob_device_get_float_property_range(impl_, propertyId, &error); + Error::handle(&error); + return range; + } + + /** + * @brief Get bool type device property range (including current value and default value) + * + * @param[in] propertyId The ID of the property + * + * @return OBBoolPropertyRange The range of the property + */ + OBBoolPropertyRange getBoolPropertyRange(OBPropertyID propertyId) const { + ob_error *error = nullptr; + auto range = ob_device_get_bool_property_range(impl_, propertyId, &error); + Error::handle(&error); + return range; + } + + /** + * @brief Set the structured data type of a device property + * + * @param[in] propertyId The ID of the property + * @param[in] data The data to set + * @param[in] dataSize The size of the data to set + */ + void setStructuredData(OBPropertyID propertyId, const uint8_t *data, uint32_t dataSize) const { + ob_error *error = nullptr; + ob_device_set_structured_data(impl_, propertyId, data, dataSize, &error); + Error::handle(&error); + } + + /** + * @brief Get the structured data type of a device property + * + * @param[in] propertyId The ID of the property + * @param[out] data The property data obtained + * @param[out] dataSize The size of the data obtained + */ + void getStructuredData(OBPropertyID propertyId, uint8_t *data, uint32_t *dataSize) const { + ob_error *error = nullptr; + ob_device_get_structured_data(impl_, propertyId, data, dataSize, &error); + Error::handle(&error); + } + + /** + * @brief Set the customer data type of a device property + * + * @param[in] data The data to set + * @param[in] dataSize The size of the data to set,the maximum length cannot exceed 65532 bytes. + */ + void writeCustomerData(const void *data, uint32_t dataSize) { + ob_error *error = nullptr; + ob_device_write_customer_data(impl_, data, dataSize, &error); + Error::handle(&error); + } + + /** + * @brief Get the customer data type of a device property + * + * @param[in] data The property data obtained + * @param[in] dataSize The size of the data obtained + */ + void readCustomerData(void *data, uint32_t *dataSize) { + ob_error *error = nullptr; + ob_device_read_customer_data(impl_, data, dataSize, &error); + Error::handle(&error); + } + + /** + * @brief Get the number of properties supported by the device + * + * @return The number of supported properties + */ + int getSupportedPropertyCount() const { + ob_error *error = nullptr; + auto count = ob_device_get_supported_property_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get the supported properties of the device + * + * @param[in] index The index of the property + * + * @return The type of supported property + */ + OBPropertyItem getSupportedProperty(uint32_t index) const { + ob_error *error = nullptr; + auto item = ob_device_get_supported_property_item(impl_, index, &error); + Error::handle(&error); + return item; + } + + /** + * @brief Check if a property permission is supported + * + * @param[in] propertyId The ID of the property + * @param[in] permission The read and write permissions to check + * + * @return Whether the property permission is supported + */ + bool isPropertySupported(OBPropertyID propertyId, OBPermissionType permission) const { + ob_error *error = nullptr; + auto result = ob_device_is_property_supported(impl_, propertyId, permission, &error); + Error::handle(&error); + return result; + } + + /** + * @brief Check if the global timestamp is supported for the device + * + * @return Whether the global timestamp is supported + */ + bool isGlobalTimestampSupported() const { + ob_error *error = nullptr; + auto result = ob_device_is_global_timestamp_supported(impl_, &error); + Error::handle(&error); + return result; + } + + /** + * @brief Enable or disable the global timestamp + * + * @param[in] enable Whether to enable the global timestamp + */ + void enableGlobalTimestamp(bool enable) { + ob_error *error = nullptr; + ob_device_enable_global_timestamp(impl_, enable, &error); + Error::handle(&error); + } + + /** + * @brief Update the device firmware + * + * @param[in] filePath Firmware path + * @param[in] callback Firmware Update progress and status callback + * @param[in] async Whether to execute asynchronously + */ + void updateFirmware(const char *filePath, DeviceFwUpdateCallback callback, bool async = true) { + ob_error *error = nullptr; + fwUpdateCallback_ = callback; + ob_device_update_firmware(impl_, filePath, &Device::firmwareUpdateCallback, async, this, &error); + Error::handle(&error); + } + + /** + * @brief Update the device firmware from data + * + * @param[in] firmwareData Firmware data + * @param[in] firmwareDataSize Firmware data size + * @param[in] callback Firmware Update progress and status callback + * @param[in] async Whether to execute asynchronously + */ + void updateFirmwareFromData(const uint8_t *firmwareData, uint32_t firmwareDataSize, DeviceFwUpdateCallback callback, bool async = true) { + ob_error *error = nullptr; + fwUpdateCallback_ = callback; + ob_device_update_firmware_from_data(impl_, firmwareData, firmwareDataSize, &Device::firmwareUpdateCallback, async, this, &error); + Error::handle(&error); + } + + /** + * @brief Update the device optional depth presets + * + * @param[in] filePathList A list(2D array) of preset file paths, each up to OB_PATH_MAX characters. + * @param[in] pathCount The number of the preset file paths. + * @param[in] callback Preset update progress and status callback + */ + void updateOptionalDepthPresets(const char filePathList[][OB_PATH_MAX], uint8_t pathCount, DeviceFwUpdateCallback callback) { + ob_error *error = nullptr; + fwUpdateCallback_ = callback; + ob_device_update_optional_depth_presets(impl_, filePathList, pathCount, &Device::firmwareUpdateCallback, this, &error); + Error::handle(&error); + } + + /** + * @brief Set the device state changed callbacks + * + * @param[in] callback The callback function that is triggered when the device status changes (for example, the frame rate is automatically reduced or the + * stream is closed due to high temperature, etc.) + */ + void setDeviceStateChangedCallback(DeviceStateChangedCallback callback) { + ob_error *error = nullptr; + deviceStateChangeCallback_ = callback; + ob_device_set_state_changed_callback(impl_, &Device::deviceStateChangedCallback, this, &error); + Error::handle(&error); + } + + static void deviceStateChangedCallback(OBDeviceState state, const char *message, void *userData) { + auto device = static_cast(userData); + device->deviceStateChangeCallback_(state, message); + } + + /** + * @brief Get current depth work mode + * + * @return ob_depth_work_mode Current depth work mode + */ + OBDepthWorkMode getCurrentDepthWorkMode() const { + ob_error *error = nullptr; + auto mode = ob_device_get_current_depth_work_mode(impl_, &error); + Error::handle(&error); + return mode; + } + + /** + * @brief Get current depth mode name + * @brief According the current preset name to return current depth mode name + * + * @return const char* return the current depth mode name. + */ + const char *getCurrentDepthModeName() { + ob_error *error = nullptr; + auto name = ob_device_get_current_depth_work_mode_name(impl_, &error); + Error::handle(&error); + return name; + } + + /** + * @brief Switch depth work mode by OBDepthWorkMode. Prefer invoke switchDepthWorkMode(const char *modeName) to switch depth mode + * when known the complete name of depth work mode. + * @param[in] workMode Depth work mode come from ob_depth_work_mode_list which return by ob_device_get_depth_work_mode_list + */ + OBStatus switchDepthWorkMode(const OBDepthWorkMode &workMode) const { + ob_error *error = nullptr; + auto status = ob_device_switch_depth_work_mode(impl_, &workMode, &error); + Error::handle(&error); + return status; + } + + /** + * @brief Switch depth work mode by work mode name. + * + * @param[in] modeName Depth work mode name which equals to OBDepthWorkMode.name + */ + OBStatus switchDepthWorkMode(const char *modeName) const { + ob_error *error = nullptr; + auto status = ob_device_switch_depth_work_mode_by_name(impl_, modeName, &error); + Error::handle(&error); + return status; + } + + /** + * @brief Request support depth work mode list + * + * @return OBDepthWorkModeList list of ob_depth_work_mode + */ + std::shared_ptr getDepthWorkModeList() const { + ob_error *error = nullptr; + auto list = ob_device_get_depth_work_mode_list(impl_, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief Device restart + * @attention The device will be disconnected and reconnected. After the device is disconnected, the access to the Device object interface may be abnormal. + * Please delete the object directly and obtain it again after the device is reconnected. + */ + void reboot() const { + ob_error *error = nullptr; + ob_device_reboot(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Device restart delay mode + * @attention The device will be disconnected and reconnected. After the device is disconnected, the access to the Device object interface may be abnormal. + * Please delete the object directly and obtain it again after the device is reconnected. + * Support devices: Gemini2 L + * + * @param[in] delayMs Time unit: ms. delayMs == 0: No delay; delayMs > 0, Delay millisecond connect to host device after reboot + */ + void reboot(uint32_t delayMs) const { + setIntProperty(OB_PROP_DEVICE_REBOOT_DELAY_INT, delayMs); + reboot(); + } + + /** + * @brief Enable or disable the device heartbeat. + * @brief After enable the device heartbeat, the sdk will start a thread to send heartbeat signal to the device error every 3 seconds. + * + * @attention If the device does not receive the heartbeat signal for a long time, it will be disconnected and rebooted. + * + * @param[in] enable Whether to enable the device heartbeat. + */ + void enableHeartbeat(bool enable) const { + ob_error *error = nullptr; + ob_device_enable_heartbeat(impl_, enable, &error); + Error::handle(&error); + } + + /** + * @brief Get the supported multi device sync mode bitmap of the device. + * @brief For example, if the return value is 0b00001100, it means the device supports @ref OB_MULTI_DEVICE_SYNC_MODE_PRIMARY and @ref + * OB_MULTI_DEVICE_SYNC_MODE_SECONDARY. User can check the supported mode by the code: + * ```c + * if(supported_mode_bitmap & OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN){ + * //support OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN + * } + * if(supported_mode_bitmap & OB_MULTI_DEVICE_SYNC_MODE_STANDALONE){ + * //support OB_MULTI_DEVICE_SYNC_MODE_STANDALONE + * } + * // and so on + * ``` + * @return uint16_t return the supported multi device sync mode bitmap of the device. + */ + uint16_t getSupportedMultiDeviceSyncModeBitmap() const { + ob_error *error = nullptr; + auto mode = ob_device_get_supported_multi_device_sync_mode_bitmap(impl_, &error); + Error::handle(&error); + return mode; + } + + /** + * @brief set the multi device sync configuration of the device. + * + * @param[in] config The multi device sync configuration. + */ + void setMultiDeviceSyncConfig(const OBMultiDeviceSyncConfig &config) const { + ob_error *error = nullptr; + ob_device_set_multi_device_sync_config(impl_, &config, &error); + Error::handle(&error); + } + + /** + * @brief get the multi device sync configuration of the device. + * + * @return OBMultiDeviceSyncConfig return the multi device sync configuration of the device. + */ + OBMultiDeviceSyncConfig getMultiDeviceSyncConfig() const { + ob_error *error = nullptr; + auto config = ob_device_get_multi_device_sync_config(impl_, &error); + Error::handle(&error); + return config; + } + + /** + * @brief send the capture command to the device. + * @brief The device will start one time image capture after receiving the capture command when it is in the @ref + * OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING + * + * @attention The frequency of the user call this function multiplied by the number of frames per trigger should be less than the frame rate of the stream. + * The number of frames per trigger can be set by @ref OBMultiDeviceSyncConfig::framesPerTrigger. + * @attention For some models, receive and execute the capture command will have a certain delay and performance consumption, so the frequency of calling + * this function should not be too high, please refer to the product manual for the specific supported frequency. + * @attention If the device is not in the @ref OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING mode, device will ignore the capture command. + */ + void triggerCapture() const { + ob_error *error = nullptr; + ob_device_trigger_capture(impl_, &error); + Error::handle(&error); + } + + /** + * @brief set the timestamp reset configuration of the device. + */ + void setTimestampResetConfig(const OBDeviceTimestampResetConfig &config) const { + ob_error *error = nullptr; + ob_device_set_timestamp_reset_config(impl_, &config, &error); + Error::handle(&error); + } + + /** + * @brief get the timestamp reset configuration of the device. + * + * @return OBDeviceTimestampResetConfig return the timestamp reset configuration of the device. + */ + OBDeviceTimestampResetConfig getTimestampResetConfig() const { + ob_error *error = nullptr; + auto config = ob_device_get_timestamp_reset_config(impl_, &error); + Error::handle(&error); + return config; + } + + /** + * @brief send the timestamp reset command to the device. + * @brief The device will reset the timer for calculating the timestamp for output frames to 0 after receiving the timestamp reset command when the + * timestamp reset function is enabled. The timestamp reset function can be enabled by call @ref ob_device_set_timestamp_reset_config. + * @brief Before calling this function, user should call @ref ob_device_set_timestamp_reset_config to disable the timestamp reset function (It is not + * required for some models, but it is still recommended to do so for code compatibility). + * + * @attention If the stream of the device is started, the timestamp of the continuous frames output by the stream will jump once after the timestamp reset. + * @attention Due to the timer of device is not high-accuracy, the timestamp of the continuous frames output by the stream will drift after a long time. + * User can call this function periodically to reset the timer to avoid the timestamp drift, the recommended interval time is 60 minutes. + */ + void timestampReset() const { + ob_error *error = nullptr; + ob_device_timestamp_reset(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Alias for @ref timestampReset() since it is more accurate. + */ + inline void timerReset() const { + timestampReset(); + } + + /** + * @brief synchronize the timer of the device with the host. + * @brief After calling this function, the timer of the device will be synchronized with the host. User can call this function to multiple devices to + * synchronize all timers of the devices. + * + * @attention If the stream of the device is started, the timestamp of the continuous frames output by the stream will may jump once after the timer + * sync. + * @attention Due to the timer of device is not high-accuracy, the timestamp of the continuous frames output by the stream will drift after a long time. + * User can call this function periodically to synchronize the timer to avoid the timestamp drift, the recommended interval time is 60 minutes. + * + */ + void timerSyncWithHost() const { + ob_error *error = nullptr; + ob_device_timer_sync_with_host(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Get current preset name + * @brief The preset mean a set of parameters or configurations that can be applied to the device to achieve a specific effect or function. + * + * @return const char* return the current preset name, it should be one of the preset names returned by @ref getAvailablePresetList. + */ + const char *getCurrentPresetName() const { + ob_error *error = nullptr; + const char *name = ob_device_get_current_preset_name(impl_, &error); + Error::handle(&error); + return name; + } + + /** + * @brief load the preset according to the preset name. + * @attention After loading the preset, the settings in the preset will set to the device immediately. Therefore, it is recommended to re-read the device + * settings to update the user program temporarily. + * @param[in] presetName The preset name to set. The name should be one of the preset names returned by @ref getAvailablePresetList. + */ + void loadPreset(const char *presetName) const { + ob_error *error = nullptr; + ob_device_load_preset(impl_, presetName, &error); + Error::handle(&error); + } + + /** + * @brief Get available preset list + * @brief The available preset list usually defined by the device manufacturer and restores on the device. + * @brief User can load the custom preset by calling @ref loadPresetFromJsonFile to append the available preset list. + * + * @return DevicePresetList return the available preset list. + */ + std::shared_ptr getAvailablePresetList() const { + ob_error *error = nullptr; + auto list = ob_device_get_available_preset_list(impl_, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief Load custom preset from file. + * @brief After loading the custom preset, the settings in the custom preset will set to the device immediately. + * @brief After loading the custom preset, the available preset list will be appended with the custom preset and named as the file name. + * + * @attention The user should ensure that the custom preset file is adapted to the device and the settings in the file are valid. + * @attention It is recommended to re-read the device settings to update the user program temporarily after successfully loading the custom preset. + * + * @param[in] filePath The path of the custom preset file. + */ + void loadPresetFromJsonFile(const char *filePath) const { + ob_error *error = nullptr; + ob_device_load_preset_from_json_file(impl_, filePath, &error); + Error::handle(&error); + } + + /** + * @brief Load custom preset from data. + * @brief After loading the custom preset, the settings in the custom preset will set to the device immediately. + * @brief After loading the custom preset, the available preset list will be appended with the custom preset and named as the @p presetName. + * + * @attention The user should ensure that the custom preset data is adapted to the device and the settings in the data are valid. + * @attention It is recommended to re-read the device settings to update the user program temporarily after successfully loading the custom preset. + * + * @param[in] presetName The name of the custome preset. + * @param[in] data The custom preset data. + * @param[in] size The size of the custom preset data. + */ + void loadPresetFromJsonData(const char *presetName, const uint8_t *data, uint32_t size) { + ob_error *error = nullptr; + ob_device_load_preset_from_json_data(impl_, presetName, data, size, &error); + } + + /** + * @brief Export current device settings as a preset json data. + * @brief After exporting the preset, a new preset named as the @p presetName will be added to the available preset list. + * + * @attention The memory of the data is allocated by the SDK, and will automatically be released by the SDK. + * @attention The memory of the data will be reused by the SDK on the next call, so the user should copy the data to a new buffer if it needs to be + * preserved. + * + * @param[in] presetName The name of the custome preset. + * @param[out] data return the preset json data. + * @param[out] dataSize return the size of the preset json data. + */ + void exportSettingsAsPresetJsonData(const char *presetName, const uint8_t **data, uint32_t *dataSize) { + ob_error *error = nullptr; + ob_device_export_current_settings_as_preset_json_data(impl_, presetName, data, dataSize, &error); + } + + /** + * @brief Export current device settings as a preset json file. + * @brief The exported preset file can be loaded by calling @ref loadPresetFromJsonFile to restore the device setting. + * @brief After exporting the preset, a new preset named as the @p filePath will be added to the available preset list. + * + * @param[in] filePath The path of the preset file to be exported. + */ + void exportSettingsAsPresetJsonFile(const char *filePath) const { + ob_error *error = nullptr; + ob_device_export_current_settings_as_preset_json_file(impl_, filePath, &error); + Error::handle(&error); + } + + /** + * @brief Get the current device status. + * + * @return OBDeviceState The device state information. + */ + OBDeviceState getDeviceState() { + OBDeviceState state = {}; + ob_error *error = nullptr; + state = ob_device_get_device_state(impl_, &error); + return state; + } + + /** + * @brief Send data to the device and receive data from the device. + * @brief This is a factory and debug function, which can be used to send and receive data from the device. The data format is secret and belongs to the + * device vendor. + * + * @attention The send and receive data buffer are managed by the caller, the receive data buffer should be allocated at 1024 bytes or larger. + * + * @param[in] sendData The data to be sent to the device. + * @param[in] sendDataSize The size of the data to be sent to the device. + * @param[out] receiveData The data received from the device. + * @param[in,out] receiveDataSize The requeseted size of the data received from the device, and the actual size of the data received from the device. + */ + void sendAndReceiveData(const uint8_t *sendData, uint32_t sendDataSize, uint8_t *receiveData, uint32_t *receiveDataSize) const { + ob_error *error = nullptr; + ob_device_send_and_receive_data(impl_, sendData, sendDataSize, receiveData, receiveDataSize, &error); + Error::handle(&error); + } + + /** + * @brief Check if the device supports the frame interleave feature. + * + * @return bool Returns true if the device supports the frame interleave feature. + */ + bool isFrameInterleaveSupported() const { + ob_error *error = nullptr; + bool ret = ob_device_is_frame_interleave_supported(impl_, &error); + Error::handle(&error); + return ret; + } + + /** + * @brief load the frame interleave according to frame interleave name. + * @param[in] frameInterleaveName The frame interleave name to set. The name should be one of the frame interleave names returned by @ref + * getAvailableFrameInterleaveList. + */ + void loadFrameInterleave(const char *frameInterleaveName) const { + ob_error *error = nullptr; + ob_device_load_frame_interleave(impl_, frameInterleaveName, &error); + Error::handle(&error); + } + + /** + * @brief Get available frame interleave list + * + * @return DeviceFrameInterleaveList return the available frame interleave list. + */ + std::shared_ptr getAvailableFrameInterleaveList() const { + ob_error *error = nullptr; + auto list = ob_device_get_available_frame_interleave_list(impl_, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief Get the available preset resolution config list + * + * @return PresetResolutionConfigList return the available preset resolution config list. + */ + std::shared_ptr getAvailablePresetResolutionConfigList() const { + ob_error *error = nullptr; + auto list = ob_device_get_available_preset_resolution_config_list(impl_, &error); + Error::handle(&error); + return std::make_shared(list); + } + +private: + static void firmwareUpdateCallback(ob_fw_update_state state, const char *message, uint8_t percent, void *userData) { + auto device = static_cast(userData); + if(device && device->fwUpdateCallback_) { + device->fwUpdateCallback_(state, message, percent); + } + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + void deviceUpgrade(const char *filePath, DeviceFwUpdateCallback callback, bool async = true) { + updateFirmware(filePath, callback, async); + } + + void deviceUpgradeFromData(const uint8_t *firmwareData, uint32_t firmwareDataSize, DeviceFwUpdateCallback callback, bool async = true) { + updateFirmwareFromData(firmwareData, firmwareDataSize, callback, async); + } + + std::shared_ptr getCalibrationCameraParamList() { + ob_error *error = nullptr; + auto impl = ob_device_get_calibration_camera_param_list(impl_, &error); + Error::handle(&error); + return std::make_shared(impl); + } + + void loadDepthFilterConfig(const char *filePath) { + // In order to compile, some high-version compilers will warn that the function parameters are not used. + (void)filePath; + } +}; + +/** + * @brief A class describing device information, representing the name, id, serial number and other basic information of an RGBD camera. + */ +class DeviceInfo { +private: + ob_device_info_t *impl_ = nullptr; + +public: + explicit DeviceInfo(ob_device_info_t *impl) : impl_(impl) {} + ~DeviceInfo() noexcept { + ob_error *error = nullptr; + ob_delete_device_info(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get device name + * + * @return const char * return the device name + */ + const char *getName() const { + ob_error *error = nullptr; + const char *name = ob_device_info_get_name(impl_, &error); + Error::handle(&error); + return name; + } + + /** + * @brief Get the pid of the device + * + * @return int return the pid of the device + */ + int getPid() const { + ob_error *error = nullptr; + int pid = ob_device_info_get_pid(impl_, &error); + Error::handle(&error); + return pid; + } + + /** + * @brief Get the vid of the device + * + * @return int return the vid of the device + */ + int getVid() const { + ob_error *error = nullptr; + int vid = ob_device_info_get_vid(impl_, &error); + Error::handle(&error); + return vid; + } + + /** + * @brief Get system assigned uid for distinguishing between different devices + * + * @return const char * return the uid of the device + */ + const char *getUid() const { + ob_error *error = nullptr; + const char *uid = ob_device_info_get_uid(impl_, &error); + Error::handle(&error); + return uid; + } + + /** + * @brief Get the serial number of the device + * + * @return const char * return the serial number of the device + */ + const char *getSerialNumber() const { + ob_error *error = nullptr; + const char *sn = ob_device_info_get_serial_number(impl_, &error); + Error::handle(&error); + return sn; + } + + /** + * @brief Get the version number of the firmware + * + * @return const char* return the version number of the firmware + */ + const char *getFirmwareVersion() const { + ob_error *error = nullptr; + const char *version = ob_device_info_get_firmware_version(impl_, &error); + Error::handle(&error); + return version; + } + + /** + * @brief Get the connection type of the device + * + * @return const char* the connection type of the device, currently supports: "USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", + * "USB3.2", "Ethernet" + */ + const char *getConnectionType() const { + ob_error *error = nullptr; + const char *type = ob_device_info_get_connection_type(impl_, &error); + Error::handle(&error); + return type; + } + + /** + * @brief Get the IP address of the device + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @return const char* the IP address of the device, such as "192.168.1.10" + */ + const char *getIpAddress() const { + ob_error *error = nullptr; + const char *ip = ob_device_info_get_ip_address(impl_, &error); + Error::handle(&error); + return ip; + } + + /** + * @brief Get the version number of the hardware + * + * @return const char* the version number of the hardware + */ + const char *getHardwareVersion() const { + ob_error *error = nullptr; + const char *version = ob_device_info_get_hardware_version(impl_, &error); + Error::handle(&error); + return version; + } + + /** + * @brief Get the minimum version number of the SDK supported by the device + * + * @return const char* the minimum SDK version number supported by the device + */ + const char *getSupportedMinSdkVersion() const { + ob_error *error = nullptr; + const char *version = ob_device_info_get_supported_min_sdk_version(impl_, &error); + Error::handle(&error); + return version; + } + + /** + * @brief Get chip type name + * + * @return const char* the chip type name + */ + const char *getAsicName() const { + ob_error *error = nullptr; + const char *name = ob_device_info_get_asicName(impl_, &error); + Error::handle(&error); + return name; + } + + /** + * @brief Get the device type + * + * @return OBDeviceType the device type + */ + OBDeviceType getDeviceType() const { + ob_error *error = nullptr; + OBDeviceType type = ob_device_info_get_device_type(impl_, &error); + Error::handle(&error); + return type; + } + + /** + * @brief Get the subnet mask of the device + * + * @return const char* the subnet mask of the device, such as "255.255.255.0" + */ + const char *getDeviceSubnetMask() const { + ob_error *error = nullptr; + const char *subnetMask = ob_device_info_get_subnet_mask(impl_, &error); + Error::handle(&error); + return subnetMask; + } + + /** + * @brief Get the gateway address of the device + * + * @return const char* the gateway address of the device, such as "192.168.1.1" + */ + const char *getDeviceGateway() const { + ob_error *error = nullptr; + const char *subnetMask = ob_device_info_get_gateway(impl_, &error); + Error::handle(&error); + return subnetMask; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + const char *getDevicegateway() { + return getDeviceGateway(); + } + + const char *name() const { + return getName(); + } + + int pid() const { + return getPid(); + } + + int vid() const { + return getVid(); + } + + const char *uid() const { + return getUid(); + } + + const char *serialNumber() const { + return getSerialNumber(); + } + + const char *firmwareVersion() const { + return getFirmwareVersion(); + } + + const char *connectionType() const { + return getConnectionType(); + } + + const char *ipAddress() const { + return getIpAddress(); + } + + const char *hardwareVersion() const { + return getHardwareVersion(); + } + + const char *supportedMinSdkVersion() const { + return getSupportedMinSdkVersion(); + } + + const char *asicName() const { + return getAsicName(); + } + + OBDeviceType deviceType() const { + return getDeviceType(); + } +}; + +/** + * @brief Class representing a list of devices + */ +class DeviceList { +private: + ob_device_list_t *impl_ = nullptr; + +public: + explicit DeviceList(ob_device_list_t *impl) : impl_(impl) {} + ~DeviceList() noexcept { + ob_error *error = nullptr; + ob_delete_device_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the number of devices in the list + * + * @return uint32_t the number of devices in the list + */ + uint32_t getCount() const { + ob_error *error = nullptr; + auto count = ob_device_list_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get the PID of the device at the specified index + * + * @param[in] index the index of the device + * + * @return int the PID of the device + */ + int getPid(uint32_t index) const { + ob_error *error = nullptr; + auto pid = ob_device_list_get_device_pid(impl_, index, &error); + Error::handle(&error); + return pid; + } + + /** + * @brief Get the VID of the device at the specified index + * + * @param[in] index the index of the device + * + * @return int the VID of the device + */ + int getVid(uint32_t index) const { + ob_error *error = nullptr; + auto vid = ob_device_list_get_device_vid(impl_, index, &error); + Error::handle(&error); + return vid; + } + + /** + * @brief Get the UID of the device at the specified index + * + * @param[in] index the index of the device + * + * @return const char* the UID of the device + */ + const char *getUid(uint32_t index) const { + ob_error *error = nullptr; + auto uid = ob_device_list_get_device_uid(impl_, index, &error); + Error::handle(&error); + return uid; + } + + /** + * @brief Get the serial number of the device at the specified index + * + * @param[in] index the index of the device + * + * @return const char* the serial number of the device + */ + const char *getSerialNumber(uint32_t index) const { + ob_error *error = nullptr; + auto sn = ob_device_list_get_device_serial_number(impl_, index, &error); + Error::handle(&error); + return sn; + } + + /** + * @brief Get the name of the device at the specified index in the device list. + * + * This function retrieves the name of the device at the given index in the device list. + * If an error occurs during the operation, it will be handled by the Error::handle function. + * + * @param[in] index The index of the device in the device list. + * + * @return const char* The name of the device at the specified index. + */ + const char *getName(uint32_t index) const { + ob_error *error = nullptr; + auto name = ob_device_list_get_device_name(impl_, index, &error); + Error::handle(&error); + return name; + } + + /** + * @brief Get device connection type + * + * @param[in] index device index + * + * @return const char* returns connection type, currently supports: "USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2", "Ethernet", + * "GMSL2" + */ + const char *getConnectionType(uint32_t index) const { + ob_error *error = nullptr; + auto type = ob_device_list_get_device_connection_type(impl_, index, &error); + Error::handle(&error); + return type; + } + + /** + * @brief get the ip address of the device at the specified index + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @param[in] index the index of the device + * + * @return const char* the ip address of the device + */ + const char *getIpAddress(uint32_t index) const { + ob_error *error = nullptr; + auto ip = ob_device_list_get_device_ip_address(impl_, index, &error); + Error::handle(&error); + return ip; + } + + /** + * @brief get the subnet mask of the device at the specified index + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @param[in] index the index of the device + * + * @return const char* the subnet mask of the device + */ + const char *getSubnetMask(uint32_t index) const { + ob_error *error = nullptr; + auto subnetMask = ob_device_list_get_device_subnet_mask(impl_, index, &error); + Error::handle(&error); + return subnetMask; + } + + /** + * @brief get the gateway of the device at the specified index + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @param[in] index the index of the device + * + * @return const char* the gateway of the device + */ + const char *getGateway(uint32_t index) const { + ob_error *error = nullptr; + auto gateway = ob_device_list_get_device_gateway(impl_, index, &error); + Error::handle(&error); + return gateway; + } + + /** + * @brief Get the MAC address of the host network interface corresponding to the device at the specified index + * + * @attention Only valid for network devices, otherwise it will return "0:0:0:0:0:0". + * + * @param[in] index the index of the device + * + * @return const char* The MAC address of the host network interface associated with the device. + */ + const char *getLocalMacAddress(uint32_t index) const { + ob_error *error = nullptr; + auto mac = ob_device_list_get_device_local_mac(impl_, index, &error); + Error::handle(&error); + return mac; + } + + /** + * @brief Get the IP address of the host network interface corresponding to the device at the specified index + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @param[in] index The index of the device + * + * @return const char* The IP address of the host network interface associated with the device. + */ + const char *getLocalIP(uint32_t index) const { + ob_error *error = nullptr; + auto ip = ob_device_list_get_device_local_ip(impl_, index, &error); + Error::handle(&error); + return ip; + } + + /** + * @brief Get the subnet length of the host network interface corresponding to the device at the specified index + * + * @attention Only valid for network devices, otherwise it will return 0. + * + * @param[in] index The index of the device + * + * @return uint8_t The subnet length (0~32) of the host network interface associated with the device. + */ + uint8_t getLocalSubnetLength(uint32_t index) const { + ob_error *error = nullptr; + auto subnetMask = ob_device_list_get_device_local_subnet_length(impl_, index, &error); + Error::handle(&error); + return subnetMask; + } + + /** + * @brief Get the gateway of the host network interface corresponding to the device at the specified index + * + * @attention Only valid for network devices, otherwise it will return "0.0.0.0". + * + * @param[in] index The index of the device + * + * @return const char* The gateway of the host network interface associated with the device. + */ + const char *getLocalGateway(uint32_t index) const { + ob_error *error = nullptr; + auto gateway = ob_device_list_get_device_local_gateway(impl_, index, &error); + Error::handle(&error); + return gateway; + } + + /** + * @brief Get the device object at the specified index + * + * @attention If the device has already been acquired and created elsewhere, repeated acquisition will throw an exception + * + * @param[in] index the index of the device to create + * @param[in] accessMode Device access mode. @ref ob_device_access_mode. + * If the device does not support setting the Access Mode, the default OB_DEVICE_DEFAULT_ACCESS is used. + * Applies only on first device creation or after release and re-creation; subsequent calls ignore it. + * + * @return std::shared_ptr the device object + */ + std::shared_ptr getDevice(uint32_t index, OBDeviceAccessMode accessMode = OB_DEVICE_DEFAULT_ACCESS) const { + ob_error *error = nullptr; + auto device = ob_device_list_get_device_ex(impl_, index, accessMode, &error); + Error::handle(&error); + return std::make_shared(device); + } + + /** + * @brief Get the device object with the specified serial number + * + * @attention If the device has already been acquired and created elsewhere, repeated acquisition will throw an exception + * + * @param[in] serialNumber the serial number of the device to create + * @param[in] accessMode Device access mode. @ref ob_device_access_mode. + * If the device does not support setting the Access Mode, the default OB_DEVICE_DEFAULT_ACCESS is used. + * Applies only on first device creation or after release and re-creation; subsequent calls ignore it. + * + * @return std::shared_ptr the device object + */ + std::shared_ptr getDeviceBySN(const char *serialNumber, OBDeviceAccessMode accessMode = OB_DEVICE_DEFAULT_ACCESS) const { + ob_error *error = nullptr; + auto device = ob_device_list_get_device_by_serial_number_ex(impl_, serialNumber, accessMode, &error); + Error::handle(&error); + return std::make_shared(device); + } + + /** + * @brief Get the specified device object from the device list by uid + * @brief On Linux platform, for usb device, the uid of the device is composed of bus-port-dev, for example 1-1.2-1. But the SDK will remove the dev number + * and only keep the bus-port as the uid to create the device, for example 1-1.2, so that we can create a device connected to the specified USB port. + * Similarly, users can also directly pass in bus-port as uid to create device. + * @brief For GMSL device, the uid is GMSL port with "gmsl2-" prefix, for example gmsl2-1. + * + * @attention If the device has been acquired and created elsewhere, repeated acquisition will throw an exception + * + * @param[in] uid The uid of the device to be created + * @param[in] accessMode Device access mode. @ref ob_device_access_mode. + * If the device does not support setting the Access Mode, the default OB_DEVICE_DEFAULT_ACCESS is used. + * Applies only on first device creation or after release and re-creation; subsequent calls ignore it. + * + * @return std::shared_ptr returns the device object + */ + std::shared_ptr getDeviceByUid(const char *uid, OBDeviceAccessMode accessMode = OB_DEVICE_DEFAULT_ACCESS) const { + ob_error *error = nullptr; + auto device = ob_device_list_get_device_by_uid_ex(impl_, uid, accessMode, &error); + Error::handle(&error); + return std::make_shared(device); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t deviceCount() const { + return getCount(); + } + + int pid(uint32_t index) const { + return getPid(index); + } + + int vid(uint32_t index) const { + return getVid(index); + } + + const char *uid(uint32_t index) const { + return getUid(index); + } + + const char *serialNumber(uint32_t index) const { + return getSerialNumber(index); + } + + const char *name(uint32_t index) const { + return getName(index); + } + + const char *connectionType(uint32_t index) const { + return getConnectionType(index); + } + + const char *ipAddress(uint32_t index) const { + return getIpAddress(index); + } +}; + +class OBDepthWorkModeList { +private: + ob_depth_work_mode_list_t *impl_ = nullptr; + +public: + explicit OBDepthWorkModeList(ob_depth_work_mode_list_t *impl) : impl_(impl) {} + ~OBDepthWorkModeList() { + ob_error *error = nullptr; + ob_delete_depth_work_mode_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the number of OBDepthWorkMode objects in the list + * + * @return uint32_t the number of OBDepthWorkMode objects in the list + */ + uint32_t getCount() { + ob_error *error = nullptr; + auto count = ob_depth_work_mode_list_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get the OBDepthWorkMode object at the specified index + * + * @param[in] index the index of the target OBDepthWorkMode object + * + * @return OBDepthWorkMode the OBDepthWorkMode object at the specified index + */ + OBDepthWorkMode getOBDepthWorkMode(uint32_t index) { + ob_error *error = nullptr; + auto mode = ob_depth_work_mode_list_get_item(impl_, index, &error); + Error::handle(&error); + return mode; + } + + /** + * @brief Get the OBDepthWorkMode object at the specified index + * + * @param[in] index the index of the target OBDepthWorkMode object + * + * @return OBDepthWorkMode the OBDepthWorkMode object at the specified index + */ + OBDepthWorkMode operator[](uint32_t index) { + return getOBDepthWorkMode(index); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t count() { + return getCount(); + } +}; + +/** + * @brief Class representing a list of device presets + * @brief A device preset is a set of parameters or configurations that can be applied to the device to achieve a specific effect or function. + */ +class DevicePresetList { +private: + ob_device_preset_list_t *impl_ = nullptr; + +public: + explicit DevicePresetList(ob_device_preset_list_t *impl) : impl_(impl) {} + ~DevicePresetList() noexcept { + ob_error *error = nullptr; + ob_delete_preset_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the number of device presets in the list + * + * @return uint32_t the number of device presets in the list + */ + uint32_t getCount() { + ob_error *error = nullptr; + auto count = ob_device_preset_list_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get the name of the device preset at the specified index + * + * @param[in] index the index of the device preset + * + * @return const char* the name of the device preset + */ + const char *getName(uint32_t index) { + ob_error *error = nullptr; + const char *name = ob_device_preset_list_get_name(impl_, index, &error); + Error::handle(&error); + return name; + } + + /** + * @brief check if the preset list contains the special name preset. + * @param[in] name The name of the preset + * + * @return bool Returns true if the special name is found in the preset list, otherwise returns false. + */ + bool hasPreset(const char *name) { + ob_error *error = nullptr; + auto result = ob_device_preset_list_has_preset(impl_, name, &error); + Error::handle(&error); + return result; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t count() { + return getCount(); + } +}; + +/** + * @brief Class representing a list of camera parameters + */ +class CameraParamList { +private: + ob_camera_param_list_t *impl_ = nullptr; + +public: + explicit CameraParamList(ob_camera_param_list_t *impl) : impl_(impl) {} + ~CameraParamList() noexcept { + ob_error *error = nullptr; + ob_delete_camera_param_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the number of camera parameters in the list. + * + * @return uint32_t the number of camera parameters in the list. + */ + uint32_t getCount() { + ob_error *error = nullptr; + auto count = ob_camera_param_list_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get the camera parameters for the specified index + * + * @param[in] index the index of the parameter group + * + * @return OBCameraParam the corresponding group parameters + */ + OBCameraParam getCameraParam(uint32_t index) { + ob_error *error = nullptr; + auto param = ob_camera_param_list_get_param(impl_, index, &error); + Error::handle(&error); + return param; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t count() { + return getCount(); + } +}; + +/** + * @brief Class representing a list of device Frame Interleave + */ +class DeviceFrameInterleaveList { +private: + ob_device_frame_interleave_list_t *impl_ = nullptr; + +public: + explicit DeviceFrameInterleaveList(ob_device_frame_interleave_list_t *impl) : impl_(impl) {} + ~DeviceFrameInterleaveList() noexcept { + ob_error *error = nullptr; + ob_delete_frame_interleave_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the number of device frame interleave in the list + * + * @return uint32_t the number of device frame interleave in the list + */ + uint32_t getCount() { + ob_error *error = nullptr; + auto count = ob_device_frame_interleave_list_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get the name of the device frame interleave at the specified index + * + * @param[in] index the index of the device frame interleave + * + * @return const char* the name of the device frame interleave + */ + const char *getName(uint32_t index) { + ob_error *error = nullptr; + const char *name = ob_device_frame_interleave_list_get_name(impl_, index, &error); + Error::handle(&error); + return name; + } + + /** + * @brief check if the frame interleave list contains the special name frame interleave. + * + * @param[in] name The name of the frame interleave + * + * @return bool Returns true if the special name is found in the frame interleave list, otherwise returns false. + */ + bool hasFrameInterleave(const char *name) { + ob_error *error = nullptr; + auto result = ob_device_frame_interleave_list_has_frame_interleave(impl_, name, &error); + Error::handle(&error); + return result; + } +}; + +/** + * @brief Class representing a list of preset resolution config list + */ +class PresetResolutionConfigList { +private: + ob_preset_resolution_config_list_t *impl_ = nullptr; + +public: + explicit PresetResolutionConfigList(ob_preset_resolution_config_list_t *impl) : impl_(impl) {} + ~PresetResolutionConfigList() noexcept { + ob_error *error = nullptr; + ob_delete_preset_resolution_config_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the number of device preset resolution ratio in the list + */ + uint32_t getCount() { + ob_error *error = nullptr; + auto count = ob_device_preset_resolution_config_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /* + * @brief Get the device preset resolution ratio at the specified index + + * @param[in] index the index of the device preset resolution ratio + * + * @return OBPresetResolutionConfig the corresponding device preset resolution ratio + */ + OBPresetResolutionConfig getPresetResolutionRatioConfig(uint32_t index) { + ob_error *error = nullptr; + auto config = ob_device_preset_resolution_config_list_get_item(impl_, index, &error); + Error::handle(&error); + return config; + } +}; + +} // namespace ob diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Error.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Error.hpp new file mode 100644 index 0000000..4badc11 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Error.hpp @@ -0,0 +1,116 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Error.hpp + * @brief This file defines the Error class, which describes abnormal errors within the SDK. + * Detailed information about the exception can be obtained through this class. + */ +#pragma once + +#include "Types.hpp" +#include "libobsensor/h/Error.h" +#include + +namespace ob { +class Error : public std::exception { +private: + ob_error *impl_; + + /** + * @brief Construct a new Error object + * + * @attention This constructor should not be called directly, use the handle() function instead. + * + * @param[in] error The ob_error object + */ + explicit Error(ob_error *error) : impl_(error) {}; + + Error& operator=(const Error&) = default; + +public: + /** + * @brief A static function to handle the ob_error and throw an exception if needed. + * + * @param[in,out] error The ob_error pointer to be handled. + * @param[in] throw_exception A boolean value to indicate whether to throw an exception or not, the default value is true. + */ + static void handle(ob_error **error, bool throw_exception = true) { + if(!error || !*error) { // no error + return; + } + + if(throw_exception) { + throw Error(*error); + } + else { + ob_delete_error(*error); + *error = nullptr; + } + } + + /** + * @brief Destroy the Error object + */ + ~Error() override { + if(impl_) { + ob_delete_error(impl_); + impl_ = nullptr; + } + } + + /** + * @brief Returns the error message of the exception. + * + * @return const char* The error message. + */ + const char *what() const noexcept override { + return impl_->message; + } + + /** + * @brief Returns the exception type of the exception. + * @brief Read the comments of the OBExceptionType enum in the libobsensor/h/ObTypes.h file for more information. + * + * @return OBExceptionType The exception type. + */ + OBExceptionType getExceptionType() const noexcept { + return impl_->exception_type; + } + + /** + * @brief Returns the name of the function where the exception occurred. + * + * @return const char* The function name. + */ + const char *getFunction() const noexcept { + return impl_->function; + } + + /** + * @brief Returns the arguments of the function where the exception occurred. + * + * @return const char* The arguments. + */ + const char *getArgs() const noexcept { + return impl_->args; + } + + /** + * @brief Returns the error message of the exception. + * @brief It is recommended to use the what() function instead. + * + * @return const char* The error message. + */ + const char *getMessage() const noexcept { + return impl_->message; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + const char *getName() const noexcept { + return impl_->function; + } +}; +} // namespace ob + diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Filter.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Filter.hpp new file mode 100644 index 0000000..86fd36e --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Filter.hpp @@ -0,0 +1,1557 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Filter.hpp + * @brief This file contains the Filter class, which is the processing unit of the SDK that can perform point cloud generation, format conversion, and other + * functions. + */ +#pragma once + +#include "Types.hpp" +#include "Error.hpp" +#include "Frame.hpp" +#include "libobsensor/h/Filter.h" +#include "libobsensor/h/Frame.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ob { + +/** + * @brief A callback function that takes a shared pointer to a Frame object as its argument. + */ +typedef std::function)> FilterCallback; + +/** + * @brief Get the type of a PropertyRange member + */ +template struct RangeTraits { + using valueType = void; +}; + +template <> struct RangeTraits { + using valueType = uint8_t; +}; + +template <> struct RangeTraits { + using valueType = uint16_t; +}; + +template <> struct RangeTraits { + using valueType = uint32_t; +}; + +template <> struct RangeTraits { + using valueType = float; +}; + +/** + * @brief Get T Property Range + */ +template T getPropertyRange(const OBFilterConfigSchemaItem &item, const double cur) { + // If T type is illegal, T will be void + using valueType = typename RangeTraits::valueType; + T range{}; + // Compilate error will be reported here if T is void + range.cur = static_cast(cur); + range.def = static_cast(item.def); + range.max = static_cast(item.max); + range.min = static_cast(item.min); + range.step = static_cast(item.step); + return range; +} + +/** + * @brief The Filter class is the base class for all filters in the SDK. + */ +class Filter : public std::enable_shared_from_this { +protected: + ob_filter *impl_ = nullptr; + std::string name_; + FilterCallback callback_; + std::vector configSchemaVec_; + +protected: + /** + * @brief Default constructor with nullptr impl, used for derived classes only. + */ + Filter() = default; + + virtual void init(ob_filter *impl) { + impl_ = impl; + ob_error *error = nullptr; + name_ = ob_filter_get_name(impl_, &error); + Error::handle(&error); + + auto configSchemaList = ob_filter_get_config_schema_list(impl_, &error); + Error::handle(&error); + + auto count = ob_filter_config_schema_list_get_count(configSchemaList, &error); + Error::handle(&error); + + for(uint32_t i = 0; i < count; i++) { + auto item = ob_filter_config_schema_list_get_item(configSchemaList, i, &error); + Error::handle(&error); + configSchemaVec_.emplace_back(item); + } + + ob_delete_filter_config_schema_list(configSchemaList, &error); + Error::handle(&error); + } + +public: + explicit Filter(ob_filter *impl) { + init(impl); + } + + virtual ~Filter() noexcept { + if(impl_ != nullptr) { + ob_error *error = nullptr; + ob_delete_filter(impl_, &error); + Error::handle(&error, false); + } + } + + /** + * @brief Get the Impl object of the filter. + * + * @return ob_filter* The Impl object of the filter. + */ + ob_filter *getImpl() const { + return impl_; + } + + /** + * @brief Get the type of filter. + * + * @return string The type of filte. + */ + virtual const std::string &getName() const { + return name_; + } + + /** + * @brief Reset the filter, freeing the internal cache, stopping the processing thread, and clearing the pending buffer frame when asynchronous processing + * is used. + */ + virtual void reset() const { + ob_error *error = nullptr; + ob_filter_reset(impl_, &error); + Error::handle(&error); + } + + /** + * @brief enable the filter + */ + virtual void enable(bool enable) const { + ob_error *error = nullptr; + ob_filter_enable(impl_, enable, &error); + Error::handle(&error); + } + + /** + * @brief Return Enable State + */ + virtual bool isEnabled() const { + ob_error *error = nullptr; + bool enable = ob_filter_is_enabled(impl_, &error); + Error::handle(&error); + return enable; + } + + /** + * @brief Processes a frame synchronously. + * + * @param[in] frame The frame to be processed. + * + * @return std::shared_ptr< Frame > The processed frame. + */ + virtual std::shared_ptr process(std::shared_ptr frame) const { + ob_error *error = nullptr; + auto result = ob_filter_process(impl_, frame->getImpl(), &error); + Error::handle(&error); + if(!result) { + return nullptr; + } + return std::make_shared(result); + } + + /** + * @brief Pushes the pending frame into the cache for asynchronous processing. + * + * @param[in] frame The pending frame. The processing result is returned by the callback function. + */ + virtual void pushFrame(std::shared_ptr frame) const { + ob_error *error = nullptr; + ob_filter_push_frame(impl_, frame->getImpl(), &error); + Error::handle(&error); + } + + /** + * @brief Set the callback function for asynchronous processing. + * + * @param[in] callback The processing result callback. + */ + virtual void setCallBack(FilterCallback callback) { + callback_ = callback; + ob_error *error = nullptr; + ob_filter_set_callback(impl_, &Filter::filterCallback, this, &error); + Error::handle(&error); + } + + /** + * @brief Get config schema of the filter + * @brief The returned string is a csv format string representing the configuration schema of the filter. The format of the string is: + * ``, ``, ``, ``, ``, ``, + * `` + * + * @return std::string The config schema of the filter. + */ + virtual std::string getConfigSchema() const { + ob_error *error = nullptr; + auto schema = ob_filter_get_config_schema(impl_, &error); + Error::handle(&error); + return schema; + } + + /** + * @brief Get the Config Schema Vec object + * @brief The returned vector contains the config schema items. Each item in the vector is an @ref OBFilterConfigSchemaItem object. + * + * @return std::vector The vector of the filter config schema. + */ + virtual std::vector getConfigSchemaVec() const { + return configSchemaVec_; + } + + /** + * @brief Set the filter config value by name. + * + * @attention The pass into value type is double, witch will be cast to the actual type inside the filter. The actual type can be queried by the filter + * config schema returned by @ref getConfigSchemaVec. + * + * @param[in] configName The name of the config. + * @param[in] value The value of the config. + */ + virtual void setConfigValue(const std::string &configName, double value) const { + ob_error *error = nullptr; + ob_filter_set_config_value(impl_, configName.c_str(), value, &error); + Error::handle(&error); + } + + /** + * @brief Get the Config Value object by name. + * + * @attention The returned value type has been casted to double inside the filter. The actual type can be queried by the filter config schema returned by + * @ref getConfigSchemaVec. + * + * @param[in] configName The name of the config. + * + * @return double The value of the config. + */ + virtual double getConfigValue(const std::string &configName) const { + ob_error *error = nullptr; + double value = ob_filter_get_config_value(impl_, configName.c_str(), &error); + Error::handle(&error); + return value; + } + +private: + static void filterCallback(ob_frame *frame, void *userData) { + auto filter = static_cast(userData); + filter->callback_(std::make_shared(frame)); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + virtual const char *type() { + return getName().c_str(); + } + + /** + * @brief Check if the runtime type of the filter object is compatible with a given type. + * + * @tparam T The given type. + * + * @return bool The result. + */ + template bool is(); + + template std::shared_ptr as() { + if(!is()) { + throw std::runtime_error("unsupported operation, object's type is not require type"); + } + + return std::static_pointer_cast(shared_from_this()); + } +}; + +/** + * @brief A factory class for creating filters. + */ +class FilterFactory { +public: + /** + * @brief Create a filter by name. + */ + static std::shared_ptr createFilter(const std::string &name) { + ob_error *error = nullptr; + auto impl = ob_create_filter(name.c_str(), &error); + Error::handle(&error); + return std::make_shared(impl); + } + + /** + * @brief Create a private filter by name and activation key. + * @brief Some private filters require an activation key to be activated, its depends on the vendor of the filter. + * + * @param[in] name The name of the filter. + * @param[in] activationKey The activation key of the filter. + */ + static std::shared_ptr createPrivateFilter(const std::string &name, const std::string &activationKey) { + ob_error *error = nullptr; + auto impl = ob_create_private_filter(name.c_str(), activationKey.c_str(), &error); + Error::handle(&error); + return std::make_shared(impl); + } + + /** + * @brief Get the vendor specific code of a filter by filter name. + * @brief A private filter can define its own vendor specific code for specific purposes. + * + * @param[in] name The name of the filter. + * + * @return std::string The vendor specific code of the filter. + */ + static std::string getFilterVendorSpecificCode(const std::string &name) { + ob_error *error = nullptr; + auto code = ob_filter_get_vendor_specific_code(name.c_str(), &error); + Error::handle(&error); + return code; + } +}; + +/** + * @brief The PointCloudFilter class is a subclass of Filter that generates point clouds. + */ +class PointCloudFilter : public Filter { +public: + PointCloudFilter() { + ob_error *error = nullptr; + auto impl = ob_create_filter("PointCloudFilter", &error); + Error::handle(&error); + init(impl); + } + + virtual ~PointCloudFilter() noexcept override = default; + + /** + * @brief Set the output pointcloud frame format. + * + * @param[in] format The point cloud frame format: OB_FORMAT_POINT or OB_FORMAT_RGB_POINT + */ + void setCreatePointFormat(OBFormat format) { + setConfigValue("pointFormat", static_cast(format)); + } + + /** + * @brief Set the point cloud coordinate data zoom factor. + * + * @brief Calling this function to set the scale will change the point coordinate scaling factor of the output point cloud frame, The point coordinate + * scaling factor for the output point cloud frame can be obtained via @ref PointsFrame::getCoordinateValueScale function. + * + * @param[in] factor The scale factor. + */ + void setCoordinateDataScaled(float factor) { + setConfigValue("coordinateDataScale", factor); + } + + /** + * @brief Set point cloud color data normalization. + * @brief If normalization is required, the output point cloud frame's color data will be normalized to the range [0, 1]. + * + * @attention This function only works for when create point format is set to OB_FORMAT_RGB_POINT. + * + * @param[in] state Whether normalization is required. + */ + void setColorDataNormalization(bool state) { + setConfigValue("colorDataNormalization", state); + } + + /** + * @brief Set the point cloud coordinate system. + * + * @param[in] type The coordinate system type. + */ + void setCoordinateSystem(OBCoordinateSystemType type) { + setConfigValue("coordinateSystemType", static_cast(type)); + } + + /** + * @brief Set the point cloud decimation factor. + * Calling this function to decimation factor will output thedownsampled data of the the cloud frame + * + * @param value The decimation factor. + */ + void setDecimationFactor(int value) { + setConfigValue("decimate", value); + } + + /** + * @brief Get the property range of the decimation factor range. + */ + OBIntPropertyRange getDecimationFactorRange() { + OBIntPropertyRange scaleRange{}; + if(configSchemaVec_.size() != 0) { + const auto &item = configSchemaVec_[5]; + scaleRange = getPropertyRange(item, getConfigValue("decimate")); + } + return scaleRange; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + void setPositionDataScaled(float scale) { + setCoordinateDataScaled(scale); + } + + // The following interfaces are deprecated and are retained here for compatibility purposes. + void setFrameAlignState(bool state) { + (void)state; // to complie + } + // The following interfaces are deprecated and are retained here for compatibility purposes. + void setCameraParam(OBCameraParam param) { + (void)param; + } +}; + +/** + * @brief Align for depth to other or other to depth. + */ +class Align : public Filter { +public: + Align(OBStreamType alignToStreamType) { + ob_error *error = nullptr; + auto impl = ob_create_filter("Align", &error); + Error::handle(&error); + init(impl); + + setConfigValue("AlignType", static_cast(alignToStreamType)); + } + + virtual ~Align() noexcept override = default; + + OBStreamType getAlignToStreamType() { + return static_cast(static_cast(getConfigValue("AlignType"))); + } + + /** + * @brief Sets whether the output frame resolution should match the target resolution. + * When enabled, the output frame resolution will be adjusted to match (same as) the target resolution. + * When disabled, the output frame resolution will match the original resolution while maintaining + * the aspect ratio of the target resolution. + * + * + * @param[in] state If true, output frame resolution will match the target resolution; otherwise, it will + * maintain the original resolution with the target's aspect ratio. + */ + void setMatchTargetResolution(bool state) { + setConfigValue("MatchTargetRes", state); + } + + /** + * @brief Set the Align To Stream Profile + * @brief It is useful when the align target stream dose not started (without any frame to get intrinsics and extrinsics). + * + * @param[in] profile The Align To Stream Profile. + */ + void setAlignToStreamProfile(std::shared_ptr profile) { + ob_error *error = nullptr; + ob_align_filter_set_align_to_stream_profile(impl_, profile->getImpl(), &error); + Error::handle(&error); + } +}; + +/** + * @brief The FormatConvertFilter class is a subclass of Filter that performs format conversion. + */ +class FormatConvertFilter : public Filter { +public: + FormatConvertFilter() { + ob_error *error = nullptr; + auto impl = ob_create_filter("FormatConverter", &error); + Error::handle(&error); + init(impl); + } + + virtual ~FormatConvertFilter() noexcept override = default; + + /** + * @brief Set the format conversion type. + * + * @param[in] type The format conversion type. + */ + void setFormatConvertType(OBConvertFormat type) { + setConfigValue("convertType", static_cast(type)); + } +}; + +/** + * @brief HdrMerge processing block, + * the processing merges between depth frames with + * different sub-preset sequence ids. + */ +class HdrMerge : public Filter { +public: + HdrMerge() { + ob_error *error = nullptr; + auto impl = ob_create_filter("HDRMerge", &error); + Error::handle(&error); + init(impl); + } + + virtual ~HdrMerge() noexcept override = default; +}; + +/** + * @brief Create SequenceIdFilter processing block. + */ +class SequenceIdFilter : public Filter { +private: + std::map sequenceIdList_{ { 0.f, "all" }, { 1.f, "1" } }; + OBSequenceIdItem *outputSequenceIdList_ = nullptr; + + void initSequenceIdList() { + outputSequenceIdList_ = new OBSequenceIdItem[sequenceIdList_.size()]; + + int i = 0; + for(const auto &pair: sequenceIdList_) { + outputSequenceIdList_[i].sequenceSelectId = static_cast(pair.first); + strncpy(outputSequenceIdList_[i].name, pair.second.c_str(), sizeof(outputSequenceIdList_[i].name) - 1); + outputSequenceIdList_[i].name[sizeof(outputSequenceIdList_[i].name) - 1] = '\0'; + ++i; + } + } + +public: + SequenceIdFilter() { + ob_error *error = nullptr; + auto impl = ob_create_filter("SequenceIdFilter", &error); + Error::handle(&error); + init(impl); + initSequenceIdList(); + } + + virtual ~SequenceIdFilter() noexcept override { + if(outputSequenceIdList_) { + delete[] outputSequenceIdList_; + outputSequenceIdList_ = nullptr; + } + } + + /** + * @brief Set the sequenceId filter params. + * + * @param[in] sequence_id id to pass the filter. + */ + void selectSequenceId(int sequence_id) { + setConfigValue("sequenceid", static_cast(sequence_id)); + } + + /** + * @brief Get the current sequence id. + * + * @return sequence id to pass the filter. + */ + int getSelectSequenceId() { + return static_cast(getConfigValue("sequenceid")); + } + + OBSequenceIdItem *getSequenceIdList() { + return outputSequenceIdList_; + } + + /** + * @brief Get the sequenceId list size. + * + * @return the size of sequenceId list. + */ + int getSequenceIdListSize() { + return static_cast(sequenceIdList_.size()); + } +}; + +/** + * @brief Decimation filter, reducing complexity by subsampling depth maps and losing depth details. + */ +class DecimationFilter : public Filter { +public: + DecimationFilter() { + ob_error *error = nullptr; + auto impl = ob_create_filter("DecimationFilter", &error); + Error::handle(&error); + init(impl); + } + + virtual ~DecimationFilter() noexcept override = default; + + /** + * @brief Set the decimation filter scale value. + * + * @param[in] value The decimation filter scale value. + */ + void setScaleValue(uint8_t value) { + setConfigValue("decimate", static_cast(value)); + } + + /** + * @brief Get the decimation filter scale value. + */ + uint8_t getScaleValue() { + return static_cast(getConfigValue("decimate")); + } + + /** + * @brief Get the property range of the decimation filter scale value. + */ + OBUint8PropertyRange getScaleRange() { + OBUint8PropertyRange scaleRange{}; + if(configSchemaVec_.size() != 0) { + const auto &item = configSchemaVec_[0]; + scaleRange = getPropertyRange(item, getConfigValue("decimate")); + } + return scaleRange; + } +}; + +/** + * @brief Creates depth Thresholding filter + * By controlling min and max options on the block + */ +class ThresholdFilter : public Filter { +public: + ThresholdFilter() { + ob_error *error = nullptr; + auto impl = ob_create_filter("ThresholdFilter", &error); + Error::handle(&error); + init(impl); + } + + virtual ~ThresholdFilter() noexcept override = default; + + /** + * @brief Get the threshold filter min range. + * + * @return OBIntPropertyRange The range of the threshold filter min. + */ + OBIntPropertyRange getMinRange() { + OBIntPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "min") == 0) { + range = getPropertyRange(item, getConfigValue("min")); + break; + } + } + return range; + } + + /** + * @brief Get the threshold filter max range. + * + * @return OBIntPropertyRange The range of the threshold filter max. + */ + OBIntPropertyRange getMaxRange() { + OBIntPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "max") == 0) { + range = getPropertyRange(item, getConfigValue("max")); + break; + } + } + return range; + } + + /** + * @brief Set the threshold filter max and min range. + */ + bool setValueRange(uint16_t min, uint16_t max) { + if(min >= max) { + return false; + } + setConfigValue("min", min); + setConfigValue("max", max); + return true; + } +}; + +/** + * @brief Spatial advanced filte smooths the image by calculating frame with alpha and delta settings + * alpha defines the weight of the current pixel for smoothing, + * delta defines the depth gradient below which the smoothing will occur as number of depth levels. + */ +class SpatialAdvancedFilter : public Filter { +public: + SpatialAdvancedFilter(const std::string &activationKey = "") { + ob_error *error = nullptr; + auto impl = ob_create_private_filter("SpatialAdvancedFilter", activationKey.c_str(), &error); + Error::handle(&error); + init(impl); + } + + virtual ~SpatialAdvancedFilter() noexcept override = default; + + /** + * @brief Get the spatial advanced filter alpha range. + * + * @return OBFloatPropertyRange the alpha value of property range. + */ + OBFloatPropertyRange getAlphaRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "alpha") == 0) { + range = getPropertyRange(item, getConfigValue("alpha")); + break; + } + } + return range; + } + + /** + * @brief Get the spatial advanced filter dispdiff range. + * + * @return OBFloatPropertyRange the dispdiff value of property range. + */ + OBUint16PropertyRange getDispDiffRange() { + OBUint16PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "disp_diff") == 0) { + range = getPropertyRange(item, getConfigValue("disp_diff")); + break; + } + } + return range; + } + + /** + * @brief Get the spatial advanced filter radius range. + * + * @return OBFloatPropertyRange the radius value of property range. + */ + OBUint16PropertyRange getRadiusRange() { + OBUint16PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "radius") == 0) { + range = getPropertyRange(item, getConfigValue("radius")); + break; + } + } + return range; + } + + /** + * @brief Get the spatial advanced filter magnitude range. + * + * @return OBFloatPropertyRange the magnitude value of property range. + */ + OBIntPropertyRange getMagnitudeRange() { + OBIntPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "magnitude") == 0) { + range = getPropertyRange(item, getConfigValue("magnitude")); + break; + } + } + return range; + } + + /** + * @brief Get the spatial advanced filter params. + * + * @return OBSpatialAdvancedFilterParams + */ + OBSpatialAdvancedFilterParams getFilterParams() { + OBSpatialAdvancedFilterParams params{}; + params.alpha = static_cast(getConfigValue("alpha")); + params.disp_diff = static_cast(getConfigValue("disp_diff")); + params.magnitude = static_cast(getConfigValue("magnitude")); + params.radius = static_cast(getConfigValue("radius")); + return params; + } + + /** + * @brief Set the spatial advanced filter params. + * + * @param[in] params OBSpatialAdvancedFilterParams. + */ + void setFilterParams(OBSpatialAdvancedFilterParams params) { + setConfigValue("alpha", params.alpha); + setConfigValue("disp_diff", params.disp_diff); + setConfigValue("magnitude", params.magnitude); + setConfigValue("radius", params.radius); + } +}; + +/** + * @brief The Spatial Fast Filter utilizes an enhanced median smoothing algorithm, + * designed to significantly reduce CPU usage and optimize processing efficiency. + */ +class SpatialFastFilter : public Filter { +public: + SpatialFastFilter(const std::string &activationKey = "") { + ob_error *error = nullptr; + auto impl = ob_create_private_filter("SpatialFastFilter", activationKey.c_str(), &error); + Error::handle(&error); + init(impl); + } + + virtual ~SpatialFastFilter() noexcept override = default; + + /** + * @brief Get the spatial fast filter radius range. + * + * @return OBIntPropertyRange the radius value of property range. + */ + OBIntPropertyRange getRadiusRange() { + OBIntPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "radius") == 0) { + range = getPropertyRange(item, getConfigValue("radius")); + break; + } + } + return range; + } + + /** + * @brief Get the spatial fast filter params. + * + * @return OBSpatialFastFilterParams + */ + OBSpatialFastFilterParams getFilterParams() { + OBSpatialFastFilterParams params{}; + params.radius = static_cast(getConfigValue("radius")); + return params; + } + + /** + * @brief Set the spatial fast filter params. + * + * @param[in] params OBSpatialFastFilterParams. + */ + void setFilterParams(OBSpatialFastFilterParams params) { + setConfigValue("radius", params.radius); + } +}; + +/** + * @brief The Spatial Moderate Filter utilizes an optimized average smoothing algorithm, + * to achieve a balance between processing speed and the quality of smoothing achieved. + */ +class SpatialModerateFilter : public Filter { +public: + SpatialModerateFilter(const std::string &activationKey = "") { + ob_error *error = nullptr; + auto impl = ob_create_private_filter("SpatialModerateFilter", activationKey.c_str(), &error); + Error::handle(&error); + init(impl); + } + + virtual ~SpatialModerateFilter() noexcept override = default; + + /** + * @brief Get the spatial moderate filter magnitude range. + * + * @return OBIntPropertyRange the magnitude value of property range. + */ + OBIntPropertyRange getMagnitudeRange() { + OBIntPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "magnitude") == 0) { + range = getPropertyRange(item, getConfigValue("magnitude")); + break; + } + } + return range; + } + + /** + * @brief Get the spatial moderate filter radius range. + * + * @return OBIntPropertyRange the radius value of property range. + */ + OBIntPropertyRange getRadiusRange() { + OBIntPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "radius") == 0) { + range = getPropertyRange(item, getConfigValue("radius")); + break; + } + } + return range; + } + + /** + * @brief Get the spatial moderate filter disp diff range. + * + * @return OBIntPropertyRange the disp diff value of property range. + */ + OBIntPropertyRange getDispDiffRange() { + OBIntPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "disp_diff") == 0) { + range = getPropertyRange(item, getConfigValue("disp_diff")); + break; + } + } + return range; + } + + /** + * @brief Get the spatial moderate filter params. + * + * @return OBSpatialModerateFilterParams + */ + OBSpatialModerateFilterParams getFilterParams() { + OBSpatialModerateFilterParams params{}; + params.magnitude = static_cast(getConfigValue("magnitude")); + params.radius = static_cast(getConfigValue("radius")); + params.disp_diff = static_cast(getConfigValue("disp_diff")); + return params; + } + + /** + * @brief Set the spatial moderate filter params. + * + * @param[in] params OBSpatialModerateFilterParams. + */ + void setFilterParams(OBSpatialModerateFilterParams params) { + setConfigValue("magnitude", params.magnitude); + setConfigValue("radius", params.radius); + setConfigValue("disp_diff", params.disp_diff); + } +}; + +/** + * @brief Hole filling filter,the processing performed depends on the selected hole filling mode. + */ +class HoleFillingFilter : public Filter { +public: + HoleFillingFilter(const std::string &activationKey = "") { + ob_error *error = nullptr; + auto impl = ob_create_private_filter("HoleFillingFilter", activationKey.c_str(), &error); + Error::handle(&error); + init(impl); + } + + ~HoleFillingFilter() noexcept override = default; + + /** + * @brief Set the HoleFillingFilter mode. + * + * @param[in] mode OBHoleFillingMode, OB_HOLE_FILL_TOP,OB_HOLE_FILL_NEAREST or OB_HOLE_FILL_FAREST. + */ + void setFilterMode(OBHoleFillingMode mode) { + setConfigValue("hole_filling_mode", static_cast(mode)); + } + + /** + * @brief Get the HoleFillingFilter mode. + * + * @return OBHoleFillingMode + */ + OBHoleFillingMode getFilterMode() { + return static_cast(static_cast(getConfigValue("hole_filling_mode"))); + } +}; + +/** + * @brief The noise removal filter,removing scattering depth pixels. + */ +class NoiseRemovalFilter : public Filter { +public: + NoiseRemovalFilter(const std::string &activationKey = "") { + ob_error *error = nullptr; + auto impl = ob_create_private_filter("NoiseRemovalFilter", activationKey.c_str(), &error); + Error::handle(&error); + init(impl); + } + + ~NoiseRemovalFilter() noexcept override = default; + + /** + * @brief Set the noise removal filter params. + * + * @param[in] filterParams ob_noise_removal_filter_params. + */ + void setFilterParams(OBNoiseRemovalFilterParams filterParams) { + setConfigValue("max_size", static_cast(filterParams.max_size)); + setConfigValue("min_diff", static_cast(filterParams.disp_diff)); + // todo:set noise remove type + } + + /** + * @brief Get the noise removal filter params. + * + * @return OBNoiseRemovalFilterParams. + */ + OBNoiseRemovalFilterParams getFilterParams() { + OBNoiseRemovalFilterParams param{}; + param.max_size = static_cast(getConfigValue("max_size")); + param.disp_diff = static_cast(getConfigValue("min_diff")); + // todo: type is not set + return param; + } + + /** + * @brief Get the noise removal filter disp diff range. + * @return OBUint16PropertyRange The disp diff of property range. + */ + OBUint16PropertyRange getDispDiffRange() { + OBUint16PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "min_diff") == 0) { + range = getPropertyRange(item, getConfigValue("min_diff")); + break; + } + } + return range; + } + + /** + * @brief Get the noise removal filter max size range. + * @return OBUint16PropertyRange The max size of property range. + */ + OBUint16PropertyRange getMaxSizeRange() { + OBUint16PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "max_size") == 0) { + range = getPropertyRange(item, getConfigValue("max_size")); + break; + } + } + return range; + } +}; + +/** + * @brief Temporal filter + */ +class TemporalFilter : public Filter { +public: + TemporalFilter(const std::string &activationKey = "") { + ob_error *error = nullptr; + auto impl = ob_create_private_filter("TemporalFilter", activationKey.c_str(), &error); + Error::handle(&error); + init(impl); + } + + ~TemporalFilter() noexcept override = default; + + /** + * @brief Get the TemporalFilter diffscale range. + * + * @return OBFloatPropertyRange the diffscale value of property range. + */ + OBFloatPropertyRange getDiffScaleRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "diff_scale") == 0) { + range = getPropertyRange(item, getConfigValue("diff_scale")); + break; + } + } + return range; + } + + /** + * @brief Set the TemporalFilter diffscale value. + * + * @param[in] value diffscale value. + */ + void setDiffScale(float value) { + setConfigValue("diff_scale", static_cast(value)); + } + + /** + * @brief Get the TemporalFilter weight range. + * + * @return OBFloatPropertyRange the weight value of property range. + */ + OBFloatPropertyRange getWeightRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "weight") == 0) { + range = getPropertyRange(item, getConfigValue("weight")); + break; + } + } + return range; + } + + /** + * @brief Set the TemporalFilter weight value. + * + * @param[in] value weight value. + */ + void setWeight(float value) { + setConfigValue("weight", static_cast(value)); + } +}; + +/** + * @brief FalsePositive filter + */ +class FalsePositiveFilter : public Filter { +public: + FalsePositiveFilter(const std::string &activationKey = "") { + ob_error *error = nullptr; + auto impl = ob_create_private_filter("FalsePositiveFilter", activationKey.c_str(), &error); + Error::handle(&error); + init(impl); + } + + virtual ~FalsePositiveFilter() noexcept override = default; + + /** + * @brief Get the FalsePositive filter fpEdgeBleedFilterEnable range. + * + * @return OBUint8PropertyRange the fpEdgeBleedFilterEnable value of property range. + */ + OBUint8PropertyRange getfpEdgeBleedFilterEnableRange() { + OBUint8PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fpEdgeBleedFilterEnable") == 0) { + range = getPropertyRange(item, getConfigValue("fpEdgeBleedFilterEnable")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fpebfROIMinXRatio range. + * + * @return OBFloatPropertyRange the fpebfROIMinXRatio value of property range. + */ + OBFloatPropertyRange getfpebfROIMinXRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fpebfROIMinXRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fpebfROIMinXRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fpebfROIMaxXRatio range. + * + * @return OBFloatPropertyRange the fpebfROIMaxXRatio value of property range. + */ + OBFloatPropertyRange getfpebfROIMaxXRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fpebfROIMaxXRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fpebfROIMaxXRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fpebfROIMinYRatio range. + * + * @return OBFloatPropertyRange the fpebfROIMinYRatio value of property range. + */ + OBFloatPropertyRange getfpebfROIMinYRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fpebfROIMinYRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fpebfROIMinYRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fpebfROIMaxYRatio range. + * + * @return OBFloatPropertyRange the fpebfROIMaxYRatio value of property range. + */ + OBFloatPropertyRange getfpebfROIMaxYRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fpebfROIMaxYRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fpebfROIMaxYRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fpTextureSparsityFilterEnable range. + * + * @return OBUint8PropertyRange the fpTextureSparsityFilterEnable value of property range. + */ + OBUint8PropertyRange getfpTextureSparsityFilterEnableRange() { + OBUint8PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fpTextureSparsityFilterEnable") == 0) { + range = getPropertyRange(item, getConfigValue("fpTextureSparsityFilterEnable")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fptsfROIMinXRatio range. + * + * @return OBFloatPropertyRange the fptsfROIMinXRatio value of property range. + */ + OBFloatPropertyRange getfptsfROIMinXRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fptsfROIMinXRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fptsfROIMinXRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fptsfROIMaxXRatio range. + * + * @return OBFloatPropertyRange the fptsfROIMaxXRatio value of property range. + */ + OBFloatPropertyRange getfptsfROIMaxXRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fptsfROIMaxXRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fptsfROIMaxXRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fptsfROIMinYRatio range. + * + * @return OBFloatPropertyRange the fptsfROIMinYRatio value of property range. + */ + OBFloatPropertyRange getfptsfROIMinYRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fptsfROIMinYRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fptsfROIMinYRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fptsfROIMaxYRatio range. + * + * @return OBFloatPropertyRange the fptsfROIMaxYRatio value of property range. + */ + OBFloatPropertyRange getfptsfROIMaxYRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fptsfROIMaxYRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fptsfROIMaxYRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fptsfMaxNoiseLevel range. + * + * @return OBUint16PropertyRange the fptsfMaxNoiseLevel value of property range. + */ + OBUint16PropertyRange getfptsfMaxNoiseLevelRange() { + OBUint16PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fptsfMaxNoiseLevel") == 0) { + range = getPropertyRange(item, getConfigValue("fptsfMaxNoiseLevel")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fptsfMaxSpeckleSize range. + * + * @return OBUint16PropertyRange the fptsfMaxSpeckleSize value of property range. + */ + OBUint16PropertyRange getfptsfMaxSpeckleSizeRange() { + OBUint16PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fptsfMaxSpeckleSize") == 0) { + range = getPropertyRange(item, getConfigValue("fptsfMaxSpeckleSize")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fpPatternAmbiguityFilterEnable range. + * + * @return OBUint8PropertyRange the fpPatternAmbiguityFilterEnable value of property range. + */ + OBUint8PropertyRange getfpPatternAmbiguityFilterEnableRange() { + OBUint8PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fpPatternAmbiguityFilterEnable") == 0) { + range = getPropertyRange(item, getConfigValue("fpPatternAmbiguityFilterEnable")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fppafROIMinXRatio range. + * + * @return OBFloatPropertyRange the fppafROIMinXRatio value of property range. + */ + OBFloatPropertyRange getfppafROIMinXRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fppafROIMinXRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fppafROIMinXRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fppafROIMaxXRatio range. + * + * @return OBFloatPropertyRange the fppafROIMaxXRatio value of property range. + */ + OBFloatPropertyRange getfppafROIMaxXRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fppafROIMaxXRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fppafROIMaxXRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fppafROIMinYRatio range. + * + * @return OBFloatPropertyRange the fppafROIMinYRatio value of property range. + */ + OBFloatPropertyRange getfppafROIMinYRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fppafROIMinYRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fppafROIMinYRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fppafROIMaxYRatio range. + * + * @return OBFloatPropertyRange the fppafROIMaxYRatio value of property range. + */ + OBFloatPropertyRange getfppafROIMaxYRatioRange() { + OBFloatPropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fppafROIMaxYRatio") == 0) { + range = getPropertyRange(item, getConfigValue("fppafROIMaxYRatio")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fppafMaxNoiseLevel range. + * + * @return OBUint16PropertyRange the fppafMaxNoiseLevel value of property range. + */ + OBUint16PropertyRange getfppafMaxNoiseLevelRange() { + OBUint16PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fppafMaxNoiseLevel") == 0) { + range = getPropertyRange(item, getConfigValue("fppafMaxNoiseLevel")); + break; + } + } + return range; + } + + /** + * @brief Get the FalsePositive filter fppafMaxSpeckleSize range. + * + * @return OBUint16PropertyRange the fppafMaxSpeckleSize value of property range. + */ + OBUint16PropertyRange getfppafMaxSpeckleSizeRange() { + OBUint16PropertyRange range{}; + const auto &schemaVec = getConfigSchemaVec(); + for(const auto &item: schemaVec) { + if(strcmp(item.name, "fppafMaxSpeckleSize") == 0) { + range = getPropertyRange(item, getConfigValue("fppafMaxSpeckleSize")); + break; + } + } + return range; + } +}; + +/** + * @brief Depth to disparity or disparity to depth + */ +class DisparityTransform : public Filter { +public: + DisparityTransform(const std::string &activationKey = "") { + ob_error *error = nullptr; + auto impl = ob_create_private_filter("DisparityTransform", activationKey.c_str(), &error); + Error::handle(&error); + init(impl); + } + + ~DisparityTransform() noexcept override = default; +}; + +class OBFilterList { +private: + ob_filter_list_t *impl_; + +public: + explicit OBFilterList(ob_filter_list_t *impl) : impl_(impl) {} + + ~OBFilterList() noexcept { + ob_error *error = nullptr; + ob_delete_filter_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the number of filters + * + * @return uint32_t The number of filters + */ + uint32_t getCount() const { + ob_error *error = nullptr; + auto count = ob_filter_list_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get the Filter object at the specified index + * + * @param[in] index The filter index. The range is [0, count-1]. If the index exceeds the range, an exception will be thrown. + * + * @return std::shared_ptr The filter object. + */ + std::shared_ptr getFilter(uint32_t index) { + ob_error *error = nullptr; + auto filter = ob_filter_list_get_filter(impl_, index, &error); + Error::handle(&error); + return std::make_shared(filter); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t count() const { + return getCount(); + } +}; + +/** + * @brief Returns the mapping of filter type names to their corresponding type_index. + */ +inline const std::unordered_map &getFilterTypeMap() { + static const std::unordered_map filterTypeMap = { + { "PointCloudFilter", typeid(PointCloudFilter) }, { "Align", typeid(Align) }, + { "FormatConverter", typeid(FormatConvertFilter) }, { "HDRMerge", typeid(HdrMerge) }, + { "SequenceIdFilter", typeid(SequenceIdFilter) }, { "DecimationFilter", typeid(DecimationFilter) }, + { "ThresholdFilter", typeid(ThresholdFilter) }, { "SpatialAdvancedFilter", typeid(SpatialAdvancedFilter) }, + { "HoleFillingFilter", typeid(HoleFillingFilter) }, { "NoiseRemovalFilter", typeid(NoiseRemovalFilter) }, + { "TemporalFilter", typeid(TemporalFilter) }, { "DisparityTransform", typeid(DisparityTransform) }, + { "SpatialFastFilter", typeid(SpatialFastFilter) }, { "SpatialModerateFilter", typeid(SpatialModerateFilter) }, + { "FalsePositiveFilter", typeid(FalsePositiveFilter) }, + }; + return filterTypeMap; +} + +/** + * @brief Define the is() template function for the Filter class + * + * @note When adding a new filter class, ensure the filter type map + * (see getFilterTypeMap()) is updated accordingly to maintain correct type matching. + */ +template bool Filter::is() { + std::string name = type(); + + const auto &filterTypeMap = getFilterTypeMap(); + auto it = filterTypeMap.find(name); + if(it != filterTypeMap.end()) { + return std::type_index(typeid(T)) == it->second; + } + return false; +} + +} // namespace ob diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Frame.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Frame.hpp new file mode 100644 index 0000000..46695ea --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Frame.hpp @@ -0,0 +1,1318 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Frame.hpp + * @brief Frame related type, which is mainly used to obtain frame data and frame information. + * + */ +#pragma once + +#include "Types.hpp" +#include "libobsensor/h/Frame.h" +#include "libobsensor/hpp/Error.hpp" +#include "libobsensor/hpp/StreamProfile.hpp" +#include +#include +#include +#include + +/** + * Frame classis inheritance hierarchy: + * Frame + * | + * +-----------+----------+----------+-----------+ + * | | | | | + * VideoFrame PointsFrame AccelFrame GyroFrame FrameSet + * | + * +----+----------+-------------------+ + * | | | + * ColorFrame DepthFrame IRFrame + * | + * +-----+-----+ + * | | + * IRLeftFrame IRRightFrame + */ + +namespace ob { +class Device; +class Sensor; + +/** + * @brief Define the frame class, which is the base class of all frame types. + * + */ +class Frame : public std::enable_shared_from_this { +protected: + /** + * @brief The pointer to the internal (c api level) frame object. + */ + const ob_frame *impl_ = nullptr; + +public: + /** + * @brief Construct a new Frame object with a given pointer to the internal frame object. + * + * @attention After calling this constructor, the frame object will own the internal frame object, and the internal frame object will be deleted when the + * frame object is destroyed. + * @attention The internal frame object should not be deleted by the caller. + * + * @param[in] impl The pointer to the internal frame object. + */ + explicit Frame(const ob_frame *impl) : impl_(impl) {} + + /** + * @brief Get the internal (impl) frame object + * + * @return const ob_frame* the pointer to the internal frame object. + */ + const ob_frame *getImpl() const { + return impl_; + } + + /** + * @brief Destroy the Frame object + */ + virtual ~Frame() noexcept { + if(impl_) { + ob_error *error = nullptr; + ob_delete_frame(impl_, &error); + Error::handle(&error, false); + impl_ = nullptr; + } + } + + /** + * @brief Get the type of frame. + * + * @return OBFrameType The type of frame. + */ + virtual OBFrameType getType() const { + ob_error *error = nullptr; + auto type = ob_frame_get_type(impl_, &error); + Error::handle(&error); + + return type; + } + + /** + * @brief Get the format of the frame. + * + * @return OBFormat The format of the frame. + */ + virtual OBFormat getFormat() const { + ob_error *error = nullptr; + auto format = ob_frame_get_format(impl_, &error); + Error::handle(&error); + + return format; + } + + /** + * @brief Get the sequence number of the frame. + * + * @note The sequence number for each frame is managed by the SDK. It increments by 1 for each frame on each stream. + * + * @return uint64_t The sequence number of the frame. + */ + virtual uint64_t getIndex() const { + ob_error *error = nullptr; + auto index = ob_frame_get_index(impl_, &error); + Error::handle(&error); + + return index; + } + + /** + * @brief Get frame data + * + * @return const uint8_t * The frame data pointer. + */ + virtual uint8_t *getData() const { + ob_error *error = nullptr; + auto data = ob_frame_get_data(impl_, &error); + Error::handle(&error); + + return data; + } + + /** + * @brief Get the size of the frame data. + * + * @return uint32_t The size of the frame data. + * For point cloud data, this returns the number of bytes occupied by all point sets. To find the number of points, divide the dataSize by the structure + * size of the corresponding point type. + */ + virtual uint32_t getDataSize() const { + ob_error *error = nullptr; + auto dataSize = ob_frame_get_data_size(impl_, &error); + Error::handle(&error); + + return dataSize; + } + + /** + * @brief Get the hardware timestamp of the frame in microseconds. + * @brief The hardware timestamp is the time point when the frame was captured by the device, on device clock domain. + * + * @return uint64_t The hardware timestamp of the frame in microseconds. + */ + uint64_t getTimeStampUs() const { + ob_error *error = nullptr; + auto timeStampUs = ob_frame_get_timestamp_us(impl_, &error); + Error::handle(&error); + + return timeStampUs; + } + + /** + * @brief Get the system timestamp of the frame in microseconds. + * @brief The system timestamp is the time point when the frame was received by the host, on host clock domain. + * + * @return uint64_t The system timestamp of the frame in microseconds. + */ + uint64_t getSystemTimeStampUs() const { + ob_error *error = nullptr; + auto systemTimeStampUs = ob_frame_get_system_timestamp_us(impl_, &error); + Error::handle(&error); + + return systemTimeStampUs; + } + + /** + * @brief Get the global timestamp of the frame in microseconds. + * @brief The global timestamp is the time point when the frame was captured by the device, and has been converted to the host clock domain. The + * conversion process base on the device timestamp and can eliminate the timer drift of the device + * + * @attention The global timestamp disable by default. If global timestamp is not enabled, the function will return 0. To enable the global timestamp, + * please call @ref Device::enableGlobalTimestamp() function. + * @attention Only some devices support getting the global timestamp. Check the device support status by @ref Device::isGlobalTimestampSupported() function. + * + * @return uint64_t The global timestamp of the frame in microseconds. + */ + uint64_t getGlobalTimeStampUs() const { + ob_error *error = nullptr; + auto globalTimeStampUs = ob_frame_get_global_timestamp_us(impl_, &error); + Error::handle(&error); + + return globalTimeStampUs; + } + + /** + * @brief Get the metadata pointer of the frame. + * + * @return const uint8_t * The metadata pointer of the frame. + */ + uint8_t *getMetadata() const { + ob_error *error = nullptr; + auto metadata = ob_frame_get_metadata(impl_, &error); + Error::handle(&error); + + return metadata; + } + + /** + * @brief Get the size of the metadata of the frame. + * + * @return uint32_t The size of the metadata of the frame. + */ + uint32_t getMetadataSize() const { + ob_error *error = nullptr; + auto metadataSize = ob_frame_get_metadata_size(impl_, &error); + Error::handle(&error); + + return metadataSize; + } + + /** + * @brief Check if the frame object has metadata of a given type. + * + * @param[in] type The metadata type. refer to @ref OBFrameMetadataType + * + * @return bool The result. + */ + bool hasMetadata(OBFrameMetadataType type) const { + ob_error *error = nullptr; + auto result = ob_frame_has_metadata(impl_, type, &error); + Error::handle(&error); + + return result; + } + + /** + * @brief Get the metadata value + * + * @param[in] type The metadata type. refer to @ref OBFrameMetadataType + * + * @return int64_t The metadata value. + */ + int64_t getMetadataValue(OBFrameMetadataType type) const { + ob_error *error = nullptr; + auto value = ob_frame_get_metadata_value(impl_, type, &error); + Error::handle(&error); + + return value; + } + + /** + * @brief get StreamProfile of the frame + * + * @return std::shared_ptr The StreamProfile of the frame, may return nullptr if the frame is not captured from a stream. + */ + std::shared_ptr getStreamProfile() const { + ob_error *error = nullptr; + auto profile = ob_frame_get_stream_profile(impl_, &error); + Error::handle(&error); + return StreamProfileFactory::create(profile); + } + + /** + * @brief get owner sensor of the frame + * + * @return std::shared_ptr The owner sensor of the frame, return nullptr if the frame is not owned by any sensor or the sensor is destroyed + */ + std::shared_ptr getSensor() const { + ob_error *error = nullptr; + auto sensor = ob_frame_get_sensor(impl_, &error); + Error::handle(&error); + + return std::make_shared(sensor); + } + + /** + * @brief get owner device of the frame + * + * @return std::shared_ptr The owner device of the frame, return nullptr if the frame is not owned by any device or the device is destroyed + */ + std::shared_ptr getDevice() const { + ob_error *error = nullptr; + auto device = ob_frame_get_device(impl_, &error); + Error::handle(&error); + + return std::make_shared(device); + } + + /** + * @brief Check if the runtime type of the frame object is compatible with a given type. + * + * @tparam T The given type. + * + * @return bool The result. + */ + template bool is() const; + + /** + * @brief Convert the frame object to a target type. + * + * @tparam T The target type. + * + * @return std::shared_ptr The result. If it cannot be converted, an exception will be thrown. + */ + template std::shared_ptr as() { + if(!is()) { + throw std::runtime_error("unsupported operation, object's type is not require type"); + } + + ob_error *error = nullptr; + ob_frame_add_ref(impl_, &error); + Error::handle(&error); + + return std::make_shared(impl_); + } + + /** + * @brief Convert the frame object to a target type. + * + * @tparam T The target type. + * + * @return std::shared_ptr The result. If it cannot be converted, an exception will be thrown. + */ + template std::shared_ptr as() const { + if(!is()) { + throw std::runtime_error("unsupported operation, object's type is not require type"); + } + + ob_error *error = nullptr; + ob_frame_add_ref(impl_, &error); + Error::handle(&error); + + return std::make_shared(impl_); + } + + /** + * @brief Copy the information of the source frame object to the destination frame object. + * @brief Including the index, timestamp, system timestamp, global timestamp and metadata will be copied. + * + * @param[in] srcFrame Source frame object to copy the information from. + */ + void copyFrameInfo(std::shared_ptr srcFrame) { + ob_error *error = nullptr; + auto unConstImpl = const_cast(impl_); + + ob_frame_copy_info(srcFrame->getImpl(), unConstImpl, &error); + Error::handle(&error); + } + + /** + * @brief Set the system timestamp of the frame in microseconds. + * + * @param systemTimestampUs frame system timestamp to set in microseconds. + */ + void setSystemTimestampUs(uint64_t systemTimestampUs) { + ob_error *error = nullptr; + auto unConstImpl = const_cast(impl_); + + ob_frame_set_system_timestamp_us(unConstImpl, systemTimestampUs, &error); + Error::handle(&error); + } + + /** + * @brief Update the data of a frame. + * @brief The data will be memcpy to the frame data buffer. + * @brief The frame data size will be also updated as the input data size. + * + * @attention It is not recommended to update the frame data if the frame was not created by the user. If you must update it, ensure that the frame is not + * being used in other threads. + * @attention The size of the new data should be equal to or less than the current data size of the frame. Exceeding the original size may cause memory + * exceptions. + * + * @param[in] data The new data to update the frame with. + * @param[in] dataSize The size of the new data. + */ + void updateData(const uint8_t *data, uint32_t dataSize) { + ob_error *error = nullptr; + auto unConstImpl = const_cast(impl_); + + ob_frame_update_data(unConstImpl, data, dataSize, &error); + Error::handle(&error); + } + + /** + * @brief Update the metadata of the frame + * @brief The metadata will be memcpy to the frame metadata buffer. + * @brief The frame metadata size will be also updated as the input metadata size. + * + * @attention It is not recommended to update the frame metadata if the frame was not created by the user. If you must update it, ensure that the frame is + * not being used in other threads or future use. + * @attention The metadata size should be equal to or less than 256 bytes, otherwise it will cause memory exception. + * + * @param[in] metadata The new metadata to update. + * @param[in] metadataSize The size of the new metadata. + */ + void updateMetadata(const uint8_t *metadata, uint32_t metadataSize) { + ob_error *error = nullptr; + auto unConstImpl = const_cast(impl_); + + ob_frame_update_metadata(unConstImpl, metadata, metadataSize, &error); + Error::handle(&error); + } + + /** + * @brief Set (override) the stream profile of the frame + * + * @param profile The stream profile to set for the frame. + */ + void setStreamProfile(std::shared_ptr profile) { + ob_error *error = nullptr; + auto unConstImpl = const_cast(impl_); + + ob_frame_set_stream_profile(unConstImpl, profile->getImpl(), &error); + Error::handle(&error); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + OBFrameType type() const { + return getType(); + } + + virtual OBFormat format() const { + return getFormat(); + } + + virtual uint64_t index() const { + return getIndex(); + } + + virtual void *data() const { + auto data = getData(); + return reinterpret_cast(data); + } + + virtual uint32_t dataSize() const { + return getDataSize(); + } + + uint64_t timeStamp() const { + return getTimeStampUs() / 1000; + } + + uint64_t timeStampUs() const { + return getTimeStampUs(); + } + + uint64_t systemTimeStamp() const { + return getSystemTimeStampUs() / 1000; + } + + uint64_t systemTimeStampUs() const { + return getSystemTimeStampUs(); + } + + uint64_t globalTimeStampUs() const { + return getGlobalTimeStampUs(); + } + + uint8_t *metadata() const { + return getMetadata(); + } + + uint32_t metadataSize() const { + return getMetadataSize(); + } +}; + +/** + * @brief Define the VideoFrame class, which inherits from the Frame class + */ +class VideoFrame : public Frame { +public: + /** + * @brief Construct a new VideoFrame object with a given pointer to the internal frame object. + * + * @attention After calling this constructor, the frame object will own the internal frame object, and the internal frame object will be deleted when the + * frame object is destroyed. + * @attention The internal frame object should not be deleted by the caller. + * + * @param[in] impl The pointer to the internal frame object. + */ + explicit VideoFrame(const ob_frame *impl) : Frame(impl) {}; + + ~VideoFrame() noexcept override = default; + + /** + * @brief Get the width of the frame. + * + * @return uint32_t The width of the frame. + */ + uint32_t getWidth() const { + ob_error *error = nullptr; + auto width = ob_video_frame_get_width(impl_, &error); + Error::handle(&error); + + return width; + } + + /** + * @brief Get the height of the frame. + * + * @return uint32_t The height of the frame. + */ + uint32_t getHeight() const { + ob_error *error = nullptr; + auto height = ob_video_frame_get_height(impl_, &error); + Error::handle(&error); + + return height; + } + + /** + * @brief Get the Pixel Type object + * @brief Usually used to determine the pixel type of depth frame (depth, disparity, raw phase, etc.) + * + * @attention Always return OB_PIXEL_UNKNOWN for non-depth frame currently + * + * @return OBPixelType + */ + OBPixelType getPixelType() const { + ob_error *error = nullptr; + auto pixelType = ob_video_frame_get_pixel_type(impl_, &error); + Error::handle(&error); + + return pixelType; + } + + /** + * @brief Get the effective number of pixels in the frame. + * @attention Only valid for Y8/Y10/Y11/Y12/Y14/Y16 format. + * + * @return uint8_t The effective number of pixels in the frame, or 0 if it is an unsupported format. + */ + uint8_t getPixelAvailableBitSize() const { + ob_error *error = nullptr; + auto bitSize = ob_video_frame_get_pixel_available_bit_size(impl_, &error); + Error::handle(&error); + + return bitSize; + } + + /** + * @brief Set video frame pixel format + * + * @param pixelType the pixel format of the frame + */ + void setPixelType(OBPixelType pixelType) { + ob_error *error = nullptr; + auto unConstImpl = const_cast(impl_); + + ob_video_frame_set_pixel_type(unConstImpl, pixelType, &error); + Error::handle(&error); + } + + /** + * @brief Set the effective number of pixels (such as Y16 format frame, but only the lower 10 bits are effective bits, and the upper 6 bits are filled with + * 0) + * @attention Only valid for Y8/Y10/Y11/Y12/Y14/Y16 format + * + * @param[in] bitSize the effective number of pixels in the pixel, or 0 if it is an unsupported format + */ + void setPixelAvailableBitSize(uint8_t bitSize) { + ob_error *error = nullptr; + auto unConstImpl = const_cast(impl_); + + ob_video_frame_set_pixel_available_bit_size(unConstImpl, bitSize, &error); + Error::handle(&error); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t width() const { + return getWidth(); + } + + uint32_t height() const { + return getHeight(); + } + + uint8_t pixelAvailableBitSize() const { + return getPixelAvailableBitSize(); + } +}; + +/** + * @brief Define the ColorFrame class, which inherits from the VideoFrame classd + */ +class ColorFrame : public VideoFrame { +public: + /** + * @brief Construct a new ColorFrame object with a given pointer to the internal frame object. + * + * @attention After calling this constructor, the frame object will own the internal frame object, and the internal frame object will be deleted when the + * frame object is destroyed. + * @attention The internal frame object should not be deleted by the caller. + * @attention Please use the FrameFactory to create a Frame object. + * + * @param[in] impl The pointer to the internal frame object. + */ + explicit ColorFrame(const ob_frame *impl) : VideoFrame(impl) {}; + + ~ColorFrame() noexcept override = default; +}; + +/** + * @brief Define the DepthFrame class, which inherits from the VideoFrame class + */ +class DepthFrame : public VideoFrame { + +public: + /** + * @brief Construct a new DepthFrame object with a given pointer to the internal frame object. + * + * @attention After calling this constructor, the frame object will own the internal frame object, and the internal frame object will be deleted when the + * frame object is destroyed. + * @attention The internal frame object should not be deleted by the caller. + * @attention Please use the FrameFactory to create a Frame object. + * + * @param[in] impl The pointer to the internal frame object. + */ + explicit DepthFrame(const ob_frame *impl) : VideoFrame(impl) {}; + + ~DepthFrame() noexcept override = default; + + /** + * @brief Get the value scale of the depth frame. The pixel value of depth frame is multiplied by the scale to give a depth value in millimeters. + * For example, if valueScale=0.1 and a certain coordinate pixel value is pixelValue=10000, then the depth value = pixelValue*valueScale = + * 10000*0.1=1000mm. + * + * @return float The scale. + */ + float getValueScale() const { + ob_error *error = nullptr; + auto scale = ob_depth_frame_get_value_scale(impl_, &error); + Error::handle(&error); + + return scale; + } + + /** + * @brief Set the value scale of the depth frame. The pixel value of the depth frame is multiplied by the scale to give a depth value in millimeters. + * For example, if valueScale=0.1 and a certain coordinate pixel value is pixelValue=10000, then the depth value = pixelValue*valueScale = 10000*0.1=1000mm. + * + * @param[in] valueScale The value scale of the depth frame + */ + void setValueScale(float valueScale) { + ob_error *error = nullptr; + auto unConstImpl = const_cast(impl_); + + ob_depth_frame_set_value_scale(unConstImpl, valueScale, &error); + Error::handle(&error); + } +}; + +/** + * @brief Define the IRFrame class, which inherits from the VideoFrame class + * + */ +class IRFrame : public VideoFrame { + +public: + /** + * @brief Construct a new IRFrame object with a given pointer to the internal frame object. + * + * @attention After calling this constructor, the frame object will own the internal frame object, and the internal frame object will be deleted when the + * frame object is destroyed. + * @attention The internal frame object should not be deleted by the caller. + * @attention Please use the FrameFactory to create a Frame object. + * + * @param[in] impl The pointer to the internal frame object. + */ + explicit IRFrame(const ob_frame *impl) : VideoFrame(impl) {}; + + ~IRFrame() noexcept override = default; +}; + +/** + * @brief Define the ConfidenceFrame class, which inherits from the VideoFrame class + * + */ +class ConfidenceFrame : public VideoFrame { + +public: + /** + * @brief Construct a new ConfidenceFrame object with a given pointer to the internal frame object. + * + * @attention After calling this constructor, the frame object will own the internal frame object, and the internal frame object will be deleted when the + * frame object is destroyed. + * @attention The internal frame object should not be deleted by the caller. + * @attention Please use the FrameFactory to create a Frame object. + * + * @param[in] impl The pointer to the internal frame object. + */ + explicit ConfidenceFrame(const ob_frame *impl) : VideoFrame(impl) {}; + + ~ConfidenceFrame() noexcept override = default; +}; + +/** + * @brief Define the PointsFrame class, which inherits from the Frame class + * @brief The PointsFrame class is used to obtain pointcloud data and point cloud information. + * + * @note The pointcloud data format can be obtained from the @ref Frame::getFormat() function. Witch can be one of the following formats: + * - @ref OB_FORMAT_POINT : 32-bit float format with 3D point coordinates (x, y, z), @ref OBPoint + * - @ref OB_FORMAT_RGB_POINT : 32-bit float format with 3D point coordinates (x, y, z) and point colors (r, g, b) @ref OBColorPoint + */ +class PointsFrame : public Frame { + +public: + /** + * @brief Construct a new PointsFrame object with a given pointer to the internal frame object. + * + * @attention After calling this constructor, the frame object will own the internal frame object, and the internal frame object will be deleted when the + * frame object is destroyed. + * @attention The internal frame object should not be deleted by the caller. + * @attention Please use the FrameFactory to create a Frame object. + * + * @param[in] impl The pointer to the internal frame object. + */ + explicit PointsFrame(const ob_frame *impl) : Frame(impl) {}; + + ~PointsFrame() noexcept override = default; + + /** + * @brief Get the point coordinate value scale of the points frame. The point position value of the points frame is multiplied by the scale to give a + * position value in millimeters. For example, if scale=0.1, the x-coordinate value of a point is x = 10000, which means that the actual x-coordinate value + * = x*scale = 10000*0.1 = 1000mm. + * + * @return float The coordinate value scale. + */ + float getCoordinateValueScale() const { + ob_error *error = nullptr; + auto scale = ob_points_frame_get_coordinate_value_scale(impl_, &error); + Error::handle(&error); + + return scale; + } + + /** + * @brief Get the width of the frame. + * + * @return uint32_t The width of the frame. + */ + uint32_t getWidth() const { + ob_error *error = nullptr; + // TODO + auto width = ob_point_cloud_frame_get_width(impl_, &error); + Error::handle(&error); + + return width; + } + + /** + * @brief Get the height of the frame. + * + * @return uint32_t The height of the frame. + */ + uint32_t getHeight() const { + ob_error *error = nullptr; + auto height = ob_point_cloud_frame_get_height(impl_, &error); + Error::handle(&error); + + return height; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. +#define getPositionValueScale getCoordinateValueScale +}; + +/** + * @brief Define the AccelFrame class, which inherits from the Frame class + * + */ +class AccelFrame : public Frame { + +public: + explicit AccelFrame(const ob_frame *impl) : Frame(impl) {}; + + ~AccelFrame() noexcept override = default; + + /** + * @brief Get the accelerometer frame data + * + * @return OBAccelValue The accelerometer frame data + */ + OBAccelValue getValue() const { + ob_error *error = nullptr; + auto value = ob_accel_frame_get_value(impl_, &error); + Error::handle(&error); + + return value; + } + + /** + * @brief Get the temperature when the frame was sampled + * + * @return float The temperature value in celsius + */ + float getTemperature() const { + ob_error *error = nullptr; + auto temp = ob_accel_frame_get_temperature(impl_, &error); + Error::handle(&error); + + return temp; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + OBAccelValue value() { + return getValue(); + } + + float temperature() { + return getTemperature(); + } +}; + +/** + * @brief Define the GyroFrame class, which inherits from the Frame class + */ +class GyroFrame : public Frame { + +public: + explicit GyroFrame(const ob_frame *impl) : Frame(impl) {}; + + ~GyroFrame() noexcept override = default; + + /** + * @brief Get the gyro frame data + * + * @return OBAccelValue The gyro frame data + */ + OBGyroValue getValue() const { + ob_error *error = nullptr; + auto value = ob_gyro_frame_get_value(impl_, &error); + Error::handle(&error); + + return value; + } + + /** + * @brief Get the temperature when the frame was sampled + * + * @return float The temperature value in celsius + */ + float getTemperature() const { + ob_error *error = nullptr; + auto temperature = ob_gyro_frame_get_temperature(impl_, &error); + Error::handle(&error); + + return temperature; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + OBGyroValue value() { + return getValue(); + } + + float temperature() { + return getTemperature(); + } +}; + +/** + * @brief Define the LiDARPointsFrame class, which inherits from the Frame class + * @brief The LiDARPointsFrame class is used to obtain LiDAR point cloud data. + * + * @note The pointcloud data format can be obtained from the @ref Frame::getFormat() function. Witch can be one of the following formats: + * - @ref OB_FORMAT_LIDAR_POINT : @ref OBLiDARPoint + * - @ref OB_FORMAT_LIDAR_SPHERE_POINT : @ref OBLiDARSpherePoint + * - @ref OB_FORMAT_LIDAR_SCAN : @ref OBLiDARScanPoint + * - @ref OB_FORMAT_LIDAR_CALIBRATION : LiDAR calibration mode point cloud, raw data + * - The pointcloud data holds a set of points. To find the number of points, divide the dataSize by the structure + * size of the corresponding point type. + */ +class LiDARPointsFrame : public Frame { +public: + /** + * @brief Construct a new LiDARPointsFrame object with a given pointer to the internal frame object. + * + * @attention After calling this constructor, the frame object will own the internal frame object, and the internal frame object will be deleted when the + * frame object is destroyed. + * @attention The internal frame object should not be deleted by the caller. + * @attention Please use the FrameFactory to create a Frame object. + * + * @param[in] impl The pointer to the internal frame object. + */ + explicit LiDARPointsFrame(const ob_frame *impl) : Frame(impl){}; + ~LiDARPointsFrame() noexcept override = default; +}; + +/** + * @brief Define the FrameSet class, which inherits from the Frame class + * @brief A FrameSet is a container for multiple frames of different types. + */ +class FrameSet : public Frame { + +public: + explicit FrameSet(const ob_frame *impl) : Frame(impl) {}; + + ~FrameSet() noexcept override = default; + + /** + * @brief Get the number of frames in the FrameSet + * + * @return uint32_t The number of frames + */ + uint32_t getCount() const { + ob_error *error = nullptr; + auto count = ob_frameset_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get a frame of a specific type from the FrameSet + * + * @param[in] frameType The type of sensor + * + * @return std::shared_ptr The corresponding type of frame + */ + std::shared_ptr getFrame(OBFrameType frameType) const { + ob_error *error = nullptr; + auto frame = ob_frameset_get_frame(impl_, frameType, &error); + if(!frame) { + return nullptr; + } + Error::handle(&error); + return std::make_shared(frame); + } + + /** + * @brief Get a frame at a specific index from the FrameSet + * + * @param[in] index The index of the frame + * + * @return std::shared_ptr The frame at the specified index + */ + std::shared_ptr getFrameByIndex(uint32_t index) const { + ob_error *error = nullptr; + auto frame = ob_frameset_get_frame_by_index(impl_, index, &error); + if(!frame) { + return nullptr; + } + Error::handle(&error); + return std::make_shared(frame); + } + + /** + * @brief Push a frame to the FrameSet + * + * @attention If the FrameSet contains the same type of frame, the new frame will replace the old one. + * + * @param[in] frame The frame to be pushed + */ + void pushFrame(std::shared_ptr frame) const { + ob_error *error = nullptr; + + // unsafe operation, need to cast const to non-const + auto unConstImpl = const_cast(impl_); + + auto otherImpl = frame->getImpl(); + ob_frameset_push_frame(unConstImpl, otherImpl, &error); + + Error::handle(&error); + } + + /** + * @brief Get the depth frame from the frameset. + * + * @return std::shared_ptr Return the depth frame. + */ + std::shared_ptr getDepthFrame() const { + ob_error *error = nullptr; + auto frame = ob_frameset_get_depth_frame(impl_, &error); + if(!frame) { + return nullptr; + } + Error::handle(&error); + return std::make_shared(frame); + } + + /** + * @brief Get the color frame from the frameset. + * + * @return std::shared_ptr Return the color frame. + */ + std::shared_ptr getColorFrame() const { + ob_error *error = nullptr; + auto frame = ob_frameset_get_color_frame(impl_, &error); + if(!frame) { + return nullptr; + } + Error::handle(&error); + return std::make_shared(frame); + } + + /** + * @brief Get the infrared frame from the frameset. + * + * @return std::shared_ptr Return the infrared frame. + */ + std::shared_ptr getIrFrame() const { + ob_error *error = nullptr; + auto frame = ob_frameset_get_ir_frame(impl_, &error); + if(!frame) { + return nullptr; + } + Error::handle(&error); + return std::make_shared(frame); + } + + /** + * @brief Get the point cloud frame from the frameset. + * + * @return std::shared_ptr Return the point cloud frame. + */ + std::shared_ptr getPointsFrame() const { + ob_error *error = nullptr; + auto frame = ob_frameset_get_points_frame(impl_, &error); + if(!frame) { + return nullptr; + } + Error::handle(&error); + return std::make_shared(frame); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t frameCount() const { + return getCount(); + } + + std::shared_ptr depthFrame() const { + auto frame = getFrame(OB_FRAME_DEPTH); + if(frame == nullptr) { + return nullptr; + } + auto depthFrame = frame->as(); + return depthFrame; + } + + std::shared_ptr colorFrame() const { + auto frame = getFrame(OB_FRAME_COLOR); + if(frame == nullptr) { + return nullptr; + } + auto colorFrame = frame->as(); + return colorFrame; + } + + std::shared_ptr irFrame() const { + auto frame = getFrame(OB_FRAME_IR); + if(frame == nullptr) { + return nullptr; + } + auto irFrame = frame->as(); + return irFrame; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + std::shared_ptr pointsFrame() const { + auto frame = getFrame(OB_FRAME_POINTS); + if(frame == nullptr) { + return nullptr; + } + auto pointsFrame = frame->as(); + return pointsFrame; + } + + std::shared_ptr getFrame(int index) const { + return getFrameByIndex(index); + } +}; + +/** + * @brief FrameFactory class, which provides some static functions to create frame objects + */ +class FrameFactory { +public: + /** + * @brief Create a Frame object of a specific type with a given format and data size. + * + * @param[in] frameType The type of the frame. + * @param[in] format The format of the frame. + * @param[in] dataSize The size of the data in bytes. + * + * @return std::shared_ptr The created frame object. + */ + static std::shared_ptr createFrame(OBFrameType frameType, OBFormat format, uint32_t dataSize) { + ob_error *error = nullptr; + auto impl = ob_create_frame(frameType, format, dataSize, &error); + Error::handle(&error); + + return std::make_shared(impl); + } + + /** + * @brief Create a VideoFrame object of a specific type with a given format, width, height, and stride. + * @note If stride is not specified, it will be calculated based on the width and format. + * + * @param[in] frameType The type of the frame. + * @param[in] format The format of the frame. + * @param[in] width The width of the frame. + * @param[in] height The height of the frame. + * @param[in] stride The stride of the frame. + * + * @return std::shared_ptr The created video frame object. + */ + static std::shared_ptr createVideoFrame(OBFrameType frameType, OBFormat format, uint32_t width, uint32_t height, uint32_t stride = 0) { + ob_error *error = nullptr; + auto impl = ob_create_video_frame(frameType, format, width, height, stride, &error); + Error::handle(&error); + + auto frame = std::make_shared(impl); + return frame->as(); + } + + /** + * @brief Create (clone) a frame object based on the specified other frame object. + * @brief The new frame object will have the same properties as the other frame object, but the data buffer is newly allocated. + * + * @param[in] otherFrame The source frame to be copied. + * @param[in] shouldCopyData If true, the data of the source frame object will be copied to the new frame object. If false, the new frame object will + * have a data buffer with random data. The default value is true. + * + * @return std::shared_ptr The new frame object. + */ + static std::shared_ptr createFrameFromOtherFrame(std::shared_ptr otherFrame, bool shouldCopyData = true) { + ob_error *error = nullptr; + auto otherImpl = otherFrame->getImpl(); + auto impl = ob_create_frame_from_other_frame(otherImpl, shouldCopyData, &error); + Error::handle(&error); + + return std::make_shared(impl); + } + + /** + * @brief Create a Frame From (according to)Stream Profile object + * + * @param[in] profile The stream profile object to create the frame from. + * + * @return std::shared_ptr The created frame object. + */ + static std::shared_ptr createFrameFromStreamProfile(std::shared_ptr profile) { + ob_error *error = nullptr; + auto impl = ob_create_frame_from_stream_profile(profile->getImpl(), &error); + Error::handle(&error); + + return std::make_shared(impl); + } + + /** + * @brief The callback function to destroy the buffer when the frame is destroyed. + */ + typedef std::function BufferDestroyCallback; + + /** + * @brief Create a frame object based on an externally created buffer. + * + * @attention The buffer is owned by the caller, and will not be destroyed by the frame object. The user should ensure that the buffer is valid and not + * modified. + * + * @param[in] frameType Frame object type. + * @param[in] format Frame object format. + * @param[in] buffer Frame object buffer. + * @param[in] destroyCallback Destroy callback, will be called when the frame object is destroyed. + * @param[in] bufferSize Frame object buffer size. + * + * @return std::shared_ptr The created frame object. + */ + static std::shared_ptr createFrameFromBuffer(OBFrameType frameType, OBFormat format, uint8_t *buffer, BufferDestroyCallback destroyCallback, + uint32_t bufferSize) { + ob_error *error = nullptr; + auto ctx = new BufferDestroyContext{ destroyCallback }; + auto impl = ob_create_frame_from_buffer(frameType, format, buffer, bufferSize, &FrameFactory::BufferDestroy, ctx, &error); + Error::handle(&error); + + return std::make_shared(impl); + } + + /** + * @brief Create a video frame object based on an externally created buffer. + * + * @attention The buffer is owned by the user and will not be destroyed by the frame object. The user should ensure that the buffer is valid and not + * modified. + * @attention The frame object is created with a reference count of 1, and the reference count should be decreased by calling @ref ob_delete_frame() when it + * is no longer needed. + * + * @param[in] frameType Frame object type. + * @param[in] format Frame object format. + * @param[in] width Frame object width. + * @param[in] height Frame object height. + * @param[in] buffer Frame object buffer. + * @param[in] bufferSize Frame object buffer size. + * @param[in] destroyCallback Destroy callback, will be called when the frame object is destroyed. + * @param[in] stride Row span in bytes. If 0, the stride is calculated based on the width and format. + * + * @return std::shared_ptr The created video frame object. + */ + static std::shared_ptr createVideoFrameFromBuffer(OBFrameType frameType, OBFormat format, uint32_t width, uint32_t height, uint8_t *buffer, + BufferDestroyCallback destroyCallback, uint32_t bufferSize, uint32_t stride = 0) { + ob_error *error = nullptr; + auto ctx = new BufferDestroyContext{ destroyCallback }; + auto impl = ob_create_video_frame_from_buffer(frameType, format, width, height, stride, buffer, bufferSize, &FrameFactory::BufferDestroy, ctx, &error); + Error::handle(&error); + + auto frame = std::make_shared(impl); + return frame->as(); + } + + /** + * @brief Create a new FrameSet object. + * + * This function creates a new FrameSet instance by internally calling the native C API. + * The returned FrameSet is managed by a std::shared_ptr, and its lifetime will be + * automatically managed. When no references remain, the underlying native resources will be released. + * + * @return std::shared_ptr The created FrameSet object. + */ + static std::shared_ptr createFrameSet() { + ob_error *error = nullptr; + auto impl = ob_create_frameset(&error); + Error::handle(&error); + return std::make_shared(impl); + } + +private: + struct BufferDestroyContext { + BufferDestroyCallback callback; + }; + + static void BufferDestroy(uint8_t *buffer, void *context) { + auto *ctx = static_cast(context); + if(ctx->callback) { + ctx->callback(buffer); + } + delete ctx; + } +}; + +/** + * @brief FrameHepler class, which provides some static functions to set timestamp for frame objects + * FrameHepler inherited from the FrameFactory and the timestamp interface implement here both for compatibility purposes. + */ +class FrameHelper : public FrameFactory { +public: + /** + * @brief Set the device timestamp of the frame. + * + * @param[in] frame The frame object. + * @param[in] deviceTimestampUs The device timestamp to set in microseconds. + */ + static void setFrameDeviceTimestampUs(std::shared_ptr frame, uint64_t deviceTimestampUs) { + ob_error *error = nullptr; + auto impl = const_cast(frame->getImpl()); + ob_frame_set_timestamp_us(impl, deviceTimestampUs, &error); + Error::handle(&error); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + static void setFrameSystemTimestamp(std::shared_ptr frame, uint64_t systemTimestamp) { + // In order to compile, some high-version compilers will warn that the function parameters are not used. + (void)frame; + (void)systemTimestamp; + } + + static void setFrameDeviceTimestamp(std::shared_ptr frame, uint64_t deviceTimestamp) { + // In order to compile, some high-version compilers will warn that the function parameters are not used. + (void)frame; + (void)deviceTimestamp; + } +}; + +// Define the is() template function for the Frame class +template bool Frame::is() const { + switch(this->getType()) { + case OB_FRAME_IR_LEFT: // Follow + case OB_FRAME_IR_RIGHT: // Follow + case OB_FRAME_IR: + return (typeid(T) == typeid(IRFrame) || typeid(T) == typeid(VideoFrame)); + case OB_FRAME_DEPTH: + return (typeid(T) == typeid(DepthFrame) || typeid(T) == typeid(VideoFrame)); + case OB_FRAME_COLOR: + case OB_FRAME_COLOR_LEFT: + case OB_FRAME_COLOR_RIGHT: + return (typeid(T) == typeid(ColorFrame) || typeid(T) == typeid(VideoFrame)); + case OB_FRAME_CONFIDENCE: + return (typeid(T) == typeid(ConfidenceFrame) || typeid(T) == typeid(VideoFrame)); + case OB_FRAME_GYRO: + return (typeid(T) == typeid(GyroFrame)); + case OB_FRAME_ACCEL: + return (typeid(T) == typeid(AccelFrame)); + case OB_FRAME_POINTS: + return (typeid(T) == typeid(PointsFrame)); + case OB_FRAME_LIDAR_POINTS: + return (typeid(T) == typeid(LiDARPointsFrame)); + case OB_FRAME_SET: + return (typeid(T) == typeid(FrameSet)); + default: + std::cout << "ob::Frame::is() did not catch frame type: " << (int)this->getType() << std::endl; + break; + } + return false; +} + +} // namespace ob diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Pipeline.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Pipeline.hpp new file mode 100644 index 0000000..d510440 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Pipeline.hpp @@ -0,0 +1,486 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Pipeline.hpp + * @brief The SDK's advanced API type can quickly implement switching streaming and frame synchronization + * operations. + */ +#pragma once + +#include "Frame.hpp" +#include "Device.hpp" +#include "StreamProfile.hpp" + +#include "libobsensor/h/Pipeline.h" +#include "libobsensor/hpp/Types.hpp" +#include "libobsensor/hpp/TypeHelper.hpp" + +#include +#include +namespace ob { + +/** + * @brief Config class for configuring pipeline parameters + * + * The Config class provides an interface for configuring pipeline parameters. + */ +class Config { +private: + ob_config_t *impl_; + +public: + /** + * @brief Construct a new Config object + */ + Config() { + ob_error *error = nullptr; + impl_ = ob_create_config(&error); + Error::handle(&error); + } + + explicit Config(ob_config_t *impl) : impl_(impl) {} + + /** + * @brief Destroy the Config object + */ + ~Config() noexcept { + ob_error *error = nullptr; + ob_delete_config(impl_, &error); + Error::handle(&error, false); + } + + ob_config_t *getImpl() const { + return impl_; + } + + /** + * @brief enable a stream with a specific stream type + * + * @param[in] streamType The stream type to be enabled + */ + void enableStream(OBStreamType streamType) const { + ob_error *error = nullptr; + ob_config_enable_stream(impl_, streamType, &error); + Error::handle(&error); + } + + /** + * @brief Enable a stream with a specific sensor type + * @brief Will convert sensor type to stream type automatically. + * + * @param[in] sensorType The sensor type to be enabled + */ + void enableStream(OBSensorType sensorType) const { + auto streamType = ob::TypeHelper::convertSensorTypeToStreamType(sensorType); + enableStream(streamType); + } + + /** + * @brief Enable a stream to be used in the pipeline + * + * @param[in] streamProfile The stream configuration to be enabled + */ + void enableStream(std::shared_ptr streamProfile) const { + ob_error *error = nullptr; + auto c_stream_profile = streamProfile->getImpl(); + ob_config_enable_stream_with_stream_profile(impl_, c_stream_profile, &error); + Error::handle(&error); + } + + /** + * @brief Enable a video stream to be used in the pipeline. + * + * This function allows users to enable a video stream with customizable parameters. + * If no parameters are specified, the stream will be enabled with default resolution settings. + * Users who wish to set custom resolutions should refer to the product manual, as available resolutions vary by camera model. + * + * @param[in] streamType The video stream type. + * @param[in] width The video stream width (default is OB_WIDTH_ANY, which selects the default resolution). + * @param[in] height The video stream height (default is OB_HEIGHT_ANY, which selects the default resolution). + * @param[in] fps The video stream frame rate (default is OB_FPS_ANY, which selects the default frame rate). + * @param[in] format The video stream format (default is OB_FORMAT_ANY, which selects the default format). + */ + void enableVideoStream(OBStreamType streamType, uint32_t width = OB_WIDTH_ANY, uint32_t height = OB_HEIGHT_ANY, uint32_t fps = OB_FPS_ANY, + OBFormat format = OB_FORMAT_ANY) const { + ob_error *error = nullptr; + ob_config_enable_video_stream(impl_, streamType, width, height, fps, format, &error); + Error::handle(&error); + } + + /** + * @brief Enable a video stream to be used in the pipeline. + * @brief Will convert sensor type to stream type automatically. + * + * @param[in] sensorType The sensor type to be enabled. + * @param[in] width The video stream width (default is OB_WIDTH_ANY, which selects the default resolution). + * @param[in] height The video stream height (default is OB_HEIGHT_ANY, which selects the default resolution). + * @param[in] fps The video stream frame rate (default is OB_FPS_ANY, which selects the default frame rate). + * @param[in] format The video stream format (default is OB_FORMAT_ANY, which selects the default format). + */ + void enableVideoStream(OBSensorType sensorType, uint32_t width = OB_WIDTH_ANY, uint32_t height = OB_HEIGHT_ANY, uint32_t fps = OB_FPS_ANY, + OBFormat format = OB_FORMAT_ANY) const { + auto streamType = ob::TypeHelper::convertSensorTypeToStreamType(sensorType); + enableVideoStream(streamType, width, height, fps, format); + } + + /** + * @brief Enable a video stream to be used in the pipeline with decimation configuration. + * @brief Will convert sensor type to stream type automatically. + * + * @param[in] sensorType The sensor type to be enabled. + * @param[in] decimationConfig The decimation configuration for this stream. + * @param[in] fps The video stream frame rate (default is OB_FPS_ANY, which selects the default frame rate). + * @param[in] format The video stream format (default is OB_FORMAT_ANY, which selects the default format). + */ + void enableVideoStream(OBSensorType sensorType, OBHardwareDecimationConfig decimationConfig, uint32_t fps = OB_FPS_ANY, + OBFormat format = OB_FORMAT_ANY) const { + auto streamType = ob::TypeHelper::convertSensorTypeToStreamType(sensorType); + ob_error *error = nullptr; + ob_config_enable_video_stream_by_decimation_config(impl_, streamType, decimationConfig, fps, format, &error); + Error::handle(&error); + } + + /** + * @brief Enable an accelerometer stream to be used in the pipeline. + * + * This function allows users to enable an accelerometer stream with customizable parameters. + * If no parameters are specified, the stream will be enabled with default settings. + * Users who wish to set custom full-scale ranges or sample rates should refer to the product manual, as available settings vary by device model. + * + * @param[in] fullScaleRange The full-scale range of the accelerometer (default is OB_ACCEL_FULL_SCALE_RANGE_ANY, which selects the default range). + * @param[in] sampleRate The sample rate of the accelerometer (default is OB_ACCEL_SAMPLE_RATE_ANY, which selects the default rate). + */ + void enableAccelStream(OBAccelFullScaleRange fullScaleRange = OB_ACCEL_FULL_SCALE_RANGE_ANY, + OBAccelSampleRate sampleRate = OB_ACCEL_SAMPLE_RATE_ANY) const { + ob_error *error = nullptr; + ob_config_enable_accel_stream(impl_, fullScaleRange, sampleRate, &error); + Error::handle(&error); + } + + /** + * @brief Enable a gyroscope stream to be used in the pipeline. + * + * This function allows users to enable a gyroscope stream with customizable parameters. + * If no parameters are specified, the stream will be enabled with default settings. + * Users who wish to set custom full-scale ranges or sample rates should refer to the product manual, as available settings vary by device model. + * + * @param[in] fullScaleRange The full-scale range of the gyroscope (default is OB_GYRO_FULL_SCALE_RANGE_ANY, which selects the default range). + * @param[in] sampleRate The sample rate of the gyroscope (default is OB_GYRO_SAMPLE_RATE_ANY, which selects the default rate). + */ + void enableGyroStream(OBGyroFullScaleRange fullScaleRange = OB_GYRO_FULL_SCALE_RANGE_ANY, OBGyroSampleRate sampleRate = OB_GYRO_SAMPLE_RATE_ANY) const { + ob_error *error = nullptr; + ob_config_enable_gyro_stream(impl_, fullScaleRange, sampleRate, &error); + Error::handle(&error); + } + + /** + * @brief Enable a LiDAR stream to be used in the pipeline. + * + * This function allows users to enable a LiDAR stream with customizable parameters. + * If no parameters are specified, the stream will be enabled with default settings. + * Users who wish to set custom full-scale ranges or sample rates should refer to the product manual, as available settings vary by device model. + * + * @param[in] scanRate The scan rate of the LiDAR (default is OB_LIDAR_SCAN_ANY, which selects the default scan rate). + * @param[in] format The stream format (default is OB_FORMAT_ANY, which selects the default format). + */ + void enableLiDARStream(OBLiDARScanRate scanRate = OB_LIDAR_SCAN_ANY, OBFormat format = OB_FORMAT_ANY) const { + ob_error *error = nullptr; + ob_config_enable_lidar_stream(impl_, scanRate, format, &error); + Error::handle(&error); + } + + /** + * @deprecated Use enableStream(std::shared_ptr streamProfile) instead + * @brief Enable all streams to be used in the pipeline + */ + void enableAllStream() { + ob_error *error = nullptr; + ob_config_enable_all_stream(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Disable a stream to be used in the pipeline + * + * @param[in] streamType The stream configuration to be disabled + */ + void disableStream(OBStreamType streamType) const { + ob_error *error = nullptr; + ob_config_disable_stream(impl_, streamType, &error); + Error::handle(&error); + } + + /** + * @brief Disable a sensor stream to be used in the pipeline. + * @brief Will convert sensor type to stream type automatically. + * + * @param[in] sensorType The sensor configuration to be disabled + */ + void disableStream(OBSensorType sensorType) const { + auto streamType = ob::TypeHelper::convertSensorTypeToStreamType(sensorType); + disableStream(streamType); + } + + /** + * @brief Disable all streams to be used in the pipeline + */ + void disableAllStream() const { + ob_error *error = nullptr; + ob_config_disable_all_stream(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Get the Enabled Stream Profile List + * + * @return std::shared_ptr + */ + std::shared_ptr getEnabledStreamProfileList() const { + ob_error *error = nullptr; + auto list = ob_config_get_enabled_stream_profile_list(impl_, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief Set the alignment mode + * + * @param[in] mode The alignment mode + */ + void setAlignMode(OBAlignMode mode) const { + ob_error *error = nullptr; + ob_config_set_align_mode(impl_, mode, &error); + Error::handle(&error); + } + + /** + * @brief Set whether the depth needs to be scaled after setting D2C + * + * @param[in] enable Whether scaling is required + */ + void setDepthScaleRequire(bool enable) const { + ob_error *error = nullptr; + ob_config_set_depth_scale_after_align_require(impl_, enable, &error); + Error::handle(&error); + } + + /** + * @brief Set the frame aggregation output mode for the pipeline configuration + * @brief The processing strategy when the FrameSet generated by the frame aggregation function does not contain the frames of all opened streams (which + * can be caused by different frame rates of each stream, or by the loss of frames of one stream): drop directly or output to the user. + * + * @param[in] mode The frame aggregation output mode to be set (default mode is @ref OB_FRAME_AGGREGATE_OUTPUT_ANY_SITUATION) + */ + void setFrameAggregateOutputMode(OBFrameAggregateOutputMode mode) const { + ob_error *error = nullptr; + ob_config_set_frame_aggregate_output_mode(impl_, mode, &error); + Error::handle(&error); + } +}; + +class Pipeline { +public: + /** + * @brief FrameSetCallback is a callback function type for frameset data arrival. + * + * @param[in] frame The returned frameset data + */ + typedef std::function frame)> FrameSetCallback; + +private: + ob_pipeline_t *impl_; + FrameSetCallback callback_; + +public: + /** + * @brief Pipeline is a high-level interface for applications, algorithms related RGBD data streams. Pipeline can provide alignment inside and synchronized + * FrameSet. Pipeline() no parameter version, which opens the first device in the list of devices connected to the OS by default. If the application has + * obtained the device through the DeviceList, opening the Pipeline() at this time will throw an exception that the device has been created. + */ + Pipeline() { + ob_error *error = nullptr; + impl_ = ob_create_pipeline(&error); + Error::handle(&error); + } + + /** + * @brief + * Pipeline(std::shared_ptr< Device > device ) Function for multi-device operations. Multiple devices need to be obtained through DeviceList, and the device + * and pipeline are bound through this interface. + */ + explicit Pipeline(std::shared_ptr device) { + ob_error *error = nullptr; + impl_ = ob_create_pipeline_with_device(device->getImpl(), &error); + Error::handle(&error); + } + + /** + * @brief Destroy the pipeline object + */ + ~Pipeline() noexcept { + ob_error *error = nullptr; + ob_delete_pipeline(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Start the pipeline with configuration parameters + * + * @param[in] config The parameter configuration of the pipeline + */ + void start(std::shared_ptr config = nullptr) const { + ob_error *error = nullptr; + ob_config_t *config_impl = config == nullptr ? nullptr : config->getImpl(); + ob_pipeline_start_with_config(impl_, config_impl, &error); + Error::handle(&error); + } + + /** + * @brief Start the pipeline and set the frameset data callback + * + * @param[in] config The configuration of the pipeline + * @param[in] callback The callback to be triggered when all frame data in the frameset arrives + */ + void start(std::shared_ptr config, FrameSetCallback callback) { + callback_ = callback; + ob_error *error = nullptr; + ob_pipeline_start_with_callback(impl_, config ? config->getImpl() : nullptr, &Pipeline::frameSetCallback, this, &error); + Error::handle(&error); + } + + static void frameSetCallback(ob_frame_t *frameSet, void *userData) { + auto pipeline = static_cast(userData); + pipeline->callback_(std::make_shared(frameSet)); + } + + /** + * @brief Stop the pipeline + */ + void stop() const { + ob_error *error = nullptr; + ob_pipeline_stop(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Get the pipeline configuration parameters + * @brief Returns the default configuration if the user has not configured it + * + * @return std::shared_ptr The configured parameters + */ + std::shared_ptr getConfig() const { + ob_error *error = nullptr; + auto config = ob_pipeline_get_config(impl_, &error); + Error::handle(&error); + return std::make_shared(config); + } + + /** + * @brief Wait for frameset + * + * @param[in] timeoutMs The waiting timeout in milliseconds + * + * @return std::shared_ptr The waiting frameset data + */ + std::shared_ptr waitForFrameset(uint32_t timeoutMs = 1000) const { + ob_error *error = nullptr; + auto frameSet = ob_pipeline_wait_for_frameset(impl_, timeoutMs, &error); + if(frameSet == nullptr) { + return nullptr; + } + Error::handle(&error); + return std::make_shared(frameSet); + } + + /** + * @brief Get the device object + * + * @return std::shared_ptr The device object + */ + std::shared_ptr getDevice() const { + ob_error *error = nullptr; + auto device = ob_pipeline_get_device(impl_, &error); + Error::handle(&error); + return std::make_shared(device); + } + + /** + * @brief Get the stream profile of the specified sensor + * + * @param[in] sensorType The type of sensor + * + * @return std::shared_ptr The stream profile list + */ + std::shared_ptr getStreamProfileList(OBSensorType sensorType) const { + ob_error *error = nullptr; + auto list = ob_pipeline_get_stream_profile_list(impl_, sensorType, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief Get the stream profile list of supported depth-to-color alignments + * + * @param[in] colorProfile The color stream profile, which is the target stream profile for the depth-to-color alignment. + * @param[in] alignMode The alignment mode. + * + * @attention Currently, only ALIGN_D2C_HW_MODE supported. For other align modes, please using the AlignFilter interface. + * + * @return std::shared_ptr The stream profile list of supported depth-to-color alignments. + */ + std::shared_ptr getD2CDepthProfileList(std::shared_ptr colorProfile, OBAlignMode alignMode) { + ob_error *error = nullptr; + auto list = ob_get_d2c_depth_profile_list(impl_, colorProfile->getImpl(), alignMode, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief Turn on frame synchronization + */ + void enableFrameSync() const { + ob_error *error = nullptr; + ob_pipeline_enable_frame_sync(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Turn off frame synchronization + */ + void disableFrameSync() const { + ob_error *error = nullptr; + ob_pipeline_disable_frame_sync(impl_, &error); + Error::handle(&error); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + + OBCameraParam getCameraParam() { + ob_error *error = nullptr; + OBCameraParam cameraParam = ob_pipeline_get_camera_param(impl_, &error); + Error::handle(&error); + return cameraParam; + } + + OBCameraParam getCameraParamWithProfile(uint32_t colorWidth, uint32_t colorHeight, uint32_t depthWidth, uint32_t depthHeight) { + ob_error *error = nullptr; + OBCameraParam cameraParam = ob_pipeline_get_camera_param_with_profile(impl_, colorWidth, colorHeight, depthWidth, depthHeight, &error); + Error::handle(&error); + return cameraParam; + } + + OBCalibrationParam getCalibrationParam(std::shared_ptr config) { + ob_error *error = nullptr; + OBCalibrationParam calibrationParam = ob_pipeline_get_calibration_param(impl_, config->getImpl(), &error); + Error::handle(&error); + return calibrationParam; + } + + std::shared_ptr waitForFrames(uint32_t timeoutMs = 1000) const { + return waitForFrameset(timeoutMs); + } +}; + +} // namespace ob diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/RecordPlayback.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/RecordPlayback.hpp new file mode 100644 index 0000000..fe61de2 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/RecordPlayback.hpp @@ -0,0 +1,188 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file RecordPlayback.hpp + * @brief Record and playback device-related types, including interfaces to create recording and playback devices, + record and playback streaming data, etc. + */ + +#pragma once + +#include "Types.hpp" +#include "Error.hpp" +#include "libobsensor/h/RecordPlayback.h" +#include "libobsensor/hpp/Device.hpp" + +namespace ob { + +typedef std::function PlaybackStatusChangeCallback; + +class RecordDevice { +private: + ob_record_device_t *impl_ = nullptr; + +public: + explicit RecordDevice(std::shared_ptr device, const std::string &file, bool compressionEnabled = true) { + ob_error *error = nullptr; + impl_ = ob_create_record_device(device->getImpl(), file.c_str(), compressionEnabled, &error); + Error::handle(&error); + } + + virtual ~RecordDevice() noexcept { + ob_error *error = nullptr; + ob_delete_record_device(impl_, &error); + Error::handle(&error, false); + } + + RecordDevice(RecordDevice &&other) noexcept { + if(this != &other) { + impl_ = other.impl_; + other.impl_ = nullptr; + } + } + + RecordDevice &operator=(RecordDevice &&other) noexcept { + if(this != &other) { + impl_ = other.impl_; + other.impl_ = nullptr; + } + + return *this; + } + + RecordDevice(const RecordDevice &) = delete; + RecordDevice &operator=(const RecordDevice &) = delete; + +public: + void pause() { + ob_error *error = nullptr; + ob_record_device_pause(impl_, &error); + Error::handle(&error); + } + + void resume() { + ob_error *error = nullptr; + ob_record_device_resume(impl_, &error); + Error::handle(&error); + } +}; + +class PlaybackDevice : public Device { +public: + explicit PlaybackDevice(const std::string &file) : Device(nullptr) { + ob_error *error = nullptr; + impl_ = ob_create_playback_device(file.c_str(), &error); + Error::handle(&error); + } + + virtual ~PlaybackDevice() noexcept override = default; + + PlaybackDevice(PlaybackDevice &&other) noexcept : Device(std::move(other)) {} + + PlaybackDevice &operator=(PlaybackDevice &&other) noexcept { + Device::operator=(std::move(other)); + return *this; + } + + PlaybackDevice(const PlaybackDevice &) = delete; + PlaybackDevice &operator=(const PlaybackDevice &) = delete; + +public: + /** + * @brief Pause the streaming data from the playback device. + */ + void pause() { + ob_error *error = nullptr; + ob_playback_device_pause(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Resume the streaming data from the playback device. + */ + void resume() { + ob_error *error = nullptr; + ob_playback_device_resume(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Seek to a specific timestamp when playing back a recording. + * @param[in] timestamp The timestamp to seek to, in milliseconds. + */ + void seek(const int64_t timestamp) { + ob_error *error = nullptr; + ob_playback_device_seek(impl_, timestamp, &error); + Error::handle(&error); + } + + /** + * @brief Set the playback rate of the playback device. + * @param[in] rate The playback rate to set. + */ + void setPlaybackRate(const float rate) { + ob_error *error = nullptr; + ob_playback_device_set_playback_rate(impl_, rate, &error); + Error::handle(&error); + } + + /** + * @brief Set a callback function to be called when the playback status changes. + * @param[in] callback The callback function to set. + */ + void setPlaybackStatusChangeCallback(PlaybackStatusChangeCallback callback) { + callback_ = callback; + ob_error *error = nullptr; + ob_playback_device_set_playback_status_changed_callback(impl_, &PlaybackDevice::playbackStatusCallback, this, &error); + Error::handle(&error); + } + + /** + * @brief Get the current playback status of the playback device. + * @return The current playback status. + */ + OBPlaybackStatus getPlaybackStatus() const { + ob_error *error = nullptr; + OBPlaybackStatus status = ob_playback_device_get_current_playback_status(impl_, &error); + Error::handle(&error); + + return status; + } + + /** + * @brief Get the current position of the playback device. + * @return The current position of the playback device, in milliseconds. + */ + uint64_t getPosition() const { + ob_error *error = nullptr; + uint64_t position = ob_playback_device_get_position(impl_, &error); + Error::handle(&error); + + return position; + } + + /** + * @brief Get the duration of the playback device. + * @return The duration of the playback device, in milliseconds. + */ + uint64_t getDuration() const { + ob_error *error = nullptr; + uint64_t duration = ob_playback_device_get_duration(impl_, &error); + Error::handle(&error); + + return duration; + } + +private: + static void playbackStatusCallback(OBPlaybackStatus status, void *userData) { + auto *playbackDevice = static_cast(userData); + if(playbackDevice && playbackDevice->callback_) { + playbackDevice->callback_(status); + } + } + +private: + PlaybackStatusChangeCallback callback_; +}; +} // namespace ob \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Sensor.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Sensor.hpp new file mode 100644 index 0000000..1bda338 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Sensor.hpp @@ -0,0 +1,239 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Sensor.hpp + * @brief Defines types related to sensors, which are used to obtain stream configurations, open and close streams, and set and get sensor properties. + */ +#pragma once + +#include "Types.hpp" +#include "libobsensor/hpp/Filter.hpp" +#include "libobsensor/h/Sensor.h" +#include "libobsensor/h/Filter.h" +#include "Error.hpp" +#include "StreamProfile.hpp" +#include "Device.hpp" +#include "Frame.hpp" +#include +#include +#include + +namespace ob { + +class Sensor { +public: + /** + * @brief Callback function for frame data. + * + * @param[in] frame The frame data. + */ + typedef std::function frame)> FrameCallback; + +protected: + ob_sensor_t *impl_; + FrameCallback callback_; + +public: + explicit Sensor(ob_sensor_t *impl) : impl_(impl) {} + + Sensor(Sensor &&sensor) noexcept : impl_(sensor.impl_) { + sensor.impl_ = nullptr; + } + + Sensor &operator=(Sensor &&sensor) noexcept { + if(this != &sensor) { + ob_error *error = nullptr; + ob_delete_sensor(impl_, &error); + Error::handle(&error); + impl_ = sensor.impl_; + sensor.impl_ = nullptr; + } + return *this; + } + + Sensor(const Sensor &sensor) = delete; + Sensor &operator=(const Sensor &sensor) = delete; + + virtual ~Sensor() noexcept { + ob_error *error = nullptr; + ob_delete_sensor(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the sensor type. + * + * @return OBSensorType The sensor type. + */ + OBSensorType getType() const { + ob_error *error = nullptr; + auto type = ob_sensor_get_type(impl_, &error); + Error::handle(&error); + return type; + } + + /** + * @brief Get the list of stream profiles. + * + * @return std::shared_ptr The stream profile list. + */ + std::shared_ptr getStreamProfileList() const { + ob_error *error = nullptr; + auto list = ob_sensor_get_stream_profile_list(impl_, &error); + Error::handle(&error); + return std::make_shared(list); + } + + /** + * @brief Create a list of recommended filters for the sensor. + * + * @return OBFilterList list of frame processing block + */ + std::vector> createRecommendedFilters() const { + ob_error *error = nullptr; + auto list = ob_sensor_create_recommended_filter_list(impl_, &error); + Error::handle(&error); + auto filter_count = ob_filter_list_get_count(list, &error); + + std::vector> filters; + for(uint32_t i = 0; i < filter_count; i++) { + auto filterImpl = ob_filter_list_get_filter(list, i, &error); + Error::handle(&error); + filters.push_back(std::make_shared(filterImpl)); + } + ob_delete_filter_list(list, &error); + Error::handle(&error, false); + return filters; + } + + /** + * @brief Open a frame data stream and set up a callback. + * + * @param[in] streamProfile The stream configuration. + * @param[in] callback The callback to set when frame data arrives. + */ + void start(std::shared_ptr streamProfile, FrameCallback callback) { + ob_error *error = nullptr; + callback_ = std::move(callback); + ob_sensor_start(impl_, const_cast(streamProfile->getImpl()), &Sensor::frameCallback, this, &error); + Error::handle(&error); + } + + /** + * @brief Stop the stream. + */ + void stop() const { + ob_error *error = nullptr; + ob_sensor_stop(impl_, &error); + Error::handle(&error); + } + + /** + * @brief Dynamically switch resolutions. + * + * @param[in] streamProfile The resolution to switch to. + */ + void switchProfile(std::shared_ptr streamProfile) { + ob_error *error = nullptr; + ob_sensor_switch_profile(impl_, const_cast(streamProfile->getImpl()), &error); + Error::handle(&error); + } + +private: + static void frameCallback(ob_frame *frame, void *userData) { + auto sensor = static_cast(userData); + sensor->callback_(std::make_shared(frame)); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + OBSensorType type() const { + return getType(); + } + + std::vector> getRecommendedFilters() const { + return createRecommendedFilters(); + } +}; + +class SensorList { +private: + ob_sensor_list_t *impl_ = nullptr; + +public: + explicit SensorList(ob_sensor_list_t *impl) : impl_(impl) {} + + ~SensorList() noexcept { + ob_error *error = nullptr; + ob_delete_sensor_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Get the number of sensors. + * + * @return uint32_t The number of sensors. + */ + uint32_t getCount() const { + ob_error *error = nullptr; + auto count = ob_sensor_list_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Get the type of the specified sensor. + * + * @param[in] index The sensor index. + * + * @return OBSensorType The sensor type. + */ + OBSensorType getSensorType(uint32_t index) const { + ob_error *error = nullptr; + auto type = ob_sensor_list_get_sensor_type(impl_, index, &error); + Error::handle(&error); + return type; + } + + /** + * @brief Get a sensor by index number. + * + * @param[in] index The sensor index. The range is [0, count-1]. If the index exceeds the range, an exception will be thrown. + * + * @return std::shared_ptr The sensor object. + */ + std::shared_ptr getSensor(uint32_t index) const { + ob_error *error = nullptr; + auto sensor = ob_sensor_list_get_sensor(impl_, index, &error); + Error::handle(&error); + return std::make_shared(sensor); + } + + /** + * @brief Get a sensor by sensor type. + * + * @param[in] sensorType The sensor type to obtain. + * + * @return std::shared_ptr A sensor object. If the specified sensor type does not exist, it will return empty. + */ + std::shared_ptr getSensor(OBSensorType sensorType) const { + ob_error *error = nullptr; + auto sensor = ob_sensor_list_get_sensor_by_type(impl_, sensorType, &error); + Error::handle(&error); + return std::make_shared(sensor); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t count() const { + return getCount(); + } + + OBSensorType type(uint32_t index) const { + return getSensorType(index); + } +}; + +} // namespace ob + diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/StreamProfile.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/StreamProfile.hpp new file mode 100644 index 0000000..9b80d4b --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/StreamProfile.hpp @@ -0,0 +1,603 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file StreamProfile.hpp + * @brief The stream profile related type is used to get information such as the width, height, frame rate, and format of the stream. + */ +#pragma once + +#include "Types.hpp" +#include "libobsensor/h/StreamProfile.h" +#include "libobsensor/h/Error.h" +#include +#include + +namespace ob { + +class StreamProfile : public std::enable_shared_from_this { +protected: + const ob_stream_profile_t *impl_ = nullptr; + +public: + StreamProfile(StreamProfile &streamProfile) = delete; + StreamProfile &operator=(StreamProfile &streamProfile) = delete; + + StreamProfile(StreamProfile &&streamProfile) noexcept : impl_(streamProfile.impl_) { + streamProfile.impl_ = nullptr; + } + + StreamProfile &operator=(StreamProfile &&streamProfile) noexcept { + if(this != &streamProfile) { + ob_error *error = nullptr; + ob_delete_stream_profile(impl_, &error); + Error::handle(&error); + impl_ = streamProfile.impl_; + streamProfile.impl_ = nullptr; + } + return *this; + } + + virtual ~StreamProfile() noexcept { + if(impl_) { + ob_error *error = nullptr; + ob_delete_stream_profile(impl_, &error); + Error::handle(&error); + } + } + + const ob_stream_profile *getImpl() const { + return impl_; + } + + /** + * @brief Get the format of the stream. + * + * @return OBFormat return the format of the stream. + */ + OBFormat getFormat() const { + ob_error *error = nullptr; + auto format = ob_stream_profile_get_format(impl_, &error); + Error::handle(&error); + return format; + } + + /** + * @brief Get the type of stream. + * + * @return OBStreamType return the type of the stream. + */ + OBStreamType getType() const { + ob_error *error = nullptr; + auto type = ob_stream_profile_get_type(impl_, &error); + Error::handle(&error); + return type; + } + + /** + * @brief Get the extrinsic parameters from current stream profile to the given target stream profile. + * + * @return OBExtrinsic Return the extrinsic parameters. + */ + OBExtrinsic getExtrinsicTo(std::shared_ptr target) const { + ob_error *error = nullptr; + auto extrinsic = ob_stream_profile_get_extrinsic_to(impl_, const_cast(target->getImpl()), &error); + Error::handle(&error); + return extrinsic; + } + + /** + * @brief Set the extrinsic parameters from current stream profile to the given target stream profile. + * + * @tparam target Target stream profile. + * @tparam extrinsic The extrinsic. + */ + void bindExtrinsicTo(std::shared_ptr target, const OBExtrinsic &extrinsic) { + ob_error *error = nullptr; + ob_stream_profile_set_extrinsic_to(const_cast(impl_), const_cast(target->getImpl()), extrinsic, + &error); + Error::handle(&error); + } + + /** + * @brief Set the extrinsic parameters from current stream profile to the given target stream type. + * + * @tparam targetStreamType Target stream type. + * @tparam extrinsic The extrinsic. + */ + void bindExtrinsicTo(const OBStreamType &targetStreamType, const OBExtrinsic &extrinsic) { + ob_error *error = nullptr; + ob_stream_profile_set_extrinsic_to_type(const_cast(impl_), targetStreamType, extrinsic, &error); + Error::handle(&error); + } + + /** + * @brief Check if frame object is compatible with the given type. + * + * @tparam T Given type. + * + * @return bool return result. + */ + template bool is() const; + + /** + * @brief Converts object type to target type. + * + * @tparam T Target type. + * + * @return std::shared_ptr Return the result. Throws an exception if conversion is not possible. + */ + template std::shared_ptr as() { + if(!is()) { + throw std::runtime_error("Unsupported operation. Object's type is not the required type."); + } + + return std::dynamic_pointer_cast(shared_from_this()); + } + + /** + * @brief Converts object type to target type (const version). + * + * @tparam T Target type. + * + * @return std::shared_ptr Return the result. Throws an exception if conversion is not possible. + */ + template std::shared_ptr as() const { + if(!is()) { + throw std::runtime_error("Unsupported operation. Object's type is not the required type."); + } + + return std::static_pointer_cast(shared_from_this()); + } + + // The following interfaces are deprecated and are retained here for compatibility purposes. + OBFormat format() const { + return getFormat(); + } + + OBStreamType type() const { + return getType(); + } + +protected: + explicit StreamProfile(const ob_stream_profile_t *impl) : impl_(impl) {} +}; + +/** + * @brief Class representing a video stream profile. + */ +class VideoStreamProfile : public StreamProfile { +public: + explicit VideoStreamProfile(const ob_stream_profile_t *impl) : StreamProfile(impl) {} + + ~VideoStreamProfile() noexcept override = default; + + /** + * @brief Return the frame rate of the stream. + * + * @return uint32_t Return the frame rate of the stream. + */ + uint32_t getFps() const { + ob_error *error = nullptr; + auto fps = ob_video_stream_profile_get_fps(impl_, &error); + Error::handle(&error); + return fps; + } + + /** + * @brief Return the width of the stream. + * + * @return uint32_t Return the width of the stream. + */ + uint32_t getWidth() const { + ob_error *error = nullptr; + auto width = ob_video_stream_profile_get_width(impl_, &error); + Error::handle(&error); + return width; + } + + /** + * @brief Return the height of the stream. + * + * @return uint32_t Return the height of the stream. + */ + uint32_t getHeight() const { + ob_error *error = nullptr; + auto height = ob_video_stream_profile_get_height(impl_, &error); + Error::handle(&error); + return height; + } + + /** + * @brief Get the intrinsic parameters of the stream. + * + * @return OBCameraIntrinsic Return the intrinsic parameters. + */ + OBCameraIntrinsic getIntrinsic() const { + ob_error *error = nullptr; + auto intrinsic = ob_video_stream_profile_get_intrinsic(impl_, &error); + Error::handle(&error); + return intrinsic; + } + + /** + * @brief Set the intrinsic parameters of the stream. + * + * @param[in] intrinsic The intrinsic parameters. + */ + void setIntrinsic(const OBCameraIntrinsic &intrinsic) { + ob_error *error = nullptr; + ob_video_stream_profile_set_intrinsic(const_cast(impl_), intrinsic, &error); + Error::handle(&error); + } + + /** + * @brief Get the distortion parameters of the stream. + * @brief Brown distortion model + * + * @return OBCameraDistortion Return the distortion parameters. + */ + OBCameraDistortion getDistortion() const { + ob_error *error = nullptr; + auto distortion = ob_video_stream_profile_get_distortion(impl_, &error); + Error::handle(&error); + return distortion; + } + + /** + * @brief Set the distortion parameters of the stream. + * + * @param[in] distortion The distortion parameters. + */ + void setDistortion(const OBCameraDistortion &distortion) { + ob_error *error = nullptr; + ob_video_stream_profile_set_distortion(const_cast(impl_), distortion, &error); + Error::handle(&error); + } + + /** + * @brief Get the decimation configuration of the stream. + * Includes original resolution and scale factor. + * + * @return OBHardwareDecimationConfig Return the decimation configuration. + */ + OBHardwareDecimationConfig getDecimationConfig() const { + ob_error *error = nullptr; + auto decimationConfig = ob_video_stream_profile_get_decimation_config(const_cast(impl_), &error); + Error::handle(&error); + return decimationConfig; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t fps() const { + return getFps(); + } + + uint32_t width() const { + return getWidth(); + } + + uint32_t height() const { + return getHeight(); + } +}; + +/** + * @brief Class representing an accelerometer stream profile. + */ +class AccelStreamProfile : public StreamProfile { +public: + explicit AccelStreamProfile(const ob_stream_profile_t *impl) : StreamProfile(impl) {} + + ~AccelStreamProfile() noexcept override = default; + + /** + * @brief Return the full scale range. + * + * @return OBAccelFullScaleRange Return the scale range value. + */ + OBAccelFullScaleRange getFullScaleRange() const { + ob_error *error = nullptr; + auto fullScaleRange = ob_accel_stream_profile_get_full_scale_range(impl_, &error); + Error::handle(&error); + return fullScaleRange; + } + + /** + * @brief Return the sampling frequency. + * + * @return OBAccelFullScaleRange Return the sampling frequency. + */ + OBAccelSampleRate getSampleRate() const { + ob_error *error = nullptr; + auto sampleRate = ob_accel_stream_profile_get_sample_rate(impl_, &error); + Error::handle(&error); + return sampleRate; + } + + /** + * @brief get the intrinsic parameters of the stream. + * + * @return OBAccelIntrinsic Return the intrinsic parameters. + */ + OBAccelIntrinsic getIntrinsic() const { + ob_error *error = nullptr; + auto intrinsic = ob_accel_stream_profile_get_intrinsic(impl_, &error); + Error::handle(&error); + return intrinsic; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + OBAccelFullScaleRange fullScaleRange() const { + return getFullScaleRange(); + } + + OBAccelSampleRate sampleRate() const { + return getSampleRate(); + } +}; + +/** + * @brief Class representing a gyroscope stream profile. + */ +class GyroStreamProfile : public StreamProfile { +public: + explicit GyroStreamProfile(const ob_stream_profile_t *impl) : StreamProfile(impl) {} + + ~GyroStreamProfile() noexcept override = default; + + /** + * @brief Return the full scale range. + * + * @return OBAccelFullScaleRange Return the scale range value. + */ + OBGyroFullScaleRange getFullScaleRange() const { + ob_error *error = nullptr; + auto fullScaleRange = ob_gyro_stream_profile_get_full_scale_range(impl_, &error); + Error::handle(&error); + return fullScaleRange; + } + + /** + * @brief Return the sampling frequency. + * + * @return OBAccelFullScaleRange Return the sampling frequency. + */ + OBGyroSampleRate getSampleRate() const { + ob_error *error = nullptr; + auto sampleRate = ob_gyro_stream_profile_get_sample_rate(impl_, &error); + Error::handle(&error); + return sampleRate; + } + + /** + * @brief get the intrinsic parameters of the stream. + * + * @return OBGyroIntrinsic Return the intrinsic parameters. + */ + OBGyroIntrinsic getIntrinsic() const { + ob_error *error = nullptr; + auto intrinsic = ob_gyro_stream_get_intrinsic(impl_, &error); + Error::handle(&error); + return intrinsic; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + OBGyroFullScaleRange fullScaleRange() const { + return getFullScaleRange(); + } + + OBGyroSampleRate sampleRate() const { + return getSampleRate(); + } +}; + +/** + * @brief Class representing a LiDAR stream profile. + */ + +class LiDARStreamProfile : public StreamProfile { +public: + explicit LiDARStreamProfile(const ob_stream_profile_t *impl) : StreamProfile(impl) {} + + ~LiDARStreamProfile() noexcept override = default; + + OBLiDARScanRate getScanRate() const { + ob_error *error = nullptr; + auto rate = ob_lidar_stream_profile_get_scan_rate(impl_, &error); + Error::handle(&error); + return rate; + } +}; + +template bool StreamProfile::is() const { + switch(this->getType()) { + case OB_STREAM_VIDEO: + case OB_STREAM_IR: + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR_RIGHT: + case OB_STREAM_COLOR: + case OB_STREAM_COLOR_LEFT: + case OB_STREAM_COLOR_RIGHT: + case OB_STREAM_DEPTH: + case OB_STREAM_RAW_PHASE: + case OB_STREAM_CONFIDENCE: + return typeid(T) == typeid(VideoStreamProfile); + case OB_STREAM_ACCEL: + return typeid(T) == typeid(AccelStreamProfile); + case OB_STREAM_GYRO: + return typeid(T) == typeid(GyroStreamProfile); + case OB_STREAM_LIDAR: + return typeid(T) == typeid(LiDARStreamProfile); + default: + break; + } + return false; +} + +class StreamProfileFactory { +public: + static std::shared_ptr create(const ob_stream_profile_t *impl) { + ob_error *error = nullptr; + const auto type = ob_stream_profile_get_type(impl, &error); + Error::handle(&error); + switch(type) { + case OB_STREAM_IR: + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR_RIGHT: + case OB_STREAM_DEPTH: + case OB_STREAM_COLOR: + case OB_STREAM_COLOR_LEFT: + case OB_STREAM_COLOR_RIGHT: + case OB_STREAM_VIDEO: + case OB_STREAM_CONFIDENCE: + return std::make_shared(impl); + case OB_STREAM_ACCEL: + return std::make_shared(impl); + case OB_STREAM_GYRO: + return std::make_shared(impl); + case OB_STREAM_LIDAR: + return std::make_shared(impl); + default: { + ob_error *err = ob_create_error(OB_STATUS_ERROR, "Unsupported stream type.", "StreamProfileFactory::create", "", OB_EXCEPTION_TYPE_INVALID_VALUE); + Error::handle(&err); + return nullptr; + } + } + } +}; + +class StreamProfileList { +protected: + const ob_stream_profile_list_t *impl_; + +public: + explicit StreamProfileList(ob_stream_profile_list_t *impl) : impl_(impl) {} + ~StreamProfileList() noexcept { + ob_error *error = nullptr; + ob_delete_stream_profile_list(impl_, &error); + Error::handle(&error, false); + } + + /** + * @brief Return the number of StreamProfile objects. + * + * @return uint32_t Return the number of StreamProfile objects. + */ + uint32_t getCount() const { + ob_error *error = nullptr; + auto count = ob_stream_profile_list_get_count(impl_, &error); + Error::handle(&error); + return count; + } + + /** + * @brief Return the StreamProfile object at the specified index. + * + * @param[in] index The index of the StreamProfile object to be retrieved. Must be in the range [0, count-1]. Throws an exception if the index is out of + * range. + * + * @return std::shared_ptr Return the StreamProfile object. + */ + std::shared_ptr getProfile(uint32_t index) const { + ob_error *error = nullptr; + auto profile = ob_stream_profile_list_get_profile(impl_, index, &error); + Error::handle(&error); + return StreamProfileFactory::create(profile); + } + + /** + * @brief Match the corresponding video stream profile based on the passed-in parameters. If multiple Match are found, the first one in the list is + * returned by default. Throws an exception if no matching profile is found. + * + * @param[in] width The width of the stream. Pass OB_WIDTH_ANY if no matching condition is required. + * @param[in] height The height of the stream. Pass OB_HEIGHT_ANY if no matching condition is required. + * @param[in] format The type of the stream. Pass OB_FORMAT_ANY if no matching condition is required. + * @param[in] fps The frame rate of the stream. Pass OB_FPS_ANY if no matching condition is required. + * + * @return std::shared_ptr Return the matching resolution. + */ + std::shared_ptr getVideoStreamProfile(int width = OB_WIDTH_ANY, int height = OB_HEIGHT_ANY, OBFormat format = OB_FORMAT_ANY, + int fps = OB_FPS_ANY) const { + ob_error *error = nullptr; + auto profile = ob_stream_profile_list_get_video_stream_profile(impl_, width, height, format, fps, &error); + Error::handle(&error); + auto vsp = StreamProfileFactory::create(profile); + return vsp->as(); + } + + /** + * @brief Match the corresponding video stream profile according to the decimation configuration. If multiple profiles match, the first one in the list is + * returned. Throws an exception when no matching profile is found. + * + * @param[in] decimationConfig Decimation configuration. The actual resolution is computed fromthe original resolution and scale factor. + * @param[in] format Stream format. Pass OB_FORMAT_ANY if no matching condition is required. + * @param[in] fps Frame rate. Pass OB_FPS_ANY if no matching condition is required. + * + * @return std::shared_ptr Return the matched video stream profile. + */ + std::shared_ptr getVideoStreamProfile(OBHardwareDecimationConfig decimationConfig, OBFormat format = OB_FORMAT_ANY, + int fps = OB_FPS_ANY) const { + ob_error *error = nullptr; + auto profile = ob_stream_profile_list_get_video_stream_profile_by_decimation_config(impl_, decimationConfig, format, fps, &error); + Error::handle(&error); + auto vsp = StreamProfileFactory::create(profile); + return vsp->as(); + } + + /** + * @brief Match the corresponding accelerometer stream profile based on the passed-in parameters. If multiple Match are found, the first one in the list + * is returned by default. Throws an exception if no matching profile is found. + * + * @param[in] fullScaleRange The full scale range. Pass 0 if no matching condition is required. + * @param[in] sampleRate The sampling frequency. Pass 0 if no matching condition is required. + */ + std::shared_ptr getAccelStreamProfile(OBAccelFullScaleRange fullScaleRange, OBAccelSampleRate sampleRate) const { + ob_error *error = nullptr; + auto profile = ob_stream_profile_list_get_accel_stream_profile(impl_, fullScaleRange, sampleRate, &error); + Error::handle(&error); + auto asp = StreamProfileFactory::create(profile); + return asp->as(); + } + + /** + * @brief Match the corresponding gyroscope stream profile based on the passed-in parameters. If multiple Match are found, the first one in the list is + * returned by default. Throws an exception if no matching profile is found. + * + * @param[in] fullScaleRange The full scale range. Pass 0 if no matching condition is required. + * @param[in] sampleRate The sampling frequency. Pass 0 if no matching condition is required. + */ + std::shared_ptr getGyroStreamProfile(OBGyroFullScaleRange fullScaleRange, OBGyroSampleRate sampleRate) const { + ob_error *error = nullptr; + auto profile = ob_stream_profile_list_get_gyro_stream_profile(impl_, fullScaleRange, sampleRate, &error); + Error::handle(&error); + auto gsp = StreamProfileFactory::create(profile); + return gsp->as(); + } + + /** + * @brief Match the corresponding LiDAR stream profile based on the passed-in parameters. If multiple Match are found, the first one in the list is + * returned by default. Throws an exception if no matching profile is found. + * + * @param[in] scanRate The scan rate of LiDAR. Pass OB_LIDAR_SCAN_ANY if no matching condition is required. + * @param[in] format The type of the stream. Pass OB_FORMAT_ANY if no matching condition is required. + */ + std::shared_ptr getLiDARStreamProfile(OBLiDARScanRate scanRate, OBFormat format) const { + ob_error *error = nullptr; + auto profile = ob_stream_profile_list_get_lidar_stream_profile(impl_, scanRate, format, &error); + Error::handle(&error); + auto lsp = StreamProfileFactory::create(profile); + return lsp->as(); + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + uint32_t count() const { + return getCount(); + } +}; + +} // namespace ob diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/TypeHelper.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/TypeHelper.hpp new file mode 100644 index 0000000..855db69 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/TypeHelper.hpp @@ -0,0 +1,168 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include "libobsensor/h/ObTypes.h" +#include "libobsensor/h/TypeHelper.h" + +#include + +namespace ob { +class TypeHelper { +public: + /** + * @brief Convert OBFormat to " string " type and then return. + * + * @param[in] type OBFormat type. + * + * @return OBFormat of "string" type. + */ + static std::string convertOBFormatTypeToString(const OBFormat &type) { + return ob_format_type_to_string(type); + } + + /** + * @brief Convert OBFrameType to " string " type and then return. + * + * @param[in] type OBFrameType type. + * + * @return OBFrameType of "string" type. + */ + static std::string convertOBFrameTypeToString(const OBFrameType &type) { + return ob_frame_type_to_string(type); + } + + /** + * @brief Convert OBStreamType to " string " type and then return. + * + * @param[in] type OBStreamType type. + * + * @return OBStreamType of "string" type. + */ + static std::string convertOBStreamTypeToString(const OBStreamType &type) { + return ob_stream_type_to_string(type); + } + + /** + * @brief Convert OBSensorType to " string " type and then return. + * + * @param[in] type OBSensorType type. + * + * @return OBSensorType of "string" type. + */ + static std::string convertOBSensorTypeToString(const OBSensorType &type) { + return ob_sensor_type_to_string(type); + } + + /** + * @brief Convert OBIMUSampleRate to " string " type and then return. + * + * @param[in] type OBIMUSampleRate type. + * + * @return OBIMUSampleRate of "string" type. + */ + static std::string convertOBIMUSampleRateTypeToString(const OBIMUSampleRate &type) { + return ob_imu_rate_type_to_string(type); + } + + /** + * @brief Convert OBGyroFullScaleRange to " string " type and then return. + * + * @param[in] type OBGyroFullScaleRange type. + * + * @return OBGyroFullScaleRange of "string" type. + */ + static std::string convertOBGyroFullScaleRangeTypeToString(const OBGyroFullScaleRange &type) { + return ob_gyro_range_type_to_string(type); + } + + /** + * @brief Convert OBAccelFullScaleRange to " string " type and then return. + * + * @param[in] type OBAccelFullScaleRange type. + * + * @return OBAccelFullScaleRange of "string" type. + */ + static std::string convertOBAccelFullScaleRangeTypeToString(const OBAccelFullScaleRange &type) { + return ob_accel_range_type_to_string(type); + } + + /** + * @brief Convert OBLiDARScanRate to " string " type and then return. + * + * @param[in] type OBLiDARScanRate type. + * @return OBLiDARScanRate of "string" type. + */ + static std::string convertOBLiDARScanRateTypeToString(const OBLiDARScanRate &type) { + return ob_lidar_scan_rate_type_to_string(type); + } + + /** + * @brief Convert OBFrameMetadataType to " string " type and then return. + * + * @param[in] type OBFrameMetadataType type. + * + * @return OBFrameMetadataType of "string" type. + */ + static std::string convertOBFrameMetadataTypeToString(const OBFrameMetadataType &type) { + return ob_meta_data_type_to_string(type); + } + + /** + * @brief Convert OBSensorType to OBStreamType type and then return. + * + * @param[in] type OBSensorType type. + * + * @return OBStreamType type. + */ + static OBStreamType convertSensorTypeToStreamType(OBSensorType type) { + return ob_sensor_type_to_stream_type(type); + } + + /** + * @brief Check if the given sensor type is a video sensor. + * @brief Video sensors are sensors that produce video frames. + * @brief The following sensor types are considered video sensors: + * OB_SENSOR_COLOR, + * OB_SENSOR_COLOR_LEFT, + * OB_SENSOR_COLOR_RIGHT, + * OB_SENSOR_DEPTH, + * OB_SENSOR_IR, + * OB_SENSOR_IR_LEFT, + * OB_SENSOR_IR_RIGHT, + * OB_SENSOR_CONFIDENCE, + * + * @param[in] type The sensor type + * + * @return true/false + */ + static bool isVideoSensorType(OBSensorType type) { + return ob_is_video_sensor_type(type); + } + + /** + * @brief Check if the given stream type is a video stream. + * @brief Video streams are streams that contain video frames. + * @brief The following stream types are considered video streams: + * OB_STREAM_VIDEO, + * OB_STREAM_DEPTH, + * OB_STREAM_COLOR, + * OB_STREAM_COLOR_LEFT, + * OB_STREAM_COLOR_RIGHT, + * OB_STREAM_IR, + * OB_STREAM_IR_LEFT, + * OB_STREAM_IR_RIGHT, + * OB_STREAM_CONFIDENCE, + * + * @param[in] type The stream type to check. + * + * @return true if the given stream type is a video stream, false otherwise. + */ + static bool isVideoStreamType(OBStreamType type) { + return ob_is_video_stream_type(type); + } +}; +} // namespace ob diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Types.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Types.hpp new file mode 100644 index 0000000..420f1a0 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Types.hpp @@ -0,0 +1,5 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +#pragma once +#include diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Utils.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Utils.hpp new file mode 100644 index 0000000..c1f8a9a --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Utils.hpp @@ -0,0 +1,206 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Utils.hpp + * @brief The SDK utils class + * + */ +#pragma once +#include "libobsensor/h/Utils.h" +#include "Device.hpp" +#include "Types.hpp" +#include "Frame.hpp" + +#include + +namespace ob { +class Device; + +class CoordinateTransformHelper { +public: + /** + * @brief Transform a 3d point of a source coordinate system into a 3d point of the target coordinate system. + * + * @param[in] source_point3f Source 3d point value + * @param[in] extrinsic Transformation matrix from source to target + * @param[out] target_point3f Target 3d point value + * + * @return bool Transform result + */ + static bool transformation3dto3d(const OBPoint3f source_point3f, OBExtrinsic extrinsic, OBPoint3f *target_point3f) { + ob_error *error = NULL; + bool result = ob_transformation_3d_to_3d(source_point3f, extrinsic, target_point3f, &error); + Error::handle(&error); + return result; + } + + /** + * @brief Transform a 2d pixel coordinate with an associated depth value of the source camera into a 3d point of the target coordinate system. + * + * @param[in] source_intrinsic Source intrinsic parameters + * @param[in] source_point2f Source 2d point value + * @param[in] source_depth_pixel_value The depth of sourcePoint2f in millimeters + * @param[in] extrinsic Transformation matrix from source to target + * @param[out] target_point3f Target 3d point value + * + * @return bool Transform result + */ + static bool transformation2dto3d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic, + OBExtrinsic extrinsic, OBPoint3f *target_point3f) { + ob_error *error = NULL; + bool result = ob_transformation_2d_to_3d(source_point2f, source_depth_pixel_value, source_intrinsic, extrinsic, target_point3f, &error); + Error::handle(&error); + return result; + } + + /** + * @brief Transform a 3d point of a source coordinate system into a 2d pixel coordinate of the target camera. + * + * @param[in] source_point3f Source 3d point value + * @param[in] target_intrinsic Target intrinsic parameters + * @param[in] target_distortion Target distortion parameters + * @param[in] extrinsic Transformation matrix from source to target + * @param[out] target_point2f Target 2d point value + * + * @return bool Transform result + */ + static bool transformation3dto2d(const OBPoint3f source_point3f, const OBCameraIntrinsic target_intrinsic, const OBCameraDistortion target_distortion, + OBExtrinsic extrinsic, OBPoint2f *target_point2f) { + ob_error *error = NULL; + bool result = ob_transformation_3d_to_2d(source_point3f, target_intrinsic, target_distortion, extrinsic, target_point2f, &error); + Error::handle(&error); + return result; + } + + /** + * @brief Transform a 2d pixel coordinate with an associated depth value of the source camera into a 2d pixel coordinate of the target camera + * + * @param[in] source_intrinsic Source intrinsic parameters + * @param[in] source_distortion Source distortion parameters + * @param[in] source_point2f Source 2d point value + * @param[in] source_depth_pixel_value The depth of sourcePoint2f in millimeters + * @param[in] target_intrinsic Target intrinsic parameters + * @param[in] target_distortion Target distortion parameters + * @param[in] extrinsic Transformation matrix from source to target + * @param[out] target_point2f Target 2d point value + * + * @return bool Transform result + */ + static bool transformation2dto2d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic, + const OBCameraDistortion source_distortion, const OBCameraIntrinsic target_intrinsic, + const OBCameraDistortion target_distortion, OBExtrinsic extrinsic, OBPoint2f *target_point2f) { + ob_error *error = NULL; + bool result = ob_transformation_2d_to_2d(source_point2f, source_depth_pixel_value, source_intrinsic, source_distortion, target_intrinsic, + target_distortion, extrinsic, target_point2f, &error); + Error::handle(&error); + return result; + } + +public: + // The following interfaces are deprecated and are retained here for compatibility purposes. + static bool calibration3dTo3d(const OBCalibrationParam calibrationParam, const OBPoint3f sourcePoint3f, const OBSensorType sourceSensorType, + const OBSensorType targetSensorType, OBPoint3f *targetPoint3f) { + ob_error *error = NULL; + bool result = ob_calibration_3d_to_3d(calibrationParam, sourcePoint3f, sourceSensorType, targetSensorType, targetPoint3f, &error); + Error::handle(&error); + return result; + } + + static bool calibration2dTo3d(const OBCalibrationParam calibrationParam, const OBPoint2f sourcePoint2f, const float sourceDepthPixelValue, + const OBSensorType sourceSensorType, const OBSensorType targetSensorType, OBPoint3f *targetPoint3f) { + ob_error *error = NULL; + bool result = + ob_calibration_2d_to_3d(calibrationParam, sourcePoint2f, sourceDepthPixelValue, sourceSensorType, targetSensorType, targetPoint3f, &error); + Error::handle(&error); + return result; + } + + static bool calibration3dTo2d(const OBCalibrationParam calibrationParam, const OBPoint3f sourcePoint3f, const OBSensorType sourceSensorType, + const OBSensorType targetSensorType, OBPoint2f *targetPoint2f) { + ob_error *error = NULL; + bool result = ob_calibration_3d_to_2d(calibrationParam, sourcePoint3f, sourceSensorType, targetSensorType, targetPoint2f, &error); + Error::handle(&error); + return result; + } + + static bool calibration2dTo2d(const OBCalibrationParam calibrationParam, const OBPoint2f sourcePoint2f, const float sourceDepthPixelValue, + const OBSensorType sourceSensorType, const OBSensorType targetSensorType, OBPoint2f *targetPoint2f) { + ob_error *error = NULL; + bool result = + ob_calibration_2d_to_2d(calibrationParam, sourcePoint2f, sourceDepthPixelValue, sourceSensorType, targetSensorType, targetPoint2f, &error); + Error::handle(&error); + return result; + } + + static std::shared_ptr transformationDepthFrameToColorCamera(std::shared_ptr device, std::shared_ptr depthFrame, + uint32_t targetColorCameraWidth, uint32_t targetColorCameraHeight) { + ob_error *error = NULL; + + // unsafe operation, need to cast const to non-const + auto unConstImpl = const_cast(depthFrame->getImpl()); + + auto result = transformation_depth_frame_to_color_camera(device->getImpl(), unConstImpl, targetColorCameraWidth, targetColorCameraHeight, &error); + Error::handle(&error); + return std::make_shared(result); + } + + static bool transformationInitXYTables(const OBCalibrationParam calibrationParam, const OBSensorType sensorType, float *data, uint32_t *dataSize, + OBXYTables *xyTables) { + ob_error *error = NULL; + bool result = transformation_init_xy_tables(calibrationParam, sensorType, data, dataSize, xyTables, &error); + Error::handle(&error); + return result; + } + + static void transformationDepthToPointCloud(OBXYTables *xyTables, const void *depthImageData, void *pointCloudData) { + ob_error *error = NULL; + transformation_depth_to_pointcloud(xyTables, depthImageData, pointCloudData, &error); + Error::handle(&error, false); + } + + static void transformationDepthToRGBDPointCloud(OBXYTables *xyTables, const void *depthImageData, const void *colorImageData, void *pointCloudData) { + ob_error *error = NULL; + transformation_depth_to_rgbd_pointcloud(xyTables, depthImageData, colorImageData, pointCloudData, &error); + Error::handle(&error, false); + } +}; + +class PointCloudHelper { +public: + /** + * @brief save point cloud to ply file. + * + * @param[in] fileName Point cloud save path + * @param[in] frame Point cloud frame + * @param[in] saveBinary Binary or textual,true: binary, false: textual + * @param[in] useMesh Save mesh or not, true: save as mesh, false: not save as mesh + * @param[in] meshThreshold Distance threshold for creating faces in point cloud,default value :50 + * + * @return bool save point cloud result + */ + static bool savePointcloudToPly(const char *fileName, std::shared_ptr frame, bool saveBinary, bool useMesh, float meshThreshold) { + ob_error *error = NULL; + auto unConstImpl = const_cast(frame->getImpl()); + bool result = ob_save_pointcloud_to_ply(fileName, unConstImpl, saveBinary, useMesh, meshThreshold, &error); + Error::handle(&error, false); + return result; + } + + /** + * @brief Save LiDAR point cloud to PLY file. + * + * @param[in] fileName Point cloud save path + * @param[in] frame LiDAR point cloud frame + * @param[in] saveBinary Binary or textual,true: binary, false: textual + * @return bool save LiDAR point cloud result + */ + static bool saveLiDARPointcloudToPly(const char *fileName, std::shared_ptr frame, bool saveBinary) { + ob_error *error = NULL; + auto unConstImpl = const_cast(frame->getImpl()); + bool result = ob_save_lidar_pointcloud_to_ply(fileName, unConstImpl, saveBinary, &error); + Error::handle(&error, false); + return result; + } +}; +} // namespace ob diff --git a/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Version.hpp b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Version.hpp new file mode 100644 index 0000000..21b5246 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/include/libobsensor/hpp/Version.hpp @@ -0,0 +1,62 @@ +// Copyright (c) Orbbec Inc. All Rights Reserved. +// Licensed under the MIT License. + +/** + * @file Version.hpp + * @brief Provides functions to retrieve version information of the SDK. + */ +#pragma once + +#include "libobsensor/h/Version.h" + +namespace ob { +class Version { +public: + /** + * @brief Get the full version number of the SDK. + * @brief The full version number equals to: major * 10000 + minor * 100 + patch + * + * @return int The full version number of the SDK. + */ + static int getVersion() { + return ob_get_version(); + } + /** + * @brief Get the major version number of the SDK. + * + * @return int The major version number of the SDK. + */ + static int getMajor() { + return ob_get_major_version(); + } + + /** + * @brief Get the minor version number of the SDK. + * + * @return int The minor version number of the SDK. + */ + static int getMinor() { + return ob_get_minor_version(); + } + + /** + * @brief Get the patch version number of the SDK. + * + * @return int The patch version number of the SDK. + */ + static int getPatch() { + return ob_get_patch_version(); + } + + /** + * @brief Get the stage version of the SDK. + * @brief The stage version string is a vendor defined string for some special releases. + * + * @return char* The stage version string of the SDK. + */ + static const char *getStageVersion() { + return ob_get_stage_version(); + } +}; +} // namespace ob + diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKConfig-release.cmake b/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKConfig-release.cmake new file mode 100644 index 0000000..6f13ce7 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKConfig-release.cmake @@ -0,0 +1,19 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "ob::OrbbecSDK" for configuration "Release" +set_property(TARGET ob::OrbbecSDK APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(ob::OrbbecSDK PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.7.6" + IMPORTED_SONAME_RELEASE "libOrbbecSDK.so.2" + ) + +list(APPEND _cmake_import_check_targets ob::OrbbecSDK ) +list(APPEND _cmake_import_check_files_for_ob::OrbbecSDK "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.7.6" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKConfig.cmake b/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKConfig.cmake new file mode 100644 index 0000000..6a35f67 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKConfig.cmake @@ -0,0 +1,104 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.0 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.28) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS ob::OrbbecSDK) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target ob::OrbbecSDK +add_library(ob::OrbbecSDK SHARED IMPORTED) + +set_target_properties(ob::OrbbecSDK PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/OrbbecSDKConfig-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKVersion.cmake b/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKVersion.cmake new file mode 100644 index 0000000..5221f45 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/lib/arm64/OrbbecSDKVersion.cmake @@ -0,0 +1,65 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "2.7.6") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("2.7.6" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") + endif() + else() + set(CVF_VERSION_MAJOR "2.7.6") + endif() + + if(PACKAGE_FIND_VERSION_RANGE) + # both endpoints of the range must have the expected major version + math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") + if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + else() + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/depthengine/libdepthengine.so b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/depthengine/libdepthengine.so new file mode 100644 index 0000000..61c3e38 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/depthengine/libdepthengine.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/depthengine/libdepthengine.so.2.0 b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/depthengine/libdepthengine.so.2.0 new file mode 100644 index 0000000..61c3e38 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/depthengine/libdepthengine.so.2.0 differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/filters/libFilterProcessor.so b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/filters/libFilterProcessor.so new file mode 100644 index 0000000..0a156db Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/filters/libFilterProcessor.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/filters/libob_priv_filter.so b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/filters/libob_priv_filter.so new file mode 100644 index 0000000..7d49e83 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/filters/libob_priv_filter.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/firmwareupdater/libfirmwareupdater.so b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/firmwareupdater/libfirmwareupdater.so new file mode 100644 index 0000000..ac4fc4d Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/firmwareupdater/libfirmwareupdater.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/frameprocessor/libob_frame_processor.so b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/frameprocessor/libob_frame_processor.so new file mode 100644 index 0000000..4945d73 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/extensions/frameprocessor/libob_frame_processor.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so b/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so new file mode 100644 index 0000000..42876b7 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so.2 b/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so.2 new file mode 100644 index 0000000..42876b7 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so.2 differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so.2.7.6 b/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so.2.7.6 new file mode 100644 index 0000000..42876b7 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/arm64/libOrbbecSDK.so.2.7.6 differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKConfig-release.cmake b/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKConfig-release.cmake new file mode 100644 index 0000000..6f13ce7 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKConfig-release.cmake @@ -0,0 +1,19 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "ob::OrbbecSDK" for configuration "Release" +set_property(TARGET ob::OrbbecSDK APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(ob::OrbbecSDK PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.7.6" + IMPORTED_SONAME_RELEASE "libOrbbecSDK.so.2" + ) + +list(APPEND _cmake_import_check_targets ob::OrbbecSDK ) +list(APPEND _cmake_import_check_files_for_ob::OrbbecSDK "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.7.6" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKConfig.cmake b/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKConfig.cmake new file mode 100644 index 0000000..6a35f67 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKConfig.cmake @@ -0,0 +1,104 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.0 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.28) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS ob::OrbbecSDK) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target ob::OrbbecSDK +add_library(ob::OrbbecSDK SHARED IMPORTED) + +set_target_properties(ob::OrbbecSDK PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/OrbbecSDKConfig-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKVersion.cmake b/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKVersion.cmake new file mode 100644 index 0000000..5221f45 --- /dev/null +++ b/dev_ws/src/orbbec_camera/SDK/lib/x64/OrbbecSDKVersion.cmake @@ -0,0 +1,65 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "2.7.6") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("2.7.6" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") + endif() + else() + set(CVF_VERSION_MAJOR "2.7.6") + endif() + + if(PACKAGE_FIND_VERSION_RANGE) + # both endpoints of the range must have the expected major version + math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") + if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + else() + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/depthengine/libdepthengine.so b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/depthengine/libdepthengine.so new file mode 100644 index 0000000..dd818fa Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/depthengine/libdepthengine.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/depthengine/libdepthengine.so.2.0 b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/depthengine/libdepthengine.so.2.0 new file mode 100644 index 0000000..dd818fa Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/depthengine/libdepthengine.so.2.0 differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/filters/libFilterProcessor.so b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/filters/libFilterProcessor.so new file mode 100644 index 0000000..f5b8ef4 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/filters/libFilterProcessor.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/filters/libob_priv_filter.so b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/filters/libob_priv_filter.so new file mode 100644 index 0000000..0fbb433 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/filters/libob_priv_filter.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/firmwareupdater/libfirmwareupdater.so b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/firmwareupdater/libfirmwareupdater.so new file mode 100644 index 0000000..86c9e89 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/firmwareupdater/libfirmwareupdater.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/frameprocessor/libob_frame_processor.so b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/frameprocessor/libob_frame_processor.so new file mode 100644 index 0000000..def842a Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/extensions/frameprocessor/libob_frame_processor.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so b/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so new file mode 100644 index 0000000..82e5787 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so.2 b/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so.2 new file mode 100644 index 0000000..82e5787 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so.2 differ diff --git a/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so.2.7.6 b/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so.2.7.6 new file mode 100644 index 0000000..82e5787 Binary files /dev/null and b/dev_ws/src/orbbec_camera/SDK/lib/x64/libOrbbecSDK.so.2.7.6 differ diff --git a/dev_ws/src/orbbec_camera/cmake/FindORBBEC_SDK.cmake b/dev_ws/src/orbbec_camera/cmake/FindORBBEC_SDK.cmake new file mode 100644 index 0000000..9bb020d --- /dev/null +++ b/dev_ws/src/orbbec_camera/cmake/FindORBBEC_SDK.cmake @@ -0,0 +1,49 @@ +message("***************************************************") +message("* *") +message("* Find Orbbec SDK *") +message("* *") +message("***************************************************") + + +find_path(ORBBEC_SDK_INCLUDE_DIR "libobsensor/ObSensor.hpp" "/usr/local/include" "/usr/include") +message("include:\n${ORBBEC_SDK_INCLUDE_DIR}") + +execute_process(COMMAND uname -m OUTPUT_VARIABLE MACHINES) +execute_process(COMMAND getconf LONG_BIT OUTPUT_VARIABLE MACHINES_BIT) +MESSAGE(STATUS "ORRBEC Machine : ${MACHINES}") +MESSAGE(STATUS "ORRBEC Machine Bits : ${MACHINES_BIT}") +if ((${MACHINES} MATCHES "x86_64") AND (${MACHINES_BIT} MATCHES "64")) + set(HOST_PLATFORM "x64") +elseif ((${MACHINES} MATCHES "x86_64") AND (${MACHINES_BIT} MATCHES "32")) + set(HOST_PLATFORM "x86") +elseif (${MACHINES} MATCHES "x86") +elseif (${MACHINES} MATCHES "x86") + set(HOST_PLATFORM "x86") +elseif (${MACHINES} MATCHES "i686") + set(HOST_PLATFORM "x86") +elseif (${MACHINES} MATCHES "i386") + set(HOST_PLATFORM "x86") +elseif (${MACHINES} MATCHES "arm") + set(HOST_PLATFORM "arm") +elseif ((${MACHINES} MATCHES "aarch64") AND (${MACHINES_BIT} MATCHES "64")) + set(HOST_PLATFORM "arm64") +elseif ((${MACHINES} MATCHES "aarch64") AND (${MACHINES_BIT} MATCHES "32")) + set(HOST_PLATFORM "arm") +endif () + +message(STATUS "ORRBEC : ${HOST_PLATFORM}") + +set(ORBBEC_LIB_PATH "/usr/local/lib" "/usr/lib") + +message("Orbbec lib path: ${ORBBEC_LIB_PATH}") + +find_library(ORBBEC_SDK_LIBRARY NAMES OrbbecSDK PATHS ${ORBBEC_LIB_PATH} REQUIRED) +find_library(POSTFILTER_LIBRARY NAMES postfilter PATHS ${ORBBEC_LIB_PATH} REQUIRED) + +message("OrbbecSDK path: ${ORBBEC_SDK_LIBRARY}") +message("postfilter path: ${POSTFILTER_LIBRARY}") + +set(ORBBEC_SDK_LIBRARIES ${ORBBEC_SDK_LIBRARY} ${POSTFILTER_LIBRARY}) +message("libraries:\n${ORBBEC_SDK_LIBRARIES}") + +set(ORBBEC_SDK_FOUND TRUE) diff --git a/dev_ws/src/orbbec_camera/config/OrbbecSDKConfig_v2.0.xml b/dev_ws/src/orbbec_camera/config/OrbbecSDKConfig_v2.0.xml new file mode 100644 index 0000000..65d247f --- /dev/null +++ b/dev_ws/src/orbbec_camera/config/OrbbecSDKConfig_v2.0.xml @@ -0,0 +1,2856 @@ + + + + 1.1 + + + + + 1 + + 3 + + + + 100 + + 3 + + false + + + + + true + + 2048 + + 10 + + 10 + + + + + + + + true + + + true + + false + + 1920 + + 1080 + + 30 + + MJPG + ]]> + + + true + + + + + + + + + true + + + Auto + + + + + LibUVC + + + true + + 1000 + + 100 + + + + true + false + + + + 0 + + 1 + + + + + + 848 + + 530 + + 30 + Y16 + + + + 848 + + 530 + + 30 + YUYV + + + + 1280 + + 800 + + 30 + YUYV + + + + 1280 + + 800 + + 30 + YUYV + + + + 848 + + 530 + + 30 + Y8 + + + + 848 + + 530 + + 30 + Y8 + + + + + + + LibUVC + + + true + + 1000 + + 100 + + + + false + true + + + + 0 + + 1 + + + 1 + + 3000 + + 3000 + + 848 + + 530 + + 30 + Y16 + + + + 1 + + 3000 + + 3000 + + 848 + + 530 + + 30 + YUYV + + + + 848 + + 530 + + 30 + Y8 + + + + 848 + + 530 + + 30 + Y8 + + + + + + V4L2 + + + false + + 1000 + + 100 + + + + + 640 + + 576 + + 30 + + Y16 + + + + + 1920 + + 1080 + + 30 + + MJPG + + + + + 640 + + 576 + + 30 + + Y16 + + + + + + false + + 1000 + + 100 + + + + + 640 + + 576 + + 30 + + Y16 + + + + + 1920 + + 1080 + + 30 + + MJPG + + + + + 640 + + 576 + + 30 + + Y16 + + + + + + LibUVC + + + false + + 1000 + + 100 + + + + + 640 + + 576 + + 30 + + Y16 + + + + + 1920 + + 1080 + + 30 + + MJPG + + + + + 640 + + 576 + + 30 + + Y16 + + + + + + + LibUVC + + + false + + 1000 + + 100 + + + + 0 + + + 1280 + + 800 + + 30 + RLE + + + + 1280 + + 720 + + 30 + MJPG + + + + 1280 + + 800 + + 30 + Y8 + + + + 1280 + + 800 + + 30 + Y8 + + + + 1280 + + 800 + + 30 + Y8 + + + + + + + + + + + + + + + + 640 + + 400 + + 30 + RLE + + + + 640 + + 400 + + 30 + Y8 + + + + + + + 640 + + 400 + + 15 + RLE + + + + + + 1920 + + 1080 + + 30 + MJPG + + + + 1280 + + 800 + + 30 + Y10 + + + + 1280 + + 800 + + 30 + Y10 + + + + + + + 1920 + + 1080 + + 30 + MJPG + + + + 1280 + + 800 + + 30 + Y8 + + + + 1280 + + 800 + + 30 + Y8 + + + + + + + + LibUVC + + + false + + 1000 + + 100 + + + + 0 + + + + 1280 + + 800 + + 30 + RLE + + + + 1280 + + 720 + + 30 + + MJPG + + + + 1280 + + 800 + + 30 + + Y8 + + + + 1280 + + 800 + + 30 + Y8 + + + + 1280 + + 800 + + 30 + Y8 + + + + + + + 640 + + 400 + + 30 + RLE + + + + 640 + + 400 + + 30 + Y8 + + + + + + 1920 + + 1080 + + 30 + MJPG + + + + 1280 + + 800 + + 30 + Y10 + + + + 1280 + + 800 + + 30 + Y10 + + + + + + + 1920 + + 1080 + + 30 + MJPG + + + + 1280 + + 800 + + 30 + Y8 + + + + 1280 + + 800 + + 30 + Y8 + + + + + + + + LibUVC + + + false + + 1000 + + 100 + + + + 0 + + + + + + 800 + + 600 + + 30 + RLE + + + + 1280 + + 720 + + 30 + MJPG + + + + 800 + + 600 + + 30 + Y8 + + + + + + 1600 + + 1200 + + 30 + RLE + + + + 1280 + + 720 + + 30 + MJPG + + + + 800 + + 600 + + 30 + Y8 + + + + + + 640 + + 480 + + 30 + RLE + + + + 1280 + + 720 + + 30 + MJPG + + + + 640 + + 480 + + 30 + Y8 + + + + + + + + LibUVC + + + false + + 1000 + + 100 + + + + 0 + + + + 1280 + + 800 + + 10 + RVL + + + + 1280 + + 800 + + 10 + MJPG + + + + 1280 + + 800 + + 10 + Y8 + + + + 1280 + + 800 + + 10 + Y8 + + + + + + + + + + + 1280 + + 800 + + 20 + MJPG + + + + 640 + + 400 + + 20 + RVL + + + + 640 + + 400 + + 20 + Y8 + + + + 640 + + 400 + + 20 + Y8 + + + + + + 1280 + + 800 + + 10 + MJPG + + + + 1280 + + 800 + + 10 + Y10 + + + + 1280 + + 800 + + 10 + Y10 + + + + + + 1280 + + 800 + + 10 + MJPG + + + + 1280 + + 800 + + 10 + Y8 + + + + 1280 + + 800 + + 10 + Y8 + + + + + + + + LibUVC + + + true + + 1000 + + 100 + + + + false + true + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + + LibUVC + + + true + + 1000 + + 100 + + + + false + true + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + LibUVC + + + true + + 1000 + + 100 + + + + false + true + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + + LibUVC + + + true + + 1000 + + 100 + + + + false + true + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + + LibUVC + + + true + + 1000 + + 100 + + + + false + true + + + + 0 + + 1 + + + 1 + + 3000 + + 3000 + + 848 + + 480 + + 30 + Y16 + + + + 1 + + 3000 + + 3000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + + 0 + + 1 + + true + + 1000 + + 100 + + + + false + true + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 640 + + 400 + + 15 + Y16 + + + + 0 + + 2000 + + 2000 + + 640 + + 400 + + 15 + MJPG + + + + 640 + + 400 + + 15 + Y8 + + + + 640 + + 400 + + 15 + Y8 + + + + + + + LibUVC + + + false + true + + + + true + + 1000 + + 100 + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + + LibUVC + + + false + true + + + + true + + 1000 + + 100 + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + LibUVC + + + true + + 1000 + + 100 + + + + true + false + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + + LibUVC + + + true + + 1000 + + 100 + + + + false + true + + + + 0 + + 1 + + + + 640 + + 480 + + 30 + Y16 + + + + 1280 + + 720 + + 30 + MJPG + + + + 640 + + 480 + + 30 + Y8 + + + + 640 + + 480 + + 30 + Y8 + + + + 640 + + 480 + + 30 + Y8 + + + + + + LibUVC + + + true + + 1000 + + 100 + + + false + true + + + + 0 + + 1 + + + + 640 + + 480 + + 30 + Y16 + + + + 1280 + + 720 + + 30 + MJPG + + + + 640 + + 480 + + 30 + Y8 + + + + 640 + + 480 + + 30 + Y8 + + + + 640 + + 480 + + 30 + Y8 + + + + + + + LibUVC + + + true + + 1000 + + 100 + + + false + true + + + + 0 + + 1 + + + + 640 + + 480 + + 30 + Y16 + + + + 1280 + + 720 + + 30 + MJPG + + + + 640 + + 480 + + 30 + Y8 + + + + 640 + + 480 + + 30 + Y8 + + + + 640 + + 480 + + 30 + Y8 + + + + + + LibUVC + + + true + + 1000 + + 100 + + + false + true + + + + 0 + + 1 + + + + 640 + + 480 + + 30 + Y16 + + + + 1280 + + 720 + + 30 + MJPG + + + + 640 + + 480 + + 30 + Y8 + + + + 640 + + 480 + + 30 + Y8 + + + + 640 + + 480 + + 30 + Y8 + + + + + + LibUVC + + + false + + 1000 + + 100 + + + + 0 + + + + 1280 + + 800 + + 15 + Y16 + + + + 1280 + + 720 + + 15 + + MJPG + + + + 1280 + + 800 + + 15 + + Y8 + + + + + + LibUVC + + + false + + 1000 + + 100 + + + + 0 + + + + 1280 + + 800 + + 15 + Y16 + + + + 1280 + + 720 + + 15 + + MJPG + + + + 1280 + + 800 + + 15 + + Y8 + + + + + + + LibUVC + + + false + true + + + + true + + 1000 + + 100 + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + + LibUVC + + + false + true + + + + true + + 1000 + + 100 + + + + 0 + + 1 + + + + + + 0 + + 2000 + + 2000 + + 848 + + 480 + + 30 + Y16 + + + + 0 + + 2000 + + 2000 + + 1280 + + 720 + + 30 + MJPG + + + + 848 + + 480 + + 30 + Y8 + + + + 848 + + 480 + + 30 + Y8 + + + + + + + LibUVC + + + 0 + + + 1.2 + + + true + + 1000 + + 100 + + + + + 15 + + 5000 + + 3000 + + 1280 + + 800 + + 10 + Y16 + + + + 1280 + + 800 + + 10 + MJPG + + 15 + + 5000 + + 3000 + + + + 1280 + + 800 + + 10 + Y8 + + 15 + + 5000 + + 3000 + + + + 1280 + + 800 + + 10 + Y8 + + 15 + + 5000 + + 3000 + + + + + 0 + + 5000 + + 3000 + + + + 0 + + 5000 + + 3000 + + + + + + + 1280 + + 800 + + 10 + MJPG + + 15 + + 5000 + + 3000 + + + + 1280 + + 800 + + 10 + Y10 + + 15 + + 5000 + + 3000 + + + + 1280 + + 800 + + 10 + Y10 + + 15 + + 5000 + + 3000 + + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 400 + + 10 + Y12 + + + + 640 + + 480 + + 10 + MJPG + + + + 640 + + 400 + + 10 + Y10 + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 400 + + 10 + Y12 + + + + 640 + + 400 + + 10 + Y10 + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 480 + + 30 + Y12 + + + + 640 + + 480 + + 30 + Y10 + + + + 640 + + 480 + + 30 + UYVY + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 480 + + 30 + Y12 + + + + 640 + + 480 + + 30 + Y10 + + + + 640 + + 480 + + 30 + UYVY + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 480 + + 30 + Y12 + + + + 640 + + 480 + + 30 + Y10 + + + + 640 + + 480 + + 30 + UYVY + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 400 + + 15 + Y12 + + + + 640 + + 400 + + 15 + Y10 + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 400 + + 15 + Y12 + + + + 640 + + 400 + + 15 + Y10 + + + + 640 + + 480 + + 15 + MJPG + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 400 + + 15 + Y12 + + + + 640 + + 400 + + 15 + Y10 + + + + + LibUVC + + + true + + + + 1 + + + + + 640 + + 400 + + 15 + Y12 + + + + 640 + + 400 + + 15 + Y10 + + + + 640 + + 480 + + 15 + MJPG + + + + diff --git a/dev_ws/src/orbbec_camera/config/camera_params.yaml b/dev_ws/src/orbbec_camera/config/camera_params.yaml new file mode 100644 index 0000000..0e3d062 --- /dev/null +++ b/dev_ws/src/orbbec_camera/config/camera_params.yaml @@ -0,0 +1,65 @@ +# common params +depth_registration: false +enable_d2c_viewer: false +enable_point_cloud: false +enable_colored_point_cloud: false +enable_ldp: false +device_preset: "Default" +enable_laser: true + +# enable_laser: true +interleave_ae_mode: "laser" +interleave_frame_enable: false +interleave_skip_enable: false +interleave_skip_index: 1 +time_domain: "global" # global, device, system +enable_sync_host_time: true + +trigger_out_enabled: true +frames_per_trigger: 0 +software_trigger_period: 0 + + +# color params +enable_color: true +color_width: 0 +color_height: 0 +color_fps: 0 +color_format: "ANY" +enable_color_auto_exposure: true +color_exposure: 30 # 3ms +color_gain: 16 # -1 default + +# depth params +enable_depth: true +depth_width: 0 +depth_height: 0 +depth_fps: 0 +depth_format: "ANY" + + +#left ir params +enable_left_ir: false +left_ir_width: 0 +left_ir_height: 0 +left_ir_fps: 0 +left_ir_format: "ANY" +enable_ir_auto_exposure: true +ir_exposure: 3000 # 3ms +ir_gain: 16 # -1 default + +#right ir params +enable_right_ir: false +right_ir_width: 0 +right_ir_height: 0 +right_ir_fps: 0 +right_ir_format: "ANY" + +#ir params +# enable_ir: true +# ir_width: 0 +# ir_height: 0 +# ir_fps: 0 +# ir_format: "ANY" + + diff --git a/dev_ws/src/orbbec_camera/config/common.yaml b/dev_ws/src/orbbec_camera/config/common.yaml new file mode 100644 index 0000000..bf8a7fd --- /dev/null +++ b/dev_ws/src/orbbec_camera/config/common.yaml @@ -0,0 +1,433 @@ +# config/*.yaml files are used to configure the camera parameters +--- +orbbec_ros: + camera_parameters: + general: + # Camera model. support product models by referencing config/*.yaml + camera_model: "gemini330_series" + # The configuration file for yaml params. + config_file_path: "gemini330_series.yaml" + # Log level. Supported levels are 'debug', 'info', 'warning' and 'error'. Default is 'none'. + log_level: "none" + + deivce: + # camera name, usually overwritten by launch file + camera_name: "camera" + # camera serial number, usually overwritten by launch file + serial_number: "" + # The USB port of the camera. This parameter is required when using multiple cameras. + usb_port: "" + # Number of devices. If multiple cameras are required, this parameter must be filled in launch file + device_num: 1 + # Optional values: v4l2, libuvc + uvc_backend: "libuvc" + # Usually no need to change,will be read from the device + product_id: "" + # The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default. + connection_delay: 10 + # Select timestamp type: "device" , 鈥済lobal鈥� and "system" + time_domain: "device" + # If the camera is connected to a USB 2.0 port and is not detected, the system will attempt to reset the camera up to three times. This setting is designed to prevent USB 3.0 devices from being mistakenly identified as USB 2.0. + # It is recommended to set this parameter to false when using a USB 2.0 connection to avoid unnecessary resets + retry_on_usb3_detection_failure: false + # If true, the heartbeat will be enabled + enable_heartbeat: false + # If true, the camera will be reset + enable_hardware_reset: false + # If true, the LDP will be enabled + enable_ldp: true + # The preset of the device. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation + # Predefined presets doc reference: docs/source/2_installation/package_description.md + # Deep working mode support is as follows:{"Default","Hand","High Accuracy","High Density","Medium Density","Custom"} + device_preset: "Default" + + network_device: + # Whether to enable the function of enumerating network devices. True means enabled and false means disabled. This function is only supported by Femto Mega and Gemini 2 XL devices. + # When accessing these devices through the network, the IP address of the device needs to be preconfigured. The enable switch needs to be set to true. + enumerate_net_device: false + # Port number of the network device. If 0, a random port will be used + net_device_port: 0 + # IP address of the network device. + net_device_ip: "" + + color: + # If true, the color image will be enabled + enable_color: true + # Quality of Service for the color image topic and the color camera info topic + # [color|depth|ir]_qos, and [color|depth|ir]_camera_info_qos and [point_cloud_qos] are the Quality of Service (QoS) settings in ROS 2 messages. + # The possible values include SYSTEM_DEFAULT, DEFAULT, PARAMETER_EVENTS, SERVICES_DEFAULT, PARAMETERS, and SENSOR_DATA, and these values are not case-sensitive. + # They respectively correspond to rmw_qos_profile_system_default, rmw_qos_profile_default, rmw_qos_profile_parameter_events, rmw_qos_profile_services_default, rmw_qos_profile_parameters, and SENSOR_DATA. + color_qos: "default" + color_camera_info_qos: "default" + # Width of the color image. If 0, the default width will be used + color_width: 0 + # Height of the color image. If 0, the default height will be used + color_height: 0 + # Fps of the color image. If 0, the default FPS will be used + color_fps: 0 + # default Format of the color image. + color_format: "ANY" + # If true, the color image will be flipped horizontally + color_flip: false + + # If true, the color image will be undistorted + enable_color_undistortion: false + # enable auto white balance for the color image + enable_color_auto_white_balance: true + # Manual set white balance value for the color image. If -1, note:enable_color_auto_white_balance: false + color_white_balance: -1 + + # Auto exposure enable & configuration + color_auto_ae: + # enable auto exposure for the color image + enable_color_auto_exposure: true + # maximum exposure value for the color image. If -1, the default value will be used + color_ae_max_exposure: -1 + # left edge of the auto exposure region of interest. If -1, the default value will be used + color_ae_roi_left: -1 + # top edge of the auto exposure region of interest. If -1, the default value will be used + color_ae_roi_top: -1 + # right edge of the auto exposure region of interest. If -1, the default value will be used + color_ae_roi_right: -1 + # bottom edge of the auto exposure region of interest. If -1, the default value will be used + color_ae_roi_bottom: -1 + + # Manual exposure must set enable_color_auto_exposure: false + color_manual_ae: + # exposure value for the color image. If -1, the default exposure will be used + color_exposure: -1 + # gain value for the color image. If -1, the default gain will be used + color_gain: -1 + # brightness value for the color image. If -1, the default brightness will be used + color_brightness: -1 + + depth: + # If true, the depth image will be enabled + enable_depth: true + # Quality of Service for the depth image topic and the depth camera info topic + # [color|depth|ir]_qos, and [color|depth|ir]_camera_info_qos and [point_cloud_qos] are the Quality of Service (QoS) settings in ROS 2 messages. + # The possible values include SYSTEM_DEFAULT, DEFAULT, PARAMETER_EVENTS, SERVICES_DEFAULT, PARAMETERS, and SENSOR_DATA, and these values are not case-sensitive. + # They respectively correspond to rmw_qos_profile_system_default, rmw_qos_profile_default, rmw_qos_profile_parameter_events, rmw_qos_profile_services_default, rmw_qos_profile_parameters, and SENSOR_DATA. + depth_qos: "default" + depth_camera_info_qos: "default" + # Width of the depth image. If 0, the default width will be used + depth_width: 0 + # Height of the depth image. If 0, the default height will be used + depth_height: 0 + # Fps of the depth image. If 0, the default FPS will be used + depth_fps: 0 + # default Format of the depth image. + depth_format: "ANY" + # If true, the depth image will be flipped horizontally + depth_flip: false + # If false, the depth scale will not be enabled + enable_depth_scale: true + # Depth accuracy, the format should be 1mm. The default value is 1mm. + depth_precision: "" + + # D2C Depth registration mode. + # Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true + depth_registration: true + # The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment + align_mode: "SW" + + # Gemini 2, Gemini 2 L, and Gemini 2 XL cameras support deep working mode switching + # Specific camera deep working mode support types can be found in the deep mode comments. + # Deep working mode support is as follows:{"Unbinned Dense Default","Unbinned Sparse Default","Binned Sparse Default","Obstacle Avoidance"} + # Depth work mode. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation. + depth_work_mode: "" + + # Configure the loading path of the deep filtering configuration file. By default, the deep filtering configuration file is located in the /config/depthfilter directory and is only supported by Gemini2. + depth_filter_config: "" + + # Auto exposure region of interest left. If -1, the default value will be used + depth_ae_roi: + depth_ae_roi_left: -1 + # Auto exposure region of interest top. If -1, the default value will be used + depth_ae_roi_top: -1 + # Auto exposure region of interest right. If -1, the default value will be used + depth_ae_roi_right: -1 + # Auto exposure region of interest bottom. If -1, the default value will be used + depth_ae_roi_bottom: -1 + + laser: + # Whether to enable the laser. Default value is true + enable_laser: true + # Laser energy level. If -1, the default energy level will be used + laser_energy_level: -1 + + filter: + # This filtering effectively reduces the complexity of the depth scene. The filtering operates with kernel sizes ranging from [2x2] to [8x8] pixels. + # The image size is proportionally reduced in both dimensions to maintain the aspect ratio. + decimation_filter: + # If true, the decimation filter will be enabled + enable_decimation_filter: false + # Decimation filter scale. If -1, the default scale will be used + decimation_filter_scale: -1 + + # This filtering removes speckle noise in the form of clusters and produces a depth map with less filling. + noise_removal_filter: + # If true, the noise removal filter will be enabled + enable_noise_removal_filter: true + # Noise removal filter min diff. + noise_removal_filter_min_diff: 256 + # Noise removal filter max size + noise_removal_filter_max_size: 80 + + # This filter retains depth values of interest and ignores depth values that are out of range. + threshold_filter: + # If true, the threshold filter will be enabled + enable_threshold_filter: false + # Threshold filter max. If -1, the default max will be used + threshold_filter_max: -1 + # Threshold filter min. If -1, the default min will be used + threshold_filter_min: -1 + + # This filtering process, specified by multiple iterations according to the amplitude parameter, is used to enhance the smoothness of depth data. + # It can also fill small holes in the depth map. + spatial_filter: + # -enable_spatial_filter + enable_spatial_filter: false + # Spatial filter alpha. If -1, the default alpha will be used + spatial_filter_alpha: -1.0 + # Spatial filter diff threshold. If -1, the default threshold will be used + spatial_filter_diff_threshold: -1 + # Spatial filter magnitude. If -1, the default magnitude will be used + spatial_filter_magnitude: -1 + # Spatial filter radius. If -1, the default radius will be used + spatial_filter_radius: -1 + + # This filtering aims to improve the persistence of depth data by manipulating per-pixel values based on previous frames. The filtering performs a single processing on the data, + # adjusting depth values while updating tracking history. + temporal_filter: + # -enable_temporal_filter + enable_temporal_filter: false + # Temporal filter diff threshold. If -1, the default threshold will be used + temporal_filter_diff_threshold: -1.0 + # Temporal filter weight. If -1, the default weight will be used + temporal_filter_weight: -1.0 + + # This filter fills all holes in the depth map using the specified mode. + hole_filling_filter: + # -enable_hole_filling_filter + enable_hole_filling_filter: false + # Hole filling filter mode. If empty, the default mode will be used + hole_filling_filter_mode: "" + + soft_filter: + # If false, the soft filter will not be enabled + enable_soft_filter: true + # The maximum difference between the current and previous depth frame to be considered valid + soft_filter_max_diff: -1 + # The size of the speckle to be filtered out + soft_filter_speckle_size: -1 + + # This filtering is used in conjunction with the deep HDR function and only outputs sequences with the specified sequence ID. + sequence_filter: + # If true, the sequence ID filter will be enabled + enable_sequence_id_filter: false + # Sequence ID filter ID. If -1, the default ID will be used + sequence_id_filter_id: -1 + + # This filtering is used in conjunction with the deep HDR function. By merging consecutive depth images with alternating exposure values, + # we can simultaneously overcome the challenges of obtaining depth values for low-light and over-illuminated objects. + hdr_filter: + # If true, the HDR merge filter will be enabled + enable_hdr_merge: false + # HDR merge exposure1, If -1, the default value will be used + hdr_merge_exposure_1: -1 + # HDR merge gain1, If -1, the default value will be used + hdr_merge_gain_1: -1 + # HDR merge exposure2, If -1, the default value will be used + hdr_merge_exposure_2: -1 + # HDR merge gain2, If -1, the default value will be used + hdr_merge_gain_2: -1 + + leftir: + # If false, the left IR image will not be enabled + enable_left_ir: false + # Quality of Service for the left IR image topic and the left IR camera info topic + # [color|depth|ir]_qos, and [color|depth|ir]_camera_info_qos and [point_cloud_qos] are the Quality of Service (QoS) settings in ROS 2 messages. + # The possible values include SYSTEM_DEFAULT, DEFAULT, PARAMETER_EVENTS, SERVICES_DEFAULT, PARAMETERS, and SENSOR_DATA, and these values are not case-sensitive. + # They respectively correspond to rmw_qos_profile_system_default, rmw_qos_profile_default, rmw_qos_profile_parameter_events, rmw_qos_profile_services_default, rmw_qos_profile_parameters, and SENSOR_DATA. + left_ir_qos: "default" + left_ir_camera_info_qos: "default" + # Width of the left IR image. If 0, the default width will be used + left_ir_width: 0 + # Height of the left IR image. If 0, the default height will be used + left_ir_height: 0 + # Fps of the left IR image. If 0, the default FPS will be used + left_ir_fps: 0 + # Format of the left IR image. Supported formats are 'Y8' + left_ir_format: "ANY" + + rightir: + # If false, the right IR image will not be enabled + enable_right_ir: false + # Quality of Service for the right IR image topic and the right IR camera info topic + # [color|depth|ir]_qos, and [color|depth|ir]_camera_info_qos and [point_cloud_qos] are the Quality of Service (QoS) settings in ROS 2 messages. + # The possible values include SYSTEM_DEFAULT, DEFAULT, PARAMETER_EVENTS, SERVICES_DEFAULT, PARAMETERS, and SENSOR_DATA, and these values are not case-sensitive. + # They respectively correspond to rmw_qos_profile_system_default, rmw_qos_profile_default, rmw_qos_profile_parameter_events, rmw_qos_profile_services_default, rmw_qos_profile_parameters, and SENSOR_DATA. + right_ir_qos: "default" + right_ir_camera_info_qos: "default" + # Width of the right IR image. If 0, the default width will be used + right_ir_width: 0 + # Height of the right IR image. If 0, the default height will be used + right_ir_height: 0 + # Fps of the right IR image. If 0, the default FPS will be used + right_ir_fps: 0 + # Format of the right IR image. Supported formats are 'Y8' + right_ir_format: "ANY" + + ir: + # If false, the left IR image will not be enabled + enable_ir: false + # Quality of Service for the IR image topic and the IR camera info topic + # [color|depth|ir]_qos, and [color|depth|ir]_camera_info_qos and [point_cloud_qos] are the Quality of Service (QoS) settings in ROS 2 messages. + # The possible values include SYSTEM_DEFAULT, DEFAULT, PARAMETER_EVENTS, SERVICES_DEFAULT, PARAMETERS, and SENSOR_DATA, and these values are not case-sensitive. + # They respectively correspond to rmw_qos_profile_system_default, rmw_qos_profile_default, rmw_qos_profile_parameter_events, rmw_qos_profile_services_default, rmw_qos_profile_parameters, and SENSOR_DATA. + ir_qos: "default" + ir_camera_info_qos: "default" + # Width of the IR image. If 0, the default width will be used + ir_width: 0 + # Height of the IR image. If 0, the default height will be used + ir_height: 0 + # Fps of the IR image. If 0, the default FPS will be used + ir_fps: 0 + # Format of the IR image. Supported formats are 'Y8' + ir_format: "Y8" + + ir_parameters: + # If false, the IR image auto exposure will not be enabled + enable_ir_auto_exposure: true + # Maximum exposure time of the IR image + ir_ae_max_exposure: -1 + # Exposure time of the IR image. If -1, auto exposure will be used + ir_exposure: -1 + # Gain of the IR image. If -1, auto gain will be used + ir_gain: -1 + # ir_brightness, if -1, auto brightness will be used + ir_brightness: -1 + # If true, the left IR image will be flipped horizontally + ir_flip: false + + imu: + # If true, the IMU accelerometer data will be enabled + enable_accel: false + # The frequency of the accelerometer can be selected as 1.5625Hz, 3.125Hz, 6.25Hz, 12.5Hz, 25Hz, 50Hz, 100Hz, 200Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz. + # The specific value depends on the current camera. + accel_rate: "200hz" + # The range of the accelerometer, the optional values are 2g, 4g, 8g, 16g. The specific value depends on the current camera. + accel_range: "4g" + # If true, the IMU gyroscope data will be enabled + enable_gyro: false + # The frequency of the gyroscope can be selected as 1.5625hz, 3.125hz, 6.25hz, 12.5hz, 25hz, 50hz, 100hz, 200hz, 500hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz. + # The specific value depends on the current camera. + gyro_rate: "200hz" + # The range of the gyroscope, the optional values are 16dps, 31dps, 62dps, 125dps, 250dps, 500dps, 1000dps, 2000dps. The specific value depends on the current camera. + gyro_range: "1000dps" + # enable_sync_output_accel_gyro + enable_sync_output_accel_gyro: false + # Covariance of the linear acceleration + linear_accel_cov: 0.01 + # Covariance of the angular velocity + angular_vel_cov: 0.01 + + point_cloud: + # enable point cloud. {fase:disable, true:enable} + enable_point_cloud: true + # enable RGBD point cloud. {fase:disable, true:enable} + enable_colored_point_cloud: false + # Quality of Service for the point cloud topic + point_cloud_qos: "default" + # Support modifying the frame_id name within the ros message, with the depth name used by default. + cloud_frame_id: "" + # If true, enable filtering of invalid point clouds, i.e., filtering point cloud data with Z=0 + ordered_pc: false + + tf: + # If true, the TF will be enabled + publish_tf: true + # Rate of the TF publication + tf_publish_rate: 0.0 + + advanced: + # If true, the extrinsics publish will be enabled + enable_publish_extrinsic: false + # If true, the frame synchronization will be enabled + enable_frame_sync: true + # Publish D2C superimposed image (only for testing). + enable_d2c_viewer: false + # false: switch to software disparity convert to depth, true: switch to hardware disparity convert to depth + disparity_to_depth_mode: 'HW' + # If false, the host time will not be synchronized with the device time + enable_sync_host_time: true + # URL of the IR image info + ir_info_url: "" + # URL of the color image info + color_info_url: "" + # Diagnostic period in seconds + diagnostic_period: 1.0 + + device_sync: + # Device synchronization mode. supports: {1.free_run 2.standalone 3.primary 4.secondary 5.secondary_synced 6.software_triggering 7.hardware_triggering}. + # For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode. + sync_mode: "standalone" + # The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds. + # For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h + depth_delay_us: 0 + # The delay time of the color image capture after receiving the capture command or trigger signal in microseconds. + color_delay_us: 0 + # The delay time of the image capture after receiving the capture command or trigger signal in microseconds. + trigger2image_delay_us: 0 + # Trigger signal output enable flag. + trigger_out_enabled: true + # The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds. + trigger_out_delay_us: 0 + # The frame number of each stream after each trigger in triggering mode. + frames_per_trigger: 2 + # software trigger period in ms + software_trigger_period: 33 + + gmsldevice_trigger: + enable_gmsl_trigger: false + gmsl_trigger_fps: 3000 + + # config for interleave mode銆� + # interleave_ae_mode is currently supported by the gemini330 series, + # and specific products can be checked for support of interleave_ae_mode by referring to the product manual. + interleave_ae_mode: + # 'hdr' or 'laser' + interleave_ae_mode: "laser" + #enable interleave frame + interleave_frame_enable: false + + interleave_skip: + #enable interleave skip + interleave_skip_enable: false + # 0:skip pattern ir 1: skip flood ir + interleave_skip_index: 1 + + interleave_hdr_param: + hdr_index1_laser_control: 1 + hdr_index1_depth_exposure: 1 + hdr_index1_depth_gain: 16 + hdr_index1_ir_brightness: 30 + hdr_index1_ir_ae_max_exposure: 30458 + hdr_index0_laser_control: 1 + hdr_index0_depth_exposure: 7500 + hdr_index0_depth_gain: 16 + hdr_index0_ir_brightness: 90 + hdr_index0_ir_ae_max_exposure: 30458 + + interleave_laser_param: + laser_index1_laser_control: 0 + laser_index1_depth_exposure: 3000 + laser_index1_depth_gain: 16 + laser_index1_ir_brightness: 60 + laser_index1_ir_ae_max_exposure: 17000 + laser_index0_laser_control: 1 + laser_index0_depth_exposure: 3000 + laser_index0_depth_gain: 16 + laser_index0_ir_brightness: 60 + laser_index0_ir_ae_max_exposure: 30000 diff --git a/dev_ws/src/orbbec_camera/config/depthfilter/Gemini2_v1.7.json b/dev_ws/src/orbbec_camera/config/depthfilter/Gemini2_v1.7.json new file mode 100644 index 0000000..124d485 --- /dev/null +++ b/dev_ws/src/orbbec_camera/config/depthfilter/Gemini2_v1.7.json @@ -0,0 +1,251 @@ +{ + "device": "Orbbec Gemini 2", + "structVersion": "0.0.c", + "dataVersion": "1.7.0", + "description": "Gemini2 depth filter params", + "configDate": "20231212", + "vid": "0x2bc5", + "pid": "0x0670", + "depthFilters": [ + { + "depthWorkMode": "Unbinned Dense Default", + "width": 1280, + "height":800, + "bxf": 30500, + "invalid_value":0, + "NoiseRemovalFilter": { + "enable": true, + "size": 200, + "disp_diff": 100, + "type": "NR_OVERALL", + "lut": [ + 200, 100, 100, 200, + 200, 100, 100, 200, + 200, 100, 100, 200, + 200, 100, 100, 200 + ] + }, + "EdgeNoiseRemovalFilter": { + "enable": true, + "type": "MG_FILTER", + "x1_th": 6, + "x2_th": 6, + "y1_th": 6, + "y2_th": 6, + "limit_x": 70, + "limit_y": 70, + "R": 750, + "width1": 40, + "width2": 40 + }, + "SpatialFastFilter": { + "enable": false, + "size": 3 + }, + "SpatialModerateFilter": { + "enable": false, + "size": 3, + "iters": 1, + "disp_diff": 100 + }, + "SpatialAdvancedFilter": { + "enable": false, + "type": "SFA_ALL", + "iters": 1, + "alpha": 0.4, + "disp_diff": 100, + "radius": 5 + }, + "HoleFillingFilter": { + "enable": false, + "type": "FILL_TOP" + }, + "TemporalFilter": { + "enable": false, + "fill": false, + "scale": 0.05, + "weight": 0.4 + } + }, + { + "depthWorkMode": "Binned Sparse Default", + "width": 640, + "height":400, + "bxf": 15250, + "invalid_value":0, + "NoiseRemovalFilter": { + "enable": true, + "size": 50, + "disp_diff": 120, + "type": "NR_OVERALL", + "lut": [ + 50, 25, 25, 50, + 50, 25, 25, 50, + 50, 25, 25, 50, + 50, 25, 25, 50 + ] + }, + "EdgeNoiseRemovalFilter": { + "enable": true, + "type": "MG_FILTER", + "x1_th": 3, + "x2_th": 3, + "y1_th": 3, + "y2_th": 3, + "limit_x": 35, + "limit_y": 35, + "R": 375, + "width1": 20, + "width2": 20 + }, + "SpatialFastFilter": { + "enable": false, + "size": 3 + }, + "SpatialModerateFilter": { + "enable": false, + "size": 3, + "iters": 1, + "disp_diff": 120 + }, + "SpatialAdvancedFilter": { + "enable": false, + "type": "SFA_ALL", + "iters": 1, + "alpha": 0.4, + "disp_diff": 120, + "radius": 5 + }, + "HoleFillingFilter": { + "enable": false, + "type": "FILL_TOP" + }, + "TemporalFilter": { + "enable": false, + "fill": false, + "scale": 0.05, + "weight": 0.4 + } + }, + { + "depthWorkMode": "Unbinned Sparse Default", + "width": 1280, + "height": 800, + "bxf": 30500, + "invalid_value":0, + "NoiseRemovalFilter": { + "enable": true, + "size": 200, + "disp_diff": 100, + "type": "NR_OVERALL", + "lut": [ + 200, 100, 100, 200, + 200, 100, 100, 200, + 200, 100, 100, 200, + 200, 100, 100, 200 + ] + }, + "EdgeNoiseRemovalFilter": { + "enable": true, + "type": "MG_FILTER", + "x1_th": 6, + "x2_th": 6, + "y1_th": 6, + "y2_th": 6, + "limit_x": 70, + "limit_y": 70, + "R": 750, + "width1": 40, + "width2": 40 + }, + "SpatialFastFilter": { + "enable": false, + "size": 3 + }, + "SpatialModerateFilter": { + "enable": false, + "size": 3, + "iters": 1, + "disp_diff": 100 + }, + "SpatialAdvancedFilter": { + "enable": false, + "type": "SFA_ALL", + "iters": 1, + "alpha": 0.4, + "disp_diff": 100, + "radius": 5 + }, + "HoleFillingFilter": { + "enable": false, + "type": "FILL_TOP" + }, + "TemporalFilter": { + "enable": false, + "fill": false, + "scale": 0.05, + "weight": 0.4 + } + }, + { + "depthWorkMode": "Obstacle Avoidance", + "width": 640, + "height":400, + "bxf": 30500, + "invalid_value":0, + "NoiseRemovalFilter": { + "enable": true, + "size": 50, + "disp_diff": 100, + "type": "NR_OVERALL", + "lut": [ + 50, 25, 25, 50, + 50, 25, 25, 50, + 50, 25, 25, 50, + 50, 25, 25, 50 + ] + }, + "EdgeNoiseRemovalFilter": { + "enable": true, + "type": "MG_FILTER", + "x1_th": 3, + "x2_th": 3, + "y1_th": 3, + "y2_th": 3, + "limit_x": 20, + "limit_y": 20, + "R": 375, + "width1": 20, + "width2": 20 + }, + "SpatialFastFilter": { + "enable": false, + "size": 5 + }, + "SpatialModerateFilter": { + "enable": false, + "size": 5, + "iters": 1, + "disp_diff": 100 + }, + "SpatialAdvancedFilter": { + "enable": true, + "type": "SFA_ALL", + "iters": 1, + "alpha": 0.6, + "disp_diff": 100, + "radius": 5 + }, + "HoleFillingFilter": { + "enable": false, + "type": "FILL_TOP" + }, + "TemporalFilter": { + "enable": false, + "fill": false, + "scale": 0.05, + "weight": 0.4 + } + } + ] +} diff --git a/dev_ws/src/orbbec_camera/config/gemini2.yaml b/dev_ws/src/orbbec_camera/config/gemini2.yaml new file mode 100644 index 0000000..c43f070 --- /dev/null +++ b/dev_ws/src/orbbec_camera/config/gemini2.yaml @@ -0,0 +1,86 @@ +# config/*.yaml files are used to configure the camera parameters +--- +orbbec_ros: + camera_parameters: + general: + # Camera model. upport product models by referencing config/*.yaml + camera_model: "gemini2" + # Path to the configuration file. If empty, default parameters will be used + config_file_path: "gemini2.yaml" + + deivce: + camera_name: "camera" + serial_number: "" + usb_port: "" + device_num: 1 + uvc_backend: "libuvc" + product_id: "" + connection_delay: 100 + time_domain: "global" + retry_on_usb3_detection_failure: false + enable_heartbeat: false + enable_ldp: true + + color: + enable_color: true + color_qos: "default" + color_camera_info_qos: "default" + color_width: 640 + color_height: 360 + color_fps: 15 + color_format: "MJPG" + enable_color_auto_white_balance: true + color_white_balance: -1 + color_auto_ae: + enable_color_auto_exposure: true + color_ae_max_exposure: -1 + color_manual_ae: + color_exposure: -1 + color_gain: -1 + color_brightness: -1 + + depth: + enable_depth: true + depth_qos: "default" + depth_camera_info_qos: "default" + depth_width: 640 + depth_height: 400 + depth_fps: 15 + depth_format: "Y14" + depth_registration: true + align_mode: "HW" + ir: + enable_ir: true + ir_qos: "default" + ir_camera_info_qos: "default" + ir_width: 640 + ir_height: 400 + ir_fps: 15 + ir_format: "Y8" + + ir_parameters: + enable_ir_auto_exposure: true + ir_ae_max_exposure: -1 + ir_exposure: -1 + ir_gain: -1 + ir_brightness: -1 + + imu: + enable_accel: false + accel_rate: "100hz" + accel_range: "4g" + enable_gyro: false + gyro_rate: "100hz" + gyro_range: "1000dps" + enable_sync_output_accel_gyro: true + linear_accel_cov: 0.01 + angular_vel_cov: 0.01 + + point_cloud: + enable_point_cloud: true + enable_colored_point_cloud: false + + advanced: + enable_frame_sync: true + enable_d2c_viewer: false + diff --git a/dev_ws/src/orbbec_camera/include/magic_enum/magic_enum.hpp b/dev_ws/src/orbbec_camera/include/magic_enum/magic_enum.hpp new file mode 100644 index 0000000..6e223de --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/magic_enum/magic_enum.hpp @@ -0,0 +1,1538 @@ +// __ __ _ ______ _____ +// | \/ | (_) | ____| / ____|_ _ +// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_ +// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _| +// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_| +// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____| +// __/ | https://github.com/Neargye/magic_enum +// |___/ version 0.8.2 +// +// Licensed under the MIT License . +// SPDX-License-Identifier: MIT +// Copyright (c) 2019 - 2022 Daniil Goncharov . +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef NEARGYE_MAGIC_ENUM_HPP +#define NEARGYE_MAGIC_ENUM_HPP + +#define MAGIC_ENUM_VERSION_MAJOR 0 +#define MAGIC_ENUM_VERSION_MINOR 8 +#define MAGIC_ENUM_VERSION_PATCH 2 + +#include +#include +#include +#include +#include +#include +#include + +#if defined(MAGIC_ENUM_CONFIG_FILE) +#include MAGIC_ENUM_CONFIG_FILE +#endif + +#if !defined(MAGIC_ENUM_USING_ALIAS_OPTIONAL) +#include +#endif +#if !defined(MAGIC_ENUM_USING_ALIAS_STRING) +#include +#endif +#if !defined(MAGIC_ENUM_USING_ALIAS_STRING_VIEW) +#include +#endif +#if !defined(MAGIC_ENUM_NO_STREAMS) +#include +#endif + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-warning-option" +# pragma clang diagnostic ignored "-Wenum-constexpr-conversion" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'. +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 26495) // Variable 'static_string::chars_' is uninitialized. +# pragma warning(disable : 28020) // Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. +# pragma warning(disable : 26451) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call. +# pragma warning(disable : 4514) // Unreferenced inline function has been removed. +#endif + +// Checks magic_enum compiler compatibility. +#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1910 +# undef MAGIC_ENUM_SUPPORTED +# define MAGIC_ENUM_SUPPORTED 1 +#endif + +// Checks magic_enum compiler aliases compatibility. +#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1920 +# undef MAGIC_ENUM_SUPPORTED_ALIASES +# define MAGIC_ENUM_SUPPORTED_ALIASES 1 +#endif + +// Enum value must be greater or equals than MAGIC_ENUM_RANGE_MIN. By default MAGIC_ENUM_RANGE_MIN = -128. +// If need another min range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MIN. +#if !defined(MAGIC_ENUM_RANGE_MIN) +# define MAGIC_ENUM_RANGE_MIN -128 +#endif + +// Enum value must be less or equals than MAGIC_ENUM_RANGE_MAX. By default MAGIC_ENUM_RANGE_MAX = 128. +// If need another max range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MAX. +#if !defined(MAGIC_ENUM_RANGE_MAX) +# define MAGIC_ENUM_RANGE_MAX 128 +#endif + +namespace magic_enum { + +// If need another optional type, define the macro MAGIC_ENUM_USING_ALIAS_OPTIONAL. +#if defined(MAGIC_ENUM_USING_ALIAS_OPTIONAL) +MAGIC_ENUM_USING_ALIAS_OPTIONAL +#else +using std::optional; +#endif + +// If need another string_view type, define the macro MAGIC_ENUM_USING_ALIAS_STRING_VIEW. +#if defined(MAGIC_ENUM_USING_ALIAS_STRING_VIEW) +MAGIC_ENUM_USING_ALIAS_STRING_VIEW +#else +using std::string_view; +#endif + +// If need another string type, define the macro MAGIC_ENUM_USING_ALIAS_STRING. +#if defined(MAGIC_ENUM_USING_ALIAS_STRING) +MAGIC_ENUM_USING_ALIAS_STRING +#else +using std::string; +#endif + +namespace customize { + +// Enum value must be in range [MAGIC_ENUM_RANGE_MIN, MAGIC_ENUM_RANGE_MAX]. By default MAGIC_ENUM_RANGE_MIN = -128, MAGIC_ENUM_RANGE_MAX = 128. +// If need another range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MIN and MAGIC_ENUM_RANGE_MAX. +// If need another range for specific enum type, add specialization enum_range for necessary enum type. +template +struct enum_range { + static_assert(std::is_enum_v, "magic_enum::customize::enum_range requires enum type."); + static constexpr int min = MAGIC_ENUM_RANGE_MIN; + static constexpr int max = MAGIC_ENUM_RANGE_MAX; + static_assert(max > min, "magic_enum::customize::enum_range requires max > min."); +}; + +static_assert(MAGIC_ENUM_RANGE_MAX > MAGIC_ENUM_RANGE_MIN, "MAGIC_ENUM_RANGE_MAX must be greater than MAGIC_ENUM_RANGE_MIN."); +static_assert((MAGIC_ENUM_RANGE_MAX - MAGIC_ENUM_RANGE_MIN) < (std::numeric_limits::max)(), "MAGIC_ENUM_RANGE must be less than UINT16_MAX."); + +namespace detail { + +enum class customize_tag { + default_tag, + invalid_tag, + custom_tag +}; + +} // namespace magic_enum::customize::detail + +class customize_t : public std::pair { + public: + constexpr customize_t(string_view srt) : std::pair{detail::customize_tag::custom_tag, srt} {} + constexpr customize_t(const char* srt) : customize_t{string_view{srt}} {} + constexpr customize_t(detail::customize_tag tag) : std::pair{tag, string_view{}} { + assert(tag != detail::customize_tag::custom_tag); + } +}; + +// Default customize. +inline constexpr auto default_tag = customize_t{detail::customize_tag::default_tag}; +// Invalid customize. +inline constexpr auto invalid_tag = customize_t{detail::customize_tag::invalid_tag}; + +// If need custom names for enum, add specialization enum_name for necessary enum type. +template +constexpr customize_t enum_name(E) noexcept { + return default_tag; +} + +// If need custom type name for enum, add specialization enum_type_name for necessary enum type. +template +constexpr customize_t enum_type_name() noexcept { + return default_tag; +} + +} // namespace magic_enum::customize + +namespace detail { + +template , std::enable_if_t, int> = 0> +using enum_constant = std::integral_constant; + +enum class value_type { + default_value, + flags_value +}; + +template +inline constexpr bool always_false_v = false; + +template +struct supported +#if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED || defined(MAGIC_ENUM_NO_CHECK_SUPPORT) + : std::true_type {}; +#else + : std::false_type {}; +#endif + +template +struct has_is_flags : std::false_type {}; + +template +struct has_is_flags::is_flags)>> : std::bool_constant::is_flags)>>> {}; + +template +struct range_min : std::integral_constant {}; + +template +struct range_min::min)>> : std::integral_constant::min), customize::enum_range::min> {}; + +template +struct range_max : std::integral_constant {}; + +template +struct range_max::max)>> : std::integral_constant::max), customize::enum_range::max> {}; + +template +class static_string { + public: + constexpr explicit static_string(string_view str) noexcept : static_string{str, std::make_integer_sequence{}} { + assert(str.size() == N); + } + + constexpr const char* data() const noexcept { return chars_; } + + constexpr std::uint16_t size() const noexcept { return N; } + + constexpr operator string_view() const noexcept { return {data(), size()}; } + + private: + template + constexpr static_string(string_view str, std::integer_sequence) noexcept : chars_{str[I]..., '\0'} {} + + char chars_[static_cast(N) + 1]; +}; + +template <> +class static_string<0> { + public: + constexpr explicit static_string() = default; + + constexpr explicit static_string(string_view) noexcept {} + + constexpr const char* data() const noexcept { return nullptr; } + + constexpr std::uint16_t size() const noexcept { return 0; } + + constexpr operator string_view() const noexcept { return {}; } +}; + +constexpr string_view pretty_name(string_view name) noexcept { + const char* str = name.data(); + for (std::size_t i = name.size(); i > 0; --i) { + const char c = str[i - 1]; + if (!((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || +#if defined(MAGIC_ENUM_ENABLE_NONASCII) + (c & 0x80) || +#endif + (c == '_'))) { + name.remove_prefix(i); + break; + } + } + + if (name.size() > 0) { + const char c = name[0]; + if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || +#if defined(MAGIC_ENUM_ENABLE_NONASCII) + (c & 0x80) || +#endif + (c == '_')) { + return name; + } + } + + return {}; // Invalid name. +} + +template> +class case_insensitive { + static constexpr char to_lower(char c) noexcept { + return (c >= 'A' && c <= 'Z') ? static_cast(c + ('a' - 'A')) : c; + } + + public: + template + constexpr auto operator()([[maybe_unused]] L lhs, [[maybe_unused]] R rhs) const noexcept -> std::enable_if_t, char> && std::is_same_v, char>, bool> { +#if defined(MAGIC_ENUM_ENABLE_NONASCII) + static_assert(always_false_v, "magic_enum::case_insensitive not supported Non-ASCII feature."); + return false; +#else + return Op{}(to_lower(lhs), to_lower(rhs)); +#endif + } +}; + +constexpr std::size_t find(string_view str, char c) noexcept { +#if defined(__clang__) && __clang_major__ < 9 && defined(__GLIBCXX__) || defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__) +// https://stackoverflow.com/questions/56484834/constexpr-stdstring-viewfind-last-of-doesnt-work-on-clang-8-with-libstdc +// https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html + constexpr bool workaround = true; +#else + constexpr bool workaround = false; +#endif + + if constexpr (workaround) { + for (std::size_t i = 0; i < str.size(); ++i) { + if (str[i] == c) { + return i; + } + } + + return string_view::npos; + } else { + return str.find(c); + } +} + +template +constexpr std::array, N> to_array(T (&a)[N], std::index_sequence) noexcept { + return {{a[I]...}}; +} + +template +constexpr bool is_default_predicate() noexcept { + return std::is_same_v, std::equal_to> || + std::is_same_v, std::equal_to<>>; +} + +template +constexpr bool is_nothrow_invocable() { + return is_default_predicate() || + std::is_nothrow_invocable_r_v; +} + +template +constexpr bool cmp_equal(string_view lhs, string_view rhs, [[maybe_unused]] BinaryPredicate&& p) noexcept(is_nothrow_invocable()) { +#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__) + // https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html + // https://developercommunity.visualstudio.com/content/problem/232218/c-constexpr-string-view.html + constexpr bool workaround = true; +#else + constexpr bool workaround = false; +#endif + + if constexpr (!is_default_predicate() || workaround) { + if (lhs.size() != rhs.size()) { + return false; + } + + const auto size = lhs.size(); + for (std::size_t i = 0; i < size; ++i) { + if (!p(lhs[i], rhs[i])) { + return false; + } + } + + return true; + } else { + return lhs == rhs; + } +} + +template +constexpr bool cmp_less(L lhs, R rhs) noexcept { + static_assert(std::is_integral_v && std::is_integral_v, "magic_enum::detail::cmp_less requires integral type."); + + if constexpr (std::is_signed_v == std::is_signed_v) { + // If same signedness (both signed or both unsigned). + return lhs < rhs; + } else if constexpr (std::is_same_v) { // bool special case + return static_cast(lhs) < rhs; + } else if constexpr (std::is_same_v) { // bool special case + return lhs < static_cast(rhs); + } else if constexpr (std::is_signed_v) { + // If 'right' is negative, then result is 'false', otherwise cast & compare. + return rhs > 0 && lhs < static_cast>(rhs); + } else { + // If 'left' is negative, then result is 'true', otherwise cast & compare. + return lhs < 0 || static_cast>(lhs) < rhs; + } +} + +template +constexpr I log2(I value) noexcept { + static_assert(std::is_integral_v, "magic_enum::detail::log2 requires integral type."); + + if constexpr (std::is_same_v) { // bool special case + return assert(false), value; + } else { + auto ret = I{0}; + for (; value > I{1}; value >>= I{1}, ++ret) {} + + return ret; + } +} + +template +inline constexpr bool is_enum_v = std::is_enum_v && std::is_same_v>; + +template +constexpr auto n() noexcept { + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); + + if constexpr (supported::value) { +#if defined(__clang__) || defined(__GNUC__) + constexpr auto name = pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 2}); +#elif defined(_MSC_VER) + constexpr auto name = pretty_name({__FUNCSIG__, sizeof(__FUNCSIG__) - 17}); +#else + constexpr auto name = string_view{}; +#endif + return name; + } else { + return string_view{}; // Unsupported compiler or Invalid customize. + } +} + +template +constexpr auto type_name() noexcept { + static_assert(is_enum_v, "magic_enum::detail::type_name requires enum type."); + + [[maybe_unused]] constexpr auto custom = customize::enum_type_name(); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (custom.first == customize::detail::customize_tag::custom_tag) { + constexpr auto name = custom.second; + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return static_string{name}; + } else if constexpr (custom.first == customize::detail::customize_tag::invalid_tag) { + return static_string<0>{}; + } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) { + constexpr auto name = n(); + return static_string{name}; + } else { + static_assert(detail::always_false_v, "magic_enum::customize invalid."); + } +} + +template +inline constexpr auto type_name_v = type_name(); + +template +constexpr auto n() noexcept { + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); + + if constexpr (supported::value) { +#if defined(__clang__) || defined(__GNUC__) + constexpr auto name = pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 2}); +#elif defined(_MSC_VER) + constexpr auto name = pretty_name({__FUNCSIG__, sizeof(__FUNCSIG__) - 17}); +#else + constexpr auto name = string_view{}; +#endif + return name; + } else { + return string_view{}; // Unsupported compiler or Invalid customize. + } +} + +template +constexpr auto enum_name() noexcept { + static_assert(is_enum_v, "magic_enum::detail::enum_name requires enum type."); + + [[maybe_unused]] constexpr auto custom = customize::enum_name(V); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (custom.first == customize::detail::customize_tag::custom_tag) { + constexpr auto name = custom.second; + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return static_string{name}; + } else if constexpr (custom.first == customize::detail::customize_tag::invalid_tag) { + return static_string<0>{}; + } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) { + constexpr auto name = n(); + return static_string{name}; + } else { + static_assert(detail::always_false_v, "magic_enum::customize invalid."); + } +} + +template +inline constexpr auto enum_name_v = enum_name(); + +template +constexpr bool is_valid() noexcept { + static_assert(is_enum_v, "magic_enum::detail::is_valid requires enum type."); + +#if defined(__clang__) && __clang_major__ >= 16 + // https://reviews.llvm.org/D130058, https://reviews.llvm.org/D131307 + constexpr E v = __builtin_bit_cast(E, V); +#else + constexpr E v = static_cast(V); +#endif + [[maybe_unused]] constexpr auto custom = customize::enum_name(v); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (custom.first == customize::detail::customize_tag::custom_tag) { + constexpr auto name = custom.second; + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return name.size() != 0; + } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) { + return n().size() != 0; + } else { + return false; + } +} + +template > +constexpr U ualue(std::size_t i) noexcept { + static_assert(is_enum_v, "magic_enum::detail::ualue requires enum type."); + + if constexpr (std::is_same_v) { // bool special case + static_assert(O == 0, "magic_enum::detail::ualue requires valid offset."); + + return static_cast(i); + } else if constexpr (IsFlags) { + return static_cast(U{1} << static_cast(static_cast(i) + O)); + } else { + return static_cast(static_cast(i) + O); + } +} + +template > +constexpr E value(std::size_t i) noexcept { + static_assert(is_enum_v, "magic_enum::detail::value requires enum type."); + + return static_cast(ualue(i)); +} + +template > +constexpr int reflected_min() noexcept { + static_assert(is_enum_v, "magic_enum::detail::reflected_min requires enum type."); + + if constexpr (IsFlags) { + return 0; + } else { + constexpr auto lhs = range_min::value; + constexpr auto rhs = (std::numeric_limits::min)(); + + if constexpr (cmp_less(rhs, lhs)) { + return lhs; + } else { + return rhs; + } + } +} + +template > +constexpr int reflected_max() noexcept { + static_assert(is_enum_v, "magic_enum::detail::reflected_max requires enum type."); + + if constexpr (IsFlags) { + return std::numeric_limits::digits - 1; + } else { + constexpr auto lhs = range_max::value; + constexpr auto rhs = (std::numeric_limits::max)(); + + if constexpr (cmp_less(lhs, rhs)) { + return lhs; + } else { + return rhs; + } + } +} + +template +inline constexpr auto reflected_min_v = reflected_min(); + +template +inline constexpr auto reflected_max_v = reflected_max(); + +template +constexpr std::size_t values_count(const bool (&valid)[N]) noexcept { + auto count = std::size_t{0}; + for (std::size_t i = 0; i < N; ++i) { + if (valid[i]) { + ++count; + } + } + + return count; +} + +template +constexpr auto values(std::index_sequence) noexcept { + static_assert(is_enum_v, "magic_enum::detail::values requires enum type."); + constexpr bool valid[sizeof...(I)] = {is_valid(I)>()...}; + constexpr std::size_t count = values_count(valid); + + if constexpr (count > 0) { + E values[count] = {}; + for (std::size_t i = 0, v = 0; v < count; ++i) { + if (valid[i]) { + values[v++] = value(i); + } + } + + return to_array(values, std::make_index_sequence{}); + } else { + return std::array{}; + } +} + +template > +constexpr auto values() noexcept { + static_assert(is_enum_v, "magic_enum::detail::values requires enum type."); + constexpr auto min = reflected_min_v; + constexpr auto max = reflected_max_v; + constexpr auto range_size = max - min + 1; + static_assert(range_size > 0, "magic_enum::enum_range requires valid size."); + static_assert(range_size < (std::numeric_limits::max)(), "magic_enum::enum_range requires valid size."); + + return values(std::make_index_sequence{}); +} + +template > +constexpr bool is_flags_enum() noexcept { + static_assert(is_enum_v, "magic_enum::detail::is_flags_enum requires enum type."); + + if constexpr (has_is_flags::value) { + return customize::enum_range::is_flags; + } else if constexpr (std::is_same_v) { // bool special case + return false; + } else { +#if defined(MAGIC_ENUM_NO_CHECK_FLAGS) + return false; +#else + constexpr auto flags_values = values(); + constexpr auto default_values = values(); + if (flags_values.size() == 0 || default_values.size() > flags_values.size()) { + return false; + } + for (std::size_t i = 0; i < default_values.size(); ++i) { + const auto v = static_cast(default_values[i]); + if (v != 0 && (v & (v - 1)) != 0) { + return false; + } + } + return flags_values.size() > 0; +#endif + } +} + +template +inline constexpr bool is_flags_v = is_flags_enum(); + +template +inline constexpr std::array values_v = values>(); + +template > +using values_t = decltype((values_v)); + +template +inline constexpr auto count_v = values_v.size(); + +template > +inline constexpr auto min_v = (count_v > 0) ? static_cast(values_v.front()) : U{0}; + +template > +inline constexpr auto max_v = (count_v > 0) ? static_cast(values_v.back()) : U{0}; + +template +constexpr auto names(std::index_sequence) noexcept { + static_assert(is_enum_v, "magic_enum::detail::names requires enum type."); + + return std::array{{enum_name_v[I]>...}}; +} + +template +inline constexpr std::array names_v = names(std::make_index_sequence>{}); + +template > +using names_t = decltype((names_v)); + +template +constexpr auto entries(std::index_sequence) noexcept { + static_assert(is_enum_v, "magic_enum::detail::entries requires enum type."); + + return std::array, sizeof...(I)>{{{values_v[I], enum_name_v[I]>}...}}; +} + +template +inline constexpr std::array entries_v = entries(std::make_index_sequence>{}); + +template > +using entries_t = decltype((entries_v)); + +template > +constexpr bool is_sparse() noexcept { + static_assert(is_enum_v, "magic_enum::detail::is_sparse requires enum type."); + + if constexpr (count_v == 0) { + return false; + } else if constexpr (std::is_same_v) { // bool special case + return false; + } else { + constexpr auto max = is_flags_v ? log2(max_v) : max_v; + constexpr auto min = is_flags_v ? log2(min_v) : min_v; + constexpr auto range_size = max - min + 1; + + return range_size != count_v; + } +} + +template +inline constexpr bool is_sparse_v = is_sparse(); + +template > +constexpr U values_ors() noexcept { + static_assert(is_enum_v, "magic_enum::detail::values_ors requires enum type."); + + auto ors = U{0}; + for (std::size_t i = 0; i < count_v; ++i) { + ors |= static_cast(values_v[i]); + } + + return ors; +} + +template +struct enable_if_enum {}; + +template +struct enable_if_enum { + using type = R; + static_assert(supported::value, "magic_enum unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility)."); +}; + +template , typename D = std::decay_t> +using enable_if_t = typename enable_if_enum && std::is_invocable_r_v, R>::type; + +template , typename D = std::decay_t> +using enable_if_default_t = typename enable_if_enum && VT == value_type::default_value && std::is_invocable_r_v, R>::type; + +template , typename D = std::decay_t> +using enable_if_flags_t = typename enable_if_enum && VT == value_type::flags_value && std::is_invocable_r_v, R>::type; + +template >, int> = 0> +using enum_concept = T; + +template > +struct is_scoped_enum : std::false_type {}; + +template +struct is_scoped_enum : std::bool_constant>> {}; + +template > +struct is_unscoped_enum : std::false_type {}; + +template +struct is_unscoped_enum : std::bool_constant>> {}; + +template >> +struct underlying_type {}; + +template +struct underlying_type : std::underlying_type> {}; + +#if defined(MAGIC_ENUM_ENABLE_HASH) + +template +inline constexpr bool has_hash = true; + +template +struct constexpr_hash_t; + +template +struct constexpr_hash_t>> { + constexpr auto operator()(Value value) const noexcept { + using U = typename underlying_type::type; + if constexpr (std::is_same_v) { // bool special case + return static_cast(value); + } else { + return static_cast(value); + } + } + using secondary_hash = constexpr_hash_t; +}; + +template +struct constexpr_hash_t>> { + static constexpr std::uint32_t crc_table[256] { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL + }; + constexpr std::uint32_t operator()(string_view value) const noexcept { + auto crc = static_cast(0xffffffffL); + for (const auto c : value) { + crc = (crc >> 8) ^ crc_table[(crc ^ static_cast(c)) & 0xff]; + } + return crc ^ 0xffffffffL; + } + + struct secondary_hash { + constexpr std::uint32_t operator()(string_view value) const noexcept { + auto acc = static_cast(2166136261ULL); + for (const auto c : value) { + acc = ((acc ^ static_cast(c)) * static_cast(16777619ULL)) & (std::numeric_limits::max)(); + } + return static_cast(acc); + } + }; +}; + +template +inline constexpr Hash hash_v{}; + +template +constexpr auto calculate_cases(std::size_t Page) noexcept { + constexpr std::array values = *GlobValues; + constexpr std::size_t size = values.size(); + + using switch_t = std::invoke_result_t; + static_assert(std::is_integral_v && !std::is_same_v); + const std::size_t values_to = (std::min)(static_cast(256), size - Page); + + std::array result{}; + auto fill = result.begin(); + { + auto first = values.begin() + static_cast(Page); + auto last = values.begin() + static_cast(Page + values_to); + while (first != last) { + *fill++ = hash_v(*first++); + } + } + + // dead cases, try to avoid case collisions + for (switch_t last_value = result[values_to - 1]; fill != result.end() && last_value != (std::numeric_limits::max)(); *fill++ = ++last_value) { + } + + { + auto it = result.begin(); + auto last_value = (std::numeric_limits::min)(); + for (; fill != result.end(); *fill++ = last_value++) { + while (last_value == *it) { + ++last_value, ++it; + } + } + } + + return result; +} + +template +constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v) { + if constexpr (std::is_void_v) { + std::forward(f)(std::forward(args)...); + } else { + return static_cast(std::forward(f)(std::forward(args)...)); + } +} + +enum class case_call_t { + index, + value +}; + +template +inline constexpr auto default_result_type_lambda = []() noexcept(std::is_nothrow_default_constructible_v) { return T{}; }; + +template <> +inline constexpr auto default_result_type_lambda = []() noexcept {}; + +template +constexpr bool has_duplicate() noexcept { + using value_t = std::decay_t; + using hash_value_t = std::invoke_result_t; + std::arraysize()> hashes{}; + std::size_t size = 0; + for (auto elem : *Arr) { + hashes[size] = hash_v(elem); + for (auto i = size++; i > 0; --i) { + if (hashes[i] < hashes[i - 1]) { + auto tmp = hashes[i]; + hashes[i] = hashes[i - 1]; + hashes[i - 1] = tmp; + } else if (hashes[i] == hashes[i - 1]) { + return false; + } else { + break; + } + } + } + return true; +} + +#define MAGIC_ENUM_FOR_EACH_256(T) T(0)T(1)T(2)T(3)T(4)T(5)T(6)T(7)T(8)T(9)T(10)T(11)T(12)T(13)T(14)T(15)T(16)T(17)T(18)T(19)T(20)T(21)T(22)T(23)T(24)T(25)T(26)T(27)T(28)T(29)T(30)T(31) \ + T(32)T(33)T(34)T(35)T(36)T(37)T(38)T(39)T(40)T(41)T(42)T(43)T(44)T(45)T(46)T(47)T(48)T(49)T(50)T(51)T(52)T(53)T(54)T(55)T(56)T(57)T(58)T(59)T(60)T(61)T(62)T(63) \ + T(64)T(65)T(66)T(67)T(68)T(69)T(70)T(71)T(72)T(73)T(74)T(75)T(76)T(77)T(78)T(79)T(80)T(81)T(82)T(83)T(84)T(85)T(86)T(87)T(88)T(89)T(90)T(91)T(92)T(93)T(94)T(95) \ + T(96)T(97)T(98)T(99)T(100)T(101)T(102)T(103)T(104)T(105)T(106)T(107)T(108)T(109)T(110)T(111)T(112)T(113)T(114)T(115)T(116)T(117)T(118)T(119)T(120)T(121)T(122)T(123)T(124)T(125)T(126)T(127) \ + T(128)T(129)T(130)T(131)T(132)T(133)T(134)T(135)T(136)T(137)T(138)T(139)T(140)T(141)T(142)T(143)T(144)T(145)T(146)T(147)T(148)T(149)T(150)T(151)T(152)T(153)T(154)T(155)T(156)T(157)T(158)T(159) \ + T(160)T(161)T(162)T(163)T(164)T(165)T(166)T(167)T(168)T(169)T(170)T(171)T(172)T(173)T(174)T(175)T(176)T(177)T(178)T(179)T(180)T(181)T(182)T(183)T(184)T(185)T(186)T(187)T(188)T(189)T(190)T(191) \ + T(192)T(193)T(194)T(195)T(196)T(197)T(198)T(199)T(200)T(201)T(202)T(203)T(204)T(205)T(206)T(207)T(208)T(209)T(210)T(211)T(212)T(213)T(214)T(215)T(216)T(217)T(218)T(219)T(220)T(221)T(222)T(223) \ + T(224)T(225)T(226)T(227)T(228)T(229)T(230)T(231)T(232)T(233)T(234)T(235)T(236)T(237)T(238)T(239)T(240)T(241)T(242)T(243)T(244)T(245)T(246)T(247)T(248)T(249)T(250)T(251)T(252)T(253)T(254)T(255) + +#define MAGIC_ENUM_CASE(val) \ + case cases[val]: \ + if constexpr ((val) + Page < size) { \ + if (!pred(values[val + Page], searched)) { \ + break; \ + } \ + if constexpr (CallValue == case_call_t::index) { \ + if constexpr (std::is_invocable_r_v>) { \ + return detail::invoke_r(std::forward(lambda), std::integral_constant{}); \ + } else if constexpr (std::is_invocable_v>) { \ + assert(false && "magic_enum::detail::constexpr_switch wrong result type."); \ + } \ + } else if constexpr (CallValue == case_call_t::value) { \ + if constexpr (std::is_invocable_r_v>) { \ + return detail::invoke_r(std::forward(lambda), enum_constant{}); \ + } else if constexpr (std::is_invocable_r_v>) { \ + assert(false && "magic_enum::detail::constexpr_switch wrong result type."); \ + } \ + } \ + break; \ + } else [[fallthrough]]; + +template ::value_type>, + typename BinaryPredicate = std::equal_to<>, + typename Lambda, + typename ResultGetterType> +constexpr decltype(auto) constexpr_switch( + Lambda&& lambda, + typename std::decay_t::value_type searched, + ResultGetterType&& def, + BinaryPredicate&& pred = {}) { + using result_t = std::invoke_result_t; + using hash_t = std::conditional_t(), Hash, typename Hash::secondary_hash>; + static_assert(has_duplicate(), "magic_enum::detail::constexpr_switch duplicated hash found, please report it: https://github.com/Neargye/magic_enum/issues."); + constexpr std::array values = *GlobValues; + constexpr std::size_t size = values.size(); + constexpr std::array cases = calculate_cases(Page); + + switch (hash_v(searched)) { + MAGIC_ENUM_FOR_EACH_256(MAGIC_ENUM_CASE) + default: + if constexpr (size > 256 + Page) { + return constexpr_switch(std::forward(lambda), searched, std::forward(def)); + } + break; + } + return def(); +} + +#undef MAGIC_ENUM_FOR_EACH_256 +#undef MAGIC_ENUM_CASE + +#else +template +inline constexpr bool has_hash = false; +#endif + +template +constexpr auto for_each(F&& f, std::index_sequence) { + static_assert(is_enum_v, "magic_enum::detail::for_each requires enum type."); + constexpr bool has_void_return = (std::is_void_v[I]>>> || ...); + constexpr bool all_same_return = (std::is_same_v[0]>>, std::invoke_result_t[I]>>> && ...); + + if constexpr (has_void_return) { + (f(enum_constant[I]>{}), ...); + } else if constexpr (all_same_return) { + return std::array{f(enum_constant[I]>{})...}; + } else { + return std::tuple{f(enum_constant[I]>{})...}; + } +} + +template +constexpr bool all_invocable(std::index_sequence) { + static_assert(is_enum_v, "magic_enum::detail::all_invocable requires enum type."); + + if constexpr (count_v == 0) { + return false; + } else { + return (std::is_invocable_v[I]>> && ...); + } +} + +} // namespace magic_enum::detail + +// Checks is magic_enum supported compiler. +inline constexpr bool is_magic_enum_supported = detail::supported::value; + +template +using Enum = detail::enum_concept; + +// Checks whether T is an Unscoped enumeration type. +// Provides the member constant value which is equal to true, if T is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration) type. Otherwise, value is equal to false. +template +struct is_unscoped_enum : detail::is_unscoped_enum {}; + +template +inline constexpr bool is_unscoped_enum_v = is_unscoped_enum::value; + +// Checks whether T is an Scoped enumeration type. +// Provides the member constant value which is equal to true, if T is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations) type. Otherwise, value is equal to false. +template +struct is_scoped_enum : detail::is_scoped_enum {}; + +template +inline constexpr bool is_scoped_enum_v = is_scoped_enum::value; + +// If T is a complete enumeration type, provides a member typedef type that names the underlying type of T. +// Otherwise, if T is not an enumeration type, there is no member type. Otherwise (T is an incomplete enumeration type), the program is ill-formed. +template +struct underlying_type : detail::underlying_type {}; + +template +using underlying_type_t = typename underlying_type::type; + +template +using enum_constant = detail::enum_constant; + +// Returns type name of enum. +template +[[nodiscard]] constexpr auto enum_type_name() noexcept -> detail::enable_if_t { + constexpr string_view name = detail::type_name_v>; + static_assert(!name.empty(), "magic_enum::enum_type_name enum type does not have a name."); + + return name; +} + +// Returns number of enum values. +template +[[nodiscard]] constexpr auto enum_count() noexcept -> detail::enable_if_t { + return detail::count_v>; +} + +// Returns enum value at specified index. +// No bounds checking is performed: the behavior is undefined if index >= number of enum values. +template +[[nodiscard]] constexpr auto enum_value(std::size_t index) noexcept -> detail::enable_if_t> { + using D = std::decay_t; + + if constexpr (detail::is_sparse_v) { + return assert((index < detail::count_v)), detail::values_v[index]; + } else { + constexpr bool is_flag = detail::is_flags_v; + constexpr auto min = is_flag ? detail::log2(detail::min_v) : detail::min_v; + + return assert((index < detail::count_v)), detail::value(index); + } +} + +// Returns enum value at specified index. +template +[[nodiscard]] constexpr auto enum_value() noexcept -> detail::enable_if_t> { + using D = std::decay_t; + static_assert(I < detail::count_v, "magic_enum::enum_value out of range."); + + return enum_value(I); +} + +// Returns std::array with enum values, sorted by enum value. +template +[[nodiscard]] constexpr auto enum_values() noexcept -> detail::enable_if_t> { + return detail::values_v>; +} + +// Returns integer value from enum value. +template +[[nodiscard]] constexpr auto enum_integer(E value) noexcept -> detail::enable_if_t> { + return static_cast>(value); +} + +// Returns underlying value from enum value. +template +[[nodiscard]] constexpr auto enum_underlying(E value) noexcept -> detail::enable_if_t> { + return static_cast>(value); +} + +// Obtains index in enum values from enum value. +// Returns optional with index. +template +[[nodiscard]] constexpr auto enum_index([[maybe_unused]] E value) noexcept -> detail::enable_if_t> { + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::count_v == 0) { + return {}; // Empty enum. + } else if constexpr (detail::is_sparse_v || detail::is_flags_v) { +#if defined(MAGIC_ENUM_ENABLE_HASH) + return detail::constexpr_switch<&detail::values_v, detail::case_call_t::index>( + [](std::size_t i) { return optional{i}; }, + value, + detail::default_result_type_lambda>); +#else + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (enum_value(i) == value) { + return i; + } + } + return {}; // Invalid value or out of range. +#endif + } else { + const auto v = static_cast(value); + if (v >= detail::min_v && v <= detail::max_v) { + return static_cast(v - detail::min_v); + } + return {}; // Invalid value or out of range. + } +} + +// Obtains index in enum values from static storage enum variable. +template +[[nodiscard]] constexpr auto enum_index() noexcept -> detail::enable_if_t { + constexpr auto index = enum_index>(V); + static_assert(index, "magic_enum::enum_index enum value does not have a index."); + + return *index; +} + +// Returns name from static storage enum variable. +// This version is much lighter on the compile times and is not restricted to the enum_range limitation. +template +[[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_t { + constexpr string_view name = detail::enum_name_v, V>; + static_assert(!name.empty(), "magic_enum::enum_name enum value does not have a name."); + + return name; +} + +// Returns name from enum value. +// If enum value does not have name or value out of range, returns empty string. +template +[[nodiscard]] constexpr auto enum_name(E value) noexcept -> detail::enable_if_default_t { + using D = std::decay_t; + + if (const auto i = enum_index(value)) { + return detail::names_v[*i]; + } + return {}; +} + +// Returns name from enum value. +// If enum value does not have name or value out of range, returns empty string. +template +[[nodiscard]] constexpr auto enum_name(E value) -> detail::enable_if_default_t { + using D = std::decay_t; + + return enum_name(value); +} + +// Returns name from enum value. +// If enum value does not have name or value out of range, returns empty string. +template +[[nodiscard]] auto enum_name(E value) -> detail::enable_if_flags_t { + using D = std::decay_t; + using U = underlying_type_t; + static_assert(detail::is_flags_v, "magic_enum::enum_flags_name requires enum-flags type."); + + string name; + auto check_value = U{0}; + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (const auto v = static_cast(enum_value(i)); (static_cast(value) & v) != 0) { + check_value |= v; + const auto n = detail::names_v[i]; + if (!name.empty()) { + name.append(1, '|'); + } + name.append(n.data(), n.size()); + } + } + + if (check_value != 0 && check_value == static_cast(value)) { + return name; + } + return {}; // Invalid value or out of range. +} + +// Returns name from enum value. +// If enum value does not have name or value out of range, returns empty string. +template +[[nodiscard]] auto enum_name(E value) -> detail::enable_if_flags_t { + using D = std::decay_t; + static_assert(detail::is_flags_v, "magic_enum::enum_flags_name requires enum-flags type."); + + return enum_name(value); +} + +// Returns name from enum-flags value. +// If enum-flags value does not have name or value out of range, returns empty string. +template +[[nodiscard]] auto enum_flags_name(E value, [[maybe_unused]] char sep = '|') -> detail::enable_if_t { + using D = std::decay_t; + static_assert(detail::is_flags_v, "magic_enum::enum_flags_name requires enum-flags type."); + + return enum_name(value); +} + +// Returns std::array with names, sorted by enum value. +template +[[nodiscard]] constexpr auto enum_names() noexcept -> detail::enable_if_t> { + return detail::names_v>; +} + +// Returns std::array with pairs (value, name), sorted by enum value. +template +[[nodiscard]] constexpr auto enum_entries() noexcept -> detail::enable_if_t> { + return detail::entries_v>; +} + +// Allows you to write magic_enum::enum_cast("bar", magic_enum::case_insensitive); +inline constexpr auto case_insensitive = detail::case_insensitive<>{}; + +// Obtains enum value from integer value. +// Returns optional with enum value. +template +[[nodiscard]] constexpr auto enum_cast(underlying_type_t value) noexcept -> detail::enable_if_t>> { + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::count_v == 0) { + return {}; // Empty enum. + } else if constexpr (VT == detail::value_type::flags_value && detail::is_flags_v) { + if constexpr (detail::is_sparse_v) { + auto check_value = U{0}; + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (const auto v = static_cast(enum_value(i)); (value & v) != 0) { + check_value |= v; + } + } + + if (check_value != 0 && check_value == value) { + return static_cast(value); + } + } else { + constexpr auto min = detail::min_v; + constexpr auto max = detail::values_ors(); + + if (value >= min && value <= max) { + return static_cast(value); + } + } + return {}; // Invalid value or out of range. + } else { +#if defined(MAGIC_ENUM_ENABLE_HASH) + return detail::constexpr_switch<&detail::values_v, detail::case_call_t::value>( + [](D v) { return optional{v}; }, + static_cast(value), + detail::default_result_type_lambda>); +#else + if constexpr (detail::is_sparse_v || detail::is_flags_v) { + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (value == static_cast(enum_value(i))) { + return static_cast(value); + } + } + } else { + if (value >= detail::min_v && value <= detail::max_v) { + return static_cast(value); + } + } + return {}; // Invalid value or out of range. +#endif + } +} + +// Obtains enum-flags value from integer value. +// Returns optional with enum-flags value. +template +[[nodiscard]] constexpr auto enum_flags_cast(underlying_type_t value) noexcept -> detail::enable_if_t>> { + using D = std::decay_t; + static_assert(detail::is_flags_v, "magic_enum::enum_flags_cast requires enum-flags type."); + + return enum_cast(value); +} + +// Obtains enum value from name. +// Returns optional with enum value. +template > +[[nodiscard]] constexpr auto enum_cast(string_view value, [[maybe_unused]] BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable()) -> detail::enable_if_t>, BinaryPredicate> { + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::count_v == 0) { + return {}; // Empty enum. + } else if constexpr (VT == detail::value_type::flags_value && detail::is_flags_v) { + auto result = U{0}; + while (!value.empty()) { + const auto d = detail::find(value, '|'); + const auto s = (d == string_view::npos) ? value : value.substr(0, d); + auto f = U{0}; + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (detail::cmp_equal(s, detail::names_v[i], p)) { + f = static_cast(enum_value(i)); + result |= f; + break; + } + } + if (f == U{0}) { + return {}; // Invalid value or out of range. + } + value.remove_prefix((d == string_view::npos) ? value.size() : d + 1); + } + + if (result != U{0}) { + return static_cast(result); + } + return {}; // Invalid value or out of range. + } else { + if constexpr (detail::is_default_predicate() && detail::has_hash) { +#if defined(MAGIC_ENUM_ENABLE_HASH) + return detail::constexpr_switch<&detail::names_v, detail::case_call_t::index>( + [](std::size_t i) { return optional{detail::values_v[i]}; }, + value, + detail::default_result_type_lambda>, + [&p](string_view lhs, string_view rhs) { return detail::cmp_equal(lhs, rhs, p); }); +#endif + } else { + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (detail::cmp_equal(value, detail::names_v[i], p)) { + return enum_value(i); + } + } + return {}; // Invalid value or out of range. + } + } +} + +// Obtains enum-flags value from name. +// Returns optional with enum-flags value. +template > +[[nodiscard]] constexpr auto enum_flags_cast(string_view value, [[maybe_unused]] BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable()) -> detail::enable_if_t>, BinaryPredicate> { + using D = std::decay_t; + static_assert(detail::is_flags_v, "magic_enum::enum_flags_cast requires enum-flags type."); + + return enum_cast(value, std::move(p)); +} + +// Checks whether enum contains value with such value. +template +[[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + using U = underlying_type_t; + + return static_cast(enum_cast(static_cast(value))); +} + +// Checks whether enum-flags contains value with such value. +template +[[nodiscard]] constexpr auto enum_flags_contains(E value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + static_assert(detail::is_flags_v, "magic_enum::enum_flags_contains requires enum-flags type."); + + return enum_contains(value); +} + +// Checks whether enum contains value with such integer value. +template +[[nodiscard]] constexpr auto enum_contains(underlying_type_t value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + + return static_cast(enum_cast(value)); +} + +// Checks whether enum-flags contains value with such integer value. +template +[[nodiscard]] constexpr auto enum_flags_contains(underlying_type_t value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + static_assert(detail::is_flags_v, "magic_enum::enum_flags_contains requires enum-flags type."); + + return enum_contains(value); +} + +// Checks whether enum contains enumerator with such name. +template > +[[nodiscard]] constexpr auto enum_contains(string_view value, BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable()) -> detail::enable_if_t { + using D = std::decay_t; + + return static_cast(enum_cast(value, std::move(p))); +} + +// Checks whether enum-flags contains enumerator with such name. +template > +[[nodiscard]] constexpr auto enum_flags_contains(string_view value, BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable()) -> detail::enable_if_t { + using D = std::decay_t; + static_assert(detail::is_flags_v, "magic_enum::enum_flags_contains requires enum-flags type."); + + return enum_contains(value, std::move(p)); +} + +template = 0> +constexpr auto enum_for_each(F&& f) { + using D = std::decay_t; + static_assert(std::is_enum_v, "magic_enum::enum_for_each requires enum type."); + constexpr auto sep = std::make_index_sequence>{}; + + if constexpr (detail::all_invocable(sep)) { + return detail::for_each(std::forward(f), sep); + } else { + static_assert(detail::always_false_v, "magic_enum::enum_for_each requires invocable of all enum value."); + } +} + +template +inline constexpr auto as_flags = AsFlags ? detail::value_type::flags_value : detail::value_type::default_value; + +#if !defined(MAGIC_ENUM_NO_STREAMS) + +namespace ostream_operators { + +template = 0> +std::basic_ostream& operator<<(std::basic_ostream& os, E value) { + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::supported::value) { + if (const auto name = enum_name>>(value); !name.empty()) { + for (const auto c : name) { + os.put(c); + } + return os; + } + } + return (os << static_cast(value)); +} + +template = 0> +std::basic_ostream& operator<<(std::basic_ostream& os, optional value) { + return value ? (os << *value) : os; +} + +} // namespace magic_enum::ostream_operators + +namespace istream_operators { + +template = 0> +std::basic_istream& operator>>(std::basic_istream& is, E& value) { + using D = std::decay_t; + + std::basic_string s; + is >> s; + if (const auto v = enum_cast>>(s)) { + value = *v; + } else { + is.setstate(std::basic_ios::failbit); + } + return is; +} + +} // namespace magic_enum::istream_operators + +namespace iostream_operators { + +using namespace ostream_operators; +using namespace istream_operators; + +} // namespace magic_enum::iostream_operators + +#endif + +namespace bitwise_operators { + +template = 0> +constexpr E operator~(E rhs) noexcept { + return static_cast(~static_cast>(rhs)); +} + +template = 0> +constexpr E operator|(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) | static_cast>(rhs)); +} + +template = 0> +constexpr E operator&(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) & static_cast>(rhs)); +} + +template = 0> +constexpr E operator^(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) ^ static_cast>(rhs)); +} + +template = 0> +constexpr E& operator|=(E& lhs, E rhs) noexcept { + return lhs = (lhs | rhs); +} + +template = 0> +constexpr E& operator&=(E& lhs, E rhs) noexcept { + return lhs = (lhs & rhs); +} + +template = 0> +constexpr E& operator^=(E& lhs, E rhs) noexcept { + return lhs = (lhs ^ rhs); +} + +} // namespace magic_enum::bitwise_operators + +} // namespace magic_enum + +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // NEARGYE_MAGIC_ENUM_HPP diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/constants.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/constants.h new file mode 100644 index 0000000..826175e --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/constants.h @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#pragma once + +#include +#include + +#define THREAD_NUM 4 + +#define OB_ROS_MAJOR_VERSION 2 +#define OB_ROS_MINOR_VERSION 7 +#define OB_ROS_PATCH_VERSION 6 + +#ifndef STRINGIFY +#define STRINGIFY(arg) #arg +#endif +#ifndef VAR_ARG_STRING +#define VAR_ARG_STRING(arg) STRINGIFY(arg) +#endif + +#define STRINGIFY(arg) #arg +#define VAR_ARG_STRING(arg) STRINGIFY(arg) +/* Return version in "X.Y.Z" format */ +#define OB_ROS_VERSION_STR \ + (VAR_ARG_STRING(OB_ROS_MAJOR_VERSION.OB_ROS_MINOR_VERSION.OB_ROS_PATCH_VERSION)) + +namespace orbbec_camera { + +const bool ALIGN_DEPTH = false; +const bool POINTCLOUD = false; +const bool ALLOW_NO_TEXTURE_POINTS = false; +const bool SYNC_FRAMES = false; +const bool ORDERED_POINTCLOUD = false; + +const bool PUBLISH_TF = true; +const double TF_PUBLISH_RATE = 0; // Static transform +const double DIAGNOSTICS_PERIOD = 0; // Static transform + +const int IMAGE_WIDTH = 640; +const int IMAGE_HEIGHT = 480; +const int IMAGE_FPS = 30; + +const std::string IMAGE_QOS = "SYSTEM_DEFAULT"; +const std::string DEFAULT_QOS = "DEFAULT"; +const std::string HID_QOS = "HID_DEFAULT"; +const std::string EXTRINSICS_QOS = "EXTRINSICS_DEFAULT"; + +const double IMU_FPS = 0; + +const bool ENABLE_DEPTH = true; +const bool ENABLE_INFRA1 = true; +const bool ENABLE_INFRA2 = true; +const bool ENABLE_COLOR = true; +const bool ENABLE_FISHEYE = true; +const bool ENABLE_IMU = true; +const bool HOLD_BACK_IMU_FOR_FRAMES = false; +const bool PUBLISH_ODOM_TF = true; + +const std::string DEFAULT_BASE_FRAME_ID = "camera_link"; +const std::string DEFAULT_ODOM_FRAME_ID = "odom_frame"; +const std::string DEFAULT_DEPTH_FRAME_ID = "camera_depth_frame"; +const std::string DEFAULT_INFRA1_FRAME_ID = "camera_infra1_frame"; +const std::string DEFAULT_INFRA2_FRAME_ID = "camera_infra2_frame"; +const std::string DEFAULT_COLOR_FRAME_ID = "camera_color_frame"; +const std::string DEFAULT_FISHEYE_FRAME_ID = "camera_fisheye_frame"; +const std::string DEFAULT_IMU_FRAME_ID = "camera_imu_frame"; + +const std::string DEFAULT_DEPTH_OPTICAL_FRAME_ID = "camera_depth_optical_frame"; +const std::string DEFAULT_INFRA1_OPTICAL_FRAME_ID = "camera_infra1_optical_frame"; +const std::string DEFAULT_INFRA2_OPTICAL_FRAME_ID = "camera_infra2_optical_frame"; +const std::string DEFAULT_COLOR_OPTICAL_FRAME_ID = "camera_color_optical_frame"; +const std::string DEFAULT_FISHEYE_OPTICAL_FRAME_ID = "camera_fisheye_optical_frame"; +const std::string DEFAULT_ACCEL_OPTICAL_FRAME_ID = "camera_accel_optical_frame"; +const std::string DEFAULT_GYRO_OPTICAL_FRAME_ID = "camera_gyro_optical_frame"; +const std::string DEFAULT_IMU_OPTICAL_FRAME_ID = "camera_imu_optical_frame"; + +const std::string DEFAULT_ALIGNED_DEPTH_TO_COLOR_FRAME_ID = "camera_aligned_depth_to_color_frame"; +const std::string DEFAULT_ALIGNED_DEPTH_TO_INFRA1_FRAME_ID = "camera_aligned_depth_to_infra1_frame"; +const std::string DEFAULT_ALIGNED_DEPTH_TO_INFRA2_FRAME_ID = "camera_aligned_depth_to_infra2_frame"; +const std::string DEFAULT_ALIGNED_DEPTH_TO_FISHEYE_FRAME_ID = + "camera_aligned_depth_to_fisheye_frame"; + +const std::string DEFAULT_UNITE_IMU_METHOD = ""; +const std::string DEFAULT_FILTERS = ""; +const std::string DEFAULT_TOPIC_ODOM_IN = ""; +const std::string DEFAULT_D2C_MODE = "sw"; // sw = software mode, hw=hardware mode, none, +const float ROS_DEPTH_SCALE = 0.001; + +const int32_t FEMTO_OW_PID = 0x0638; +const int32_t FEMTO_BOLT_PID = 0x066b; +const int32_t FEMTO_LIVE_PID = 0x0668; +const uint32_t FEMTO_MEGA_PID = 0x0669; +const int32_t FEMTO_PID = 0x0635; +const int32_t ASTRA_PLUS_PID = 0x0636; +const int32_t ASTRA_PLUS_S_PID = 0x0637; +const int32_t OPENNI_START_PID = 0x0601; +const int32_t OPENNI_END_PID = 0x06FF; +const int32_t ASTRA_MINI_PID = 0x0404; +const int32_t ASTRA_MINI_S_PID = 0x0407; +const int GEMINI2_PID = 0x0670; +const int GEMINI2L_PID = 0x0673; + +const int GEMINI2R_PID = 0x06d0; +const int GEMINI2RL_PID = 0x06d1; + +const int GEMINI2R_PID2 = 0x0800; +const int GEMINI2RL_PID2 = 0x0804; +const std::string ORB_DEFAULT_LOCK_NAME = "orbbec_device_lock"; +const int32_t GEMINI_335_PID = 0x0800; // Gemini 335 / 335e +const int32_t GEMINI_330_PID = 0x0801; // Gemini 330 +const int32_t GEMINI_336_PID = 0x0803; // Gemini 336 / 336e +const int32_t GEMINI_335L_PID = 0x0804; // Gemini 335L +const int32_t GEMINI_330L_PID = 0x0805; // Gemini 336L +const int32_t GEMINI_336L_PID = 0x0807; // Gemini 335Lg +const int32_t GEMINI_335LG_PID = 0x080B; // Gemini 336Lg +const int32_t GEMINI_336LG_PID = 0x080D; +const int32_t GEMINI_335LE_PID = 0x080E; // Gemini 335Le +const int32_t GEMINI_336LE_PID = 0x0810; // Gemini 335Le +const int32_t CUSTOM_ADVANTECH_GEMINI_336_PID = 0x0816; // Custom Advantech Gemini 336 +const int32_t CUSTOM_ADVANTECH_GEMINI_336L_PID = 0x0817; // Custom Advantech Gemini 336L +const int32_t DABAI_MAX_PID = 0x069a; // dabai max +const int32_t GEMINI_338_PID = 0x0818; // Gemini 338 +const uint16_t GEMINI_435Le_PID = 0x815; // Gemini 435Le +const uint16_t GEMINI_305_PID = 0x0840; // Gemini 305 + +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/d2c_viewer.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/d2c_viewer.h new file mode 100644 index 0000000..54886a6 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/d2c_viewer.h @@ -0,0 +1,50 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#pragma once +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +namespace orbbec_camera { +class D2CViewer { + public: + explicit D2CViewer(rclcpp::Node* const node, rmw_qos_profile_t rgb_qos, + rmw_qos_profile_t depth_qos, bool use_intra_process = false); + ~D2CViewer(); + + void messageCallback(const sensor_msgs::msg::Image::ConstSharedPtr & rgb_msg, + const sensor_msgs::msg::Image::ConstSharedPtr& depth_msg); + + private: + rclcpp::Node* node_; + rclcpp::Logger logger_; + std::shared_ptr> rgb_sub_; + std::shared_ptr> depth_sub_; + using MySyncPolicy = message_filters::sync_policies::ApproximateTime; + std::shared_ptr> sync_; + rclcpp::Publisher::SharedPtr d2c_viewer_pub_; + + // Add thread safety + std::mutex callback_mutex_; + std::atomic is_active_{true}; +}; +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/dynamic_params.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/dynamic_params.h new file mode 100644 index 0000000..22cf12b --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/dynamic_params.h @@ -0,0 +1,54 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#pragma once +#include + +#include "ros_param_backend.h" + +namespace orbbec_camera { +class Parameters { + public: + explicit Parameters(rclcpp::Node* node); + ~Parameters() noexcept; + rclcpp::ParameterValue setParam(const std::string& param_name, + rclcpp::ParameterValue initial_value, + const std::function& func = + std::function(), + const rcl_interfaces::msg::ParameterDescriptor& descriptor = + rcl_interfaces::msg::ParameterDescriptor()); + + template + void setParamT(std::string param_name, rclcpp::ParameterValue initial_value, T& param, + std::function func = + std::function(), + rcl_interfaces::msg::ParameterDescriptor descriptor = + rcl_interfaces::msg::ParameterDescriptor()); + template + void setParamValue(T& param, const T& value); // function updates the parameter value both + // locally and in the parameters server + void removeParam(const std::string& param_name); + + private: + private: + rclcpp::Node* node_; + rclcpp::Logger logger_; + std::map > > + param_functions_; + std::map param_names_; + ParametersBackend params_backend_; +}; +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/fps_counter.hpp b/dev_ws/src/orbbec_camera/include/orbbec_camera/fps_counter.hpp new file mode 100644 index 0000000..3a0dce3 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/fps_counter.hpp @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#pragma once + +#include + +#include +#include +#include +namespace orbbec_camera { + +enum class LogLevel { DEBUG, INFO }; +class FpsCounter { + public: + explicit FpsCounter(const std::string &name, rclcpp::Logger logger, int print_interval_sec = 1) + : name_(name), + print_interval_(std::chrono::seconds(print_interval_sec)), + last_print_time_(std::chrono::steady_clock::now()), + frame_count_(0), + log_level_(LogLevel::INFO), + logger_(logger) + + {} + + void setLogLevel(LogLevel level) { log_level_ = level; } + + void tick() { + ++frame_count_; + auto now = std::chrono::steady_clock::now(); + if (now - last_print_time_ >= print_interval_) { + double fps = + static_cast(frame_count_) / + std::chrono::duration_cast>(now - last_print_time_).count(); + + if (log_level_ == LogLevel::INFO) { + RCLCPP_INFO_STREAM(logger_, name_ << " FPS " << fps); + } else { + RCLCPP_DEBUG_STREAM(logger_, name_ << " FPS " << fps); + } + + last_print_time_ = now; + frame_count_ = 0; + } + } + + private: + std::string name_; + std::chrono::seconds print_interval_; + std::chrono::steady_clock::time_point last_print_time_; + uint32_t frame_count_; + LogLevel log_level_; + rclcpp::Logger logger_; +}; + +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/fps_delay_status.hpp b/dev_ws/src/orbbec_camera/include/orbbec_camera/fps_delay_status.hpp new file mode 100644 index 0000000..e85501d --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/fps_delay_status.hpp @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#pragma once + +#include +#include "orbbec_camera_msgs/msg/device_status.hpp" +#include +#include +#include +namespace orbbec_camera { +class FpsDelayStatus { + public: + explicit FpsDelayStatus(rclcpp::Logger logger) : log_level_(LogLevel::INFO), logger_(logger) {} + + void tick(u_int64_t stream_timestamp) { + std::lock_guard lock(mutex_); + + double dt = (stream_timestamp - last_stream_timestamp_) / 1000000.0; + double fps = (dt > 0) ? (1.0 / dt) : 0.0; + + // Convert now to milliseconds since steady_clock epoch + auto now2 = std::chrono::system_clock::now(); + uint64_t ms_since_epoch = + std::chrono::duration_cast(now2.time_since_epoch()).count(); + double delay_ms = + static_cast(ms_since_epoch) - static_cast(stream_timestamp / 1000.0); + + frame_count_++; + fps_sum_ += fps; + delay_sum_ += delay_ms; + + last_fps_ = fps; + last_delay_ms_ = delay_ms; + last_stream_timestamp_ = stream_timestamp; + + if (fps_max_ <= 0) fps_max_ = fps; + if (fps_min_ <= 0) fps_min_ = fps; + fps_max_ = std::max(fps_max_, fps); + fps_min_ = std::min(fps_min_, fps); + if (delay_max_ <= 0) delay_max_ = delay_ms; + if (delay_min_ <= 0) delay_min_ = delay_ms; + delay_max_ = std::max(delay_max_, delay_ms); + delay_min_ = std::min(delay_min_, delay_ms); + } + + void fillColorStatus(orbbec_camera_msgs::msg::DeviceStatus &msg) { + std::lock_guard lock(mutex_); + msg.color_frame_rate_cur = last_fps_; + msg.color_frame_rate_avg = frame_count_ > 0 ? fps_sum_ / frame_count_ : 0; + msg.color_frame_rate_min = fps_min_; + msg.color_frame_rate_max = fps_max_; + + msg.color_delay_ms_cur = last_delay_ms_; + msg.color_delay_ms_avg = frame_count_ > 0 ? delay_sum_ / frame_count_ : 0; + msg.color_delay_ms_min = delay_min_; + msg.color_delay_ms_max = delay_max_; + + last_delay_ms_ = 0.0; + last_fps_ = 0.0; + frame_count_ = 0; + fps_sum_ = delay_sum_ = 0.0; + fps_max_ = delay_max_ = 0.0; + fps_min_ = delay_min_ = 0.0; + } + + void fillDepthStatus(orbbec_camera_msgs::msg::DeviceStatus &msg) { + std::lock_guard lock(mutex_); + msg.depth_frame_rate_cur = last_fps_; + msg.depth_frame_rate_avg = frame_count_ > 0 ? fps_sum_ / frame_count_ : 0; + msg.depth_frame_rate_min = fps_min_; + msg.depth_frame_rate_max = fps_max_; + + msg.depth_delay_ms_cur = last_delay_ms_; + msg.depth_delay_ms_avg = frame_count_ > 0 ? delay_sum_ / frame_count_ : 0; + msg.depth_delay_ms_min = delay_min_; + msg.depth_delay_ms_max = delay_max_; + + // RCLCPP_ERROR_STREAM(logger_, "Depth status: " << fps_sum_ << "," << frame_count_); + + last_delay_ms_ = 0.0; + last_fps_ = 0.0; + frame_count_ = 0; + fps_sum_ = delay_sum_ = 0.0; + fps_max_ = delay_max_ = 0.0; + fps_min_ = delay_min_ = 0.0; + } + + private: + mutable std::mutex mutex_; + u_int64_t last_stream_timestamp_{0}; + double last_delay_ms_{0.0}; + double last_fps_{0.0}; + + int frame_count_{0}; + double fps_sum_{0.0}; + double delay_sum_{0.0}; + double fps_max_{std::numeric_limits::lowest()}; + double fps_min_{std::numeric_limits::max()}; + double delay_max_{std::numeric_limits::lowest()}; + double delay_min_{std::numeric_limits::max()}; + + LogLevel log_level_; + rclcpp::Logger logger_; +}; + +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/image_publisher.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/image_publisher.h new file mode 100644 index 0000000..f114ec1 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/image_publisher.h @@ -0,0 +1,52 @@ +// Copyright 2023 Intel Corporation. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include +namespace orbbec_camera { +class image_publisher { + public: + virtual void publish(sensor_msgs::msg::Image::UniquePtr image_ptr) = 0; + virtual size_t get_subscription_count() const = 0; + virtual ~image_publisher() = default; +}; // namespace image_publisher + +// Native RCL implementation of an image publisher (needed for intra-process communication) +class image_rcl_publisher : public image_publisher { + public: + image_rcl_publisher(rclcpp::Node& node, const std::string& topic_name, + const rmw_qos_profile_t& qos); + void publish(sensor_msgs::msg::Image::UniquePtr image_ptr) override; + size_t get_subscription_count() const override; + + private: + rclcpp::Publisher::SharedPtr image_publisher_impl; +}; + +// image_transport implementation of an image publisher (adds a compressed image topic) +class image_transport_publisher : public image_publisher { + public: + image_transport_publisher(rclcpp::Node& node, const std::string& topic_name, + const rmw_qos_profile_t& qos); + void publish(sensor_msgs::msg::Image::UniquePtr image_ptr) override; + size_t get_subscription_count() const override; + + private: + std::shared_ptr image_publisher_impl; +}; +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/jetson_nv_decoder.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/jetson_nv_decoder.h new file mode 100644 index 0000000..2aea741 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/jetson_nv_decoder.h @@ -0,0 +1,38 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#pragma once +#include "utils.h" +#include + +#include "jpeg_decoder.h" +#include +#include +#include +#include +#include + +namespace orbbec_camera { +class JetsonNvJPEGDecoder : public JPEGDecoder { + public: + JetsonNvJPEGDecoder(int width, int height); + ~JetsonNvJPEGDecoder() override; + + bool decode(const std::shared_ptr& frame, uint8_t* dest) override; + + private: + NvJPEGDecoder* decoder_; +}; +} // namespace orbbec_camera \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/jpeg_decoder.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/jpeg_decoder.h new file mode 100644 index 0000000..7a0d6c4 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/jpeg_decoder.h @@ -0,0 +1,40 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#pragma once + +#include +#include +#include "libobsensor/ObSensor.hpp" +#include "utils.h" + +namespace orbbec_camera { + +class JPEGDecoder { + public: + JPEGDecoder(int width, int height); + + virtual ~JPEGDecoder(); + + virtual bool decode(const std::shared_ptr &frame, uint8_t *dest) = 0; + + std::string getErrorMsg() const { return error_msg_; } + + protected: + int width_ = 0; + int height_ = 0; + std::string error_msg_; +}; +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_camera_node.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_camera_node.h new file mode 100644 index 0000000..a65d1b7 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_camera_node.h @@ -0,0 +1,909 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include "libobsensor/ObSensor.hpp" + +#include "orbbec_camera_msgs/msg/device_info.hpp" +#include "orbbec_camera_msgs/srv/get_device_info.hpp" +#include "orbbec_camera_msgs/msg/extrinsics.hpp" +#include "orbbec_camera_msgs/msg/metadata.hpp" +#include "orbbec_camera_msgs/msg/imu_info.hpp" +#include "orbbec_camera_msgs/srv/get_int32.hpp" +#include "orbbec_camera_msgs/srv/get_string.hpp" +#include "orbbec_camera_msgs/srv/set_int32.hpp" +#include "orbbec_camera_msgs/srv/get_bool.hpp" +#include "orbbec_camera_msgs/srv/set_string.hpp" +#include "orbbec_camera_msgs/srv/set_filter.hpp" +#include "orbbec_camera_msgs/srv/set_arrays.hpp" +#include "orbbec_camera_msgs/srv/get_user_calib_params.hpp" +#include "orbbec_camera_msgs/srv/set_user_calib_params.hpp" +#include "orbbec_camera/constants.h" +#include "orbbec_camera/dynamic_params.h" +#include "orbbec_camera/d2c_viewer.h" +#include "magic_enum/magic_enum.hpp" +#include "orbbec_camera/image_publisher.h" +#include "orbbec_camera/fps_counter.hpp" +#include "orbbec_camera/fps_delay_status.hpp" +#include "jpeg_decoder.h" +#include +#include +#include + +#if __has_include() +#include +#elif __has_include() +#include +#endif + +#define STREAM_NAME(sip) \ + (static_cast(std::ostringstream() \ + << _stream_name[sip.first] \ + << ((sip.second > 0) ? std::to_string(sip.second) : ""))) \ + .str() +#define FRAME_ID(sip) \ + (static_cast(std::ostringstream() \ + << getNamespaceStr() << "_" << STREAM_NAME(sip) << "_frame")) \ + .str() +#define OPTICAL_FRAME_ID(sip) \ + (static_cast( \ + std::ostringstream() << getNamespaceStr() << "_" << STREAM_NAME(sip) << "_optical_frame")) \ + .str() +#define ALIGNED_DEPTH_TO_FRAME_ID(sip) \ + (static_cast(std::ostringstream() \ + << getNamespaceStr() << "_aligned_depth_to_" \ + << STREAM_NAME(sip) << "_frame")) \ + .str() +#define BASE_FRAME_ID() \ + (static_cast(std::ostringstream() << getNamespaceStr() << "_link")).str() +#define ODOM_FRAME_ID() \ + (static_cast(std::ostringstream() << getNamespaceStr() << "_odom_frame")) \ + .str() + +#define DEVICE_PATH "/dev/camsync" + +namespace orbbec_camera { +using GetDeviceInfo = orbbec_camera_msgs::srv::GetDeviceInfo; +using Extrinsics = orbbec_camera_msgs::msg::Extrinsics; +using SetInt32 = orbbec_camera_msgs::srv::SetInt32; +using GetInt32 = orbbec_camera_msgs::srv::GetInt32; +using GetString = orbbec_camera_msgs::srv::GetString; +using SetString = orbbec_camera_msgs::srv::SetString; +using SetBool = std_srvs::srv::SetBool; +using GetBool = orbbec_camera_msgs::srv::GetBool; +using SetFilter = orbbec_camera_msgs::srv::SetFilter; +using SetArrays = orbbec_camera_msgs::srv::SetArrays; +using SetUserCalibParams = orbbec_camera_msgs::srv::SetUserCalibParams; +using GetUserCalibParams = orbbec_camera_msgs::srv::GetUserCalibParams; + +typedef std::pair stream_index_pair; + +const stream_index_pair COLOR{OB_STREAM_COLOR, 0}; +const stream_index_pair COLOR_LEFT{OB_STREAM_COLOR_LEFT, 0}; +const stream_index_pair COLOR_RIGHT{OB_STREAM_COLOR_RIGHT, 0}; +const stream_index_pair DEPTH{OB_STREAM_DEPTH, 0}; +const stream_index_pair INFRA0{OB_STREAM_IR, 0}; +const stream_index_pair INFRA1{OB_STREAM_IR_LEFT, 0}; +const stream_index_pair INFRA2{OB_STREAM_IR_RIGHT, 0}; +const stream_index_pair LIDAR{OB_STREAM_LIDAR, 0}; + +const stream_index_pair GYRO{OB_STREAM_GYRO, 0}; +const stream_index_pair ACCEL{OB_STREAM_ACCEL, 0}; + +const std::vector IMAGE_STREAMS = {COLOR, COLOR_LEFT, COLOR_RIGHT, DEPTH, + INFRA0, INFRA1, INFRA2, LIDAR}; + +const std::vector HID_STREAMS = {GYRO, ACCEL}; + +const std::map STREAM_TYPE_TO_FRAME_TYPE = { + {OB_STREAM_COLOR, OB_FRAME_COLOR}, + {OB_STREAM_COLOR_LEFT, OB_FRAME_COLOR_LEFT}, + {OB_STREAM_COLOR_RIGHT, OB_FRAME_COLOR_RIGHT}, + {OB_STREAM_DEPTH, OB_FRAME_DEPTH}, + {OB_STREAM_IR, OB_FRAME_IR}, + {OB_STREAM_IR_LEFT, OB_FRAME_IR_LEFT}, + {OB_STREAM_IR_RIGHT, OB_FRAME_IR_RIGHT}, + {OB_STREAM_GYRO, OB_FRAME_GYRO}, + {OB_STREAM_ACCEL, OB_FRAME_ACCEL}, +}; + +typedef struct { + uint8_t mode; + uint16_t fps; +} cs_param_t; + +class OBCameraNode { + public: + OBCameraNode(rclcpp::Node* node, std::shared_ptr device, + std::shared_ptr parameters, bool use_intra_process = false); + + template + void setAndGetNodeParameter( + T& param, const std::string& param_name, const T& default_value, + const rcl_interfaces::msg::ParameterDescriptor& parameter_descriptor = + rcl_interfaces::msg::ParameterDescriptor()); // set and get parameter + + ~OBCameraNode() noexcept; + + void clean() noexcept; + + // Safely expose the lock + template + auto withDeviceLock(Func&& func) -> decltype(func()) { + std::lock_guard lock(device_lock_); + return func(); + } + + void rebootDevice(); + + void startStreams(); + + void startIMUSyncStream(); + + void startIMU(); + + int openSocSyncPwmTrigger(uint16_t fps); + int closeSocSyncPwmTrigger(); + void startGmslTrigger(); + void stopGmslTrigger(); + + bool isParamCalibrated() const { + return (color_info_manager_ && color_info_manager_->isCalibrated() && ir_info_manager_ && + ir_info_manager_->isCalibrated()); + } + void getColorStatus(orbbec_camera_msgs::msg::DeviceStatus& status_msg) { + fps_delay_status_color_->fillColorStatus(status_msg); + } + + void getDepthStatus(orbbec_camera_msgs::msg::DeviceStatus& status_msg) { + fps_delay_status_depth_->fillDepthStatus(status_msg); + } + + bool checkUserCalibrationReady() { + static bool first_check = true; + if (first_check) { + first_check = false; + std::string data_read; + if (readCustomerData(data_read)) { + user_calibration_ready_ = true; + } else { + user_calibration_ready_ = false; + } + } + return user_calibration_ready_; + } + + private: + struct IMUData { + IMUData() = default; + IMUData(stream_index_pair stream, Eigen::Vector3d data, double timestamp) + : stream_(std::move(stream)), data_(std::move(data)), timestamp_(timestamp) {} + [[nodiscard]] bool isSet() const { return timestamp_ >= 0; } + stream_index_pair stream_{}; + Eigen::Vector3d data_{}; + double timestamp_ = -1; // in nanoseconds + }; + + void setupDevices(); + + void setupProfiles(); + + void updateImageConfig(const stream_index_pair& stream_index); + + void printSensorProfiles(const std::shared_ptr& sensor); + + void selectBaseStream(); + + void getParameters(); + + void setupTopics(); + + void setupPipelineConfig(); + + void setupDiagnosticUpdater(); + + void onTemperatureUpdate(diagnostic_updater::DiagnosticStatusWrapper& status); + + void setupCameraCtrlServices(); + + void stopStreams(); + + void stopIMU(); + + void setupDefaultImageFormat(); + + void setupPublishers(); + + void setupCameraInfo(); + + void publishStaticTF(const rclcpp::Time& t, const tf2::Vector3& trans, const tf2::Quaternion& q, + const std::string& from, const std::string& to); + + void calcAndPublishStaticTransform(); + + void publishDynamicTransforms(); + + void publishStaticTransforms(); + + std::optional findDefaultCameraParam(); + + std::optional getDepthCameraParam(); + + std::optional getColorCameraParam(); + + void setStreamsEnableCallback(const std::shared_ptr request, + std::shared_ptr response); + + void getStreamsEnableCallback( + const std::shared_ptr request, + std::shared_ptr response); + + void getExposureCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void setExposureCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void getGainCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void setGainCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void getWhiteBalanceCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void setWhiteBalanceCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void getAutoWhiteBalanceCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void setAutoWhiteBalanceCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void setAutoExposureCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void setAeRoiCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void setLaserEnableCallback(const std::shared_ptr& request_header, + const std::shared_ptr& request, + std::shared_ptr& response); + + void setFloorEnableCallback(const std::shared_ptr& request_header, + const std::shared_ptr& request, + std::shared_ptr& response); + + void setLdpEnableCallback(const std::shared_ptr& request_header, + const std::shared_ptr& request, + std::shared_ptr& response); + + void setPtpConfigCallback(const std::shared_ptr& request_header, + const std::shared_ptr& request, + std::shared_ptr& response); + + void setFanWorkModeCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void getDeviceInfoCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void getSDKVersion(const std::shared_ptr& request, + std::shared_ptr& response); + + void toggleSensorCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void setMirrorCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void setFlipCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + + void setRotationCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index); + void getLaserStatusCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void getLdpStatusCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void getPtpConfigCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void getLrmMeasureDistanceCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void setRESETTimestampCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void setSYNCInterleaveLaserCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void setFilterCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void setPointCloudDecimationCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void getPointCloudDecimationCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void setSYNCHostimeCallback(const std::shared_ptr& request, + std::shared_ptr& response); + void sendSoftwareTriggerCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + bool toggleSensor(const stream_index_pair& stream_index, bool enabled, std::string& msg); + + void saveImageCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void savePointCloudCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void switchIRCameraCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + bool writeCustomerData(const std::string& data); + + bool readCustomerData(std::string& out_data); + + void writeCustomerDataCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void readCustomerDataCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void getUserCalibParamsCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void setAEModeCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void setSportsModeCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void setUserCalibParamsCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void setIRLongExposureCallback(const std::shared_ptr& request, + std::shared_ptr& response); + + void publishPointCloud(const std::shared_ptr& frame_set); + + void publishDepthPointCloud(const std::shared_ptr& frame_set); + + void publishColoredPointCloud(const std::shared_ptr& frame_set); + + std::shared_ptr processDepthFrameFilter(std::shared_ptr& frame); + + std::shared_ptr processColorFrameFilter(std::shared_ptr& frame); + + std::shared_ptr processRightIrFrameFilter(std::shared_ptr& frame); + + std::shared_ptr processLeftIrFrameFilter(std::shared_ptr& frame); + + uint64_t getFrameTimestampUs(const std::shared_ptr& frame); + + void onNewFrameSetCallback(std::shared_ptr frame_set); + + std::shared_ptr softwareDecodeColorFrame(const std::shared_ptr& frame, + const stream_index_pair& stream_index); + + bool decodeColorFrameToBuffer(const std::shared_ptr& frame, uint8_t* buffer); + + std::shared_ptr decodeIRMJPGFrame(const std::shared_ptr& frame); + + void onNewFrameCallback(const std::shared_ptr& frame, + const stream_index_pair& stream_index); + + void publishMetadata(const std::shared_ptr& frame, + const stream_index_pair& stream_index, const std_msgs::msg::Header& header); + + void onNewColorFrameCallback(); + + void onNewLeftColorFrameCallback(); + + void onNewRightColorFrameCallback(); + + void saveImageToFile(const stream_index_pair& stream_index, const cv::Mat& image, + const sensor_msgs::msg::Image& image_msg); + + void onNewIMUFrameSyncOutputCallback(const std::shared_ptr& accelframe, + const std::shared_ptr& gryoframe); + + void onNewIMUFrameCallback(const std::shared_ptr& frame, + const stream_index_pair& stream_index); + + void setDefaultIMUMessage(sensor_msgs::msg::Imu& imu_msg); + + sensor_msgs::msg::Imu createUnitIMUMessage(const IMUData& accel_data, const IMUData& gyro_data); + + void FillImuDataLinearInterpolation(const IMUData& imu_data, + std::deque& imu_msgs); + + void FillImuDataCopy(const IMUData& imu_data, std::deque& imu_msgs); + + bool setupFormatConvertType(OBFormat format); + bool setupFormatConvertType(OBFormat format, ob::FormatConvertFilter& filter); + + orbbec_camera_msgs::msg::IMUInfo createIMUInfo(const stream_index_pair& stream_index); + + static bool isGemini335PID(uint32_t pid); + + static bool isGemini435LePID(uint32_t pid); + static bool isPublishMetaData(uint32_t pid); + + static bool isDepthWorkModeDevices(uint32_t pid); + static bool isnotLaserDevices(uint32_t pid); + + void setupDepthPostProcessFilter(); + void setupColorPostProcessFilter(); + void setupRightIrPostProcessFilter(); + void setupLeftIrPostProcessFilter(); + + // interleave AE + int init_interleave_hdr_param(); + int init_interleave_laser_param(); + + // Set ROI + void setColorAutoExposureROI(); + void setDepthAutoExposureROI(); + + void setDisparitySearchOffset(); + + bool isWriteCustomerDataSuccess() const; + + private: + std::atomic_bool write_customer_data_success_{false}; + std::atomic_bool user_calibration_ready_{false}; + // New state flags to make clean() and rebootDevice() idempotent and thread-safe + std::atomic_bool cleaning_{false}; + rclcpp::Node* node_ = nullptr; + std::shared_ptr device_ = nullptr; + std::shared_ptr parameters_ = nullptr; + rclcpp::Logger logger_; + std::atomic_bool is_running_{false}; + std::unique_ptr pipeline_ = nullptr; + std::unique_ptr imuPipeline_ = nullptr; + std::atomic_bool pipeline_started_{false}; + std::string camera_name_ = "camera"; + std::string accel_gyro_frame_id_ = "camera_accel_gyro_optical_frame"; + const std::string imu_frame_id_ = "camera_gyro_frame"; + std::shared_ptr pipeline_config_ = nullptr; + std::map> sensors_; + std::map stream_intrinsics_; + std::map camera_infos_; + std::map ob_camera_param_; + std::map depth_to_other_extrinsics_; + std::map::SharedPtr> + depth_to_other_extrinsics_publishers_; + std::map::SharedPtr> + metadata_publishers_; + std::map::SharedPtr> + imu_info_publishers_; + std::map width_; + std::map height_; + std::map fps_; + std::map frame_id_; + std::map optical_frame_id_; + std::map depth_aligned_frame_id_; + std::string camera_link_frame_id_; + bool depth_registration_ = false; + std::map image_qos_; + std::map camera_info_qos_; + std::map format_; + std::map format_str_; + std::map image_format_; + std::map>> + supported_profiles_; + std::map> stream_profile_; + stream_index_pair base_stream_ = DEPTH; + std::map seq_; + std::map images_; + std::map encoding_; + std::map unit_step_size_; + std::vector compression_params_; + ob::FormatConvertFilter format_convert_filter_; + ob::FormatConvertFilter format_convert_filter_left_; + ob::FormatConvertFilter format_convert_filter_right_; + + std::map enable_stream_; + std::map flip_stream_; + std::map mirror_stream_; + std::map rotation_stream_; + std::map stream_name_; + std::map> image_publishers_; + std::map::SharedPtr> + camera_info_publishers_; + + std::map::SharedPtr> get_exposure_srv_; + std::map::SharedPtr> set_exposure_srv_; + std::map::SharedPtr> get_gain_srv_; + std::map::SharedPtr> set_gain_srv_; + std::map::SharedPtr> toggle_sensor_srv_; + std::map::SharedPtr> set_mirror_srv_; + std::map::SharedPtr> set_flip_srv_; + std::map::SharedPtr> set_rotation_srv_; + rclcpp::Service::SharedPtr get_white_balance_srv_; + rclcpp::Service::SharedPtr set_white_balance_srv_; + rclcpp::Service::SharedPtr get_auto_white_balance_srv_; + rclcpp::Service::SharedPtr set_auto_white_balance_srv_; + rclcpp::Service::SharedPtr get_sdk_version_srv_; + rclcpp::Service::SharedPtr switch_ir_camera_srv_; + rclcpp::Service::SharedPtr write_customerdata_srv_; + rclcpp::Service::SharedPtr read_customerdata_srv_; + rclcpp::Service::SharedPtr set_ir_long_exposure_srv_; + std::map::SharedPtr> + set_auto_exposure_srv_; + std::map::SharedPtr> set_ae_roi_srv_; + rclcpp::Service::SharedPtr get_device_srv_; + rclcpp::Service::SharedPtr set_laser_enable_srv_; + rclcpp::Service::SharedPtr set_ldp_enable_srv_; + rclcpp::Service::SharedPtr get_ldp_status_srv_; + rclcpp::Service::SharedPtr get_laser_status_srv_; + rclcpp::Service::SharedPtr set_ptp_config_srv_; + rclcpp::Service::SharedPtr get_ptp_config_srv_; + rclcpp::Service::SharedPtr set_floor_enable_srv_; + rclcpp::Service::SharedPtr set_fan_work_mode_srv_; + rclcpp::Service::SharedPtr toggle_sensors_srv_; + rclcpp::Service::SharedPtr get_lrm_measure_distance_srv_; + rclcpp::Service::SharedPtr set_reset_timestamp_srv_; + rclcpp::Service::SharedPtr set_interleaver_laser_sync_srv_; + rclcpp::Service::SharedPtr set_sync_host_time_srv_; + rclcpp::Service::SharedPtr send_software_trigger_srv_; + rclcpp::Service::SharedPtr set_filter_srv_; + rclcpp::Service::SharedPtr set_point_cloud_decimation_srv_; + rclcpp::Service::SharedPtr get_point_cloud_decimation_srv_; + rclcpp::Service::SharedPtr get_streams_enable_srv_; + rclcpp::Service::SharedPtr set_streams_enable_srv_; + rclcpp::Service::SharedPtr get_user_calib_params_srv_; + rclcpp::Service::SharedPtr set_user_calib_params_srv_; + rclcpp::Service::SharedPtr set_ae_mode_srv_; + rclcpp::Service::SharedPtr set_sports_mode_srv_; + + bool enable_sync_output_accel_gyro_ = false; + bool publish_tf_ = false; + bool tf_published_ = false; + std::shared_ptr static_tf_broadcaster_ = nullptr; + std::shared_ptr dynamic_tf_broadcaster_ = nullptr; + std::vector tf_msgs; + rclcpp::Publisher::SharedPtr depth_registration_cloud_pub_; + rclcpp::Publisher::SharedPtr depth_cloud_pub_; + bool enable_point_cloud_ = true; + bool enable_colored_point_cloud_ = false; + int point_cloud_decimation_filter_factor_ = 1; + std::recursive_mutex point_cloud_mutex_; + + orbbec_camera_msgs::msg::DeviceInfo device_info_; + std::string point_cloud_qos_; + std::vector static_tf_msgs_; + std::shared_ptr tf_thread_ = nullptr; + std::condition_variable tf_cv_; + double tf_publish_rate_ = 10.0; + std::unique_ptr ir_info_manager_ = nullptr; + std::unique_ptr color_info_manager_ = nullptr; + std::string color_info_url_; + std::string ir_info_url_; + std::optional camera_param_; + bool enable_d2c_viewer_ = false; + std::unique_ptr d2c_viewer_ = nullptr; + std::map save_images_; + std::map save_images_count_; + int max_save_images_count_ = 10; + std::atomic_bool save_point_cloud_{false}; + std::atomic_bool save_colored_point_cloud_{false}; + rclcpp::Service::SharedPtr save_images_srv_; + rclcpp::Service::SharedPtr save_point_cloud_srv_; + std::string depth_filter_config_; + bool enable_depth_filter_ = false; + bool enable_color_auto_exposure_priority_ = false; + bool enable_color_auto_exposure_ = true; + bool enable_color_auto_white_balance_ = true; + bool enable_depth_auto_exposure_priority_ = false; + bool enable_ir_auto_exposure_ = true; + bool enable_ir_long_exposure_ = false; + bool enable_ldp_ = true; + int ldp_power_level_ = -1; + int color_rotation_ = -1; + // color ae roi + int color_ae_roi_left_ = -1; + int color_ae_roi_top_ = -1; + int color_ae_roi_right_ = -1; + int color_ae_roi_bottom_ = -1; + int color_exposure_ = -1; + int color_gain_ = -1; + int color_white_balance_ = -1; + int color_ae_max_exposure_ = -1; + int color_brightness_ = -1; + int color_roi_brightness_ = -1; + int color_sharpness_ = -1; + int color_gamma_ = -1; + int color_saturation_ = -1; + int color_contrast_ = -1; + int color_hue_ = -1; + int color_backlight_compensation_ = -1; + std::string color_powerline_freq_; + std::string color_preset_; + int color_denoising_level_ = -1; + bool enable_color_decimation_filter_ = false; + int color_decimation_filter_scale_ = -1; + bool enable_left_color_decimation_filter_ = false; + int left_color_decimation_filter_scale_ = -1; + bool enable_right_color_decimation_filter_ = false; + int right_color_decimation_filter_scale_ = -1; + // depth ae roi + int depth_ae_roi_left_ = -1; + int depth_ae_roi_top_ = -1; + int depth_ae_roi_right_ = -1; + int depth_ae_roi_bottom_ = -1; + int mean_intensity_set_point_ = -1; + int depth_brightness_ = -1; + int depth_exposure_ = -1; + int depth_gain_ = -1; + int ir_exposure_ = -1; + int ir_gain_ = -1; + int ir_ae_max_exposure_ = -1; + int ir_brightness_ = -1; + bool enable_right_ir_sequence_id_filter_ = false; + int right_ir_sequence_id_filter_id_ = -1; + bool enable_left_ir_sequence_id_filter_ = false; + int left_ir_sequence_id_filter_id_ = -1; + bool enable_frame_sync_ = false; + // Only for Gemini2 device + std::string disparity_to_depth_mode_ = "HW"; + std::string depth_work_mode_; + std::string preset_resolution_config_; + OBMultiDeviceSyncMode sync_mode_ = OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN; + std::string sync_mode_str_; + int depth_delay_us_ = 0; + int color_delay_us_ = 0; + int trigger2image_delay_us_ = 0; + int trigger_out_delay_us_ = 0; + bool trigger_out_enabled_ = false; + bool software_trigger_enabled_ = false; + int frames_per_trigger_ = 2; + bool enable_ptp_config_ = false; + std::string depth_precision_str_; + OB_DEPTH_PRECISION_LEVEL depth_precision_ = OB_PRECISION_0MM8; + double depth_precision_float_ = 0.10; + // IMU + std::map::SharedPtr> imu_publishers_; + rclcpp::Publisher::SharedPtr imu_gyro_accel_publisher_; + std::atomic_bool imu_sync_output_start_{false}; + std::map imu_rate_; + std::map imu_range_; + std::map imu_qos_; + std::map imu_started_; + double linear_accel_cov_ = 0.0001; + double angular_vel_cov_ = 0.0001; + std::deque imu_history_; + IMUData accel_data_{ACCEL, {0, 0, 0}, -1.0}; + bool enable_accel_data_correction_ = true; + bool enable_gyro_data_correction_ = true; + // mjpeg decoder + std::shared_ptr jpeg_decoder_ = nullptr; + std::shared_ptr jpeg_decoder_left_ = nullptr; + std::shared_ptr jpeg_decoder_right_ = nullptr; + uint8_t* rgb_buffer_ = nullptr; + uint8_t* rgb_buffer_left_ = nullptr; + uint8_t* rgb_buffer_right_ = nullptr; + bool is_left_color_frame_decoded_ = false; + bool is_right_color_frame_decoded_ = false; + bool is_color_frame_decoded_ = false; + std::recursive_mutex device_lock_; + // For color + std::queue> color_frame_queue_; + std::shared_ptr colorFrameThread_ = nullptr; + std::mutex color_frame_queue_lock_; + std::condition_variable color_frame_queue_cv_; + + // For left color + std::queue> left_color_frame_queue_; + std::shared_ptr leftColorFrameThread_ = nullptr; + std::mutex left_color_frame_queue_lock_; + std::condition_variable left_color_frame_queue_cv_; + + // For right color + std::queue> right_color_frame_queue_; + std::shared_ptr rightColorFrameThread_ = nullptr; + std::mutex right_color_frame_queue_lock_; + std::condition_variable right_color_frame_queue_cv_; + + bool ordered_pc_ = false; + bool enable_depth_scale_ = true; + int depth_decimation_factor_ = 1; + int left_ir_decimation_factor_ = 1; + int right_ir_decimation_factor_ = 1; + std::string device_preset_; + // filter switch + bool enable_decimation_filter_ = false; + bool enable_hdr_merge_ = false; + bool enable_sequence_id_filter_ = false; + bool enable_disparity_to_depth_ = true; + bool enable_threshold_filter_ = false; + bool enable_hardware_noise_removal_filter_ = true; + bool enable_noise_removal_filter_ = true; + bool enable_spatial_filter_ = true; + bool enable_temporal_filter_ = false; + bool enable_hole_filling_filter_ = false; + bool enable_spatial_fast_filter_ = false; + bool enable_spatial_moderate_filter_ = false; + bool enable_false_positive_filter_ = false; + + // filter params + int decimation_filter_scale_ = -1; + int sequence_id_filter_id_ = -1; + int threshold_filter_max_ = -1; + int threshold_filter_min_ = -1; + float hardware_noise_removal_filter_threshold_ = -1.0; + int noise_removal_filter_min_diff_ = 256; + int noise_removal_filter_max_size_ = 80; + float spatial_filter_alpha_ = -1; + int spatial_filter_diff_threshold_ = -1; + int spatial_filter_magnitude_ = -1; + int spatial_filter_radius_ = -1; + float temporal_filter_diff_threshold_ = -1.0; + float temporal_filter_weight_ = -1.0; + std::string hole_filling_filter_mode_; + int hdr_merge_exposure_1_ = -1; + int hdr_merge_gain_1_ = -1; + int hdr_merge_exposure_2_ = -1; + int hdr_merge_gain_2_ = -1; + int gmsl_trigger_fd_ = -1; + int gmsl_trigger_fps_ = -1; + bool enable_gmsl_trigger_ = false; + int spatial_fast_filter_radius_ = -1; + int spatial_moderate_filter_radius_ = -1; + int spatial_moderate_filter_diff_threshold_ = -1; + int spatial_moderate_filter_magnitude_ = -1; + rclcpp::Publisher::SharedPtr filter_status_pub_; + nlohmann::json filter_status_; + std::string align_mode_ = "HW"; + std::unique_ptr diagnostic_updater_ = nullptr; + double diagnostic_period_ = 1.0; + bool enable_laser_ = false; + std::unique_ptr align_filter_ = nullptr; + OBStreamType align_target_stream_ = OB_STREAM_COLOR; + bool retry_on_usb3_detection_failure_ = false; + std::atomic_bool is_camera_node_initialized_{false}; + int laser_energy_level_ = -1; + ob::PointCloudFilter depth_point_cloud_filter_; + ob::PointCloudFilter color_point_cloud_filter_; + std::optional calibration_param_; + std::optional xy_tables_; + float* xy_table_data_ = nullptr; + uint32_t xy_table_data_size_ = 0; + uint8_t* rgb_point_cloud_buffer_ = nullptr; + uint32_t rgb_point_cloud_buffer_size_ = 0; + std::optional depth_xy_tables_; + float* depth_xy_table_data_ = nullptr; + uint32_t depth_xy_table_data_size_ = 0; + uint8_t* depth_point_cloud_buffer_ = nullptr; + uint32_t depth_point_cloud_buffer_size_ = 0; + int min_depth_limit_ = 0; + int max_depth_limit_ = 0; + std::string time_domain_ = "global"; // device, system, global + std::string exposure_range_mode_ = "default"; + std::string load_config_json_file_path_ = ""; + std::string export_config_json_file_path_ = ""; + // soft ware trigger + rclcpp::TimerBase::SharedPtr software_trigger_timer_; + rclcpp::TimerBase::SharedPtr diagnostic_timer_; + std::mutex diagnostic_mutex_; + std::condition_variable diagnostic_cv_; + bool diagnostic_running_ = false; + std::chrono::milliseconds software_trigger_period_{33}; + bool enable_heartbeat_ = false; + bool enable_color_undistortion_ = false; + std::shared_ptr color_undistortion_publisher_; + bool has_first_color_frame_ = false; + bool use_intra_process_ = false; + std::string cloud_frame_id_; + std::vector> depth_filter_list_; + std::vector> color_filter_list_; + std::vector> left_color_filter_list_; + std::vector> right_color_filter_list_; + std::vector> left_ir_filter_list_; + std::vector> right_ir_filter_list_; + + // interleave AE + std::string interleave_ae_mode_ = "hdr"; // hdr or laser + bool interleave_frame_enable_ = false; + bool interleave_skip_enable_ = false; + int interleave_skip_index_ = 1; + + // hdr and laser interleave params + int hdr_index1_laser_control_ = 1; + int hdr_index1_depth_exposure_ = 1; + int hdr_index1_depth_gain_ = 16; + int hdr_index1_ir_brightness_ = 30; + int hdr_index1_ir_ae_max_exposure_ = 30458; + int hdr_index0_laser_control_ = 1; + int hdr_index0_depth_exposure_ = 7500; + int hdr_index0_depth_gain_ = 16; + int hdr_index0_ir_brightness_ = 90; + int hdr_index0_ir_ae_max_exposure_ = 30458; + + int laser_index1_laser_control_ = 0; + int laser_index1_depth_exposure_ = 3000; + int laser_index1_depth_gain_ = 16; + int laser_index1_ir_brightness_ = 60; + int laser_index1_ir_ae_max_exposure_ = 7000; + int laser_index0_laser_control_ = 1; + int laser_index0_depth_exposure_ = 3000; + int laser_index0_depth_gain_ = 16; + int laser_index0_ir_brightness_ = 60; + int laser_index0_ir_ae_max_exposure_ = 17000; + + int disparity_range_mode_ = -1; + int disparity_search_offset_ = -1; + bool disparity_offset_config_ = false; + int offset_index0_ = -1; + int offset_index1_ = -1; + + std::string frame_aggregate_mode_ = "ANY"; // # full_frame, color_frame, ANY or disable + + bool show_fps_enable_ = false; + bool enable_publish_extrinsic_ = false; + std::unique_ptr fps_counter_color_{nullptr}; + std::unique_ptr fps_counter_depth_{nullptr}; + std::unique_ptr fps_counter_left_ir_{nullptr}; + std::unique_ptr fps_counter_right_ir_{nullptr}; + + std::unique_ptr fps_delay_status_color_{nullptr}; + std::unique_ptr fps_delay_status_depth_{nullptr}; + + std::string intra_camera_sync_reference_ = ""; + std::string ae_mode_; + bool enable_sports_mode_; + int pid_ = 0; +}; +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_camera_node_driver.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_camera_node_driver.h new file mode 100644 index 0000000..8f46f18 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_camera_node_driver.h @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +#pragma once +#include +#include +#include + +#include +#include +#include "ob_camera_node.h" +#include "ob_lidar_node.h" +#include "utils.h" +#include "dynamic_params.h" +#include + +#include "libobsensor/ObSensor.hpp" +#include +#include +#include +#include "libobsensor/hpp/Device.hpp" + +namespace orbbec_camera { + +class OBCameraNodeDriver : public rclcpp::Node { + public: + explicit OBCameraNodeDriver(const rclcpp::NodeOptions& node_options = rclcpp::NodeOptions()); + OBCameraNodeDriver(const std::string& node_name, const std::string& ns, + const rclcpp::NodeOptions& node_options = rclcpp::NodeOptions()); + ~OBCameraNodeDriver() override; + + private: + void init(); + + std::shared_ptr selectDevice(const std::shared_ptr& list); + + std::shared_ptr selectDeviceBySerialNumber( + const std::shared_ptr& list, const std::string& serial_number); + + std::shared_ptr selectDeviceByUSBPort(const std::shared_ptr& list, + const std::string& usb_port); + + std::shared_ptr selectDeviceByNetIP(const std::shared_ptr& list, + const std::string& net_ip); + + void initializeDevice(const std::shared_ptr& device); + + void startDevice(const std::shared_ptr& list); + + void connectNetDevice(const std::string& net_device_ip, int net_device_port); + + void onDeviceConnected(const std::shared_ptr& device_list); + + void onDeviceDisconnected(const std::shared_ptr& device_list); + + static OBLogSeverity obLogSeverityFromString(const std::string_view& log_level); + + void checkConnectTimer(); + + void queryDevice(); + + void resetDevice(); + + void deviceStatusTimer(); + + void rebootDeviceCallback(const std::shared_ptr request, + std::shared_ptr response); + void presetUpdateCallback(bool firstCall, OBFwUpdateState state, const char* message, + uint8_t percent); + void updatePresetFirmware(std::string path); + + void firmwareUpdateCallback(OBFwUpdateState state, const char* message, uint8_t percent); + + bool applyForceIpConfig(); + + OBDeviceAccessMode stringToAccessMode(const std::string& mode_str); + std::string accessModeToString(OBDeviceAccessMode mode); + + private: + const rclcpp::NodeOptions node_options_; + std::string config_path_; + std::unique_ptr ctx_ = nullptr; + rclcpp::Logger logger_; + OBCallbackId device_changed_callback_id_ = + INVALID_CALLBACK_ID; // Store callback ID for unregistering + std::unique_ptr ob_camera_node_ = nullptr; + std::unique_ptr ob_lidar_node_ = nullptr; + std::shared_ptr device_ = nullptr; + std::shared_ptr device_info_ = nullptr; + std::atomic_bool is_alive_{false}; + std::atomic_bool device_connected_{false}; + std::atomic_bool device_connecting_{false}; + std::string serial_number_; + std::string device_unique_id_; + std::string usb_port_; + std::string device_access_mode_str_; + OBDeviceAccessMode device_access_mode_ = OB_DEVICE_DEFAULT_ACCESS; + bool enumerate_net_device_ = false; // default false + std::string uvc_backend_; + std::shared_ptr parameters_ = nullptr; + std::shared_ptr query_thread_ = nullptr; + std::shared_ptr device_count_update_thread_ = nullptr; + std::recursive_mutex device_lock_; + int device_num_ = 1; + rclcpp::TimerBase::SharedPtr check_connect_timer_ = nullptr; + rclcpp::TimerBase::SharedPtr sync_host_time_timer_ = nullptr; + std::shared_ptr reset_device_thread_ = nullptr; + std::mutex reset_device_mutex_; + std::condition_variable reset_device_cond_; + std::atomic_bool reset_device_flag_{false}; + std::chrono::steady_clock::time_point last_reset_device_completion_time_; + pthread_mutex_t* orb_device_lock_ = nullptr; + pthread_mutexattr_t orb_device_lock_attr_; + uint8_t* orb_device_lock_shm_addr_ = nullptr; + int orb_device_lock_shm_fd_ = -1; + // net config + std::string net_device_ip_; + int net_device_port_ = 0; + int connection_delay_ = 100; + bool enable_sync_host_time_ = true; + std::chrono::milliseconds time_sync_period_{6000}; + std::string preset_firmware_path_; + rclcpp::Service::SharedPtr reboot_device_srv_ = nullptr; + std::chrono::time_point start_time_; + std::string extension_path_; + static backward::SignalHandling sh; // for stack trace + std::string upgrade_firmware_; + std::atomic firmware_update_success_{false}; + std::atomic need_reupdate_{false}; + std::atomic is_reupdating_{false}; // Flag to track if we're in reupdate process + rclcpp::TimerBase::SharedPtr device_status_timer_ = nullptr; + int device_status_interval_hz = 2; // 2Hz + rclcpp::Publisher::SharedPtr device_status_pub_ = nullptr; + std::string node_name_; + bool force_ip_enable_{false}; + bool force_ip_dhcp_{false}; + std::string force_ip_mac_; // e.g. "54:14:FD:06:07:DA" + std::string force_ip_address_; // e.g. "192.168.1.10" + std::string force_ip_subnet_mask_; // e.g. "255.255.255.0" + std::string force_ip_gateway_; // e.g. "192.168.1.1" + std::atomic force_ip_success_{false}; + std::string device_type_; +}; +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_lidar_node.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_lidar_node.h new file mode 100644 index 0000000..06da634 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/ob_lidar_node.h @@ -0,0 +1,296 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// #include "ob_lidar_node.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include "libobsensor/ObSensor.hpp" + +#include "orbbec_camera_msgs/msg/device_info.hpp" +#include "orbbec_camera_msgs/srv/get_device_info.hpp" +#include "orbbec_camera_msgs/msg/extrinsics.hpp" +#include "orbbec_camera_msgs/msg/metadata.hpp" +#include "orbbec_camera_msgs/msg/imu_info.hpp" +#include "orbbec_camera_msgs/srv/get_int32.hpp" +#include "orbbec_camera_msgs/srv/get_string.hpp" +#include "orbbec_camera_msgs/srv/set_int32.hpp" +#include "orbbec_camera_msgs/srv/get_bool.hpp" +#include "orbbec_camera_msgs/srv/set_string.hpp" +#include "orbbec_camera_msgs/srv/set_filter.hpp" +#include "orbbec_camera_msgs/srv/set_arrays.hpp" +#include "orbbec_camera/constants.h" +#include "orbbec_camera/dynamic_params.h" +#include "orbbec_camera/d2c_viewer.h" +#include "magic_enum/magic_enum.hpp" +#include "orbbec_camera/image_publisher.h" +#include +#include +#include + +#if __has_include() +#include +#elif __has_include() +#include +#endif + +#define STREAM_NAME(sip) \ + (static_cast(std::ostringstream() \ + << _stream_name[sip.first] \ + << ((sip.second > 0) ? std::to_string(sip.second) : ""))) \ + .str() +#define FRAME_ID(sip) \ + (static_cast(std::ostringstream() \ + << getNamespaceStr() << "_" << STREAM_NAME(sip) << "_frame")) \ + .str() +#define OPTICAL_FRAME_ID(sip) \ + (static_cast( \ + std::ostringstream() << getNamespaceStr() << "_" << STREAM_NAME(sip) << "_optical_frame")) \ + .str() +#define ALIGNED_DEPTH_TO_FRAME_ID(sip) \ + (static_cast(std::ostringstream() \ + << getNamespaceStr() << "_aligned_depth_to_" \ + << STREAM_NAME(sip) << "_frame")) \ + .str() +#define BASE_FRAME_ID() \ + (static_cast(std::ostringstream() << getNamespaceStr() << "_link")).str() +#define ODOM_FRAME_ID() \ + (static_cast(std::ostringstream() << getNamespaceStr() << "_odom_frame")) \ + .str() + +#define DEVICE_PATH "/dev/camsync" + +namespace orbbec_camera { +namespace orbbec_lidar { +using GetDeviceInfo = orbbec_camera_msgs::srv::GetDeviceInfo; +using Extrinsics = orbbec_camera_msgs::msg::Extrinsics; +using SetInt32 = orbbec_camera_msgs::srv::SetInt32; +using GetInt32 = orbbec_camera_msgs::srv::GetInt32; +using GetString = orbbec_camera_msgs::srv::GetString; +using SetString = orbbec_camera_msgs::srv::SetString; +using SetBool = std_srvs::srv::SetBool; +using GetBool = orbbec_camera_msgs::srv::GetBool; +using SetFilter = orbbec_camera_msgs::srv::SetFilter; +using SetArrays = orbbec_camera_msgs::srv::SetArrays; + +typedef std::pair stream_index_pair; + +const stream_index_pair LIDAR{OB_STREAM_LIDAR, 0}; + +const stream_index_pair GYRO{OB_STREAM_GYRO, 0}; +const stream_index_pair ACCEL{OB_STREAM_ACCEL, 0}; + +const std::vector LIDAR_STREAMS = {LIDAR}; + +const std::vector HID_STREAMS = {GYRO, ACCEL}; + +class OBLidarNode { + public: + OBLidarNode(rclcpp::Node* node, std::shared_ptr device, + std::shared_ptr parameters, bool use_intra_process = false); + + template + void setAndGetNodeParameter( + T& param, const std::string& param_name, const T& default_value, + const rcl_interfaces::msg::ParameterDescriptor& parameter_descriptor = + rcl_interfaces::msg::ParameterDescriptor()); // set and get parameter + + ~OBLidarNode() noexcept; + + void clean() noexcept; + + void rebootDevice(); + + void startStreams(); + + void startIMU(); + + private: + void setupDevices(); + + void selectBaseStream(); + + void setupProfiles(); + + void getParameters(); + + void setupTopics(); + + void setupPipelineConfig(); + + void printSensorProfiles(const std::shared_ptr& sensor); + + void setupPublishers(); + + void stopStreams(); + + void stopIMU(); + + void onNewFrameSetCallback(std::shared_ptr frame_set); + + void onNewIMUFrameCallback(const std::shared_ptr& accelframe, + const std::shared_ptr& gyroframe); + + std::vector spherePointToPoint(OBLiDARSpherePoint* sphere_point, + uint32_t point_count); + + void publishScan(std::shared_ptr frame_set); + + void publishScanToPoint(std::shared_ptr frame_set); + + void publishPointCloud(std::shared_ptr frame_set); + + void publishSpherePointCloud(std::shared_ptr frame_set); + + void publishMergedPointCloud(); + + void publishMergedSpherePointCloud(); + + uint64_t getFrameTimestampUs(const std::shared_ptr& frame); + + void filterScan(sensor_msgs::msg::LaserScan& scan); + + sensor_msgs::msg::PointCloud2 filterPointCloud(sensor_msgs::msg::PointCloud2& point_cloud) const; + + orbbec_camera_msgs::msg::IMUInfo createIMUInfo(const stream_index_pair& stream_index); + + void setDefaultIMUMessage(sensor_msgs::msg::Imu& imu_msg); + + void publishStaticTransforms(); + + void calcAndPublishStaticTransform(); + + void publishStaticTF(const rclcpp::Time& t, const tf2::Vector3& trans, const tf2::Quaternion& q, + const std::string& from, const std::string& to); + + void publishDynamicTransforms(); + + private: + rclcpp::Node* node_ = nullptr; + std::shared_ptr device_ = nullptr; + std::shared_ptr parameters_ = nullptr; + rclcpp::Logger logger_; + std::atomic_bool is_running_{false}; + std::unique_ptr pipeline_ = nullptr; + std::unique_ptr imuPipeline_ = nullptr; + std::atomic_bool pipeline_started_{false}; + std::string camera_name_ = "camera"; + std::shared_ptr pipeline_config_ = nullptr; + std::map> sensors_; + std::map optical_frame_id_; + std::map format_; + std::map format_str_; + std::map>> + supported_profiles_; + std::map> stream_profile_; + OBExtrinsic lidar_to_imu_extrinsic_; + rclcpp::Publisher::SharedPtr + lidar_to_imu_extrinsics_publisher_; + stream_index_pair base_stream_ = LIDAR; + + std::map enable_stream_; + std::map stream_name_; + + std::atomic_bool is_camera_node_initialized_{false}; + std::mutex device_lock_; + bool publish_tf_ = false; + bool tf_published_ = false; + std::shared_ptr static_tf_broadcaster_ = nullptr; + std::shared_ptr dynamic_tf_broadcaster_ = nullptr; + std::vector tf_msgs; + rclcpp::Publisher::SharedPtr scan_pub_; + rclcpp::Publisher::SharedPtr point_cloud_pub_; + + std::string point_cloud_qos_; + std::vector static_tf_msgs_; + std::shared_ptr tf_thread_ = nullptr; + std::condition_variable tf_cv_; + double tf_publish_rate_ = 10.0; + // Only for Gemini2 device + + std::string time_domain_ = "device"; // device, system, global + bool enable_scan_to_point_ = false; + bool enable_heartbeat_ = false; + bool use_intra_process_ = false; + + // lidar + std::string lidar_format_ = "ANY"; + int lidar_rate_ = 0; + std::string echo_mode_ = ""; + std::map rate_int_; + std::map rate_; + std::map frame_id_; + float min_angle_ = -135.0; + float max_angle_ = 135.0; + float min_range_ = 0.05; + float max_range_ = 30.0; + int repetitive_scan_mode_ = -1; + int filter_level_ = -1; + float vertical_fov_ = -1; + double angle_increment_ = 0.0; + bool enable_cloud_accumulated_ = false; + int cloud_accumulation_count_ = -1; + + // Multi-frame publishing parameters + int publish_n_pkts_ = 1; + std::mutex frame_buffer_mutex_; + std::vector> frame_buffer_; + rclcpp::Time last_frame_timestamp_; + + // IMU + bool enable_imu_ = false; + std::string imu_rate_ = "50hz"; + std::string accel_range_ = "2g"; + std::string gyro_range_ = "1000dps"; + std::string imu_qos_ = "default"; + rclcpp::Publisher::SharedPtr imu_publisher_; + bool imu_sync_output_start_ = false; + std::string accel_gyro_frame_id_ = "camera_imu_frame"; + double liner_accel_cov_ = 0.0001; + double angular_vel_cov_ = 0.0001; + // std::unique_ptr cloud_accumulated_ = nullptr; +}; + +} // namespace orbbec_lidar +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/rk_mpp_decoder.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/rk_mpp_decoder.h new file mode 100644 index 0000000..f1564cc --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/rk_mpp_decoder.h @@ -0,0 +1,63 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#pragma once + +#include "jpeg_decoder.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" + +#if defined(USE_LIBYUV) +#include +#else +#include +#endif +#define MPP_ALIGN(x, a) (((x) + (a)-1) & ~((a)-1)) + +namespace orbbec_camera { +class RKJPEGDecoder : public JPEGDecoder { + public: + RKJPEGDecoder(int width, int height); + + ~RKJPEGDecoder() override; + + bool decode(const std::shared_ptr& frame, uint8_t* dest) override; + + bool mppFrame2RGB(const MppFrame frame, uint8_t* data); + + private: + MppCtx mpp_ctx_ = nullptr; + MppApi* mpp_api_ = nullptr; + MppPacket mpp_packet_ = nullptr; + MppFrame mpp_frame_ = nullptr; + MppDecCfg mpp_dec_cfg_ = nullptr; + MppBuffer mpp_frame_buffer_ = nullptr; + MppBuffer mpp_packet_buffer_ = nullptr; + uint8_t* data_buffer_ = nullptr; + MppBufferGroup mpp_frame_group_ = nullptr; + MppBufferGroup mpp_packet_group_ = nullptr; + MppTask mpp_task_ = nullptr; + uint32_t need_split_ = 0; + uint8_t* rgb_buffer_ = nullptr; +}; + +} // namespace orbbec_camera \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/ros_param_backend.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/ros_param_backend.h new file mode 100644 index 0000000..b1f7154 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/ros_param_backend.h @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#pragma once +#include + +namespace orbbec_camera { +class ParametersBackend { + public: + explicit ParametersBackend(rclcpp::Node* node); + ~ParametersBackend(); + + template + void addOnSetParametersCallback(T callback) { + ros_callback_ = node_->add_on_set_parameters_callback(callback); + } + + private: + rclcpp::Node* node_; + rclcpp::Logger logger_; + std::shared_ptr ros_callback_; +}; +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/synced_imu_publisher.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/synced_imu_publisher.h new file mode 100644 index 0000000..0c16e84 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/synced_imu_publisher.h @@ -0,0 +1,48 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#pragma once +#include +#include +#include +#include +#include + +namespace orbbec_camera { +class SyncedImuPublisher { + public: + SyncedImuPublisher(rclcpp::Publisher::SharedPtr imu_publisher, + size_t queue_size = 1000); + ~SyncedImuPublisher(); + void publish(const sensor_msgs::msg::Imu& imu_msg); + void pause(); + void resume(); + void setQueueSize(size_t queue_size); + + void enable(bool enable); + + private: + void publishPendingMessages(); + + private: + std::mutex mutex_; + std::queue queue_; + rclcpp::Publisher::SharedPtr imu_publisher_; + bool is_enabled_ = true; + bool is_paused_ = false; + size_t queue_size_ = 1000; +}; +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/include/orbbec_camera/utils.h b/dev_ws/src/orbbec_camera/include/orbbec_camera/utils.h new file mode 100644 index 0000000..1e93bc7 --- /dev/null +++ b/dev_ws/src/orbbec_camera/include/orbbec_camera/utils.h @@ -0,0 +1,225 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#pragma once +#include +#include +#include +#include + +#include "libobsensor/ObSensor.hpp" +#include "sensor_msgs/distortion_models.hpp" +#include "sensor_msgs/msg/camera_info.hpp" +#include "orbbec_camera_msgs/msg/extrinsics.hpp" +#include "magic_enum/magic_enum.hpp" +#include +#include +#include +#include +#include +#include + +namespace orbbec_camera { +inline void LogFatal(const char* file, int line, const std::string& message) { + std::cerr << "Check failed at " << file << ":" << line << ": " << message << std::endl; + std::abort(); +} +} // namespace orbbec_camera + +#define TRY_EXECUTE_BLOCK(block) \ + try { \ + block; \ + } catch (const ob::Error& e) { \ + std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error"; \ + if (error_msg.find("Device is deactivated") != std::string::npos || \ + error_msg.find("disconnected") != std::string::npos || \ + error_msg.find("Send control transfer failed") != std::string::npos) { \ + RCLCPP_WARN(logger_, \ + "Device communication error in %s at line %d: %s - Device may be disconnected", \ + __FUNCTION__, __LINE__, error_msg.c_str()); \ + } else { \ + RCLCPP_ERROR(logger_, "Error in %s at line %d: %s", __FUNCTION__, __LINE__, \ + error_msg.c_str()); \ + } \ + } catch (const std::exception& e) { \ + RCLCPP_ERROR(logger_, "Exception in %s at line %d: %s", __FUNCTION__, __LINE__, e.what()); \ + } catch (...) { \ + RCLCPP_ERROR(logger_, "Unknown exception in %s at line %d", __FUNCTION__, __LINE__); \ + } + +#define TRY_TO_SET_PROPERTY(func, property, value) \ + try { \ + device_->func(property, value); \ + } catch (const ob::Error& e) { \ + RCLCPP_ERROR_STREAM(logger_, "Failed to set " << property << " to " << value << " in " \ + << __FUNCTION__ << " at line " << __LINE__ \ + << ": " << e.getMessage()); \ + } catch (const std::exception& e) { \ + RCLCPP_ERROR_STREAM(logger_, "Failed to set " << property << " to " << value << " in " \ + << __FUNCTION__ << " at line " << __LINE__ \ + << ": " << e.what()); \ + } catch (...) { \ + RCLCPP_ERROR_STREAM(logger_, "Failed to set " << property << " to " << value << " in " \ + << __FUNCTION__ << " at line " << __LINE__); \ + } + +// Macros for checking conditions and comparing values +#define CHECK(condition) \ + (!(condition) ? LogFatal(__FILE__, __LINE__, "Check failed: " #condition) : (void)0) + +template +void CheckOp(const char* expr, const char* file, int line, T1 val1, T2 val2, bool result) { + if (!result) { + std::ostringstream os; + os << "Check failed: " << expr << " (" << val1 << " vs. " << val2 << ")"; + orbbec_camera::LogFatal(file, line, os.str()); + } +} + +#define CHECK_OP(opname, op, val1, val2) \ + CheckOp(#val1 " " #op " " #val2, __FILE__, __LINE__, val1, val2, (val1)op(val2)) + +#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2) +#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2) +#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2) +#define CHECK_LT(val1, val2) CHECK_OP(_LT, <, val1, val2) +#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2) +#define CHECK_GT(val1, val2) CHECK_OP(_GT, >, val1, val2) + +// Overload for raw pointers +template +T* CheckNotNull(T* ptr, const char* file, int line) { + if (ptr == nullptr) { + std::ostringstream os; + os << "Null pointer passed to CheckNotNull at " << file << ":" << line; + orbbec_camera::LogFatal(file, line, os.str()); + } + return ptr; +} + +// Template for smart pointers like std::shared_ptr, std::unique_ptr +template +T& CheckNotNull(T& ptr, const char* file, int line) { + if (ptr == nullptr) { + std::ostringstream os; + os << "Null pointer passed to CheckNotNull at " << file << ":" << line; + orbbec_camera::LogFatal(file, line, os.str()); + } + return ptr; +} + +#if defined(CHECK_NOTNULL) +#undef CHECK_NOTNULL +#endif +#define CHECK_NOTNULL(val) CheckNotNull(val, __FILE__, __LINE__) + +namespace orbbec_camera { +sensor_msgs::msg::CameraInfo convertToCameraInfo(OBCameraIntrinsic intrinsic, + OBCameraDistortion distortion, int width); + +void saveRGBPointsToPly(const std::shared_ptr& frame, const std::string& fileName); + +void saveRGBPointCloudMsgToPly(const sensor_msgs::msg::PointCloud2::UniquePtr& msg, + const std::string& fileName); + +void saveDepthPointsToPly(const sensor_msgs::msg::PointCloud2::UniquePtr& msg, + const std::string& fileName); + +void savePointsToPly(const std::shared_ptr& frame, const std::string& fileName); + +tf2::Quaternion rotationMatrixToQuaternion(const float rotation[9]); + +std::ostream& operator<<(std::ostream& os, const OBCameraParam& rhs); + +orbbec_camera_msgs::msg::Extrinsics obExtrinsicsToMsg(const OBD2CTransform& extrinsics, + const std::string& frame_id); + +rclcpp::Time fromMsToROSTime(uint64_t ms); + +rclcpp::Time fromUsToROSTime(uint64_t us); + +std::string getObSDKVersion(); + +OBFormat OBFormatFromString(const std::string& format); + +OBLiDARScanRate OBScanRateFromInt(const int rate); + +std::string OBFormatToString(const OBFormat& format); + +std::ostream& operator<<(std::ostream& os, const OBFormat& rhs); + +std::string ObDeviceTypeToString(const OBDeviceType& type); + +rmw_qos_profile_t getRMWQosProfileFromString(const std::string& str_qos); + +bool isOpenNIDevice(int pid); + +OB_DEPTH_PRECISION_LEVEL depthPrecisionLevelFromString( + const std::string& depth_precision_level_str); + +float depthPrecisionFromString(const std::string& depth_precision_level_str); + +OBMultiDeviceSyncMode OBSyncModeFromString(const std::string& mode); + +OB_SAMPLE_RATE sampleRateFromString(std::string& sample_rate); + +std::string sampleRateToString(const OB_SAMPLE_RATE& sample_rate); + +std::ostream& operator<<(std::ostream& os, const OB_SAMPLE_RATE& rhs); + +OB_GYRO_FULL_SCALE_RANGE fullGyroScaleRangeFromString(std::string& full_scale_range); + +std::string fullGyroScaleRangeToString(const OB_GYRO_FULL_SCALE_RANGE& full_scale_range); + +std::ostream& operator<<(std::ostream& os, const OB_GYRO_FULL_SCALE_RANGE& rhs); + +OBAccelFullScaleRange fullAccelScaleRangeFromString(std::string& full_scale_range); + +std::string fullAccelScaleRangeToString(const OBAccelFullScaleRange& full_scale_range); + +std::ostream& operator<<(std::ostream& os, const OBAccelFullScaleRange& rhs); + +std::string parseUsbPort(const std::string& line); + +bool isValidJPEG(const std::shared_ptr& frame); + +std::string metaDataTypeToString(const OBFrameMetadataType& meta_data_type); + +std::ostream& operator<<(std::ostream& os, const OBFrameMetadataType& rhs); + +OBHoleFillingMode holeFillingModeFromString(const std::string& hole_filling_mode); + +bool isGemini2R(int pid); + +OBStreamType obStreamTypeFromString(const std::string& stream_type); + +struct UndistortedImageResult { + cv::Mat image; + OBCameraIntrinsic new_intrinsic; +}; + +UndistortedImageResult undistortImage(const cv::Mat& image, const OBCameraIntrinsic& intrinsic, + const OBCameraDistortion& distortion); + +std::string getDistortionModels(OBCameraDistortion distortion); + +std::string calcMD5(const std::string& data); +double getScanAngleIncrement(OBLiDARScanRate fps); + +double deg2rad(double deg); + +double rad2deg(double rad); +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/launch/gemini2.launch.py b/dev_ws/src/orbbec_camera/launch/gemini2.launch.py new file mode 100644 index 0000000..1910844 --- /dev/null +++ b/dev_ws/src/orbbec_camera/launch/gemini2.launch.py @@ -0,0 +1,183 @@ +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import PushRosNamespace +from launch.actions import GroupAction +from launch_ros.actions import ComposableNodeContainer +from launch_ros.descriptions import ComposableNode +from launch_ros.actions import Node +import os + + +def generate_launch_description(): + # Declare arguments + args = [ + DeclareLaunchArgument("camera_name", default_value="camera"), + DeclareLaunchArgument("depth_registration", default_value="true"), + DeclareLaunchArgument("serial_number", default_value=""), + DeclareLaunchArgument("usb_port", default_value=""), + DeclareLaunchArgument("device_num", default_value="1"), + DeclareLaunchArgument("uvc_backend", default_value="libuvc"), # libuvc or v4l2 + DeclareLaunchArgument("product_id", default_value=""), + DeclareLaunchArgument("enable_point_cloud", default_value="true"), + DeclareLaunchArgument("cloud_frame_id", default_value=""), + DeclareLaunchArgument("enable_colored_point_cloud", default_value="false"), + DeclareLaunchArgument("point_cloud_qos", default_value="default"), + DeclareLaunchArgument("connection_delay", default_value="100"), + DeclareLaunchArgument("color_width", default_value="0"), + DeclareLaunchArgument("color_height", default_value="0"), + DeclareLaunchArgument("color_fps", default_value="0"), + DeclareLaunchArgument("color_format", default_value="ANY"), + DeclareLaunchArgument("enable_color", default_value="true"), + DeclareLaunchArgument("color_flip", default_value="false"), + DeclareLaunchArgument("color_qos", default_value="default"), + DeclareLaunchArgument("color_camera_info_qos", default_value="default"), + DeclareLaunchArgument("enable_color_auto_exposure", default_value="true"), + DeclareLaunchArgument("color_ae_max_exposure", default_value="-1"), + DeclareLaunchArgument("color_ae_roi_left", default_value="-1"), + DeclareLaunchArgument("color_ae_roi_right", default_value="-1"), + DeclareLaunchArgument("color_ae_roi_top", default_value="-1"), + DeclareLaunchArgument("color_ae_roi_bottom", default_value="-1"), + DeclareLaunchArgument("color_exposure", default_value="-1"), + DeclareLaunchArgument("color_gain", default_value="-1"), + DeclareLaunchArgument("enable_color_auto_white_balance", default_value="true"), + DeclareLaunchArgument("color_white_balance", default_value="-1"), + DeclareLaunchArgument("color_brightness", default_value="-1"), + DeclareLaunchArgument('enable_color_decimation_filter', default_value='false'), + DeclareLaunchArgument('color_decimation_filter_scale', default_value='-1'), + DeclareLaunchArgument("depth_width", default_value="0"), + DeclareLaunchArgument("depth_height", default_value="0"), + DeclareLaunchArgument("depth_fps", default_value="0"), + DeclareLaunchArgument("depth_format", default_value="ANY"), + DeclareLaunchArgument("enable_depth", default_value="true"), + DeclareLaunchArgument("depth_flip", default_value="false"), + DeclareLaunchArgument("depth_qos", default_value="default"), + DeclareLaunchArgument("depth_camera_info_qos", default_value="default"), + DeclareLaunchArgument("depth_ae_roi_left", default_value="-1"), + DeclareLaunchArgument("depth_ae_roi_right", default_value="-1"), + DeclareLaunchArgument("depth_ae_roi_top", default_value="-1"), + DeclareLaunchArgument("depth_ae_roi_bottom", default_value="-1"), + DeclareLaunchArgument("ir_width", default_value="0"), + DeclareLaunchArgument("ir_height", default_value="0"), + DeclareLaunchArgument("ir_fps", default_value="0"), + DeclareLaunchArgument("ir_format", default_value="ANY"), + DeclareLaunchArgument("enable_ir", default_value="true"), + DeclareLaunchArgument("ir_flip", default_value="false"), + DeclareLaunchArgument("ir_qos", default_value="default"), + DeclareLaunchArgument("ir_camera_info_qos", default_value="default"), + DeclareLaunchArgument("enable_ir_auto_exposure", default_value="true"), + DeclareLaunchArgument("ir_ae_max_exposure", default_value="-1"), + DeclareLaunchArgument("ir_exposure", default_value="-1"), + DeclareLaunchArgument("ir_gain", default_value="-1"), + DeclareLaunchArgument("ir_brightness", default_value="-1"), + DeclareLaunchArgument("enable_sync_output_accel_gyro", default_value="true"), + DeclareLaunchArgument("enable_accel", default_value="false"), + DeclareLaunchArgument("accel_rate", default_value="100hz"), + DeclareLaunchArgument("accel_range", default_value="4g"), + DeclareLaunchArgument("enable_gyro", default_value="false"), + DeclareLaunchArgument("gyro_rate", default_value="100hz"), + DeclareLaunchArgument("gyro_range", default_value="1000dps"), + DeclareLaunchArgument("linear_accel_cov", default_value="0.01"), + DeclareLaunchArgument("angular_vel_cov", default_value="0.01"), + DeclareLaunchArgument("publish_tf", default_value="true"), + DeclareLaunchArgument("tf_publish_rate", default_value="0.0"), + DeclareLaunchArgument("ir_info_url", default_value=""), + DeclareLaunchArgument("color_info_url", default_value=""), + DeclareLaunchArgument("log_level", default_value="none"), + DeclareLaunchArgument("log_file_name", default_value=""), + DeclareLaunchArgument("enable_publish_extrinsic", default_value="false"), + DeclareLaunchArgument("enable_d2c_viewer", default_value="false"), + DeclareLaunchArgument('disparity_to_depth_mode', default_value='SW'), + DeclareLaunchArgument("enable_ldp", default_value="true"), + DeclareLaunchArgument('enable_decimation_filter', default_value='false'), + DeclareLaunchArgument('enable_threshold_filter', default_value='false'), + DeclareLaunchArgument('enable_noise_removal_filter', default_value='true'), + DeclareLaunchArgument('enable_spatial_filter', default_value='false'), + DeclareLaunchArgument('enable_temporal_filter', default_value='false'), + DeclareLaunchArgument('enable_disparity_to_depth', default_value='true'), + DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'), + DeclareLaunchArgument('decimation_filter_scale', default_value='-1'), + DeclareLaunchArgument('threshold_filter_max', default_value='-1'), + DeclareLaunchArgument('threshold_filter_min', default_value='-1'), + DeclareLaunchArgument('noise_removal_filter_min_diff', default_value='256'), + DeclareLaunchArgument('noise_removal_filter_max_size', default_value='200'), + DeclareLaunchArgument('spatial_filter_alpha', default_value='-1.0'), + DeclareLaunchArgument('spatial_filter_diff_threshold', default_value='-1'), + DeclareLaunchArgument('spatial_filter_magnitude', default_value='-1'), + DeclareLaunchArgument('spatial_filter_radius', default_value='-1'), + DeclareLaunchArgument('temporal_filter_diff_threshold', default_value='-1.0'), + DeclareLaunchArgument('temporal_filter_weight', default_value='-1.0'), + DeclareLaunchArgument('hole_filling_filter_mode', default_value=''), + # Configure the path for depth filter file, for example: /config/depthfilter/Gemini2_v1.7.json + DeclareLaunchArgument("depth_filter_config", default_value=""), + # Depth work mode support is as follows: + # Unbinned Dense Default + # Unbinned Sparse Default + # Binned Sparse Default + # Obstacle Avoidance + DeclareLaunchArgument("depth_work_mode", default_value="Unbinned Dense Default"), + DeclareLaunchArgument("sync_mode", default_value="standalone"), + DeclareLaunchArgument("depth_delay_us", default_value="0"), + DeclareLaunchArgument("color_delay_us", default_value="0"), + DeclareLaunchArgument("trigger2image_delay_us", default_value="0"), + DeclareLaunchArgument("trigger_out_delay_us", default_value="0"), + DeclareLaunchArgument("trigger_out_enabled", default_value="false"), + DeclareLaunchArgument("enable_frame_sync", default_value="true"), + DeclareLaunchArgument("ordered_pc", default_value="false"), + DeclareLaunchArgument("enable_depth_scale", default_value="true"), + DeclareLaunchArgument("align_mode", default_value="HW"), + DeclareLaunchArgument("retry_on_usb3_detection_failure", default_value="false"), + DeclareLaunchArgument("laser_energy_level", default_value="-1"), + DeclareLaunchArgument("enable_heartbeat", default_value="false"), + DeclareLaunchArgument("time_domain", default_value="global"), + ] + + # Node configuration + parameters = [{arg.name: LaunchConfiguration(arg.name)} for arg in args] + # get ROS_DISTRO + ros_distro = os.environ["ROS_DISTRO"] + if ros_distro == "foxy": + return LaunchDescription( + args + + [ + Node( + package="orbbec_camera", + executable="orbbec_camera_node", + name="ob_camera_node", + namespace=LaunchConfiguration("camera_name"), + parameters=parameters, + output="log", + ) + ] + ) + # Define the ComposableNode + else: + # Define the ComposableNode + compose_node = ComposableNode( + package="orbbec_camera", + plugin="orbbec_camera::OBCameraNodeDriver", + name=LaunchConfiguration("camera_name"), + namespace="", + parameters=parameters, + ) + # Define the ComposableNodeContainer + container = ComposableNodeContainer( + name="camera_container", + namespace="", + package="rclcpp_components", + executable="component_container", + composable_node_descriptions=[ + compose_node, + ], + output="log", + ) + # Launch description + ld = LaunchDescription( + args + + [ + GroupAction( + [PushRosNamespace(LaunchConfiguration("camera_name")), container] + ) + ] + ) + return ld diff --git a/dev_ws/src/orbbec_camera/package.xml b/dev_ws/src/orbbec_camera/package.xml new file mode 100644 index 0000000..8b237cf --- /dev/null +++ b/dev_ws/src/orbbec_camera/package.xml @@ -0,0 +1,42 @@ + + + + orbbec_camera + 2.7.6 + Orbbec Camera package + Joe Dong + Apache-2.0 + + ament_cmake + ament_lint_auto + ament_lint_common + ament_index_cpp + backward_ros + image_transport + image_publisher + rclcpp_components + cv_bridge + camera_info_manager + orbbec_camera_msgs + builtin_interfaces + rclcpp + sensor_msgs + std_msgs + std_srvs + statistics_msgs + tf2 + tf2_ros + tf2_sensor_msgs + tf2_msgs + diagnostic_updater + diagnostic_msgs + libgflags-dev + nlohmann-json-dev + libgoogle-glog-dev + libssl-dev + opengl + + + ament_cmake + + diff --git a/dev_ws/src/orbbec_camera/scripts/99-obsensor-libusb.rules b/dev_ws/src/orbbec_camera/scripts/99-obsensor-libusb.rules new file mode 100644 index 0000000..0410a42 --- /dev/null +++ b/dev_ws/src/orbbec_camera/scripts/99-obsensor-libusb.rules @@ -0,0 +1,123 @@ +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0501", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Bootloader_Device" + +# UVC Modules +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0635", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0638", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto-w" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0668", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto-live" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0636", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra+" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0637", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra+s" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0536", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra+_rgb" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0537", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra+s_rgb" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0669", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto-mega" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="066b", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto_Bolt" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0660", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra_2" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0670", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_2" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0671", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_2_XL" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0673", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_2_L" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0675", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_2_VL" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0800", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_335" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0801", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_330" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0802", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_dm330" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0803", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_336" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0804", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_335L" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0805", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_330L" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0806", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_dm330L" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0807", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_336L" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="080b", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_335Lg" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="080d", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_336Lg" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="080e", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_335Le" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0810", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_336Le" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0674", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_2_I" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0701", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Dabai_DCL" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="069d", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra_Pro2" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0808", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_215" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0809", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_210" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0a12", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Dabai_A" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0a13", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Dabai_AL" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0812", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_345" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0813", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_345Lg" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0816", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="CAM-5330" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0817", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="CAM-5530" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0818", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_338" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0840", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Gemini_305" + +# OpenNI Modules +SUBSYSTEM=="usb", ATTR{idProduct}=="0400", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_bootloader" +SUBSYSTEM=="usb", ATTR{idProduct}=="0401", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra" +SUBSYSTEM=="usb", ATTR{idProduct}=="0402", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_s" +SUBSYSTEM=="usb", ATTR{idProduct}=="0403", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_pro" +SUBSYSTEM=="usb", ATTR{idProduct}=="0404", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini" +SUBSYSTEM=="usb", ATTR{idProduct}=="0407", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini_s" +SUBSYSTEM=="usb", ATTR{idProduct}=="0601", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_NH_GLST" +SUBSYSTEM=="usb", ATTR{idProduct}=="060b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="deeyea" +SUBSYSTEM=="usb", ATTR{idProduct}=="050b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="deeyea_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="060e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel" +SUBSYSTEM=="usb", ATTR{idProduct}=="050e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="060f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astro_pro_plus" +SUBSYSTEM=="usb", ATTR{idProduct}=="050f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astro_pro_plus_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0610", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="bus_cl" +SUBSYSTEM=="usb", ATTR{idProduct}=="0603", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="atlas" +SUBSYSTEM=="usb", ATTR{idProduct}=="0510", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="atlas_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0614", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini" +SUBSYSTEM=="usb", ATTR{idProduct}=="0511", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0616", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="u1s" +SUBSYSTEM=="usb", ATTR{idProduct}=="0516", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="u1s_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0617", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="projector" +SUBSYSTEM=="usb", ATTR{idProduct}=="0517", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="projector_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0618", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="butterfly" +SUBSYSTEM=="usb", ATTR{idProduct}=="0518", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="butterfly_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="061b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="pavo" +SUBSYSTEM=="usb", ATTR{idProduct}=="051b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="pavo_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="062b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_pro" +SUBSYSTEM=="usb", ATTR{idProduct}=="052b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_pro_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="062c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_plus" +SUBSYSTEM=="usb", ATTR{idProduct}=="052c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_plus_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="062d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="pictor" +SUBSYSTEM=="usb", ATTR{idProduct}=="0632", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra+" +SUBSYSTEM=="usb", ATTR{idProduct}=="0532", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra+rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0633", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra+s" +SUBSYSTEM=="usb", ATTR{idProduct}=="0533", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra+s_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0634", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_petal_b" +SUBSYSTEM=="usb", ATTR{idProduct}=="0534", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_petal_b_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0635", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="femto" +SUBSYSTEM=="usb", ATTR{idProduct}=="0636", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="jarvis" +SUBSYSTEM=="usb", ATTR{idProduct}=="0536", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="jarvis_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0637", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="jarvis+s" +SUBSYSTEM=="usb", ATTR{idProduct}=="0537", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="jarvis+s_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0638", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="femto_w" +SUBSYSTEM=="usb", ATTR{idProduct}=="0639", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="argus" +SUBSYSTEM=="usb", ATTR{idProduct}=="0539", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="argus_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="063a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="u2" +SUBSYSTEM=="usb", ATTR{idProduct}=="0650", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0651", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0654", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="qi_long_zhu" +SUBSYSTEM=="usb", ATTR{idProduct}=="0554", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="qi_long_zhu_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0655", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_plus" +SUBSYSTEM=="usb", ATTR{idProduct}=="0656", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_mini" +SUBSYSTEM=="usb", ATTR{idProduct}=="0657", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dc1" +SUBSYSTEM=="usb", ATTR{idProduct}=="0557", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dc1_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0658", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_d1" +SUBSYSTEM=="usb", ATTR{idProduct}=="0657", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dc1" +SUBSYSTEM=="usb", ATTR{idProduct}=="0557", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dc1_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="0659", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dcw" +SUBSYSTEM=="usb", ATTR{idProduct}=="0559", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dcw_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="065a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dw" +SUBSYSTEM=="usb", ATTR{idProduct}=="065b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini_pro" +SUBSYSTEM=="usb", ATTR{idProduct}=="065c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_e" +SUBSYSTEM=="usb", ATTR{idProduct}=="055c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_e_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="065d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_e_lite" +SUBSYSTEM=="usb", ATTR{idProduct}=="065e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini_s_pro" +SUBSYSTEM=="usb", ATTR{idProduct}=="0698", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="j1" +SUBSYSTEM=="usb", ATTR{idProduct}=="069c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="TB2201" +SUBSYSTEM=="usb", ATTR{idProduct}=="06a0", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dcw2" +SUBSYSTEM=="usb", ATTR{idProduct}=="0561", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dcw2_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="069f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dw2" +SUBSYSTEM=="usb", ATTR{idProduct}=="069a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_max" +SUBSYSTEM=="usb", ATTR{idProduct}=="069e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_max_pro" +SUBSYSTEM=="usb", ATTR{idProduct}=="0560", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_max_pro_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="06aa", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_gemini_uw" +SUBSYSTEM=="usb", ATTR{idProduct}=="05aa", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_gemini_uw_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="06a6", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_ew" +SUBSYSTEM=="usb", ATTR{idProduct}=="05a6", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_ew_rgb" +SUBSYSTEM=="usb", ATTR{idProduct}=="06a7", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_ew_lite" +SUBSYSTEM=="usb", ATTR{idProduct}=="069d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_pro2" diff --git a/dev_ws/src/orbbec_camera/src/d2c_viewer.cpp b/dev_ws/src/orbbec_camera/src/d2c_viewer.cpp new file mode 100644 index 0000000..d8a5280 --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/d2c_viewer.cpp @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#if __has_include() +#include +#elif __has_include() +#include +#endif +#include + +#include + +#include "orbbec_camera/d2c_viewer.h" + +namespace orbbec_camera { +D2CViewer::D2CViewer(rclcpp::Node* const node, rmw_qos_profile_t rgb_qos, + rmw_qos_profile_t depth_qos, bool use_intra_process) + : node_(node), logger_(rclcpp::get_logger("d2c_viewer")), is_active_(true) { + rgb_sub_ = std::make_shared>( + node_, "color/image_raw", rgb_qos); + depth_sub_ = std::make_shared>( + node_, "depth/image_raw", depth_qos); + sync_ = std::make_shared>(MySyncPolicy(10), *rgb_sub_, + *depth_sub_); + sync_->setMaxIntervalDuration(rclcpp::Duration::from_seconds(1.0)); // 1s + + using std::placeholders::_1; + using std::placeholders::_2; + sync_->registerCallback(std::bind(&D2CViewer::messageCallback, this, _1, _2)); + + auto qos = rclcpp::QoS(1).transient_local(); + if (use_intra_process) { + qos = rclcpp::QoS(1); + } + d2c_viewer_pub_ = + node_->create_publisher("depth_to_color/image_raw", qos); +} + +D2CViewer::~D2CViewer() { + is_active_.store(false); + + // Safely shut down subscribers and synchronizer + { + std::lock_guard lock(callback_mutex_); + if (sync_) { + sync_.reset(); + } + if (rgb_sub_) { + rgb_sub_.reset(); + } + if (depth_sub_) { + depth_sub_.reset(); + } + if (d2c_viewer_pub_) { + d2c_viewer_pub_.reset(); + } + } +} + +void D2CViewer::messageCallback(const sensor_msgs::msg::Image::ConstSharedPtr& rgb_msg, + const sensor_msgs::msg::Image::ConstSharedPtr& depth_msg) { + std::lock_guard lock(callback_mutex_); + if (!is_active_.load()) { + return; + } + + if (rgb_msg->width != depth_msg->width || rgb_msg->height != depth_msg->height) { + RCLCPP_ERROR(logger_, "rgb and depth image size not match(%d, %d) vs (%d, %d)", rgb_msg->width, + rgb_msg->height, depth_msg->width, depth_msg->height); + return; + } + auto rgb_encode = (rgb_msg->step == 5760) ? sensor_msgs::image_encodings::RGB8 + : sensor_msgs::image_encodings::RGBA8; + auto gray_type = (rgb_msg->step == 5760) ? cv::COLOR_GRAY2RGB : cv::COLOR_GRAY2RGBA; + auto rgb_img_ptr = cv_bridge::toCvCopy(rgb_msg, rgb_encode); + auto depth_img_ptr = cv_bridge::toCvCopy(depth_msg, sensor_msgs::image_encodings::TYPE_16UC1); + cv::Mat gray_depth, depth_img, d2c_img; + depth_img_ptr->image.convertTo(gray_depth, CV_8UC1); + cv::cvtColor(gray_depth, depth_img, gray_type); + depth_img.setTo(cv::Scalar(255, 255, 0), depth_img); + cv::bitwise_or(rgb_img_ptr->image, depth_img, d2c_img); + sensor_msgs::msg::Image::SharedPtr d2c_msg = + cv_bridge::CvImage(std_msgs::msg::Header(), rgb_encode, d2c_img).toImageMsg(); + if (d2c_msg != nullptr) { + d2c_msg->header = rgb_msg->header; + d2c_viewer_pub_->publish(*d2c_msg); + } else { + RCLCPP_ERROR(logger_, "d2c_viewer publishing failed"); + } +} +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/src/dynamic_params.cpp b/dev_ws/src/orbbec_camera/src/dynamic_params.cpp new file mode 100644 index 0000000..de82bb2 --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/dynamic_params.cpp @@ -0,0 +1,158 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#include "orbbec_camera/dynamic_params.h" + +namespace orbbec_camera { + +Parameters::Parameters(rclcpp::Node *node) + : node_(node), logger_(node_->get_logger()), params_backend_(node) { + params_backend_.addOnSetParametersCallback( + [this](const std::vector ¶meters) { + for (const auto ¶meter : parameters) { + if (param_functions_.find(parameter.get_name()) != param_functions_.end()) { + auto functions = param_functions_[parameter.get_name()]; + if (functions.empty()) { + RCLCPP_WARN_STREAM(logger_, "Parameter " << parameter.get_name() + << " can not be changed in runtime."); + } else { + for (const auto &func : param_functions_[parameter.get_name()]) { + func(parameter); + } + } + } + } + rcl_interfaces::msg::SetParametersResult result; + result.successful = true; + return result; + }); +} + +Parameters::~Parameters() noexcept { + for (auto const ¶m : param_functions_) { + try { + node_->undeclare_parameter(param.first); + } catch (const rclcpp::exceptions::InvalidParameterTypeException &e) { + // ignore + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, e.what()); + } + } +} + +rclcpp::ParameterValue Parameters::setParam( + const std::string ¶m_name, rclcpp::ParameterValue initial_value, + const std::function &func, + const rcl_interfaces::msg::ParameterDescriptor &descriptor) { + rclcpp::ParameterValue result_value(initial_value); + try { + if (!node_->has_parameter(param_name)) { + result_value = node_->declare_parameter(param_name, initial_value, descriptor); + } else { + result_value = node_->get_parameter(param_name).get_parameter_value(); + } + } catch (const std::exception &e) { + std::stringstream range; + for (auto val : descriptor.floating_point_range) { + range << val.from_value << ", " << val.to_value; + } + for (auto val : descriptor.integer_range) { + range << val.from_value << ", " << val.to_value; + } + RCLCPP_WARN_STREAM( + logger_, + "Could not set param: " << param_name << " with " + << rclcpp::Parameter(param_name, initial_value).value_to_string() + << "Range: [" << range.str() << "]" + << ": " << e.what()); + return initial_value; + } + + if (func) { + param_functions_[param_name].push_back(func); + } else { + param_functions_[param_name] = std::vector>(); + } + if (result_value != initial_value && func) { + func(rclcpp::Parameter(param_name, result_value)); + } + return result_value; +} + +template +void Parameters::setParamT(std::string param_name, rclcpp::ParameterValue initial_value, T ¶m, + std::function func, + rcl_interfaces::msg::ParameterDescriptor descriptor) { + // NOTICE: callback function is set AFTER the parameter is declared!!! + if (!node_->has_parameter(param_name)) + param = node_->declare_parameter(param_name, initial_value, descriptor).get(); + else { + param = node_->get_parameter(param_name).get_parameter_value().get(); + } + param_functions_[param_name].push_back( + [¶m, func](const rclcpp::Parameter ¶meter) { param = parameter.get_value(); }); + if (func) { + param_functions_[param_name].push_back(func); + } + param_names_[¶m] = param_name; +} + +template +void Parameters::setParamValue(T ¶m, const T &value) { + param = value; + try { + std::string param_name = param_names_.at(¶m); + + rcl_interfaces::msg::SetParametersResult results = + node_->set_parameter(rclcpp::Parameter(param_name, value)); + if (!results.successful) { + RCLCPP_WARN_STREAM(logger_, "Parameter: " << param_name << " was not set:" << results.reason); + } + } catch (const std::out_of_range &e) { + RCLCPP_WARN_STREAM(logger_, "Parameter was not internally declared."); + } catch (const rclcpp::exceptions::ParameterNotDeclaredException &e) { + std::string param_name = param_names_.at(¶m); + RCLCPP_WARN_STREAM(logger_, "Parameter: " << param_name << " was not declared:" << e.what()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, e.what()); + } +} + +void Parameters::removeParam(const std::string ¶m_name) { + node_->undeclare_parameter(param_name); + param_functions_.erase(param_name); +} + +template void Parameters::setParamT(std::string param_name, + rclcpp::ParameterValue initial_value, bool ¶m, + std::function func, + rcl_interfaces::msg::ParameterDescriptor descriptor); + +template void Parameters::setParamT(std::string param_name, + rclcpp::ParameterValue initial_value, int ¶m, + std::function func, + rcl_interfaces::msg::ParameterDescriptor descriptor); + +template void Parameters::setParamT(std::string param_name, + rclcpp::ParameterValue initial_value, double ¶m, + std::function func, + rcl_interfaces::msg::ParameterDescriptor descriptor); + +template void Parameters::setParamValue(int ¶m, const int &value); + +template void Parameters::setParamValue(bool ¶m, const bool &value); + +template void Parameters::setParamValue(double ¶m, const double &value); +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/src/image_publisher.cpp b/dev_ws/src/orbbec_camera/src/image_publisher.cpp new file mode 100644 index 0000000..a68d151 --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/image_publisher.cpp @@ -0,0 +1,48 @@ +// Copyright 2023 Intel Corporation. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "orbbec_camera/image_publisher.h" + +namespace orbbec_camera { + +// --- image_rcl_publisher implementation --- +image_rcl_publisher::image_rcl_publisher(rclcpp::Node& node, const std::string& topic_name, + const rmw_qos_profile_t& qos) { + image_publisher_impl = node.create_publisher( + topic_name, rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos), qos)); +} + +void image_rcl_publisher::publish(sensor_msgs::msg::Image::UniquePtr image_ptr) { + image_publisher_impl->publish(std::move(image_ptr)); +} + +size_t image_rcl_publisher::get_subscription_count() const { + return image_publisher_impl->get_subscription_count(); +} + +// --- image_transport_publisher implementation --- +image_transport_publisher::image_transport_publisher(rclcpp::Node& node, + const std::string& topic_name, + const rmw_qos_profile_t& qos) { + image_publisher_impl = std::make_shared( + image_transport::create_publisher(&node, topic_name, qos)); +} +void image_transport_publisher::publish(sensor_msgs::msg::Image::UniquePtr image_ptr) { + image_publisher_impl->publish(*image_ptr); +} + +size_t image_transport_publisher::get_subscription_count() const { + return image_publisher_impl->getNumSubscribers(); +} +} // namespace orbbec_camera \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera/src/jetson_nv_decoder.cpp b/dev_ws/src/orbbec_camera/src/jetson_nv_decoder.cpp new file mode 100644 index 0000000..16967cc --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/jetson_nv_decoder.cpp @@ -0,0 +1,119 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#include "orbbec_camera/jetson_nv_decoder.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "orbbec_camera/utils.h" + +namespace orbbec_camera { + +JetsonNvJPEGDecoder::JetsonNvJPEGDecoder(int width, int height) : JPEGDecoder(width, height) {} + +JetsonNvJPEGDecoder::~JetsonNvJPEGDecoder() { delete decoder_; } + +bool JetsonNvJPEGDecoder::decode(const std::shared_ptr &frame, uint8_t *dest) { + if (!isValidJPEG(frame)) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("jetson_nv_decoder"), "Invalid JPEG frame"); + return false; + } + uint32_t pixfmt = 0; + auto *data = static_cast(frame->data()); + uint32_t width = 0; + uint32_t height = 0; + auto data_size = frame->dataSize(); + while (data_size > 4 && data[data_size - 1] == 0x00) { + data_size--; + } + int fd = -1; + decoder_ = NvJPEGDecoder::createJPEGDecoder("jpegdec"); + std::shared_ptr decoder_deleter(nullptr, [&](int *) { delete decoder_; }); + decoder_->decodeToFd(fd, data, data_size, pixfmt, width, height); + if (pixfmt != V4L2_PIX_FMT_YUV422M) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("jetson_nv_decoder"), "Unexpected pixfmt: " << pixfmt); + if (fd != -1) { + close(fd); + } + return false; + } + if (width != static_cast(width_) || height != static_cast(height_)) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("jetson_nv_decoder"), + "Unexpected width/height: " << width << "x" << height); + if (fd != -1) { + close(fd); + } + return false; + } + NvBufSurf::NvCommonAllocateParams nvbufParams; + memset(&nvbufParams, 0, sizeof(nvbufParams)); + + nvbufParams.memType = NVBUF_MEM_SURFACE_ARRAY; + nvbufParams.width = width; + nvbufParams.height = height; + nvbufParams.layout = NVBUF_LAYOUT_PITCH; + nvbufParams.colorFormat = NVBUF_COLOR_FORMAT_RGBA; + int rgba_fd = -1; + int ret = NvBufSurf::NvAllocate(&nvbufParams, 1, &rgba_fd); + if (ret != 0) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("jetson_nv_decoder"), "Failed to allocate buffer"); + return false; + } + NvBufSurf::NvCommonTransformParams transform_params; + transform_params.src_top = 0; + transform_params.src_left = 0; + transform_params.src_width = width; + transform_params.src_height = height; + transform_params.dst_top = 0; + transform_params.dst_left = 0; + transform_params.dst_width = width; + transform_params.dst_height = height; + transform_params.flag = NVBUFSURF_TRANSFORM_FILTER; + transform_params.flip = NvBufSurfTransform_None; + transform_params.filter = NvBufSurfTransformInter_Nearest; + ret = NvBufSurf::NvTransform(&transform_params, fd, rgba_fd); + if (ret != 0) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("jetson_nv_decoder"), "Failed to transform buffer"); + if (rgba_fd != -1) { + NvBufSurf::NvDestroy(rgba_fd); + } + return false; + } + NvBufSurface *nvbuf_surf = 0; + NvBufSurfaceFromFd(rgba_fd, (void **)&nvbuf_surf); + ret = NvBufSurfaceMap(nvbuf_surf, 0, 0, NVBUF_MAP_READ_WRITE); + if (ret < 0) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("jetson_nv_decoder"), "Failed to map buffer"); + return false; + } + NvBufSurfaceSyncForCpu(nvbuf_surf, 0, 0); + uint8_t *rgba = (uint8_t *)nvbuf_surf->surfaceList[0].mappedAddr.addr[0]; + int src_stride_argb = width * 4; + int dst_stride_rgb24 = width * 3; + + libyuv::ARGBToRGB24(rgba, src_stride_argb, dest, dst_stride_rgb24, width, height); + NvBufSurfaceUnMap(nvbuf_surf, 0, 0); + if (rgba_fd != -1) { + NvBufSurf::NvDestroy(rgba_fd); + } + return true; +} +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/src/jpeg_decoder.cpp b/dev_ws/src/orbbec_camera/src/jpeg_decoder.cpp new file mode 100644 index 0000000..ba9bde2 --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/jpeg_decoder.cpp @@ -0,0 +1,22 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#include + +namespace orbbec_camera { +JPEGDecoder::JPEGDecoder(int width, int height) : width_(width), height_(height) {} +JPEGDecoder::~JPEGDecoder() {} + +} // namespace orbbec_camera \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera/src/ob_camera_node.cpp b/dev_ws/src/orbbec_camera/src/ob_camera_node.cpp new file mode 100644 index 0000000..34f22bb --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/ob_camera_node.cpp @@ -0,0 +1,4655 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "orbbec_camera/ob_camera_node.h" +#include +#include +#include +#include + +#include "orbbec_camera/utils.h" +#include +#include +#include "diagnostic_msgs/msg/diagnostic_status.hpp" +#include "libobsensor/hpp/Utils.hpp" + +#if defined(USE_RK_HW_DECODER) +#include "orbbec_camera/rk_mpp_decoder.h" +#elif defined(USE_NV_HW_DECODER) +#include "orbbec_camera/jetson_nv_decoder.h" +#endif + +#include + +namespace orbbec_camera { +using namespace std::chrono_literals; + +OBCameraNode::OBCameraNode(rclcpp::Node *node, std::shared_ptr device, + std::shared_ptr parameters, bool use_intra_process) + : node_(node), + device_(std::move(device)), + parameters_(std::move(parameters)), + logger_(node->get_logger()), + use_intra_process_(use_intra_process) { + pid_ = device_->getDeviceInfo()->getPid(); + RCLCPP_INFO_STREAM(logger_, + "OBCameraNode: use_intra_process: " << (use_intra_process ? "ON" : "OFF")); + is_running_.store(true); + stream_name_[COLOR] = "color"; + stream_name_[COLOR_LEFT] = "left_color"; + stream_name_[COLOR_RIGHT] = "right_color"; + stream_name_[DEPTH] = "depth"; + stream_name_[INFRA0] = "ir"; + stream_name_[INFRA1] = "left_ir"; + stream_name_[INFRA2] = "right_ir"; + stream_name_[ACCEL] = "accel"; + stream_name_[GYRO] = "gyro"; + compression_params_.push_back(cv::IMWRITE_PNG_COMPRESSION); + compression_params_.push_back(0); + compression_params_.push_back(cv::IMWRITE_PNG_STRATEGY); + compression_params_.push_back(cv::IMWRITE_PNG_STRATEGY_DEFAULT); + setupDefaultImageFormat(); + setupTopics(); +#if defined(USE_RK_HW_DECODER) + if (enable_stream_[COLOR] && width_.count(COLOR) && height_.count(COLOR)) { + jpeg_decoder_ = std::make_unique(width_[COLOR], height_[COLOR]); + } + if (enable_stream_[COLOR_LEFT] && width_.count(COLOR_LEFT) && height_.count(COLOR_LEFT)) { + jpeg_decoder_left_ = std::make_unique(width_[COLOR_LEFT], height_[COLOR_LEFT]); + } + if (enable_stream_[COLOR_RIGHT] && width_.count(COLOR_RIGHT) && height_.count(COLOR_RIGHT)) { + jpeg_decoder_right_ = + std::make_unique(width_[COLOR_RIGHT], height_[COLOR_RIGHT]); + } +#elif defined(USE_NV_HW_DECODER) + if (enable_stream_[COLOR] && width_.count(COLOR) && height_.count(COLOR)) { + jpeg_decoder_ = std::make_unique(width_[COLOR], height_[COLOR]); + } + if (enable_stream_[COLOR_LEFT] && width_.count(COLOR_LEFT) && height_.count(COLOR_LEFT)) { + jpeg_decoder_left_ = + std::make_unique(width_[COLOR_LEFT], height_[COLOR_LEFT]); + } + if (enable_stream_[COLOR_RIGHT] && width_.count(COLOR_RIGHT) && height_.count(COLOR_RIGHT)) { + jpeg_decoder_right_ = + std::make_unique(width_[COLOR_RIGHT], height_[COLOR_RIGHT]); + } +#endif + if (enable_d2c_viewer_) { + auto rgb_qos = getRMWQosProfileFromString(image_qos_[COLOR]); + auto depth_qos = getRMWQosProfileFromString(image_qos_[DEPTH]); + d2c_viewer_ = std::make_unique(node_, rgb_qos, depth_qos, use_intra_process_); + } + if (enable_stream_[COLOR]) { + rgb_buffer_ = new uint8_t[width_[COLOR] * height_[COLOR] * 4]; + } + if (enable_stream_[COLOR_LEFT]) { + rgb_buffer_left_ = new uint8_t[width_[COLOR_LEFT] * height_[COLOR_LEFT] * 4]; + } + if (enable_stream_[COLOR_RIGHT]) { + rgb_buffer_right_ = new uint8_t[width_[COLOR_RIGHT] * height_[COLOR_RIGHT] * 4]; + } + if (enable_colored_point_cloud_ && enable_stream_[DEPTH] && enable_stream_[COLOR]) { + rgb_point_cloud_buffer_size_ = width_[COLOR] * height_[COLOR] * sizeof(OBColorPoint); + xy_table_data_size_ = width_[DEPTH] * height_[DEPTH] * 2; + } + is_camera_node_initialized_ = true; + + fps_counter_color_ = std::make_unique("Color", logger_, 1); + fps_counter_depth_ = std::make_unique("Depth", logger_, 1); + fps_counter_left_ir_ = std::make_unique("Left Ir", logger_, 1); + fps_counter_right_ir_ = std::make_unique("Right Ir", logger_, 1); + + LogLevel log_level = LogLevel::DEBUG; + if (show_fps_enable_) { + log_level = LogLevel::INFO; + } + fps_counter_color_->setLogLevel(log_level); + fps_counter_depth_->setLogLevel(log_level); + fps_counter_left_ir_->setLogLevel(log_level); + fps_counter_right_ir_->setLogLevel(log_level); + + fps_delay_status_color_ = std::make_unique(logger_); + fps_delay_status_depth_ = std::make_unique(logger_); +} + +template +void OBCameraNode::setAndGetNodeParameter( + T ¶m, const std::string ¶m_name, const T &default_value, + const rcl_interfaces::msg::ParameterDescriptor ¶meter_descriptor) { + try { + param = parameters_ + ->setParam(param_name, rclcpp::ParameterValue(default_value), + std::function(), parameter_descriptor) + .get(); + } catch (const rclcpp::ParameterTypeException &ex) { + RCLCPP_ERROR_STREAM(logger_, "Failed to set parameter: " << param_name << ". " << ex.what()); + throw; + } +} + +OBCameraNode::~OBCameraNode() noexcept { clean(); } + +void OBCameraNode::rebootDevice() { + RCLCPP_INFO_STREAM(logger_, "Do clean before rebooting device"); + malloc_trim(0); + clean(); + malloc_trim(0); + std::lock_guard lock(device_lock_); + RCLCPP_INFO_STREAM(logger_, "Reboot device"); + if (device_) { + device_->reboot(); + } + malloc_trim(0); + RCLCPP_INFO_STREAM(logger_, "Reboot device DONE"); +} + +void OBCameraNode::clean() noexcept { + if (cleaning_.exchange(true)) { + RCLCPP_DEBUG(logger_, "clean() already running, skip re-entry"); + return; + } + // Set running flag to false first to signal all operations to stop + is_running_.store(false); + + // Stop diagnostic timer and updater first BEFORE acquiring device_lock to prevent deadlock + try { + if (diagnostic_timer_) { + diagnostic_timer_->cancel(); + // Wait for any currently executing timer callbacks to complete + { + std::unique_lock lk(diagnostic_mutex_); + diagnostic_cv_.wait_for(lk, std::chrono::milliseconds(100), + [this]() { return !diagnostic_running_; }); + } + diagnostic_timer_.reset(); + } + if (software_trigger_timer_) { + software_trigger_timer_->cancel(); + software_trigger_timer_.reset(); + } + if (diagnostic_updater_) { + diagnostic_updater_.reset(); + } + } catch (...) { + // Ignore exceptions during diagnostic cleanup + } + + // Now acquire the device lock for the rest of the cleanup + std::lock_guard lock(device_lock_); + RCLCPP_WARN_STREAM(logger_, "Do OBCameraNode clean"); + + RCLCPP_WARN_STREAM(logger_, "Stop tf thread"); + try { + if (tf_thread_ && tf_thread_->joinable()) { + tf_cv_.notify_all(); // Wake up tf thread if it's waiting + tf_thread_->join(); + } + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception while stopping tf thread"); + } + + RCLCPP_WARN_STREAM(logger_, "Stop color frame thread"); + try { + if (colorFrameThread_ && colorFrameThread_->joinable()) { + color_frame_queue_cv_.notify_all(); + colorFrameThread_->join(); + } + if (leftColorFrameThread_ && leftColorFrameThread_->joinable()) { + left_color_frame_queue_cv_.notify_all(); + leftColorFrameThread_->join(); + } + if (rightColorFrameThread_ && rightColorFrameThread_->joinable()) { + right_color_frame_queue_cv_.notify_all(); + rightColorFrameThread_->join(); + } + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception while stopping color frame thread"); + } + + RCLCPP_WARN_STREAM(logger_, "stop streams"); + try { + stopStreams(); + stopIMU(); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception while stopping streams"); + } + + // Clean up d2c_viewer_ before cleaning buffers + RCLCPP_WARN_STREAM(logger_, "Clean d2c_viewer"); + try { + if (d2c_viewer_) { + d2c_viewer_.reset(); + } + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception while cleaning up d2c_viewer"); + } + + RCLCPP_WARN_STREAM(logger_, "Clean up buffers"); + try { + delete[] rgb_buffer_; + rgb_buffer_ = nullptr; + delete[] rgb_buffer_left_; + rgb_buffer_left_ = nullptr; + delete[] rgb_buffer_right_; + rgb_buffer_right_ = nullptr; + + if (jpeg_decoder_) { + jpeg_decoder_.reset(); + } + if (jpeg_decoder_left_) { + jpeg_decoder_left_.reset(); + } + if (jpeg_decoder_right_) { + jpeg_decoder_right_.reset(); + } + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception while cleaning up buffers"); + } + + RCLCPP_WARN_STREAM(logger_, "Do OBCameraNode clean DONE"); + cleaning_.store(false); +} + +void OBCameraNode::setupDevices() { + if (!depth_work_mode_.empty() && + device_->isPropertySupported(OB_STRUCT_CURRENT_DEPTH_ALG_MODE, OB_PERMISSION_READ_WRITE)) { + auto depthModeList = device_->getDepthWorkModeList(); + for (uint32_t i = 0; i < depthModeList->getCount(); i++) { + RCLCPP_INFO_STREAM(logger_, "depthModeList[" << i << "]: " << (*depthModeList)[i].name); + } + TRY_EXECUTE_BLOCK(device_->switchDepthWorkMode(depth_work_mode_.c_str())); + RCLCPP_INFO_STREAM(logger_, "Set device preset: " << depth_work_mode_); + } else if (!device_preset_.empty()) { + try { + RCLCPP_INFO_STREAM(logger_, "Available presets:"); + auto preset_list = device_->getAvailablePresetList(); + for (uint32_t i = 0; i < preset_list->getCount(); i++) { + RCLCPP_INFO_STREAM(logger_, "Preset " << i << ": " << preset_list->getName(i)); + } + RCLCPP_INFO_STREAM(logger_, "Load device preset: " << device_preset_); + TRY_EXECUTE_BLOCK(device_->loadPreset(device_preset_.c_str())); + RCLCPP_INFO_STREAM(logger_, "Device preset " << device_->getCurrentPresetName() << " loaded"); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to load device preset: " << e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to load device preset: " << e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to load device preset"); + } + } + + if (!preset_resolution_config_.empty()) { + OBPresetResolutionConfig presetResolutionConfig; + std::istringstream iss(preset_resolution_config_); + std::string token; + std::vector values; + values.reserve(4); + while (std::getline(iss, token, ',')) { + values.push_back(std::stoi(token)); + } + + if (values.size() >= 4) { + presetResolutionConfig.width = values[0]; + presetResolutionConfig.height = values[1]; + presetResolutionConfig.irDecimationFactor = values[2]; + presetResolutionConfig.depthDecimationFactor = values[3]; + } else { + RCLCPP_WARN_STREAM( + logger_, + "Invalid preset_resolution_config parameter. " + "Expected format: width,height,ir_decimation_factor,depth_decimation_factor"); + } + + RCLCPP_INFO_STREAM( + logger_, "Setting preset resolution config to " + << "width: " << presetResolutionConfig.width + << ", height: " << presetResolutionConfig.height << ", ir decimation factor: " + << presetResolutionConfig.irDecimationFactor << ", depth decimation factor: " + << presetResolutionConfig.depthDecimationFactor); + + TRY_EXECUTE_BLOCK(device_->setStructuredData(OB_STRUCT_PRESET_RESOLUTION_CONFIG, + (uint8_t *)&presetResolutionConfig, + sizeof(presetResolutionConfig))); + } + + auto sensor_list = device_->getSensorList(); + for (size_t i = 0; i < sensor_list->getCount(); i++) { + auto sensor = sensor_list->getSensor(i); + auto profiles = sensor->getStreamProfileList(); + for (size_t j = 0; j < profiles->getCount(); j++) { + auto profile = profiles->getProfile(j); + stream_index_pair sip{profile->getType(), 0}; + if (sensors_.find(sip) != sensors_.end()) { + continue; + } + sensors_[sip] = sensor; + } + } + + for (const auto &[stream_index, enable] : enable_stream_) { + if (enable && sensors_.find(stream_index) == sensors_.end()) { + RCLCPP_INFO_STREAM(logger_, + magic_enum::enum_name(stream_index.first) + << "sensor isn't supported by current device! -- Skipping..."); + enable_stream_[stream_index] = false; + } + } + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info); + + if (retry_on_usb3_detection_failure_ && + device_->isPropertySupported(OB_PROP_DEVICE_USB3_REPEAT_IDENTIFY_BOOL, + OB_PERMISSION_READ_WRITE)) { + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_DEVICE_USB3_REPEAT_IDENTIFY_BOOL, + retry_on_usb3_detection_failure_); + } + if (device_->isPropertySupported(OB_PROP_HEARTBEAT_BOOL, OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting heartbeat to " << (enable_heartbeat_ ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_HEARTBEAT_BOOL, enable_heartbeat_); + } + if (max_depth_limit_ > 0 && + device_->isPropertySupported(OB_PROP_MAX_DEPTH_INT, OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting max depth limit to " << max_depth_limit_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_MAX_DEPTH_INT, max_depth_limit_); + } + if (min_depth_limit_ > 0 && + device_->isPropertySupported(OB_PROP_MIN_DEPTH_INT, OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting min depth limit to " << min_depth_limit_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_MIN_DEPTH_INT, min_depth_limit_); + } + if (laser_energy_level_ != -1 && + device_->isPropertySupported(OB_PROP_LASER_ENERGY_LEVEL_INT, OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting laser energy level to " << laser_energy_level_); + auto range = device_->getIntPropertyRange(OB_PROP_LASER_ENERGY_LEVEL_INT); + if (laser_energy_level_ < range.min || laser_energy_level_ > range.max) { + RCLCPP_ERROR_STREAM(logger_, + "Laser energy level is out of range " << range.min << " - " << range.max); + } else { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LASER_ENERGY_LEVEL_INT, laser_energy_level_); + auto new_laser_energy_level = device_->getIntProperty(OB_PROP_LASER_ENERGY_LEVEL_INT); + RCLCPP_INFO_STREAM(logger_, + "Laser energy level set to " << new_laser_energy_level << " (new value)"); + } + } + if (depth_registration_ && align_mode_ == "SW") { + RCLCPP_INFO_STREAM(logger_, "Create align filter"); + align_filter_ = std::make_unique(align_target_stream_); + } + if (sensors_.find(DEPTH) != sensors_.end() && + device_->isPropertySupported(OB_PROP_DISPARITY_TO_DEPTH_BOOL, OB_PERMISSION_READ_WRITE) && + device_->isPropertySupported(OB_PROP_SDK_DISPARITY_TO_DEPTH_BOOL, OB_PERMISSION_READ_WRITE)) { + if (disparity_to_depth_mode_ == "HW") { + device_->setBoolProperty(OB_PROP_DISPARITY_TO_DEPTH_BOOL, 1); + device_->setBoolProperty(OB_PROP_SDK_DISPARITY_TO_DEPTH_BOOL, 0); + RCLCPP_INFO_STREAM(logger_, "Depth process is HW"); + } else if (disparity_to_depth_mode_ == "SW") { + device_->setBoolProperty(OB_PROP_DISPARITY_TO_DEPTH_BOOL, 0); + device_->setBoolProperty(OB_PROP_SDK_DISPARITY_TO_DEPTH_BOOL, 1); + RCLCPP_INFO_STREAM(logger_, "Depth process is SW"); + } else if (disparity_to_depth_mode_ == "disable") { + device_->setBoolProperty(OB_PROP_DISPARITY_TO_DEPTH_BOOL, 0); + device_->setBoolProperty(OB_PROP_SDK_DISPARITY_TO_DEPTH_BOOL, 0); + RCLCPP_INFO_STREAM(logger_, "Depth process is disable"); + } else { + RCLCPP_ERROR_STREAM(logger_, "Depth process is keep default"); + } + } + if (device_->isPropertySupported(OB_PROP_LDP_BOOL, OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting LDP to " << (enable_ldp_ ? "ON" : "OFF")); + if (device_->isPropertySupported(OB_PROP_LASER_CONTROL_INT, OB_PERMISSION_READ_WRITE)) { + auto laser_enable = device_->getIntProperty(OB_PROP_LASER_CONTROL_INT); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_LDP_BOOL, enable_ldp_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LASER_CONTROL_INT, laser_enable); + } else if (device_->isPropertySupported(OB_PROP_LASER_BOOL, OB_PERMISSION_READ_WRITE)) { + if (!enable_ldp_) { + auto laser_enable = device_->getIntProperty(OB_PROP_LASER_BOOL); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_LDP_BOOL, enable_ldp_); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LASER_BOOL, laser_enable); + } else { + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_LDP_BOOL, enable_ldp_); + } + } + } + if (ldp_power_level_ != -1 && + device_->isPropertySupported(OB_PROP_LASER_POWER_LEVEL_CONTROL_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_LASER_POWER_LEVEL_CONTROL_INT); + if (ldp_power_level_ < range.min || ldp_power_level_ > range.max) { + RCLCPP_ERROR(logger_, "ldp power level value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting lrm power level to " << ldp_power_level_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LASER_POWER_LEVEL_CONTROL_INT, ldp_power_level_); + } + } + if (device_->isPropertySupported(OB_PROP_LASER_CONTROL_INT, OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting G300 laser control to " << enable_laser_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LASER_CONTROL_INT, enable_laser_); + } + if (device_->isPropertySupported(OB_PROP_LASER_BOOL, OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting laser control to " << enable_laser_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LASER_BOOL, enable_laser_); + } + if (!sync_mode_str_.empty()) { + auto sync_config = device_->getMultiDeviceSyncConfig(); + RCLCPP_INFO_STREAM(logger_, + "Current sync mode: " << magic_enum::enum_name(sync_config.syncMode)); + std::transform(sync_mode_str_.begin(), sync_mode_str_.end(), sync_mode_str_.begin(), ::toupper); + sync_mode_ = OBSyncModeFromString(sync_mode_str_); + sync_config.syncMode = sync_mode_; + sync_config.depthDelayUs = depth_delay_us_; + sync_config.colorDelayUs = color_delay_us_; + sync_config.trigger2ImageDelayUs = trigger2image_delay_us_; + sync_config.triggerOutDelayUs = trigger_out_delay_us_; + sync_config.triggerOutEnable = trigger_out_enabled_; + sync_config.framesPerTrigger = frames_per_trigger_; + TRY_EXECUTE_BLOCK(device_->setMultiDeviceSyncConfig(sync_config)); + sync_config = device_->getMultiDeviceSyncConfig(); + RCLCPP_INFO_STREAM(logger_, "Set sync mode: " << magic_enum::enum_name(sync_config.syncMode)); + if (sync_mode_ == OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING) { + RCLCPP_INFO_STREAM(logger_, "Frames per trigger: " << sync_config.framesPerTrigger); + RCLCPP_INFO_STREAM(logger_, + "Software trigger period " << software_trigger_period_.count() << " ms"); + software_trigger_timer_ = node_->create_wall_timer(software_trigger_period_, [this]() { + if (software_trigger_enabled_) { + TRY_EXECUTE_BLOCK(device_->triggerCapture()); + } + }); + } + } + if (device_->isPropertySupported(OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL, + OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Set PTP Config: " << (enable_ptp_config_ ? "ON" : "OFF")); + device_->setBoolProperty(OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL, enable_ptp_config_); + } + + if (device_->isPropertySupported(OB_PROP_DEPTH_PRECISION_LEVEL_INT, OB_PERMISSION_READ_WRITE) && + !depth_precision_str_.empty()) { + auto default_precision_level = device_->getIntProperty(OB_PROP_DEPTH_PRECISION_LEVEL_INT); + if (default_precision_level != depth_precision_) { + device_->setIntProperty(OB_PROP_DEPTH_PRECISION_LEVEL_INT, depth_precision_); + RCLCPP_INFO_STREAM(logger_, "set depth precision to " << depth_precision_str_); + } + } else if (device_->isPropertySupported(OB_PROP_DEPTH_UNIT_FLEXIBLE_ADJUSTMENT_FLOAT, + OB_PERMISSION_READ_WRITE) && + !depth_precision_str_.empty()) { + auto depth_unit_flexible_adjustment = depthPrecisionFromString(depth_precision_str_); + auto range = device_->getFloatPropertyRange(OB_PROP_DEPTH_UNIT_FLEXIBLE_ADJUSTMENT_FLOAT); + RCLCPP_INFO_STREAM(logger_, + "Depth unit flexible adjustment range: " << range.min << " - " << range.max); + if (depth_unit_flexible_adjustment < range.min || depth_unit_flexible_adjustment > range.max) { + RCLCPP_ERROR_STREAM( + logger_, "depth unit flexible adjustment value is out of range, please check the value"); + } else { + RCLCPP_INFO_STREAM(logger_, "set depth unit to " << depth_unit_flexible_adjustment << "mm"); + TRY_TO_SET_PROPERTY(setFloatProperty, OB_PROP_DEPTH_UNIT_FLEXIBLE_ADJUSTMENT_FLOAT, + depth_unit_flexible_adjustment); + } + } + + for (const auto &stream_index : IMAGE_STREAMS) { + if (enable_stream_[stream_index]) { + OBPropertyID mirrorPropertyID = OB_PROP_DEPTH_MIRROR_BOOL; + if (stream_index == COLOR) { + mirrorPropertyID = OB_PROP_COLOR_MIRROR_BOOL; + } else if (stream_index == DEPTH) { + mirrorPropertyID = OB_PROP_DEPTH_MIRROR_BOOL; + } else if (stream_index == INFRA0) { + mirrorPropertyID = OB_PROP_IR_MIRROR_BOOL; + } else if (stream_index == INFRA1) { + mirrorPropertyID = OB_PROP_IR_MIRROR_BOOL; + } else if (stream_index == INFRA2) { + mirrorPropertyID = OB_PROP_IR_RIGHT_MIRROR_BOOL; + } else if (stream_index == COLOR_LEFT) { + mirrorPropertyID = OB_PROP_COLOR_LEFT_MIRROR_BOOL; + } else if (stream_index == COLOR_RIGHT) { + mirrorPropertyID = OB_PROP_COLOR_RIGHT_MIRROR_BOOL; + } + if (device_->isPropertySupported(mirrorPropertyID, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting " << stream_name_[stream_index] << " mirror to " + << (mirror_stream_[stream_index] ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, mirrorPropertyID, mirror_stream_[stream_index]); + } + OBPropertyID flipPropertyID = OB_PROP_DEPTH_FLIP_BOOL; + if (stream_index == COLOR) { + flipPropertyID = OB_PROP_COLOR_FLIP_BOOL; + } else if (stream_index == DEPTH) { + flipPropertyID = OB_PROP_DEPTH_FLIP_BOOL; + } else if (stream_index == INFRA0) { + flipPropertyID = OB_PROP_IR_FLIP_BOOL; + } else if (stream_index == INFRA1) { + flipPropertyID = OB_PROP_IR_FLIP_BOOL; + } else if (stream_index == INFRA2) { + flipPropertyID = OB_PROP_IR_RIGHT_FLIP_BOOL; + } else if (stream_index == COLOR_LEFT) { + flipPropertyID = OB_PROP_COLOR_LEFT_FLIP_BOOL; + } else if (stream_index == COLOR_RIGHT) { + flipPropertyID = OB_PROP_COLOR_RIGHT_FLIP_BOOL; + } + if (device_->isPropertySupported(flipPropertyID, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting " << stream_name_[stream_index] << " flip to " + << (flip_stream_[stream_index] ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, flipPropertyID, flip_stream_[stream_index]); + } + OBPropertyID rotationPropertyID = OB_PROP_DEPTH_ROTATE_INT; + if (stream_index == COLOR) { + rotationPropertyID = OB_PROP_COLOR_ROTATE_INT; + } else if (stream_index == DEPTH) { + rotationPropertyID = OB_PROP_DEPTH_ROTATE_INT; + } else if (stream_index == INFRA0) { + rotationPropertyID = OB_PROP_IR_ROTATE_INT; + } else if (stream_index == INFRA1) { + rotationPropertyID = OB_PROP_IR_ROTATE_INT; + } else if (stream_index == INFRA2) { + rotationPropertyID = OB_PROP_IR_RIGHT_ROTATE_INT; + } else if (stream_index == COLOR_LEFT) { + rotationPropertyID = OB_PROP_COLOR_LEFT_ROTATE_INT; + } else if (stream_index == COLOR_RIGHT) { + rotationPropertyID = OB_PROP_COLOR_RIGHT_ROTATE_INT; + } + if (rotation_stream_[stream_index] != -1 && + device_->isPropertySupported(rotationPropertyID, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting " << stream_name_[stream_index] << " rotation to " + << rotation_stream_[stream_index]); + TRY_TO_SET_PROPERTY(setIntProperty, rotationPropertyID, rotation_stream_[stream_index]); + } + } + } + + if (sensors_.find(DEPTH) != sensors_.end() && + device_->isPropertySupported(OB_PROP_DEPTH_SOFT_FILTER_BOOL, OB_PERMISSION_READ_WRITE)) { + device_->setBoolProperty(OB_PROP_DEPTH_SOFT_FILTER_BOOL, enable_noise_removal_filter_); + RCLCPP_INFO_STREAM( + logger_, "Setting noise removal filter:" << (enable_noise_removal_filter_ ? "ON" : "OFF")); + } + + if (device_->isPropertySupported(OB_PROP_COLOR_AUTO_WHITE_BALANCE_BOOL, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting color auto white balance to " + << (enable_color_auto_white_balance_ ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_COLOR_AUTO_WHITE_BALANCE_BOOL, + enable_color_auto_white_balance_); + } + if (!color_preset_.empty() && + device_->isPropertySupported(OB_PROP_COLOR_PRESET_PRIORITY_INT, OB_PERMISSION_WRITE)) { + std::string preset_key = color_preset_; + std::transform(preset_key.begin(), preset_key.end(), preset_key.begin(), ::tolower); + int preset_value = -1; + if (preset_key == "default") { + preset_value = 0; + } else if (preset_key == "warm biased awb") { + preset_value = 1; + } else { + RCLCPP_WARN_STREAM( + logger_, "Unsupported color_preset: " << color_preset_ + << ". Supported values: Default, Warm Biased AWB"); + } + if (preset_value >= 0) { + RCLCPP_INFO_STREAM(logger_, "Setting color preset to " << color_preset_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_PRESET_PRIORITY_INT, preset_value); + } + } + if (color_exposure_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_EXPOSURE_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_EXPOSURE_INT); + if (color_exposure_ < range.min || color_exposure_ > range.max) { + RCLCPP_ERROR(logger_, "color exposure value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color exposure to " << color_exposure_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_EXPOSURE_INT, color_exposure_); + } + } + if (color_gain_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_GAIN_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_GAIN_INT); + if (color_gain_ < range.min || color_gain_ > range.max) { + RCLCPP_ERROR(logger_, "color gain value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color gain to " << color_gain_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_GAIN_INT, color_gain_); + } + } + if (device_->isPropertySupported(OB_PROP_COLOR_AUTO_EXPOSURE_PRIORITY_INT, OB_PERMISSION_WRITE)) { + int set_enable_color_auto_exposure_priority = enable_color_auto_exposure_priority_ ? 1 : 0; + RCLCPP_INFO_STREAM(logger_, "Setting color auto exposure priority to " + << (set_enable_color_auto_exposure_priority ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_AUTO_EXPOSURE_PRIORITY_INT, + set_enable_color_auto_exposure_priority); + } + if (device_->isPropertySupported(OB_PROP_COLOR_AUTO_EXPOSURE_BOOL, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM( + logger_, "Setting color auto exposure to " << (enable_color_auto_exposure_ ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_COLOR_AUTO_EXPOSURE_BOOL, + enable_color_auto_exposure_); + } + if (color_white_balance_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_WHITE_BALANCE_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_WHITE_BALANCE_INT); + if (color_white_balance_ < range.min || color_white_balance_ > range.max) { + RCLCPP_ERROR(logger_, + "color white balance value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color white balance to " << color_white_balance_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_WHITE_BALANCE_INT, color_white_balance_); + } + } + + if (color_ae_max_exposure_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_AE_MAX_EXPOSURE_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_AE_MAX_EXPOSURE_INT); + if (color_ae_max_exposure_ < range.min || color_ae_max_exposure_ > range.max) { + RCLCPP_ERROR(logger_, + "color AE max exposure value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color AE max exposure to " << color_ae_max_exposure_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_AE_MAX_EXPOSURE_INT, + color_ae_max_exposure_); + } + } + if (color_brightness_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_BRIGHTNESS_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_BRIGHTNESS_INT); + if (color_brightness_ < range.min || color_brightness_ > range.max) { + RCLCPP_ERROR(logger_, "color brightness value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color brightness to " << color_brightness_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_BRIGHTNESS_INT, color_brightness_); + } + } + if (color_roi_brightness_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_ROI_BRIGHTNESS_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_ROI_BRIGHTNESS_INT); + if (color_roi_brightness_ < range.min || color_roi_brightness_ > range.max) { + RCLCPP_ERROR(logger_, + "color roi brightness value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color roi brightness to " << color_roi_brightness_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_ROI_BRIGHTNESS_INT, color_roi_brightness_); + } + } + if (color_sharpness_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_SHARPNESS_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_SHARPNESS_INT); + if (color_sharpness_ < range.min || color_sharpness_ > range.max) { + RCLCPP_ERROR(logger_, "color sharpness value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color sharpness to " << color_sharpness_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_SHARPNESS_INT, color_sharpness_); + } + } + if (color_gamma_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_GAMMA_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_GAMMA_INT); + if (color_gamma_ < range.min || color_gamma_ > range.max) { + RCLCPP_ERROR(logger_, "color gamm value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color gamm to " << color_gamma_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_GAMMA_INT, color_gamma_); + } + } + if (color_saturation_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_SATURATION_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_SATURATION_INT); + if (color_saturation_ < range.min || color_saturation_ > range.max) { + RCLCPP_ERROR(logger_, "color saturation value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color saturation to " << color_saturation_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_SATURATION_INT, color_saturation_); + } + } + if (color_contrast_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_CONTRAST_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_CONTRAST_INT); + if (color_contrast_ < range.min || color_contrast_ > range.max) { + RCLCPP_ERROR(logger_, "color contrast value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color contrast to " << color_contrast_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_CONTRAST_INT, color_contrast_); + } + } + if (color_hue_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_HUE_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_HUE_INT); + if (color_hue_ < range.min || color_hue_ > range.max) { + RCLCPP_ERROR(logger_, "color hue value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting color hue to " << color_hue_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_HUE_INT, color_hue_); + } + } + if (color_backlight_compensation_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_BACKLIGHT_COMPENSATION_INT, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, + "Setting color backlight compensation to " << color_backlight_compensation_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_BACKLIGHT_COMPENSATION_INT, + color_backlight_compensation_); + } + if (isGemini335PID(pid_) && color_denoising_level_ != -1 && + device_->isPropertySupported(OB_PROP_COLOR_DENOISING_LEVEL_INT, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting color denoising level to " << color_denoising_level_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_DENOISING_LEVEL_INT, color_denoising_level_); + } + if (!color_powerline_freq_.empty() && + device_->isPropertySupported(OB_PROP_COLOR_POWER_LINE_FREQUENCY_INT, OB_PERMISSION_WRITE)) { + if (color_powerline_freq_ == "disable") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_POWER_LINE_FREQUENCY_INT, 0); + } else if (color_powerline_freq_ == "50hz") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_POWER_LINE_FREQUENCY_INT, 1); + } else if (color_powerline_freq_ == "60hz") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_POWER_LINE_FREQUENCY_INT, 2); + } else if (color_powerline_freq_ == "auto") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_COLOR_POWER_LINE_FREQUENCY_INT, 3); + } + RCLCPP_INFO_STREAM(logger_, "Setting color powerline freq to " << color_powerline_freq_); + } + if (depth_exposure_ != -1 && + device_->isPropertySupported(OB_PROP_DEPTH_EXPOSURE_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_DEPTH_EXPOSURE_INT); + if (depth_exposure_ < range.min || depth_exposure_ > range.max) { + RCLCPP_ERROR(logger_, "depth exposure value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting depth exposure to " << depth_exposure_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_DEPTH_EXPOSURE_INT, depth_exposure_); + } + } + if (depth_gain_ != -1 && + device_->isPropertySupported(OB_PROP_DEPTH_GAIN_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_DEPTH_GAIN_INT); + if (depth_gain_ < range.min || depth_gain_ > range.max) { + RCLCPP_ERROR(logger_, "depth gain value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting depth gain to " << depth_gain_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_DEPTH_GAIN_INT, depth_gain_); + } + } + if (sensors_.find(DEPTH) != sensors_.end() && + device_->isPropertySupported(OB_PROP_DEPTH_AUTO_EXPOSURE_PRIORITY_INT, OB_PERMISSION_WRITE)) { + int set_enable_depth_auto_exposure_priority = enable_depth_auto_exposure_priority_ ? 1 : 0; + RCLCPP_INFO_STREAM(logger_, "Setting depth auto exposure priority to " + << (set_enable_depth_auto_exposure_priority ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_DEPTH_AUTO_EXPOSURE_PRIORITY_INT, + set_enable_depth_auto_exposure_priority); + } + if (device_->isPropertySupported(OB_PROP_IR_AUTO_EXPOSURE_BOOL, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, + "Setting IR auto exposure to " << (enable_ir_auto_exposure_ ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_IR_AUTO_EXPOSURE_BOOL, enable_ir_auto_exposure_); + } + if (mean_intensity_set_point_ != -1 && + device_->isPropertySupported(OB_PROP_IR_BRIGHTNESS_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_IR_BRIGHTNESS_INT); + if (mean_intensity_set_point_ < range.min || mean_intensity_set_point_ > range.max) { + RCLCPP_ERROR(logger_, "depth brightness value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting depth brightness to " << mean_intensity_set_point_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_IR_BRIGHTNESS_INT, mean_intensity_set_point_); + } + } + // ir ae max + if (ir_ae_max_exposure_ != -1 && + device_->isPropertySupported(OB_PROP_IR_AE_MAX_EXPOSURE_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_IR_AE_MAX_EXPOSURE_INT); + if (ir_ae_max_exposure_ < range.min || ir_ae_max_exposure_ > range.max) { + RCLCPP_ERROR(logger_, + "IR AE max exposure value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting IR AE max exposure to " << ir_ae_max_exposure_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_IR_AE_MAX_EXPOSURE_INT, ir_ae_max_exposure_); + } + } + // ir brightness + if (ir_brightness_ != -1 && + device_->isPropertySupported(OB_PROP_IR_BRIGHTNESS_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_IR_BRIGHTNESS_INT); + if (ir_brightness_ < range.min || ir_brightness_ > range.max) { + RCLCPP_ERROR(logger_, "IR brightness value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting IR brightness to " << ir_brightness_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_IR_BRIGHTNESS_INT, ir_brightness_); + } + } + if (ir_exposure_ != -1 && + device_->isPropertySupported(OB_PROP_IR_EXPOSURE_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_IR_EXPOSURE_INT); + if (ir_exposure_ < range.min || ir_exposure_ > range.max) { + RCLCPP_ERROR(logger_, "ir exposure value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting IR exposure to " << ir_exposure_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_IR_EXPOSURE_INT, ir_exposure_); + } + } + if (ir_gain_ != -1 && device_->isPropertySupported(OB_PROP_IR_GAIN_INT, OB_PERMISSION_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_IR_GAIN_INT); + if (ir_gain_ < range.min || ir_gain_ > range.max) { + RCLCPP_ERROR(logger_, "ir gain value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting IR gain to " << ir_gain_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_IR_GAIN_INT, ir_gain_); + } + } + if (device_->isPropertySupported(OB_PROP_IR_LONG_EXPOSURE_BOOL, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, + "Setting IR long exposure to " << (enable_ir_long_exposure_ ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_IR_LONG_EXPOSURE_BOOL, enable_ir_long_exposure_); + } + + if (sensors_.find(DEPTH) != sensors_.end() && + device_->isPropertySupported(OB_PROP_DEPTH_MAX_DIFF_INT, OB_PERMISSION_WRITE)) { + auto default_noise_removal_filter_min_diff = + device_->getIntProperty(OB_PROP_DEPTH_MAX_DIFF_INT); + RCLCPP_INFO_STREAM(logger_, "default noise removal filter min diff: " + << default_noise_removal_filter_min_diff); + if (noise_removal_filter_min_diff_ != -1 && + default_noise_removal_filter_min_diff != noise_removal_filter_min_diff_) { + auto range = device_->getIntPropertyRange(OB_PROP_DEPTH_MAX_DIFF_INT); + if (noise_removal_filter_min_diff_ < range.min || + noise_removal_filter_min_diff_ > range.max) { + RCLCPP_ERROR(logger_, + "noise removal filter min diff value is out of range[%d,%d], please check " + "the value", + range.min, range.max); + } else { + device_->setIntProperty(OB_PROP_DEPTH_MAX_DIFF_INT, noise_removal_filter_min_diff_); + auto new_noise_removal_filter_min_diff = + device_->getIntProperty(OB_PROP_DEPTH_MAX_DIFF_INT); + RCLCPP_INFO_STREAM(logger_, "after set noise removal filter min diff: " + << new_noise_removal_filter_min_diff); + } + } + } + + if (sensors_.find(DEPTH) != sensors_.end() && + device_->isPropertySupported(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT, OB_PERMISSION_WRITE)) { + auto default_noise_removal_filter_max_size = + device_->getIntProperty(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT); + RCLCPP_INFO_STREAM(logger_, "default noise removal filter max size: " + << default_noise_removal_filter_max_size); + if (noise_removal_filter_max_size_ != -1 && + default_noise_removal_filter_max_size != noise_removal_filter_max_size_) { + auto range = device_->getIntPropertyRange(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT); + if (noise_removal_filter_max_size_ < range.min || + noise_removal_filter_max_size_ > range.max) { + RCLCPP_ERROR(logger_, + "noise removal filter max size value is out of range[%d,%d], please check " + "the value", + range.min, range.max); + } else { + device_->setIntProperty(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT, noise_removal_filter_max_size_); + auto new_noise_removal_filter_max_size = + device_->getIntProperty(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT); + RCLCPP_INFO_STREAM(logger_, "after set noise removal filter max size: " + << new_noise_removal_filter_max_size); + } + } + } + if (disparity_range_mode_ != -1 && + device_->isPropertySupported(OB_PROP_DISP_SEARCH_RANGE_MODE_INT, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting disparity range mode: " << disparity_range_mode_); + if (disparity_range_mode_ == 64) { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_DISP_SEARCH_RANGE_MODE_INT, 0); + } else if (disparity_range_mode_ == 128) { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_DISP_SEARCH_RANGE_MODE_INT, 1); + } else if (disparity_range_mode_ == 256) { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_DISP_SEARCH_RANGE_MODE_INT, 2); + } else { + RCLCPP_ERROR(logger_, "disparity range mode does not support this setting"); + } + } + if (device_->isPropertySupported(OB_PROP_HW_NOISE_REMOVE_FILTER_ENABLE_BOOL, + OB_PERMISSION_READ_WRITE)) { + device_->setBoolProperty(OB_PROP_HW_NOISE_REMOVE_FILTER_ENABLE_BOOL, + enable_hardware_noise_removal_filter_); + RCLCPP_INFO_STREAM(logger_, "Setting hardware noise removal filter:" + << (enable_hardware_noise_removal_filter_ ? "ON" : "OFF")); + if (device_->isPropertySupported(OB_PROP_HW_NOISE_REMOVE_FILTER_THRESHOLD_FLOAT, + OB_PERMISSION_READ_WRITE)) { + if (hardware_noise_removal_filter_threshold_ != -1.0 && + enable_hardware_noise_removal_filter_) { + device_->setFloatProperty(OB_PROP_HW_NOISE_REMOVE_FILTER_THRESHOLD_FLOAT, + hardware_noise_removal_filter_threshold_); + RCLCPP_INFO_STREAM(logger_, "Setting hardware noise removal filter threshold :" + << hardware_noise_removal_filter_threshold_); + } + } + } + if (exposure_range_mode_ != "default" && + device_->isPropertySupported(OB_PROP_DEVICE_PERFORMANCE_MODE_INT, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting exposure range mode : " << exposure_range_mode_); + if (exposure_range_mode_ == "ultimate") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_DEVICE_PERFORMANCE_MODE_INT, 1); + } else if (exposure_range_mode_ == "regular") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_DEVICE_PERFORMANCE_MODE_INT, 0); + } else { + RCLCPP_ERROR(logger_, "exposure range mode does not support this setting"); + } + } + if (!load_config_json_file_path_.empty()) { + device_->loadPresetFromJsonFile(load_config_json_file_path_.c_str()); + RCLCPP_INFO_STREAM(logger_, "Loading config json file path : " << load_config_json_file_path_); + } + if (!export_config_json_file_path_.empty()) { + device_->exportSettingsAsPresetJsonFile(export_config_json_file_path_.c_str()); + RCLCPP_INFO_STREAM(logger_, + "Exporting config json file path : " << export_config_json_file_path_); + } + if (device_->isPropertySupported(OB_PROP_SDK_ACCEL_FRAME_TRANSFORMED_BOOL, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting accel data correction to " + << (enable_accel_data_correction_ ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_SDK_ACCEL_FRAME_TRANSFORMED_BOOL, + enable_accel_data_correction_); + } + if (device_->isPropertySupported(OB_PROP_SDK_GYRO_FRAME_TRANSFORMED_BOOL, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting gyro data correction to " + << (enable_gyro_data_correction_ ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_SDK_GYRO_FRAME_TRANSFORMED_BOOL, + enable_gyro_data_correction_); + } + if (isGemini335PID(pid_) && !intra_camera_sync_reference_.empty() && + (sync_mode_ == OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING || + sync_mode_ == OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING) && + device_->isPropertySupported(OB_PROP_INTRA_CAMERA_SYNC_REFERENCE_INT, OB_PERMISSION_WRITE)) { + RCLCPP_INFO_STREAM(logger_, + "Setting intra camera sync reference to " << intra_camera_sync_reference_); + if (intra_camera_sync_reference_ == "Start") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_INTRA_CAMERA_SYNC_REFERENCE_INT, 0); + } else if (intra_camera_sync_reference_ == "Middle") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_INTRA_CAMERA_SYNC_REFERENCE_INT, 1); + } else if (intra_camera_sync_reference_ == "End") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_INTRA_CAMERA_SYNC_REFERENCE_INT, 2); + } else { + RCLCPP_ERROR(logger_, "intra camera sync reference does not support this setting"); + } + } + if (device_->isPropertySupported(OB_PROP_DEVICE_AE_STRATEGY_INT, OB_PERMISSION_WRITE)) { + device_->setIntProperty(OB_PROP_DEVICE_AE_STRATEGY_INT, (enable_sports_mode_ ? 0 : 1)); + RCLCPP_INFO_STREAM(logger_, "Setting Sports Mode to " << (enable_sports_mode_ ? "ON" : "OFF")); + } + + if ((ae_mode_ == "depthbased" || ae_mode_ == "colorbased") && + device_->isPropertySupported(OB_PROP_DEVICE_AE_REFERENCE_INT, OB_PERMISSION_WRITE)) { + if (device_->isPropertySupported(OB_PROP_DEVICE_AE_REFERENCE_INT, OB_PERMISSION_WRITE)) { + auto ae_mode = ae_mode_ == "depthbased" ? 0 : 1; + device_->setIntProperty(OB_PROP_DEVICE_AE_REFERENCE_INT, ae_mode); + RCLCPP_INFO_STREAM(logger_, "Setting AE Mode to " << ae_mode_); + } + } +} +void OBCameraNode::setupColorPostProcessFilter() { + try { + auto color_sensor = device_->getSensor(OB_SENSOR_COLOR); + if (color_sensor) { + color_filter_list_ = color_sensor->createRecommendedFilters(); + } + } catch (const std::exception &e) { + RCLCPP_DEBUG_STREAM(logger_, "Main color sensor not found, trying left/right color sensors"); + auto left_color_sensor = device_->getSensor(OB_SENSOR_COLOR_LEFT); + if (left_color_sensor) { + left_color_filter_list_ = left_color_sensor->createRecommendedFilters(); + } + auto right_color_sensor = device_->getSensor(OB_SENSOR_COLOR_RIGHT); + if (right_color_sensor) { + right_color_filter_list_ = right_color_sensor->createRecommendedFilters(); + } + } + if (color_filter_list_.empty() && left_color_filter_list_.empty() && + right_color_filter_list_.empty()) { + RCLCPP_WARN_STREAM(logger_, "Failed to get any color sensor filter list"); + } + for (size_t i = 0; i < color_filter_list_.size(); i++) { + auto filter = color_filter_list_[i]; + std::map filter_params = { + {"DecimationFilter", enable_color_decimation_filter_}, + }; + std::string filter_name = filter->type(); + RCLCPP_INFO_STREAM(logger_, "Setting " << filter_name << "......"); + if (filter_params.find(filter_name) != filter_params.end()) { + std::string value = filter_params[filter_name] ? "true" : "false"; + RCLCPP_INFO_STREAM(logger_, "set color " << filter_name << " to " << value); + filter->enable(filter_params[filter_name]); + } + if (filter_name == "DecimationFilter" && enable_color_decimation_filter_) { + auto decimation_filter = filter->as(); + auto range = decimation_filter->getScaleRange(); + if (color_decimation_filter_scale_ != -1 && color_decimation_filter_scale_ <= range.max && + color_decimation_filter_scale_ >= range.min) { + RCLCPP_INFO_STREAM(logger_, "Set color decimation filter scale value to " + << color_decimation_filter_scale_); + decimation_filter->setScaleValue(color_decimation_filter_scale_); + } + if (color_decimation_filter_scale_ != -1 && (color_decimation_filter_scale_ < range.min || + color_decimation_filter_scale_ > range.max)) { + RCLCPP_ERROR_STREAM(logger_, "Color Decimation filter scale value is out of range " + << range.min << " - " << range.max); + } + } + } + + for (size_t i = 0; i < left_color_filter_list_.size(); i++) { + auto filter = left_color_filter_list_[i]; + std::map filter_params = { + {"DecimationFilter", enable_left_color_decimation_filter_}, + }; + std::string filter_name = filter->type(); + RCLCPP_INFO_STREAM(logger_, "Setting left " << filter_name << "......"); + if (filter_params.find(filter_name) != filter_params.end()) { + std::string value = filter_params[filter_name] ? "true" : "false"; + RCLCPP_INFO_STREAM(logger_, "set left color " << filter_name << " to " << value); + filter->enable(filter_params[filter_name]); + } + if (filter_name == "DecimationFilter" && enable_left_color_decimation_filter_) { + auto decimation_filter = filter->as(); + auto range = decimation_filter->getScaleRange(); + if (left_color_decimation_filter_scale_ != -1 && + left_color_decimation_filter_scale_ <= range.max && + left_color_decimation_filter_scale_ >= range.min) { + RCLCPP_INFO_STREAM(logger_, "Set left color decimation filter scale value to " + << left_color_decimation_filter_scale_); + decimation_filter->setScaleValue(left_color_decimation_filter_scale_); + } + if (left_color_decimation_filter_scale_ != -1 && + (left_color_decimation_filter_scale_ < range.min || + left_color_decimation_filter_scale_ > range.max)) { + RCLCPP_ERROR_STREAM(logger_, "Left Color Decimation filter scale value is out of range " + << range.min << " - " << range.max); + } + } + } + + for (size_t i = 0; i < right_color_filter_list_.size(); i++) { + auto filter = right_color_filter_list_[i]; + std::map filter_params = { + {"DecimationFilter", enable_right_color_decimation_filter_}, + }; + std::string filter_name = filter->type(); + RCLCPP_INFO_STREAM(logger_, "Setting right " << filter_name << "......"); + if (filter_params.find(filter_name) != filter_params.end()) { + std::string value = filter_params[filter_name] ? "true" : "false"; + RCLCPP_INFO_STREAM(logger_, "set right color " << filter_name << " to " << value); + filter->enable(filter_params[filter_name]); + } + if (filter_name == "DecimationFilter" && enable_right_color_decimation_filter_) { + auto decimation_filter = filter->as(); + auto range = decimation_filter->getScaleRange(); + if (right_color_decimation_filter_scale_ != -1 && + right_color_decimation_filter_scale_ <= range.max && + right_color_decimation_filter_scale_ >= range.min) { + RCLCPP_INFO_STREAM(logger_, "Set right color decimation filter scale value to " + << right_color_decimation_filter_scale_); + decimation_filter->setScaleValue(right_color_decimation_filter_scale_); + } + if (right_color_decimation_filter_scale_ != -1 && + (right_color_decimation_filter_scale_ < range.min || + right_color_decimation_filter_scale_ > range.max)) { + RCLCPP_ERROR_STREAM(logger_, "Right Color Decimation filter scale value is out of range " + << range.min << " - " << range.max); + } + } + } + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info); + if (pid_ == GEMINI2_PID || pid_ == GEMINI2L_PID) { + if (enable_color_decimation_filter_) { + auto decimation_filter = std::make_shared(); + decimation_filter->enable(true); + color_filter_list_.push_back(decimation_filter); + auto range = decimation_filter->getScaleRange(); + if (color_decimation_filter_scale_ != -1 && color_decimation_filter_scale_ <= range.max && + color_decimation_filter_scale_ >= range.min) { + RCLCPP_INFO_STREAM(logger_, "Set color decimation filter scale value to " + << color_decimation_filter_scale_); + decimation_filter->setScaleValue(color_decimation_filter_scale_); + } + if (color_decimation_filter_scale_ != -1 && (color_decimation_filter_scale_ < range.min || + color_decimation_filter_scale_ > range.max)) { + RCLCPP_ERROR_STREAM(logger_, "Color Decimation filter scale value is out of range " + << range.min << " - " << range.max); + } + } + } +} +void OBCameraNode::setupLeftIrPostProcessFilter() { + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info); + if (isGemini335PID(pid_)) { + auto left_ir_sensor = device_->getSensor(OB_SENSOR_IR_LEFT); + left_ir_filter_list_ = left_ir_sensor->createRecommendedFilters(); + if (left_ir_filter_list_.empty()) { + RCLCPP_WARN_STREAM(logger_, "Failed to get left ir sensor filter list"); + return; + } + for (size_t i = 0; i < left_ir_filter_list_.size(); i++) { + auto filter = left_ir_filter_list_[i]; + std::map filter_params = { + {"SequenceIdFilter", enable_left_ir_sequence_id_filter_}, + }; + std::string filter_name = filter->type(); + RCLCPP_INFO_STREAM(logger_, "Setting " << filter_name << "......"); + if (filter_params.find(filter_name) != filter_params.end()) { + std::string value = filter_params[filter_name] ? "true" : "false"; + RCLCPP_INFO_STREAM(logger_, "set left ir " << filter_name << " to " << value); + filter->enable(filter_params[filter_name]); + } + if (filter_name == "SequenceIdFilter" && enable_left_ir_sequence_id_filter_) { + auto sequenced_filter = filter->as(); + if (left_ir_sequence_id_filter_id_ != -1) { + sequenced_filter->selectSequenceId(left_ir_sequence_id_filter_id_); + RCLCPP_INFO_STREAM( + logger_, "Set left ir SequenceIdFilter ID to " << left_ir_sequence_id_filter_id_); + } + } + } + } +} + +void OBCameraNode::setupRightIrPostProcessFilter() { + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info); + if (isGemini335PID(pid_)) { + auto right_ir_sensor = device_->getSensor(OB_SENSOR_IR_RIGHT); + right_ir_filter_list_ = right_ir_sensor->createRecommendedFilters(); + if (right_ir_filter_list_.empty()) { + RCLCPP_WARN_STREAM(logger_, "Failed to get right ir sensor filter list"); + return; + } + for (size_t i = 0; i < right_ir_filter_list_.size(); i++) { + auto filter = right_ir_filter_list_[i]; + std::map filter_params = { + {"SequenceIdFilter", enable_right_ir_sequence_id_filter_}, + }; + std::string filter_name = filter->type(); + RCLCPP_INFO_STREAM(logger_, "Setting " << filter_name << "......"); + if (filter_params.find(filter_name) != filter_params.end()) { + std::string value = filter_params[filter_name] ? "true" : "false"; + RCLCPP_INFO_STREAM(logger_, "set right ir " << filter_name << " to " << value); + filter->enable(filter_params[filter_name]); + } + if (filter_name == "SequenceIdFilter" && enable_right_ir_sequence_id_filter_) { + auto sequenced_filter = filter->as(); + if (right_ir_sequence_id_filter_id_ != -1) { + sequenced_filter->selectSequenceId(right_ir_sequence_id_filter_id_); + RCLCPP_INFO_STREAM( + logger_, "Set right ir SequenceIdFilter ID to " << right_ir_sequence_id_filter_id_); + } + } + } + } +} +void OBCameraNode::setupDepthPostProcessFilter() { + auto depth_sensor = device_->getSensor(OB_SENSOR_DEPTH); + // set depth sensor to filter + depth_filter_list_ = depth_sensor->createRecommendedFilters(); + if (depth_filter_list_.empty()) { + RCLCPP_WARN_STREAM(logger_, "Failed to get depth sensor filter list"); + return; + } + for (size_t i = 0; i < depth_filter_list_.size(); i++) { + auto filter = depth_filter_list_[i]; + std::map filter_params = { + {"DecimationFilter", enable_decimation_filter_}, + {"HDRMerge", enable_hdr_merge_}, + {"SequenceIdFilter", enable_sequence_id_filter_}, + {"SpatialAdvancedFilter", enable_spatial_filter_}, + {"TemporalFilter", enable_temporal_filter_}, + {"HoleFillingFilter", enable_hole_filling_filter_}, + {"DisparityTransform", enable_disparity_to_depth_}, + {"ThresholdFilter", enable_threshold_filter_}, + {"SpatialFastFilter", enable_spatial_fast_filter_}, + {"SpatialModerateFilter", enable_spatial_moderate_filter_}, + {"FalsePositiveFilter", enable_false_positive_filter_}, + }; + std::string filter_name = filter->type(); + RCLCPP_INFO_STREAM(logger_, "Setting " << filter_name << "......"); + if (filter_params.find(filter_name) != filter_params.end()) { + std::string value = filter_params[filter_name] ? "true" : "false"; + RCLCPP_INFO_STREAM(logger_, "set " << filter_name << " to " << value); + filter->enable(filter_params[filter_name]); + filter_status_[filter_name] = filter_params[filter_name]; + } + if (filter_name == "DecimationFilter" && enable_decimation_filter_) { + auto decimation_filter = filter->as(); + auto range = decimation_filter->getScaleRange(); + if (decimation_filter_scale_ != -1 && decimation_filter_scale_ <= range.max && + decimation_filter_scale_ >= range.min) { + RCLCPP_INFO_STREAM(logger_, + "Set decimation filter scale value to " << decimation_filter_scale_); + decimation_filter->setScaleValue(decimation_filter_scale_); + } + if (decimation_filter_scale_ != -1 && + (decimation_filter_scale_ < range.min || decimation_filter_scale_ > range.max)) { + RCLCPP_ERROR_STREAM(logger_, "Decimation filter scale value is out of range " + << range.min << " - " << range.max); + } + } else if (filter_name == "ThresholdFilter" && enable_threshold_filter_) { + auto threshold_filter = filter->as(); + if (threshold_filter_min_ != -1 && threshold_filter_max_ != -1) { + RCLCPP_INFO_STREAM(logger_, "Set threshold filter value range to " + << threshold_filter_min_ << " - " << threshold_filter_max_); + threshold_filter->setValueRange(threshold_filter_min_, threshold_filter_max_); + } + } else if (filter_name == "SpatialAdvancedFilter" && enable_spatial_filter_) { + auto spatial_filter = filter->as(); + if (spatial_filter_alpha_ != -1.0 && spatial_filter_magnitude_ != -1 && + spatial_filter_radius_ != -1 && spatial_filter_diff_threshold_ != -1) { + OBSpatialAdvancedFilterParams params{}; + params.alpha = spatial_filter_alpha_; + params.magnitude = spatial_filter_magnitude_; + params.radius = spatial_filter_radius_; + params.disp_diff = spatial_filter_diff_threshold_; + spatial_filter->setFilterParams(params); + } + } else if (filter_name == "TemporalFilter" && enable_temporal_filter_) { + auto temporal_filter = filter->as(); + if (temporal_filter_diff_threshold_ != -1.0 && temporal_filter_weight_ != -1.0) { + RCLCPP_INFO_STREAM(logger_, "Set temporal filter value to " + << temporal_filter_diff_threshold_ << " - " + << temporal_filter_weight_); + temporal_filter->setDiffScale(temporal_filter_diff_threshold_); + temporal_filter->setWeight(temporal_filter_weight_); + } + } else if (filter_name == "HoleFillingFilter" && enable_hole_filling_filter_ && + !hole_filling_filter_mode_.empty()) { + auto hole_filling_filter = filter->as(); + RCLCPP_INFO_STREAM(logger_, + "Default hole filling filter mode: " << hole_filling_filter_mode_); + OBHoleFillingMode hole_filling_mode = holeFillingModeFromString(hole_filling_filter_mode_); + hole_filling_filter->setFilterMode(hole_filling_mode); + } else if (filter_name == "SequenceIdFilter" && enable_sequence_id_filter_) { + auto sequenced_filter = filter->as(); + if (sequence_id_filter_id_ != -1) { + sequenced_filter->selectSequenceId(sequence_id_filter_id_); + } + } else if (filter_name == "HDRMerge" && enable_hdr_merge_) { + if (hdr_merge_exposure_1_ != -1 && hdr_merge_gain_1_ != -1 && hdr_merge_exposure_2_ != -1 && + hdr_merge_gain_2_ != -1) { + auto hdr_merge_filter = filter->as(); + hdr_merge_filter->enable(true); + RCLCPP_INFO_STREAM(logger_, "Set HDR merge filter params: " + << "exposure_1: " << hdr_merge_exposure_1_ + << ", gain_1: " << hdr_merge_gain_1_ + << ", exposure_2: " << hdr_merge_exposure_2_ + << ", gain_2: " << hdr_merge_gain_2_); + auto config = OBHdrConfig(); + config.enable = true; + config.exposure_1 = hdr_merge_exposure_1_; + config.gain_1 = hdr_merge_gain_1_; + config.exposure_2 = hdr_merge_exposure_2_; + config.gain_2 = hdr_merge_gain_2_; + device_->setStructuredData(OB_STRUCT_DEPTH_HDR_CONFIG, + reinterpret_cast(&config), sizeof(config)); + } + } else if (filter_name == "SpatialFastFilter" && enable_spatial_fast_filter_) { + auto spatial_fast_filter = filter->as(); + OBSpatialFastFilterParams params{}; + if (spatial_fast_filter_radius_ != -1) { + params.radius = spatial_fast_filter_radius_; + RCLCPP_INFO_STREAM(logger_, + "Set SpatialFastFilter radius to " << spatial_fast_filter_radius_); + spatial_fast_filter->setFilterParams(params); + } + } else if (filter_name == "SpatialModerateFilter" && enable_spatial_moderate_filter_) { + auto spatial_moderate_filter = filter->as(); + OBSpatialModerateFilterParams params{}; + if (spatial_moderate_filter_diff_threshold_ != -1 && + spatial_moderate_filter_magnitude_ != -1 && spatial_moderate_filter_radius_ != -1) { + params.magnitude = spatial_moderate_filter_magnitude_; + params.radius = spatial_moderate_filter_radius_; + params.disp_diff = spatial_moderate_filter_diff_threshold_; + RCLCPP_INFO_STREAM(logger_, "Set SpatialModerateFilter params: " + << "magnitude=" << params.magnitude << ", radius=" + << params.radius << ", disp_diff=" << params.disp_diff); + spatial_moderate_filter->setFilterParams(params); + } + + } else { + RCLCPP_INFO_STREAM(logger_, "Skip setting filter: " << filter_name); + } + } + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info); + if (pid_ == GEMINI2_PID || pid_ == GEMINI2L_PID) { + if (enable_decimation_filter_) { + auto decimation_filter = std::make_shared(); + decimation_filter->enable(true); + depth_filter_list_.push_back(decimation_filter); + auto range = decimation_filter->getScaleRange(); + if (decimation_filter_scale_ != -1 && decimation_filter_scale_ <= range.max && + decimation_filter_scale_ >= range.min) { + RCLCPP_INFO_STREAM(logger_, + "Set decimation filter scale value to " << decimation_filter_scale_); + decimation_filter->setScaleValue(decimation_filter_scale_); + } + if (decimation_filter_scale_ != -1 && + (decimation_filter_scale_ < range.min || decimation_filter_scale_ > range.max)) { + RCLCPP_ERROR_STREAM(logger_, "Decimation filter scale value is out of range " + << range.min << " - " << range.max); + } + } + } + set_filter_srv_ = node_->create_service( + "set_filter", [this](const std::shared_ptr request, + std::shared_ptr response) { + setFilterCallback(request, response); + }); +} + +void OBCameraNode::selectBaseStream() { + if (enable_stream_[DEPTH]) { + base_stream_ = DEPTH; + } else if (enable_stream_[INFRA0]) { + base_stream_ = INFRA0; + } else if (enable_stream_[INFRA1]) { + base_stream_ = INFRA1; + } else if (enable_stream_[INFRA2]) { + base_stream_ = INFRA2; + } else if (enable_stream_[COLOR_LEFT]) { + base_stream_ = COLOR_LEFT; + } else if (enable_stream_[COLOR_RIGHT]) { + base_stream_ = COLOR_RIGHT; + } else if (enable_stream_[COLOR]) { + base_stream_ = COLOR; + } +} + +void OBCameraNode::printSensorProfiles(const std::shared_ptr &sensor) { + auto profiles = sensor->getStreamProfileList(); + for (size_t i = 0; i < profiles->getCount(); i++) { + auto origin_profile = profiles->getProfile(i); + if (sensor->getType() == OB_SENSOR_COLOR) { + auto profile = origin_profile->as(); + RCLCPP_INFO_STREAM( + logger_, "color profile: " << profile->getWidth() << "x" << profile->getHeight() << " " + << profile->getFps() << "fps " << profile->getFormat()); + } else if (sensor->getType() == OB_SENSOR_DEPTH) { + auto profile = origin_profile->as(); + RCLCPP_INFO_STREAM( + logger_, "depth profile: " << profile->getWidth() << "x" << profile->getHeight() << " " + << profile->getFps() << "fps " << profile->getFormat()); + } else if (sensor->getType() == OB_SENSOR_IR) { + auto profile = origin_profile->as(); + RCLCPP_INFO_STREAM(logger_, "ir profile: " << profile->getWidth() << "x" + << profile->getHeight() << " " << profile->getFps() + << "fps " << profile->getFormat()); + } else if (sensor->getType() == OB_SENSOR_ACCEL) { + auto profile = origin_profile->as(); + RCLCPP_INFO_STREAM(logger_, "accel profile: sampleRate " << profile->getSampleRate() + << " full scale_range " + << profile->getFullScaleRange()); + } else if (sensor->getType() == OB_SENSOR_GYRO) { + auto profile = origin_profile->as(); + RCLCPP_INFO_STREAM(logger_, "gyro profile: sampleRate " << profile->getSampleRate() + << " full scale_range " + << profile->getFullScaleRange()); + } else { + RCLCPP_INFO_STREAM(logger_, "unknown profile: " << magic_enum::enum_name(sensor->getType())); + } + } +} + +void OBCameraNode::setupProfiles() { + // Image stream + for (const auto &elem : IMAGE_STREAMS) { + if (enable_stream_[elem]) { + const auto &sensor = sensors_[elem]; + CHECK_NOTNULL(sensor.get()); + auto profiles = sensor->getStreamProfileList(); + CHECK_NOTNULL(profiles.get()); + CHECK(profiles->getCount() > 0); + for (size_t i = 0; i < profiles->getCount(); i++) { + auto base_profile = profiles->getProfile(i)->as(); + if (base_profile == nullptr) { + throw std::runtime_error("Failed to get profile " + std::to_string(i)); + } + auto profile = base_profile->as(); + if (profile == nullptr) { + throw std::runtime_error("Failed cast profile to VideoStreamProfile"); + } + RCLCPP_DEBUG_STREAM( + logger_, "Sensor profile: " + << "stream_type: " << magic_enum::enum_name(profile->getType()) + << "Format: " << profile->getFormat() << ", Width: " << profile->getWidth() + << ", Height: " << profile->getHeight() << ", FPS: " << profile->getFps()); + supported_profiles_[elem].emplace_back(profile); + } + std::shared_ptr selected_profile; + std::shared_ptr default_profile; + try { + if (width_[elem] == 0 && height_[elem] == 0 && fps_[elem] == 0 && + format_[elem] == OB_FORMAT_UNKNOWN) { + selected_profile = profiles->getProfile(0)->as(); + } else { + if (pid_ == GEMINI_305_PID && elem == DEPTH) { + OBHardwareDecimationConfig conf; + conf.originWidth = width_[elem]; + conf.originHeight = height_[elem]; + conf.factor = depth_decimation_factor_; + selected_profile = profiles->getVideoStreamProfile(conf, format_[elem], fps_[elem]); + } else if (pid_ == GEMINI_305_PID && elem == INFRA1) { + OBHardwareDecimationConfig conf; + conf.originWidth = width_[elem]; + conf.originHeight = height_[elem]; + conf.factor = left_ir_decimation_factor_; + selected_profile = profiles->getVideoStreamProfile(conf, format_[elem], fps_[elem]); + } else if (pid_ == GEMINI_305_PID && elem == INFRA2) { + OBHardwareDecimationConfig conf; + conf.originWidth = width_[elem]; + conf.originHeight = height_[elem]; + conf.factor = right_ir_decimation_factor_; + selected_profile = profiles->getVideoStreamProfile(conf, format_[elem], fps_[elem]); + } else { + selected_profile = profiles->getVideoStreamProfile(width_[elem], height_[elem], + format_[elem], fps_[elem]); + } + } + + } catch (const ob::Error &ex) { + RCLCPP_ERROR_STREAM( + logger_, "Failed to get " << stream_name_[elem] << " profile: " << ex.getMessage()); + RCLCPP_ERROR_STREAM( + logger_, "Stream: " << magic_enum::enum_name(elem.first) + << ", Stream Index: " << elem.second << ", Width: " << width_[elem] + << ", Height: " << height_[elem] << ", FPS: " << fps_[elem] + << ", Format: " << magic_enum::enum_name(format_[elem])); + RCLCPP_ERROR(logger_, + "Error: The device might be connected via USB 2.0. Please verify your " + "configuration and try again. The current process will now exit."); + RCLCPP_INFO_STREAM(logger_, "Available profiles:"); + printSensorProfiles(sensor); + RCLCPP_ERROR(logger_, "Because can not set this stream, so exit."); + exit(-1); + } + + if (!selected_profile) { + RCLCPP_WARN_STREAM(logger_, "Given stream configuration is not supported by the device! " + << " Stream: " << magic_enum::enum_name(elem.first) + << ", Stream Index: " << elem.second + << ", Width: " << width_[elem] + << ", Height: " << height_[elem] << ", FPS: " << fps_[elem] + << ", Format: " << magic_enum::enum_name(format_[elem])); + if (default_profile) { + RCLCPP_WARN_STREAM(logger_, "Using default profile instead."); + RCLCPP_WARN_STREAM(logger_, "default FPS " << default_profile->getFps()); + selected_profile = default_profile; + } else { + RCLCPP_ERROR_STREAM( + logger_, " NO default_profile found , Stream: " << magic_enum::enum_name(elem.first) + << " will be disable"); + enable_stream_[elem] = false; + continue; + } + } + CHECK_NOTNULL(selected_profile); + stream_profile_[elem] = selected_profile; + height_[elem] = static_cast(selected_profile->getHeight()); + width_[elem] = static_cast(selected_profile->getWidth()); + fps_[elem] = static_cast(selected_profile->getFps()); + format_[elem] = selected_profile->getFormat(); + updateImageConfig(elem); + if (selected_profile->format() == OB_FORMAT_BGRA) { + images_[elem] = cv::Mat(height_[elem], width_[elem], CV_8UC4, cv::Scalar(0, 0, 0, 0)); + encoding_[elem] = sensor_msgs::image_encodings::BGRA8; + unit_step_size_[COLOR] = 4 * sizeof(uint8_t); + } else if (selected_profile->format() == OB_FORMAT_RGBA) { + images_[elem] = cv::Mat(height_[elem], width_[elem], CV_8UC4, cv::Scalar(0, 0, 0, 0)); + encoding_[elem] = sensor_msgs::image_encodings::RGBA8; + unit_step_size_[COLOR] = 4 * sizeof(uint8_t); + } else { + images_[elem] = + cv::Mat(height_[elem], width_[elem], image_format_[elem], cv::Scalar(0, 0, 0)); + } + } + } + // IMU + for (const auto &stream_index : HID_STREAMS) { + if (!enable_stream_[stream_index]) { + continue; + } + try { + auto profile_list = sensors_[stream_index]->getStreamProfileList(); + if (stream_index == ACCEL) { + auto full_scale_range = fullAccelScaleRangeFromString(imu_range_[stream_index]); + auto sample_rate = sampleRateFromString(imu_rate_[stream_index]); + auto profile = profile_list->getAccelStreamProfile(full_scale_range, sample_rate); + stream_profile_[stream_index] = profile; + } else if (stream_index == GYRO) { + auto full_scale_range = fullGyroScaleRangeFromString(imu_range_[stream_index]); + auto sample_rate = sampleRateFromString(imu_rate_[stream_index]); + auto profile = profile_list->getGyroStreamProfile(full_scale_range, sample_rate); + stream_profile_[stream_index] = profile; + } + RCLCPP_INFO_STREAM(logger_, "stream " << stream_name_[stream_index] << " full scale range " + << imu_range_[stream_index] << " sample rate " + << imu_rate_[stream_index]); + } catch (const ob::Error &e) { + RCLCPP_INFO_STREAM(logger_, "Failed to setup << " << stream_name_[stream_index] + << " profile: " << e.getMessage()); + enable_stream_[stream_index] = false; + stream_profile_[stream_index] = nullptr; + } + } +} +void OBCameraNode::updateImageConfig(const stream_index_pair &stream_index) { + if (format_[stream_index] == OB_FORMAT_Y8) { + image_format_[stream_index] = CV_8UC1; + encoding_[stream_index] = stream_index.first == OB_STREAM_DEPTH + ? sensor_msgs::image_encodings::TYPE_8UC1 + : sensor_msgs::image_encodings::MONO8; + unit_step_size_[stream_index] = sizeof(uint8_t); + } + if (format_[stream_index] == OB_FORMAT_MJPG) { + if (stream_index.first == OB_STREAM_IR || stream_index.first == OB_STREAM_IR_LEFT || + stream_index.first == OB_STREAM_IR_RIGHT) { + image_format_[stream_index] = CV_8UC1; + encoding_[stream_index] = sensor_msgs::image_encodings::MONO8; + unit_step_size_[stream_index] = sizeof(uint8_t); + } + } + if (format_[stream_index] == OB_FORMAT_Y16 && + (stream_index == COLOR || stream_index == COLOR_LEFT || stream_index == COLOR_RIGHT)) { + image_format_[stream_index] = CV_16UC1; + encoding_[stream_index] = sensor_msgs::image_encodings::MONO16; + unit_step_size_[stream_index] = sizeof(uint16_t); + } +} +int OBCameraNode::init_interleave_hdr_param() { + device_->setIntProperty(OB_PROP_FRAME_INTERLEAVE_CONFIG_INDEX_INT, 1); + if (!isnotLaserDevices(pid_)) { + device_->setIntProperty(OB_PROP_LASER_CONTROL_INT, hdr_index1_laser_control_); + } + device_->setIntProperty(OB_PROP_DEPTH_EXPOSURE_INT, hdr_index1_depth_exposure_); + device_->setIntProperty(OB_PROP_IR_EXPOSURE_INT, hdr_index1_depth_exposure_); + device_->setIntProperty(OB_PROP_DEPTH_GAIN_INT, hdr_index1_depth_gain_); + device_->setIntProperty(OB_PROP_IR_BRIGHTNESS_INT, hdr_index1_ir_brightness_); + device_->setIntProperty(OB_PROP_IR_AE_MAX_EXPOSURE_INT, hdr_index1_ir_ae_max_exposure_); + + // set interleaveae + device_->setIntProperty(OB_PROP_FRAME_INTERLEAVE_CONFIG_INDEX_INT, 0); + if (!isnotLaserDevices(pid_)) { + device_->setIntProperty(OB_PROP_LASER_CONTROL_INT, hdr_index0_laser_control_); + } + device_->setIntProperty(OB_PROP_DEPTH_EXPOSURE_INT, hdr_index0_depth_exposure_); + device_->setIntProperty(OB_PROP_IR_EXPOSURE_INT, hdr_index0_depth_exposure_); + device_->setIntProperty(OB_PROP_DEPTH_GAIN_INT, hdr_index0_depth_gain_); + device_->setIntProperty(OB_PROP_IR_BRIGHTNESS_INT, hdr_index0_ir_brightness_); + device_->setIntProperty(OB_PROP_IR_AE_MAX_EXPOSURE_INT, hdr_index0_ir_ae_max_exposure_); + return 0; +} + +int OBCameraNode::init_interleave_laser_param() { + device_->setIntProperty(OB_PROP_FRAME_INTERLEAVE_CONFIG_INDEX_INT, 1); + device_->setIntProperty(OB_PROP_LASER_CONTROL_INT, laser_index1_laser_control_); + device_->setIntProperty(OB_PROP_DEPTH_EXPOSURE_INT, laser_index1_depth_exposure_); + device_->setIntProperty(OB_PROP_IR_EXPOSURE_INT, laser_index1_depth_exposure_); + device_->setIntProperty(OB_PROP_DEPTH_GAIN_INT, laser_index1_depth_gain_); + device_->setIntProperty(OB_PROP_IR_BRIGHTNESS_INT, laser_index1_ir_brightness_); + device_->setIntProperty(OB_PROP_IR_AE_MAX_EXPOSURE_INT, laser_index1_ir_ae_max_exposure_); + + // set interleaveae + device_->setIntProperty(OB_PROP_FRAME_INTERLEAVE_CONFIG_INDEX_INT, 0); + device_->setIntProperty(OB_PROP_LASER_CONTROL_INT, laser_index0_laser_control_); + device_->setIntProperty(OB_PROP_DEPTH_EXPOSURE_INT, laser_index0_depth_exposure_); + device_->setIntProperty(OB_PROP_IR_EXPOSURE_INT, laser_index0_depth_exposure_); + device_->setIntProperty(OB_PROP_DEPTH_GAIN_INT, laser_index0_depth_gain_); + device_->setIntProperty(OB_PROP_IR_BRIGHTNESS_INT, laser_index0_ir_brightness_); + device_->setIntProperty(OB_PROP_IR_AE_MAX_EXPOSURE_INT, laser_index0_ir_ae_max_exposure_); + return 0; +} +void OBCameraNode::startStreams() { + if (pipeline_ != nullptr) { + pipeline_.reset(); + } + pipeline_ = std::make_unique(device_); + + try { + setupPipelineConfig(); + pipeline_->start(pipeline_config_, [this](const std::shared_ptr &frame_set) { + onNewFrameSetCallback(frame_set); + }); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to start pipeline: " << e.getMessage()); + RCLCPP_INFO_STREAM(logger_, "try to disable ir stream and try again"); + enable_stream_[INFRA0] = false; + setupPipelineConfig(); + pipeline_->start(pipeline_config_, [this](const std::shared_ptr &frame_set) { + onNewFrameSetCallback(frame_set); + }); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to start pipeline"); + throw std::runtime_error("Failed to start pipeline"); + } + if (enable_stream_[COLOR] && !colorFrameThread_) { + colorFrameThread_ = std::make_shared([this]() { onNewColorFrameCallback(); }); + } + if (enable_stream_[COLOR_LEFT] && !leftColorFrameThread_) { + leftColorFrameThread_ = + std::make_shared([this]() { onNewLeftColorFrameCallback(); }); + } + if (enable_stream_[COLOR_RIGHT] && !rightColorFrameThread_) { + rightColorFrameThread_ = + std::make_shared([this]() { onNewRightColorFrameCallback(); }); + } + if (enable_frame_sync_) { + RCLCPP_INFO_STREAM(logger_, "Enable frame sync"); + TRY_EXECUTE_BLOCK(pipeline_->enableFrameSync()); + } else { + RCLCPP_INFO_STREAM(logger_, "Disable frame sync"); + TRY_EXECUTE_BLOCK(pipeline_->disableFrameSync()); + } + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + // set interleave mode + if (interleave_ae_mode_ == "hdr" && interleave_frame_enable_) { + RCLCPP_INFO_STREAM(logger_, "Setting interleave mode to hdr"); + device_->loadFrameInterleave("Depth from HDR"); + init_interleave_hdr_param(); + } else if (interleave_ae_mode_ == "laser" && interleave_frame_enable_) { + RCLCPP_INFO_STREAM(logger_, "Setting interleave mode to laser"); + device_->loadFrameInterleave("Laser On-Off"); + init_interleave_laser_param(); + } else { + RCLCPP_INFO_STREAM(logger_, "Setting interleave mode to nothing"); + } + // enable interleave frame + if ((interleave_ae_mode_ == "hdr") || (interleave_ae_mode_ == "laser")) { + RCLCPP_INFO_STREAM(logger_, "current interleave_ae_mode_: " << interleave_ae_mode_); + if (device_->isPropertySupported(OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL, OB_PERMISSION_WRITE)) { + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL, + interleave_frame_enable_); + RCLCPP_INFO_STREAM(logger_, "Enable enable_interleave_depth_frame to " + << (interleave_frame_enable_ ? "true" : "false")); + } + } + // set interleave larse PATTERN_SYNC_DELAY + if ((interleave_ae_mode_ == "laser") && interleave_frame_enable_ && + device_->isPropertySupported(OB_PROP_FRAME_INTERLEAVE_LASER_PATTERN_SYNC_DELAY_INT, + OB_PERMISSION_READ_WRITE) && + (sync_mode_str_ == "PRIMARY" || sync_mode_str_ == "SOFTWARE_TRIGGERING")) { + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_FRAME_INTERLEAVE_LASER_PATTERN_SYNC_DELAY_INT, 0); + RCLCPP_INFO_STREAM(logger_, "Setting OB_PROP_FRAME_INTERLEAVE_LASER_PATTERN_SYNC_DELAY_INT 0 "); + } + pipeline_started_.store(true); +} + +void OBCameraNode::startIMUSyncStream() { + if (imuPipeline_ != nullptr) { + imuPipeline_.reset(); + } + + imuPipeline_ = std::make_unique(device_); + if (imu_sync_output_start_) { + return; + } + + // ACCEL + auto accelProfiles = imuPipeline_->getStreamProfileList(OB_SENSOR_ACCEL); + auto accel_range = fullAccelScaleRangeFromString(imu_range_[ACCEL]); + auto accel_rate = sampleRateFromString(imu_rate_[ACCEL]); + auto accelProfile = accelProfiles->getAccelStreamProfile(accel_range, accel_rate); + // GYRO + auto gyroProfiles = imuPipeline_->getStreamProfileList(OB_SENSOR_GYRO); + auto gyro_range = fullGyroScaleRangeFromString(imu_range_[GYRO]); + auto gyro_rate = sampleRateFromString(imu_rate_[GYRO]); + auto gyroProfile = gyroProfiles->getGyroStreamProfile(gyro_range, gyro_rate); + std::shared_ptr imuConfig = std::make_shared(); + imuConfig->enableStream(accelProfile); + imuConfig->enableStream(gyroProfile); + TRY_EXECUTE_BLOCK(imuPipeline_->enableFrameSync()); + + try { + imuPipeline_->start(imuConfig, [&](std::shared_ptr frame) { + auto frameSet = frame->as(); + auto aFrame = frameSet->getFrame(OB_FRAME_ACCEL); + auto gFrame = frameSet->getFrame(OB_FRAME_GYRO); + if (aFrame && gFrame) { + onNewIMUFrameSyncOutputCallback(aFrame, gFrame); + } + }); + + imu_sync_output_start_ = true; + RCLCPP_INFO_STREAM( + logger_, "start accel stream with range: " << fullAccelScaleRangeToString(accel_range) + << ",rate:" << sampleRateToString(accel_rate) + << ", and start gyro stream with range:" + << fullGyroScaleRangeToString(gyro_range) + << ",rate:" << sampleRateToString(gyro_rate)); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to start IMU sync stream: " << e.getMessage()); + imu_sync_output_start_ = false; + } catch (...) { + RCLCPP_ERROR_STREAM( + logger_, "Failed to start IMU stream, please check the imu_rate and imu_range parameters."); + imu_sync_output_start_ = false; + } +} + +void OBCameraNode::startIMU() { + if (enable_sync_output_accel_gyro_) { + startIMUSyncStream(); + } else { + for (const auto &stream_index : HID_STREAMS) { + if (enable_stream_[stream_index] && !imu_started_[stream_index]) { + auto imu_profile = stream_profile_[stream_index]; + CHECK_NOTNULL(imu_profile); + RCLCPP_INFO_STREAM(logger_, "start " << stream_name_[stream_index] << " stream"); + CHECK_NOTNULL(sensors_[stream_index]); + sensors_[stream_index]->start( + imu_profile, [this, stream_index](const std::shared_ptr &frame) { + onNewIMUFrameCallback(frame, stream_index); + }); + } + } + } +} + +void OBCameraNode::stopStreams() { + std::lock_guard lock(device_lock_); + + if (!pipeline_started_ || !pipeline_) { + RCLCPP_INFO_STREAM(logger_, "pipeline not started or not exist, skip stop pipeline"); + return; + } + + // Stop diagnostic timer first to prevent crashes during shutdown + try { + if (diagnostic_timer_) { + diagnostic_timer_->cancel(); + diagnostic_timer_.reset(); + } + if (diagnostic_updater_) { + diagnostic_updater_.reset(); + } + } catch (...) { + // Ignore exceptions during diagnostic cleanup + } + + // Mark pipeline as stopping to prevent new operations + pipeline_started_.store(false); + + try { + // Check if device is still valid before stopping pipeline + if (device_ && pipeline_) { + pipeline_->stop(); + + // disable interleave frame only if device is still connected + if ((interleave_ae_mode_ == "hdr") || (interleave_ae_mode_ == "laser")) { + try { + RCLCPP_INFO_STREAM(logger_, "current interleave_ae_mode_: " << interleave_ae_mode_); + if (device_->isPropertySupported(OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL, + OB_PERMISSION_WRITE)) { + interleave_frame_enable_ = false; + RCLCPP_INFO_STREAM(logger_, "Enable enable_interleave_depth_frame to " + << (interleave_frame_enable_ ? "true" : "false")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL, + interleave_frame_enable_); + } + } catch (const ob::Error &e) { + RCLCPP_WARN_STREAM( + logger_, "Failed to disable interleave frame during shutdown: " << e.getMessage()); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Failed to disable interleave frame during shutdown"); + } + } + } else { + RCLCPP_WARN_STREAM(logger_, + "Device or pipeline not available during stop - likely disconnected"); + } + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop pipeline: " << e.getMessage()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop pipeline"); + } +} + +void OBCameraNode::stopIMU() { + std::lock_guard lock(device_lock_); + + if (enable_sync_output_accel_gyro_) { + if (!imu_sync_output_start_ || !imuPipeline_) { + RCLCPP_INFO_STREAM(logger_, "imu pipeline not started or not exist, skip stop imu pipeline"); + return; + } + try { + imuPipeline_->stop(); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop imu pipeline: " << e.getMessage()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop imu pipeline"); + } + imu_sync_output_start_.store(false); + } else { + for (const auto &stream_index : HID_STREAMS) { + if (imu_started_[stream_index]) { + CHECK(sensors_.count(stream_index)); + RCLCPP_INFO_STREAM(logger_, "stop " << stream_name_[stream_index] << " stream"); + try { + sensors_[stream_index]->stop(); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop " << stream_name_[stream_index] + << " stream: " << e.getMessage()); + } + imu_started_[stream_index] = false; + } + } + } +} + +// cs_param_t rd_par = {0, 0}, param = {1, 3000}; //30 +int OBCameraNode::openSocSyncPwmTrigger(uint16_t fps) { + const char *devicePath = DEVICE_PATH; + const int TRIGGER_MODE_ENABLE = 1; + const int TRIGGER_MODE_DISABLE = 0; + + int ret = -1; + cs_param_t param = {TRIGGER_MODE_ENABLE, fps}; + cs_param_t rd_par = {TRIGGER_MODE_DISABLE, 0}; + + if (access(devicePath, F_OK) != 0) { + std::cerr << "Device node " << devicePath << " does not exist." << std::endl; + return ret; + } + gmsl_trigger_fd_ = open(DEVICE_PATH, O_RDWR); + if (gmsl_trigger_fd_ < 0) { + perror("open device failed\n"); + return gmsl_trigger_fd_; + } + + std::cout << "Written param mode=" << param.mode << ", fps=" << param.fps << std::endl; + ret = write(gmsl_trigger_fd_, ¶m, sizeof(param)); + if (ret < 0) { + perror("write device failed\n"); + close(gmsl_trigger_fd_); + return ret; + } + + ret = read(gmsl_trigger_fd_, &rd_par, sizeof(rd_par)); + if (ret < 0) { + perror("read device failed\n"); + close(gmsl_trigger_fd_); + return ret; + } + std::cout << "Read param mode=" << rd_par.mode << ", fps=" << rd_par.fps << std::endl; + + std::cout << "Start hardware triggering..." << std::endl; + + return 0; +} +int OBCameraNode::closeSocSyncPwmTrigger() { + if (gmsl_trigger_fd_ >= 0) { + close(gmsl_trigger_fd_); + gmsl_trigger_fd_ = -1; // Reset file descriptors + std::cout << "close camSync success" << std::endl; + return 0; + } + return -1; +} + +void OBCameraNode::startGmslTrigger() { + if (gmsl_trigger_fps_ > 0 && enable_gmsl_trigger_) { + RCLCPP_WARN_STREAM(logger_, "Start HardwareTrigger by soc-trigger-source. gmsl_trigger_fps_: " + << gmsl_trigger_fps_); + openSocSyncPwmTrigger(gmsl_trigger_fps_); + } else { + RCLCPP_WARN_STREAM(logger_, + "Start HardwareTrigger by soc-trigger-source. gmsl_trigger_fps_ illegal: " + << gmsl_trigger_fps_); + } +} +void OBCameraNode::stopGmslTrigger() { closeSocSyncPwmTrigger(); } + +void OBCameraNode::setupDefaultImageFormat() { + format_[DEPTH] = OB_FORMAT_Y16; + format_str_[DEPTH] = "Y16"; + image_format_[DEPTH] = CV_16UC1; + encoding_[DEPTH] = sensor_msgs::image_encodings::TYPE_16UC1; + unit_step_size_[DEPTH] = sizeof(uint16_t); + format_[INFRA0] = OB_FORMAT_Y16; + format_str_[INFRA0] = "Y16"; + image_format_[INFRA0] = CV_16UC1; + encoding_[INFRA0] = sensor_msgs::image_encodings::MONO16; + unit_step_size_[INFRA0] = sizeof(uint16_t); + + format_[INFRA1] = OB_FORMAT_Y16; + format_str_[INFRA1] = "Y16"; + image_format_[INFRA1] = CV_16UC1; + encoding_[INFRA1] = sensor_msgs::image_encodings::MONO16; + unit_step_size_[INFRA1] = sizeof(uint16_t); + + format_[INFRA2] = OB_FORMAT_Y16; + format_str_[INFRA2] = "Y16"; + image_format_[INFRA2] = CV_16UC1; + encoding_[INFRA2] = sensor_msgs::image_encodings::MONO16; + unit_step_size_[INFRA2] = sizeof(uint16_t); + + image_format_[COLOR] = CV_8UC3; + encoding_[COLOR] = sensor_msgs::image_encodings::RGB8; + unit_step_size_[COLOR] = 3 * sizeof(uint8_t); + + image_format_[COLOR_LEFT] = CV_8UC3; + encoding_[COLOR_LEFT] = sensor_msgs::image_encodings::RGB8; + unit_step_size_[COLOR_LEFT] = 3 * sizeof(uint8_t); + + image_format_[COLOR_RIGHT] = CV_8UC3; + encoding_[COLOR_RIGHT] = sensor_msgs::image_encodings::RGB8; + unit_step_size_[COLOR_RIGHT] = 3 * sizeof(uint8_t); +} + +void OBCameraNode::getParameters() { + setAndGetNodeParameter(camera_name_, "camera_name", "camera"); + camera_link_frame_id_ = camera_name_ + "_link"; + for (auto stream_index : IMAGE_STREAMS) { + std::string param_name = stream_name_[stream_index] + "_width"; + setAndGetNodeParameter(width_[stream_index], param_name, 0); + param_name = stream_name_[stream_index] + "_height"; + setAndGetNodeParameter(height_[stream_index], param_name, 0); + param_name = stream_name_[stream_index] + "_fps"; + setAndGetNodeParameter(fps_[stream_index], param_name, 0); + param_name = "enable_" + stream_name_[stream_index]; + if (stream_index == DEPTH) { + setAndGetNodeParameter(enable_stream_[stream_index], param_name, true); + } else { + setAndGetNodeParameter(enable_stream_[stream_index], param_name, false); + } + param_name = stream_name_[stream_index] + "_flip"; + setAndGetNodeParameter(flip_stream_[stream_index], param_name, false); + param_name = stream_name_[stream_index] + "_mirror"; + setAndGetNodeParameter(mirror_stream_[stream_index], param_name, false); + param_name = stream_name_[stream_index] + "_rotation"; + setAndGetNodeParameter(rotation_stream_[stream_index], param_name, -1); + param_name = camera_name_ + "_" + stream_name_[stream_index] + "_frame_id"; + std::string default_frame_id = camera_name_ + "_" + stream_name_[stream_index] + "_frame"; + setAndGetNodeParameter(frame_id_[stream_index], param_name, default_frame_id); + std::string default_optical_frame_id = + camera_name_ + "_" + stream_name_[stream_index] + "_optical_frame"; + param_name = stream_name_[stream_index] + "_optical_frame_id"; + setAndGetNodeParameter(optical_frame_id_[stream_index], param_name, default_optical_frame_id); + param_name = stream_name_[stream_index] + "_format"; + setAndGetNodeParameter(format_str_[stream_index], param_name, format_str_[stream_index]); + format_[stream_index] = OBFormatFromString(format_str_[stream_index]); + updateImageConfig(stream_index); + param_name = stream_name_[stream_index] + "_qos"; + setAndGetNodeParameter(image_qos_[stream_index], param_name, "default"); + param_name = stream_name_[stream_index] + "_camera_info_qos"; + setAndGetNodeParameter(camera_info_qos_[stream_index], param_name, "default"); + } + + for (auto stream_index : IMAGE_STREAMS) { + depth_aligned_frame_id_[stream_index] = optical_frame_id_[COLOR]; + } + + accel_gyro_frame_id_ = camera_name_ + "_accel_gyro_optical_frame"; + + setAndGetNodeParameter(enable_sync_output_accel_gyro_, "enable_sync_output_accel_gyro", + false); + for (const auto &stream_index : HID_STREAMS) { + std::string param_name = stream_name_[stream_index] + "_qos"; + setAndGetNodeParameter(imu_qos_[stream_index], param_name, "default"); + param_name = "enable_" + stream_name_[stream_index]; + setAndGetNodeParameter(enable_stream_[stream_index], param_name, false); + if (enable_sync_output_accel_gyro_) { + enable_stream_[stream_index] = true; + } + param_name = stream_name_[stream_index] + "_rate"; + setAndGetNodeParameter(imu_rate_[stream_index], param_name, ""); + param_name = stream_name_[stream_index] + "_range"; + setAndGetNodeParameter(imu_range_[stream_index], param_name, ""); + param_name = camera_name_ + "_" + stream_name_[stream_index] + "_frame_id"; + std::string default_frame_id = camera_name_ + "_" + stream_name_[stream_index] + "_frame"; + setAndGetNodeParameter(frame_id_[stream_index], param_name, default_frame_id); + std::string default_optical_frame_id = + camera_name_ + "_" + stream_name_[stream_index] + "_optical_frame"; + param_name = stream_name_[stream_index] + "_optical_frame_id"; + setAndGetNodeParameter(optical_frame_id_[stream_index], param_name, default_optical_frame_id); + depth_aligned_frame_id_[stream_index] = + camera_name_ + "_" + stream_name_[COLOR] + "_optical_frame"; + } + setAndGetNodeParameter(publish_tf_, "publish_tf", true); + setAndGetNodeParameter(tf_publish_rate_, "tf_publish_rate", 0.0); + setAndGetNodeParameter(depth_registration_, "depth_registration", false); + setAndGetNodeParameter(enable_point_cloud_, "enable_point_cloud", false); + setAndGetNodeParameter(ir_info_url_, "ir_info_url", ""); + setAndGetNodeParameter(color_info_url_, "color_info_url", ""); + setAndGetNodeParameter(enable_colored_point_cloud_, "enable_colored_point_cloud", false); + setAndGetNodeParameter(enable_point_cloud_, "enable_point_cloud", false); + setAndGetNodeParameter(point_cloud_decimation_filter_factor_, + "point_cloud_decimation_filter_factor", 1); + setAndGetNodeParameter(point_cloud_qos_, "point_cloud_qos", "default"); + setAndGetNodeParameter(enable_d2c_viewer_, "enable_d2c_viewer", false); + setAndGetNodeParameter(disparity_to_depth_mode_, "disparity_to_depth_mode", "HW"); + setAndGetNodeParameter(depth_filter_config_, "depth_filter_config", ""); + if (!depth_filter_config_.empty()) { + enable_depth_filter_ = true; + } + setAndGetNodeParameter(enable_frame_sync_, "enable_frame_sync", false); + setAndGetNodeParameter(enable_color_auto_exposure_priority_, + "enable_color_auto_exposure_priority", false); + setAndGetNodeParameter(enable_color_auto_exposure_, "enable_color_auto_exposure", true); + setAndGetNodeParameter(enable_color_auto_white_balance_, "enable_color_auto_white_balance", + true); + setAndGetNodeParameter(color_ae_roi_left_, "color_ae_roi_left", -1); + setAndGetNodeParameter(color_ae_roi_top_, "color_ae_roi_top", -1); + setAndGetNodeParameter(color_ae_roi_right_, "color_ae_roi_right", -1); + setAndGetNodeParameter(color_ae_roi_bottom_, "color_ae_roi_bottom", -1); + setAndGetNodeParameter(color_exposure_, "color_exposure", -1); + setAndGetNodeParameter(color_gain_, "color_gain", -1); + setAndGetNodeParameter(color_white_balance_, "color_white_balance", -1); + setAndGetNodeParameter(color_ae_max_exposure_, "color_ae_max_exposure", -1); + setAndGetNodeParameter(color_brightness_, "color_brightness", -1); + setAndGetNodeParameter(color_roi_brightness_, "color_roi_brightness", -1); + setAndGetNodeParameter(color_sharpness_, "color_sharpness", -1); + setAndGetNodeParameter(color_gamma_, "color_gamma", -1); + setAndGetNodeParameter(color_saturation_, "color_saturation", -1); + setAndGetNodeParameter(color_contrast_, "color_contrast", -1); + setAndGetNodeParameter(color_hue_, "color_hue", -1); + setAndGetNodeParameter(color_backlight_compensation_, "color_backlight_compensation", -1); + setAndGetNodeParameter(color_denoising_level_, "color_denoising_level", -1); + setAndGetNodeParameter(color_powerline_freq_, "color_powerline_freq", ""); + setAndGetNodeParameter(color_preset_, "color_preset", "Default"); + setAndGetNodeParameter(enable_color_decimation_filter_, "enable_color_decimation_filter", + false); + setAndGetNodeParameter(color_decimation_filter_scale_, "color_decimation_filter_scale", -1); + setAndGetNodeParameter(enable_left_color_decimation_filter_, + "enable_left_color_decimation_filter", false); + setAndGetNodeParameter(left_color_decimation_filter_scale_, + "left_color_decimation_filter_scale", -1); + setAndGetNodeParameter(enable_right_color_decimation_filter_, + "enable_right_color_decimation_filter", false); + setAndGetNodeParameter(right_color_decimation_filter_scale_, + "right_color_decimation_filter_scale", -1); + setAndGetNodeParameter(enable_depth_auto_exposure_priority_, + "enable_depth_auto_exposure_priority", false); + setAndGetNodeParameter(depth_ae_roi_left_, "depth_ae_roi_left", -1); + setAndGetNodeParameter(depth_ae_roi_top_, "depth_ae_roi_top", -1); + setAndGetNodeParameter(depth_ae_roi_right_, "depth_ae_roi_right", -1); + setAndGetNodeParameter(depth_ae_roi_bottom_, "depth_ae_roi_bottom", -1); + setAndGetNodeParameter(depth_exposure_, "depth_exposure", -1); + setAndGetNodeParameter(depth_gain_, "depth_gain", -1); + setAndGetNodeParameter(depth_brightness_, "depth_brightness", -1); + setAndGetNodeParameter(mean_intensity_set_point_, "mean_intensity_set_point", + depth_brightness_); + setAndGetNodeParameter(depth_precision_str_, "depth_precision", ""); + setAndGetNodeParameter(enable_ir_auto_exposure_, "enable_ir_auto_exposure", true); + setAndGetNodeParameter(ir_exposure_, "ir_exposure", -1); + setAndGetNodeParameter(ir_gain_, "ir_gain", -1); + setAndGetNodeParameter(ir_ae_max_exposure_, "ir_ae_max_exposure", -1); + setAndGetNodeParameter(ir_brightness_, "ir_brightness", -1); + setAndGetNodeParameter(enable_ir_long_exposure_, "enable_ir_long_exposure", true); + setAndGetNodeParameter(enable_right_ir_sequence_id_filter_, + "enable_right_ir_sequence_id_filter", false); + setAndGetNodeParameter(right_ir_sequence_id_filter_id_, "right_ir_sequence_id_filter_id", + -1); + setAndGetNodeParameter(enable_left_ir_sequence_id_filter_, + "enable_left_ir_sequence_id_filter", false); + setAndGetNodeParameter(left_ir_sequence_id_filter_id_, "left_ir_sequence_id_filter_id", -1); + setAndGetNodeParameter(preset_resolution_config_, "preset_resolution_config", ""); + setAndGetNodeParameter(sync_mode_str_, "sync_mode", ""); + setAndGetNodeParameter(depth_delay_us_, "depth_delay_us", 0); + setAndGetNodeParameter(color_delay_us_, "color_delay_us", 0); + setAndGetNodeParameter(trigger2image_delay_us_, "trigger2image_delay_us", 0); + setAndGetNodeParameter(trigger_out_delay_us_, "trigger_out_delay_us", 0); + setAndGetNodeParameter(trigger_out_enabled_, "trigger_out_enabled", true); + setAndGetNodeParameter(software_trigger_enabled_, "software_trigger_enabled", true); + setAndGetNodeParameter(enable_ptp_config_, "enable_ptp_config", false); + setAndGetNodeParameter(cloud_frame_id_, "cloud_frame_id", ""); + if (enable_colored_point_cloud_ || enable_d2c_viewer_) { + depth_registration_ = true; + } + if (!enable_stream_[COLOR]) { + enable_colored_point_cloud_ = false; + depth_registration_ = false; + } + setAndGetNodeParameter(enable_ldp_, "enable_ldp", true); + setAndGetNodeParameter(ldp_power_level_, "ldp_power_level", -1); + setAndGetNodeParameter(linear_accel_cov_, "linear_accel_cov", 0.0003); + setAndGetNodeParameter(angular_vel_cov_, "angular_vel_cov", 0.02); + setAndGetNodeParameter(ordered_pc_, "ordered_pc", false); + setAndGetNodeParameter(max_save_images_count_, "max_save_images_count", 10); + setAndGetNodeParameter(enable_depth_scale_, "enable_depth_scale", true); + setAndGetNodeParameter(depth_decimation_factor_, "depth_decimation_factor", 1); + setAndGetNodeParameter(left_ir_decimation_factor_, "left_ir_decimation_factor", 1); + setAndGetNodeParameter(right_ir_decimation_factor_, "right_ir_decimation_factor", 1); + setAndGetNodeParameter(depth_work_mode_, "depth_work_mode", ""); + if (isDepthWorkModeDevices(device_->getDeviceInfo()->getPid())) { + setAndGetNodeParameter(depth_work_mode_, "device_preset", ""); + } else { + setAndGetNodeParameter(device_preset_, "device_preset", ""); + } + setAndGetNodeParameter(enable_decimation_filter_, "enable_decimation_filter", false); + setAndGetNodeParameter(enable_hdr_merge_, "enable_hdr_merge", false); + setAndGetNodeParameter(enable_sequence_id_filter_, "enable_sequence_id_filter", false); + setAndGetNodeParameter(enable_disparity_to_depth_, "enable_disparity_to_depth", true); + setAndGetNodeParameter(enable_threshold_filter_, "enable_threshold_filter", false); + setAndGetNodeParameter(enable_hardware_noise_removal_filter_, + "enable_hardware_noise_removal_filter", true); + setAndGetNodeParameter(enable_noise_removal_filter_, "enable_noise_removal_filter", true); + setAndGetNodeParameter(enable_spatial_filter_, "enable_spatial_filter", false); + setAndGetNodeParameter(enable_temporal_filter_, "enable_temporal_filter", false); + setAndGetNodeParameter(enable_hole_filling_filter_, "enable_hole_filling_filter", false); + setAndGetNodeParameter(enable_spatial_fast_filter_, "enable_spatial_fast_filter", false); + setAndGetNodeParameter(enable_spatial_moderate_filter_, "enable_spatial_moderate_filter", + false); + setAndGetNodeParameter(decimation_filter_scale_, "decimation_filter_scale", -1); + setAndGetNodeParameter(sequence_id_filter_id_, "sequence_id_filter_id", -1); + setAndGetNodeParameter(threshold_filter_max_, "threshold_filter_max", -1); + setAndGetNodeParameter(threshold_filter_min_, "threshold_filter_min", -1); + setAndGetNodeParameter(hardware_noise_removal_filter_threshold_, + "hardware_noise_removal_filter_threshold", -1.0); + setAndGetNodeParameter(noise_removal_filter_min_diff_, "noise_removal_filter_min_diff", 256); + setAndGetNodeParameter(noise_removal_filter_max_size_, "noise_removal_filter_max_size", 80); + setAndGetNodeParameter(spatial_filter_alpha_, "spatial_filter_alpha", -1.0); + setAndGetNodeParameter(spatial_filter_diff_threshold_, "spatial_filter_diff_threshold", -1); + setAndGetNodeParameter(spatial_filter_magnitude_, "spatial_filter_magnitude", -1); + setAndGetNodeParameter(spatial_filter_radius_, "spatial_filter_radius", -1); + setAndGetNodeParameter(temporal_filter_diff_threshold_, "temporal_filter_diff_threshold", + -1.0); + setAndGetNodeParameter(temporal_filter_weight_, "temporal_filter_weight", -1.0); + setAndGetNodeParameter(hole_filling_filter_mode_, "hole_filling_filter_mode", ""); + setAndGetNodeParameter(enable_false_positive_filter_, "enable_false_positive_filter", + false); + setAndGetNodeParameter(hdr_merge_exposure_1_, "hdr_merge_exposure_1", -1); + setAndGetNodeParameter(hdr_merge_gain_1_, "hdr_merge_gain_1", -1); + setAndGetNodeParameter(hdr_merge_exposure_2_, "hdr_merge_exposure_2", -1); + setAndGetNodeParameter(hdr_merge_gain_2_, "hdr_merge_gain_2", -1); + setAndGetNodeParameter(align_mode_, "align_mode", "HW"); + setAndGetNodeParameter(diagnostic_period_, "diagnostic_period", 1.0); + setAndGetNodeParameter(enable_laser_, "enable_laser", true); + std::string align_target_stream_str_; + setAndGetNodeParameter(align_target_stream_str_, "align_target_stream", "COLOR"); + align_target_stream_ = obStreamTypeFromString(align_target_stream_str_); + setAndGetNodeParameter(retry_on_usb3_detection_failure_, "retry_on_usb3_detection_failure", + false); + setAndGetNodeParameter(laser_energy_level_, "laser_energy_level", -1); + setAndGetNodeParameter(min_depth_limit_, "min_depth_limit", 0); + setAndGetNodeParameter(max_depth_limit_, "max_depth_limit", 0); + setAndGetNodeParameter(enable_heartbeat_, "enable_heartbeat", false); + setAndGetNodeParameter(enable_color_undistortion_, "enable_color_undistortion", false); + setAndGetNodeParameter(time_domain_, "time_domain", "global"); + setAndGetNodeParameter(exposure_range_mode_, "exposure_range_mode", "default"); + setAndGetNodeParameter(load_config_json_file_path_, "load_config_json_file_path", + ""); + setAndGetNodeParameter(export_config_json_file_path_, "export_config_json_file_path", + ""); + setAndGetNodeParameter(enable_accel_data_correction_, "enable_accel_data_correction", true); + setAndGetNodeParameter(enable_gyro_data_correction_, "enable_gyro_data_correction", true); + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info.get()); + + if (device_preset_ == "Dual Color Streams") { + RCLCPP_INFO_STREAM(logger_, + "Using Double Color preset, only left and right color streams are enabled."); + enable_stream_[COLOR] = false; + enable_stream_[DEPTH] = false; + enable_stream_[INFRA0] = false; + enable_stream_[INFRA1] = false; + enable_stream_[INFRA2] = false; + enable_stream_[LIDAR] = false; + enable_stream_[COLOR_LEFT] = true; + enable_stream_[COLOR_RIGHT] = true; + + enable_point_cloud_ = false; + enable_colored_point_cloud_ = false; + depth_registration_ = false; + enable_d2c_viewer_ = false; + enable_depth_filter_ = false; + enable_color_undistortion_ = false; + } + + if (isOpenNIDevice(pid_)) { + time_domain_ = "system"; + } + if (time_domain_ == "global") { + device_->enableGlobalTimestamp(true); + } + setAndGetNodeParameter(frames_per_trigger_, "frames_per_trigger", 2); + int software_trigger_period = 33; + setAndGetNodeParameter(software_trigger_period, "software_trigger_period", 33); + software_trigger_period_ = std::chrono::milliseconds(software_trigger_period); + setAndGetNodeParameter(gmsl_trigger_fps_, "gmsl_trigger_fps", 3000); + setAndGetNodeParameter(enable_gmsl_trigger_, "enable_gmsl_trigger", false); + setAndGetNodeParameter(interleave_ae_mode_, "interleave_ae_mode", "hdr"); + setAndGetNodeParameter(interleave_frame_enable_, "interleave_frame_enable", false); + setAndGetNodeParameter(interleave_skip_enable_, "interleave_skip_enable", false); + setAndGetNodeParameter(interleave_skip_index_, "interleave_skip_index", 1); + + // hdr and laser interleave params + setAndGetNodeParameter(hdr_index1_laser_control_, "hdr_index1_laser_control", 1); + setAndGetNodeParameter(hdr_index1_depth_exposure_, "hdr_index1_depth_exposure", 1); + setAndGetNodeParameter(hdr_index1_depth_gain_, "hdr_index1_depth_gain", 16); + setAndGetNodeParameter(hdr_index1_ir_brightness_, "hdr_index1_ir_brightness", 30); + setAndGetNodeParameter(hdr_index1_ir_ae_max_exposure_, "hdr_index1_ir_ae_max_exposure", + 30458); + setAndGetNodeParameter(hdr_index0_laser_control_, "hdr_index0_laser_control", 1); + setAndGetNodeParameter(hdr_index0_depth_exposure_, "hdr_index0_depth_exposure", 7500); + setAndGetNodeParameter(hdr_index0_depth_gain_, "hdr_index0_depth_gain", 16); + setAndGetNodeParameter(hdr_index0_ir_brightness_, "hdr_index0_ir_brightness", 90); + setAndGetNodeParameter(hdr_index0_ir_ae_max_exposure_, "hdr_index0_ir_ae_max_exposure", + 30458); + + setAndGetNodeParameter(laser_index1_laser_control_, "laser_index1_laser_control", 0); + setAndGetNodeParameter(laser_index1_depth_exposure_, "laser_index1_depth_exposure", 3000); + setAndGetNodeParameter(laser_index1_depth_gain_, "laser_index1_depth_gain", 16); + setAndGetNodeParameter(laser_index1_ir_brightness_, "laser_index1_ir_brightness", 60); + setAndGetNodeParameter(laser_index1_ir_ae_max_exposure_, "laser_index1_ir_ae_max_exposure", + 7000); + setAndGetNodeParameter(laser_index0_laser_control_, "laser_index0_laser_control", 1); + setAndGetNodeParameter(laser_index0_depth_exposure_, "laser_index0_depth_exposure", 3000); + setAndGetNodeParameter(laser_index0_depth_gain_, "laser_index0_depth_gain", 16); + setAndGetNodeParameter(laser_index0_ir_brightness_, "laser_index0_ir_brightness", 60); + setAndGetNodeParameter(laser_index0_ir_ae_max_exposure_, "laser_index0_ir_ae_max_exposure", + 17000); + setAndGetNodeParameter(disparity_range_mode_, "disparity_range_mode", -1); + setAndGetNodeParameter(disparity_search_offset_, "disparity_search_offset", -1); + setAndGetNodeParameter(disparity_offset_config_, "disparity_offset_config", false); + setAndGetNodeParameter(offset_index0_, "offset_index0", -1); + setAndGetNodeParameter(offset_index1_, "offset_index1", -1); + + setAndGetNodeParameter(frame_aggregate_mode_, "frame_aggregate_mode", "ANY"); + + setAndGetNodeParameter(show_fps_enable_, "show_fps_enable", false); + setAndGetNodeParameter(enable_publish_extrinsic_, "enable_publish_extrinsic", false); + setAndGetNodeParameter(intra_camera_sync_reference_, "intra_camera_sync_reference", + "Middle"); + setAndGetNodeParameter(ae_mode_, "ae_mode", "depthbased"); + setAndGetNodeParameter(enable_sports_mode_, "enable_sports_mode", false); + + RCLCPP_INFO_STREAM(logger_, "current time domain: " << time_domain_); + RCLCPP_INFO_STREAM(logger_, "hdr_index1_laser_control_ " + << hdr_index1_laser_control_ << " hdr_index1_depth_exposure_ " + << hdr_index1_depth_exposure_ << " hdr_index1_depth_gain_ " + << hdr_index1_depth_gain_ << " hdr_index1_ir_brightness_ " + << hdr_index1_ir_brightness_ << " hdr_index1_ir_ae_max_exposure_ " + << hdr_index1_ir_ae_max_exposure_ << "\n"); + RCLCPP_INFO_STREAM(logger_, "hdr_index0_laser_control_ " + << hdr_index0_laser_control_ << " hdr_index0_depth_exposure_ " + << hdr_index0_depth_exposure_ << " hdr_index0_depth_gain_ " + << hdr_index0_depth_gain_ << " hdr_index0_ir_brightness_ " + << hdr_index0_ir_brightness_ << " hdr_index0_ir_ae_max_exposure_ " + << hdr_index0_ir_ae_max_exposure_ << "\n"); + RCLCPP_INFO_STREAM(logger_, "laser_index1_laser_control_ " + << laser_index1_laser_control_ << " laser_index1_depth_exposure_ " + << laser_index1_depth_exposure_ << " laser_index1_depth_gain_ " + << laser_index1_depth_gain_ << " laser_index1_ir_brightness_ " + << laser_index1_ir_brightness_ + << " laser_index1_ir_ae_max_exposure_ " + << laser_index1_ir_ae_max_exposure_ << "\n"); + RCLCPP_INFO_STREAM(logger_, "laser_index0_laser_control_ " + << laser_index0_laser_control_ << " laser_index0_depth_exposure_ " + << laser_index0_depth_exposure_ << " laser_index0_depth_gain_ " + << laser_index0_depth_gain_ << " laser_index0_ir_brightness_ " + << laser_index0_ir_brightness_ + << " laser_index0_ir_ae_max_exposure_ " + << laser_index0_ir_ae_max_exposure_ << "\n"); +} + +void OBCameraNode::setupTopics() { + try { + getParameters(); + setupDevices(); + if (enable_stream_[DEPTH]) { + setupDepthPostProcessFilter(); + } + if (enable_stream_[COLOR] || enable_stream_[COLOR_LEFT] || enable_stream_[COLOR_RIGHT]) { + setupColorPostProcessFilter(); + } + if (enable_stream_[INFRA2]) { + setupRightIrPostProcessFilter(); + } + if (enable_stream_[INFRA1]) { + setupLeftIrPostProcessFilter(); + } + setupProfiles(); + setupCameraInfo(); + selectBaseStream(); + setupCameraCtrlServices(); + setupPublishers(); + setupDiagnosticUpdater(); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to setup topics: " << e.getMessage()); + throw std::runtime_error(e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to setup topics: " << e.what()); + throw std::runtime_error(e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Failed to setup topics"); + throw std::runtime_error("Failed to setup topics"); + } +} + +void OBCameraNode::onTemperatureUpdate(diagnostic_updater::DiagnosticStatusWrapper &status) { + try { + // Check to ensure we're not shutting down and device is valid + if (!is_running_.load() || !is_camera_node_initialized_.load()) { + status.summary(diagnostic_msgs::msg::DiagnosticStatus::STALE, + "Device disconnected or shutting down"); + return; + } + + // Try to acquire device lock with timeout to avoid blocking during shutdown + std::unique_lock lock(device_lock_, std::try_to_lock); + if (!lock.owns_lock()) { + status.summary(diagnostic_msgs::msg::DiagnosticStatus::STALE, "Device busy or shutting down"); + return; + } + + if (!device_) { + status.summary(diagnostic_msgs::msg::DiagnosticStatus::STALE, "Device not available"); + return; + } + + // Additional safety check - verify device is actually accessible + try { + auto device_info = device_->getDeviceInfo(); + if (!device_info) { + status.summary(diagnostic_msgs::msg::DiagnosticStatus::STALE, "Device info not available"); + return; + } + } catch (...) { + status.summary(diagnostic_msgs::msg::DiagnosticStatus::STALE, "Device not accessible"); + return; + } + + OBDeviceTemperature temperature; + uint32_t data_size = sizeof(OBDeviceTemperature); + device_->getStructuredData(OB_STRUCT_DEVICE_TEMPERATURE, + reinterpret_cast(&temperature), &data_size); + status.add("CPU Temperature", temperature.cpuTemp); + status.add("IR Temperature", temperature.irTemp); + status.add("LDM Temperature", temperature.ldmTemp); + status.add("MainBoard Temperature", temperature.mainBoardTemp); + status.add("TEC Temperature", temperature.tecTemp); + status.add("IMU Temperature", temperature.imuTemp); + status.add("RGB Temperature", temperature.rgbTemp); + status.add("Left IR Temperature", temperature.irLeftTemp); + status.add("Right IR Temperature", temperature.irRightTemp); + status.add("Chip Top Temperature", temperature.chipTopTemp); + status.add("Chip Bottom Temperature", temperature.chipBottomTemp); + status.summary(diagnostic_msgs::msg::DiagnosticStatus::OK, "Temperature is normal"); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to TemperatureUpdate1: " << e.getMessage()); + status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to TemperatureUpdate2: " << e.what()); + status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Failed to TemperatureUpdate3: Device is deactivated/disconnected!"); + status.summary(diagnostic_msgs::msg::DiagnosticStatus::ERROR, "Unknown error"); + } +} + +void OBCameraNode::setupDiagnosticUpdater() { + if (diagnostic_period_ <= 0.0) { + return; + } + try { + RCLCPP_INFO_STREAM(logger_, "Publish diagnostics every " << diagnostic_period_ << " seconds"); + auto info = device_->getDeviceInfo(); + std::string serial_number = info->getSerialNumber(); + diagnostic_updater_ = std::make_unique(node_, 10000.0); + diagnostic_updater_->setHardwareID(serial_number); + diagnostic_updater_->add("Temperatures", this, &OBCameraNode::onTemperatureUpdate); + diagnostic_timer_ = + node_->create_wall_timer(std::chrono::seconds(int(diagnostic_period_)), [this]() { + try { + // Check if we're still running and all components are valid + if (!is_running_.load() || !diagnostic_updater_ || + !is_camera_node_initialized_.load() || !device_) { + return; + } + + // Try to acquire device lock with timeout to avoid blocking during shutdown + std::unique_lock lock(device_lock_, std::try_to_lock); + if (!lock.owns_lock()) { + // Device is busy or shutting down, skip this update + return; + } + // Mark diagnostic as running to prevent concurrent reset/publish races + { + std::lock_guard lk(diagnostic_mutex_); + diagnostic_running_ = true; + } + try { + diagnostic_updater_->force_update(); + } catch (...) { + std::lock_guard lk(diagnostic_mutex_); + diagnostic_running_ = false; + diagnostic_cv_.notify_all(); + throw; + } + { + std::lock_guard lk(diagnostic_mutex_); + diagnostic_running_ = false; + } + diagnostic_cv_.notify_all(); + } catch (const ob::Error &e) { + RCLCPP_WARN_STREAM(logger_, "Diagnostic update failed: " + << e.getMessage() << " - Device may be disconnected"); + // Stop the diagnostic timer if device is having issues + try { + if (diagnostic_timer_) { + diagnostic_timer_->cancel(); + diagnostic_timer_.reset(); + } + } catch (...) { + // Ignore cleanup exceptions + } + } catch (const std::exception &e) { + RCLCPP_WARN_STREAM(logger_, "Diagnostic update failed: " << e.what()); + } catch (...) { + RCLCPP_WARN(logger_, "Diagnostic update failed: Unknown error"); + } + }); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to setup diagnostic updater: " << e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to setup diagnostic updater: " << e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Failed to TemperatureUpdate"); + } +} + +void OBCameraNode::setupPipelineConfig() { + if (pipeline_config_) { + pipeline_config_.reset(); + } + pipeline_config_ = std::make_shared(); + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info.get()); + if (depth_registration_ && enable_stream_[COLOR] && enable_stream_[DEPTH] && + align_mode_ == "HW") { + OBAlignMode align_mode = ALIGN_D2C_HW_MODE; + RCLCPP_INFO_STREAM(logger_, "set align mode to " << magic_enum::enum_name(align_mode)); + pipeline_config_->setAlignMode(align_mode); + RCLCPP_INFO_STREAM(logger_, "enable depth scale " << (enable_depth_scale_ ? "ON" : "OFF")); + pipeline_config_->setDepthScaleRequire(enable_depth_scale_); + } + for (const auto &stream_index : IMAGE_STREAMS) { + if (enable_stream_[stream_index]) { + RCLCPP_INFO_STREAM(logger_, "Enable " << stream_name_[stream_index] << " stream"); + auto profile = stream_profile_[stream_index]->as(); + + if (stream_index == COLOR && align_target_stream_ == OB_STREAM_COLOR && align_filter_) { + auto video_profile = profile; + align_filter_->setAlignToStreamProfile(video_profile); + } + if (stream_index == DEPTH && align_target_stream_ == OB_STREAM_DEPTH && align_filter_) { + auto video_profile = profile; + align_filter_->setAlignToStreamProfile(video_profile); + } + pipeline_config_->enableStream(stream_profile_[stream_index]); + } + } + + if (frame_aggregate_mode_ == "full_frame") { + pipeline_config_->setFrameAggregateOutputMode(OB_FRAME_AGGREGATE_OUTPUT_FULL_FRAME_REQUIRE); + } else if (frame_aggregate_mode_ == "color_frame") { + pipeline_config_->setFrameAggregateOutputMode(OB_FRAME_AGGREGATE_OUTPUT_COLOR_FRAME_REQUIRE); + } else if (frame_aggregate_mode_ == "disable") { + pipeline_config_->setFrameAggregateOutputMode(OB_FRAME_AGGREGATE_OUTPUT_DISABLE); + } else { + pipeline_config_->setFrameAggregateOutputMode(OB_FRAME_AGGREGATE_OUTPUT_ANY_SITUATION); + } +} + +void OBCameraNode::setupCameraInfo() { + std::string color_camera_name = camera_name_ + "_color"; + if (!color_info_url_.empty()) { + color_info_manager_ = std::make_unique( + node_, color_camera_name, color_info_url_); + } + std::string ir_camera_name = camera_name_ + "_ir"; + if (!ir_info_url_.empty()) { + ir_info_manager_ = std::make_unique( + node_, ir_camera_name, ir_info_url_); + } +} + +void OBCameraNode::setupPublishers() { + using PointCloud2 = sensor_msgs::msg::PointCloud2; + using CameraInfo = sensor_msgs::msg::CameraInfo; + auto point_cloud_qos_profile = getRMWQosProfileFromString(point_cloud_qos_); + if (use_intra_process_) { + point_cloud_qos_profile = rmw_qos_profile_default; + } + if (enable_colored_point_cloud_) { + depth_registration_cloud_pub_ = node_->create_publisher( + "depth_registered/points", + rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(point_cloud_qos_profile), + point_cloud_qos_profile)); + } + if (enable_point_cloud_) { + depth_cloud_pub_ = node_->create_publisher( + "depth/points", rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(point_cloud_qos_profile), + point_cloud_qos_profile)); + } + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info.get()); + for (const auto &stream_index : IMAGE_STREAMS) { + if (!enable_stream_[stream_index]) { + continue; + } + std::string name = stream_name_[stream_index]; + std::string topic = name + "/image_raw"; + auto image_qos = image_qos_[stream_index]; + auto image_qos_profile = getRMWQosProfileFromString(image_qos); + if (use_intra_process_) { + image_qos_profile = rmw_qos_profile_default; + } + if (use_intra_process_) { + image_publishers_[stream_index] = + std::make_shared(*node_, topic, image_qos_profile); + } else { + image_publishers_[stream_index] = + std::make_shared(*node_, topic, image_qos_profile); + } + + topic = name + "/camera_info"; + auto camera_info_qos = camera_info_qos_[stream_index]; + auto camera_info_qos_profile = getRMWQosProfileFromString(camera_info_qos); + if (use_intra_process_) { + camera_info_qos_profile = rmw_qos_profile_default; + } + camera_info_publishers_[stream_index] = node_->create_publisher( + topic, rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(camera_info_qos_profile), + camera_info_qos_profile)); + if (isPublishMetaData(pid_)) { + metadata_publishers_[stream_index] = + node_->create_publisher( + name + "/metadata", + rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(camera_info_qos_profile), + camera_info_qos_profile)); + } + if (stream_index == COLOR && enable_color_undistortion_) { + if (use_intra_process_) { + color_undistortion_publisher_ = std::make_shared( + *node_, "color/image_undistorted", image_qos_profile); + } else { + color_undistortion_publisher_ = std::make_shared( + *node_, "color/image_undistorted", image_qos_profile); + } + } + } + + if (enable_sync_output_accel_gyro_) { + std::string topic_name = stream_name_[GYRO] + "_" + stream_name_[ACCEL] + "/sample"; + auto data_qos = getRMWQosProfileFromString(imu_qos_[GYRO]); + if (use_intra_process_) { + data_qos = rmw_qos_profile_default; + } + imu_gyro_accel_publisher_ = node_->create_publisher( + topic_name, rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(data_qos), data_qos)); + topic_name = stream_name_[GYRO] + "/imu_info"; + imu_info_publishers_[GYRO] = node_->create_publisher( + topic_name, rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(data_qos), data_qos)); + topic_name = stream_name_[ACCEL] + "/imu_info"; + imu_info_publishers_[ACCEL] = node_->create_publisher( + topic_name, rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(data_qos), data_qos)); + } else { + for (const auto &stream_index : HID_STREAMS) { + if (!enable_stream_[stream_index]) { + continue; + } + std::string data_topic_name = stream_name_[stream_index] + "/sample"; + auto data_qos = getRMWQosProfileFromString(imu_qos_[stream_index]); + if (use_intra_process_) { + data_qos = rmw_qos_profile_default; + } + imu_publishers_[stream_index] = node_->create_publisher( + data_topic_name, rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(data_qos), data_qos)); + data_topic_name = stream_name_[stream_index] + "/imu_info"; + imu_info_publishers_[stream_index] = + node_->create_publisher( + data_topic_name, + rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(data_qos), data_qos)); + } + } + auto extrinsics_qos = rclcpp::QoS(1).transient_local(); + if (use_intra_process_) { + extrinsics_qos = rclcpp::QoS(1); + } + if (enable_stream_[DEPTH] && enable_stream_[INFRA0] && enable_publish_extrinsic_) { + depth_to_other_extrinsics_publishers_[INFRA0] = + node_->create_publisher("depth_to_ir", extrinsics_qos); + } + if (enable_stream_[DEPTH] && enable_stream_[COLOR] && enable_publish_extrinsic_) { + depth_to_other_extrinsics_publishers_[COLOR] = + node_->create_publisher("depth_to_color", + extrinsics_qos); + } + if (enable_stream_[DEPTH] && enable_stream_[INFRA1] && enable_publish_extrinsic_) { + depth_to_other_extrinsics_publishers_[INFRA1] = + node_->create_publisher("depth_to_left_ir", + extrinsics_qos); + } + if (enable_stream_[DEPTH] && enable_stream_[INFRA2] && enable_publish_extrinsic_) { + depth_to_other_extrinsics_publishers_[INFRA2] = + node_->create_publisher("depth_to_right_ir", + extrinsics_qos); + } + if (enable_stream_[DEPTH] && enable_stream_[ACCEL] && enable_publish_extrinsic_) { + depth_to_other_extrinsics_publishers_[ACCEL] = + node_->create_publisher("depth_to_accel", + extrinsics_qos); + } + if (enable_stream_[DEPTH] && enable_stream_[GYRO] && enable_publish_extrinsic_) { + depth_to_other_extrinsics_publishers_[GYRO] = + node_->create_publisher("depth_to_gyro", + extrinsics_qos); + } + if (enable_stream_[COLOR_LEFT] && enable_stream_[COLOR_RIGHT] && enable_publish_extrinsic_) { + depth_to_other_extrinsics_publishers_[COLOR_LEFT] = + node_->create_publisher("left_color_to_right_color", + extrinsics_qos); + } + filter_status_pub_ = + node_->create_publisher("depth_filter_status", extrinsics_qos); + std_msgs::msg::String msg; + msg.data = filter_status_.dump(2); + filter_status_pub_->publish(msg); +} + +void OBCameraNode::publishPointCloud(const std::shared_ptr &frame_set) { + try { + if (depth_registration_ || enable_colored_point_cloud_) { + if (frame_set->depthFrame() != nullptr && frame_set->colorFrame() != nullptr) { + publishColoredPointCloud(frame_set); + } + } + + if (enable_point_cloud_ && frame_set->depthFrame() != nullptr) { + publishDepthPointCloud(frame_set); + } + + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "publishPointCloud with unknown error"); + } +} + +void OBCameraNode::publishDepthPointCloud(const std::shared_ptr &frame_set) { + (void)frame_set; + if (!depth_cloud_pub_ || depth_cloud_pub_->get_subscription_count() == 0 || + !enable_point_cloud_) { + return; + } + std::lock_guard point_cloud_msg_lock(point_cloud_mutex_); + auto depth_frame = frame_set->depthFrame(); + if (!depth_frame) { + RCLCPP_ERROR_STREAM(logger_, "depth frame is null"); + return; + } + if (!pipeline_) { + RCLCPP_ERROR_STREAM(logger_, "pipeline is null in publishDepthPointCloud"); + return; + } + auto camera_params = pipeline_->getCameraParam(); + if (!device_) { + RCLCPP_ERROR_STREAM(logger_, "device is null in publishDepthPointCloud"); + return; + } + auto device_info = device_->getDeviceInfo(); + if (!device_info || !device_info.get()) { + RCLCPP_ERROR_STREAM(logger_, "device_info is null in publishDepthPointCloud"); + return; + } + if (depth_registration_ || pid_ == DABAI_MAX_PID) { + camera_params.depthIntrinsic = camera_params.rgbIntrinsic; + } + depth_point_cloud_filter_.setCameraParam(camera_params); + float depth_scale = depth_frame->getValueScale(); + depth_point_cloud_filter_.setPositionDataScaled(depth_scale); + depth_point_cloud_filter_.setCreatePointFormat(OB_FORMAT_POINT); + depth_point_cloud_filter_.setDecimationFactor(point_cloud_decimation_filter_factor_); + auto result_frame = depth_point_cloud_filter_.process(depth_frame); + if (!result_frame) { + RCLCPP_ERROR_STREAM(logger_, "Failed to process depth frame"); + return; + } + auto point_size = result_frame->dataSize() / sizeof(OBPoint); + auto *points = static_cast(result_frame->data()); + auto width = depth_frame->width() / point_cloud_decimation_filter_factor_; + auto height = depth_frame->height() / point_cloud_decimation_filter_factor_; + auto point_cloud_msg = std::make_unique(); + sensor_msgs::PointCloud2Modifier modifier(*point_cloud_msg); + modifier.setPointCloud2FieldsByString(1, "xyz"); + modifier.resize(width * height); + point_cloud_msg->width = width; + point_cloud_msg->height = height; + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + point_cloud_msg->data.resize(point_cloud_msg->height * point_cloud_msg->row_step); + sensor_msgs::PointCloud2Iterator iter_x(*point_cloud_msg, "x"); + sensor_msgs::PointCloud2Iterator iter_y(*point_cloud_msg, "y"); + sensor_msgs::PointCloud2Iterator iter_z(*point_cloud_msg, "z"); + const static float MIN_DISTANCE = 20.0; // 2cm + const static float MAX_DISTANCE = 10000.0; // 10m + const static float min_depth = MIN_DISTANCE / depth_scale; + const static float max_depth = MAX_DISTANCE / depth_scale; + size_t valid_count = 0; + for (size_t i = 0; i < point_size; i++) { + bool valid_point = points[i].z >= min_depth && points[i].z <= max_depth; + if (valid_point || ordered_pc_) { + *iter_x = static_cast(points[i].x / 1000.0); + *iter_y = static_cast(points[i].y / 1000.0); + *iter_z = static_cast(points[i].z / 1000.0); + ++iter_x, ++iter_y, ++iter_z; + valid_count++; + } + } + if (valid_count == 0) { + RCLCPP_WARN(logger_, "No valid point in point cloud"); + return; + } + if (!ordered_pc_) { + point_cloud_msg->is_dense = true; + point_cloud_msg->width = valid_count; + point_cloud_msg->height = 1; + modifier.resize(valid_count); + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + } + auto frame_timestamp = getFrameTimestampUs(depth_frame); + auto timestamp = fromUsToROSTime(frame_timestamp); + std::string frame_id = depth_registration_ ? optical_frame_id_[COLOR] : optical_frame_id_[DEPTH]; + if (!cloud_frame_id_.empty()) { + frame_id = cloud_frame_id_; + } + point_cloud_msg->header.stamp = timestamp; + point_cloud_msg->header.frame_id = frame_id; + if (save_point_cloud_) { + save_point_cloud_ = false; + auto now = std::time(nullptr); + std::stringstream ss; + ss << std::put_time(std::localtime(&now), "%Y%m%d_%H%M%S"); + auto current_path = std::filesystem::current_path().string(); + std::string filename = current_path + "/point_cloud/points_" + ss.str() + ".ply"; + if (!std::filesystem::exists(current_path + "/point_cloud")) { + std::filesystem::create_directory(current_path + "/point_cloud"); + } + RCLCPP_INFO_STREAM(logger_, "Saving point cloud to " << filename); + try { + saveDepthPointsToPly(point_cloud_msg, filename); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to save point cloud: " << e.what()); + } + } + depth_cloud_pub_->publish(std::move(point_cloud_msg)); +} + +void OBCameraNode::publishColoredPointCloud(const std::shared_ptr &frame_set) { + if (!depth_registration_cloud_pub_ || + depth_registration_cloud_pub_->get_subscription_count() == 0 || + !enable_colored_point_cloud_ || !frame_set) { + return; + } + std::lock_guard point_cloud_msg_lock(point_cloud_mutex_); + + auto depth_frame = frame_set->depthFrame(); + auto color_frame = frame_set->colorFrame(); + + if (!depth_frame || !color_frame) { + return; + } + + auto depth_width = depth_frame->getWidth(); + auto depth_height = depth_frame->getHeight(); + auto color_width = color_frame->getWidth(); + auto color_height = color_frame->getHeight(); + if (depth_width != color_width || depth_height != color_height) { + RCLCPP_DEBUG(logger_, "Depth (%d x %d) and color (%d x %d) frame size mismatch", depth_width, + depth_height, color_width, color_height); + return; + } + + if (!pipeline_) { + RCLCPP_ERROR_STREAM(logger_, "pipeline is null in publishColoredPointCloud"); + return; + } + auto camera_params = pipeline_->getCameraParam(); + if (!device_) { + RCLCPP_ERROR_STREAM(logger_, "device is null in publishColoredPointCloud"); + return; + } + auto device_info = device_->getDeviceInfo(); + if (!device_info || !device_info.get()) { + RCLCPP_ERROR_STREAM(logger_, "device_info is null in publishColoredPointCloud"); + return; + } + if (depth_registration_ || pid_ == DABAI_MAX_PID) { + camera_params.depthIntrinsic = camera_params.rgbIntrinsic; + } + + color_point_cloud_filter_.setCameraParam(camera_params); + auto depth_scale = depth_frame->getValueScale(); + color_point_cloud_filter_.setPositionDataScaled(depth_scale); + color_point_cloud_filter_.setCreatePointFormat(OB_FORMAT_RGB_POINT); + color_point_cloud_filter_.setDecimationFactor(point_cloud_decimation_filter_factor_); + auto result_frame = color_point_cloud_filter_.process(frame_set); + if (!result_frame) { + RCLCPP_ERROR_STREAM(logger_, "Failed to process depth frame"); + return; + } + auto point_size = result_frame->dataSize() / sizeof(OBColorPoint); + auto *point_cloud = static_cast(result_frame->data()); + auto width = color_frame->getWidth() / point_cloud_decimation_filter_factor_; + auto height = color_frame->getHeight() / point_cloud_decimation_filter_factor_; + auto point_cloud_msg = std::make_unique(); + sensor_msgs::PointCloud2Modifier modifier(*point_cloud_msg); + modifier.setPointCloud2FieldsByString(1, "xyz"); + modifier.resize(width * height); + point_cloud_msg->width = width; + point_cloud_msg->height = height; + std::string format_str = "rgb"; + point_cloud_msg->point_step = + addPointField(*point_cloud_msg, format_str, 1, sensor_msgs::msg::PointField::FLOAT32, + static_cast(point_cloud_msg->point_step)); + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + point_cloud_msg->data.resize(point_cloud_msg->height * point_cloud_msg->row_step); + sensor_msgs::PointCloud2Iterator iter_x(*point_cloud_msg, "x"); + sensor_msgs::PointCloud2Iterator iter_y(*point_cloud_msg, "y"); + sensor_msgs::PointCloud2Iterator iter_z(*point_cloud_msg, "z"); + sensor_msgs::PointCloud2Iterator iter_r(*point_cloud_msg, "r"); + sensor_msgs::PointCloud2Iterator iter_g(*point_cloud_msg, "g"); + sensor_msgs::PointCloud2Iterator iter_b(*point_cloud_msg, "b"); + size_t valid_count = 0; + static const float MIN_DISTANCE = 20.0; + static const float MAX_DISTANCE = 10000.0; + static float min_depth = MIN_DISTANCE / depth_scale; + static float max_depth = MAX_DISTANCE / depth_scale; + for (size_t i = 0; i < point_size; i++) { + bool valid_point = point_cloud[i].z >= min_depth && point_cloud[i].z <= max_depth; + if (valid_point || ordered_pc_) { + *iter_x = static_cast(point_cloud[i].x / 1000.0); + *iter_y = static_cast(point_cloud[i].y / 1000.0); + *iter_z = static_cast(point_cloud[i].z / 1000.0); + *iter_r = static_cast(point_cloud[i].r); + *iter_g = static_cast(point_cloud[i].g); + *iter_b = static_cast(point_cloud[i].b); + ++iter_x, ++iter_y, ++iter_z, ++iter_r, ++iter_g, ++iter_b; + ++valid_count; + } + } + + if (valid_count == 0) { + RCLCPP_WARN(logger_, "No valid points in point cloud"); + return; + } + if (!ordered_pc_) { + point_cloud_msg->is_dense = true; + point_cloud_msg->width = valid_count; + point_cloud_msg->height = 1; + modifier.resize(valid_count); + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + } + auto frame_timestamp = getFrameTimestampUs(depth_frame); + std::string frame_id = optical_frame_id_[COLOR]; + if (!cloud_frame_id_.empty()) { + frame_id = cloud_frame_id_; + } + auto timestamp = fromUsToROSTime(frame_timestamp); + point_cloud_msg->header.stamp = timestamp; + point_cloud_msg->header.frame_id = frame_id; + if (save_colored_point_cloud_) { + save_colored_point_cloud_ = false; + auto now = std::time(nullptr); + std::stringstream ss; + ss << std::put_time(std::localtime(&now), "%Y%m%d_%H%M%S"); + auto current_path = std::filesystem::current_path().string(); + std::string filename = current_path + "/point_cloud/colored_points_" + ss.str() + ".ply"; + if (!std::filesystem::exists(current_path + "/point_cloud")) { + std::filesystem::create_directory(current_path + "/point_cloud"); + } + RCLCPP_INFO_STREAM(logger_, "Saving point cloud to " << filename); + try { + saveRGBPointCloudMsgToPly(point_cloud_msg, filename); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to save point cloud: " << e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Failed to save point cloud"); + } + } + + depth_registration_cloud_pub_->publish(std::move(point_cloud_msg)); +} +std::shared_ptr OBCameraNode::processRightIrFrameFilter( + std::shared_ptr &frame) { + if (frame == nullptr || frame->getType() != OB_FRAME_IR_RIGHT) { + return nullptr; + } + for (size_t i = 0; i < right_ir_filter_list_.size(); i++) { + auto filter = right_ir_filter_list_[i]; + CHECK_NOTNULL(filter.get()); + if (filter->isEnabled() && frame != nullptr) { + frame = filter->process(frame); + if (frame == nullptr) { + RCLCPP_ERROR_STREAM(logger_, "Right Ir filter process failed"); + break; + } + } + } + return frame; +} +std::shared_ptr OBCameraNode::processLeftIrFrameFilter( + std::shared_ptr &frame) { + if (frame == nullptr || frame->getType() != OB_FRAME_IR_LEFT) { + return nullptr; + } + for (size_t i = 0; i < left_ir_filter_list_.size(); i++) { + auto filter = left_ir_filter_list_[i]; + CHECK_NOTNULL(filter.get()); + if (filter->isEnabled() && frame != nullptr) { + frame = filter->process(frame); + if (frame == nullptr) { + RCLCPP_ERROR_STREAM(logger_, "Left Ir filter process failed"); + break; + } + } + } + return frame; +} +std::shared_ptr OBCameraNode::processColorFrameFilter( + std::shared_ptr &frame) { + if (frame == nullptr) { + return nullptr; + } + auto frame_type = frame->getType(); + if (frame_type == OB_FRAME_COLOR) { + for (size_t i = 0; i < color_filter_list_.size(); i++) { + auto filter = color_filter_list_[i]; + CHECK_NOTNULL(filter.get()); + if (filter->isEnabled() && frame != nullptr) { + frame = filter->process(frame); + if (frame == nullptr) { + RCLCPP_ERROR_STREAM(logger_, "Color filter process failed"); + break; + } + } + } + return frame; + } else if (frame_type == OB_FRAME_COLOR_LEFT) { + for (size_t i = 0; i < left_color_filter_list_.size(); i++) { + auto filter = left_color_filter_list_[i]; + CHECK_NOTNULL(filter.get()); + if (filter->isEnabled() && frame != nullptr) { + frame = filter->process(frame); + if (frame == nullptr) { + RCLCPP_ERROR_STREAM(logger_, "Left color filter process failed"); + break; + } + } + } + return frame; + } else if (frame_type == OB_FRAME_COLOR_RIGHT) { + for (size_t i = 0; i < right_color_filter_list_.size(); i++) { + auto filter = right_color_filter_list_[i]; + CHECK_NOTNULL(filter.get()); + if (filter->isEnabled() && frame != nullptr) { + frame = filter->process(frame); + if (frame == nullptr) { + RCLCPP_ERROR_STREAM(logger_, "Right color filter process failed"); + break; + } + } + } + return frame; + } + return nullptr; +} +std::shared_ptr OBCameraNode::processDepthFrameFilter( + std::shared_ptr &frame) { + if (frame == nullptr || frame->getType() != OB_FRAME_DEPTH) { + return nullptr; + } + for (size_t i = 0; i < depth_filter_list_.size(); i++) { + auto filter = depth_filter_list_[i]; + CHECK_NOTNULL(filter.get()); + if (filter->isEnabled() && frame != nullptr) { + frame = filter->process(frame); + if (frame == nullptr) { + RCLCPP_ERROR_STREAM(logger_, "Depth filter process failed"); + break; + } + } + } + return frame; +} +void OBCameraNode::setDisparitySearchOffset() { + static bool has_run = false; + auto config = OBDispOffsetConfig(); + if (has_run) { + return; + } + if (device_->isPropertySupported(OB_PROP_DISP_SEARCH_OFFSET_INT, OB_PERMISSION_WRITE)) { + if (disparity_search_offset_ >= 0 && disparity_search_offset_ <= 127) { + device_->setIntProperty(OB_PROP_DISP_SEARCH_OFFSET_INT, disparity_search_offset_); + RCLCPP_INFO_STREAM(logger_, "disparity_search_offset: " << disparity_search_offset_); + } + if (offset_index0_ >= 0 && offset_index0_ <= 127 && offset_index1_ >= 0 && + offset_index1_ <= 127) { + config.enable = disparity_offset_config_; + config.offset0 = offset_index0_; + config.offset1 = offset_index1_; + config.reserved = 0; + + device_->setStructuredData(OB_STRUCT_DISP_OFFSET_CONFIG, + reinterpret_cast(&config), sizeof(config)); + RCLCPP_INFO_STREAM(logger_, "disparity_offset_config: " + << disparity_offset_config_ << " offset_index0:" + << offset_index0_ << " offset_index1:" << offset_index1_); + } + } + has_run = true; +} + +void OBCameraNode::setDepthAutoExposureROI() { + static bool depth_roi_has_run = false; + if (depth_roi_has_run) { + return; + } + if (device_->isPropertySupported(OB_STRUCT_DEPTH_AE_ROI, OB_PERMISSION_READ_WRITE)) { + auto config = OBRegionOfInterest(); + uint32_t data_size = sizeof(config); + device_->getStructuredData(OB_STRUCT_DEPTH_AE_ROI, reinterpret_cast(&config), + &data_size); + if (depth_ae_roi_left_ != -1) { + config.x0_left = (depth_ae_roi_left_ < 0) ? 0 : depth_ae_roi_left_; + config.x0_left = + (depth_ae_roi_left_ > width_[DEPTH] - 1) ? width_[DEPTH] - 1 : config.x0_left; + } + if (depth_ae_roi_top_ != -1) { + config.y0_top = (depth_ae_roi_top_ < 0) ? 0 : depth_ae_roi_top_; + config.y0_top = (depth_ae_roi_top_ > height_[DEPTH] - 1) ? height_[DEPTH] - 1 : config.y0_top; + } + if (depth_ae_roi_right_ != -1) { + config.x1_right = (depth_ae_roi_right_ < 0) ? 0 : depth_ae_roi_right_; + config.x1_right = + (depth_ae_roi_right_ > width_[DEPTH] - 1) ? width_[DEPTH] - 1 : config.x1_right; + } + if (depth_ae_roi_bottom_ != -1) { + config.y1_bottom = (depth_ae_roi_bottom_ < 0) ? 0 : depth_ae_roi_bottom_; + config.y1_bottom = + (depth_ae_roi_bottom_ > height_[DEPTH] - 1) ? height_[DEPTH] - 1 : config.y1_bottom; + } + device_->setStructuredData(OB_STRUCT_DEPTH_AE_ROI, reinterpret_cast(&config), + sizeof(config)); + device_->getStructuredData(OB_STRUCT_DEPTH_AE_ROI, reinterpret_cast(&config), + &data_size); + RCLCPP_INFO_STREAM(logger_, "Setting depth AE ROI to " + << config.x0_left << ", " << config.x1_right << ", " + << config.y0_top << ", " << config.y1_bottom); + } + depth_roi_has_run = true; +} + +void OBCameraNode::setColorAutoExposureROI() { + static bool color_roi_has_run = false; + if (color_roi_has_run) { + return; + } + if (device_->isPropertySupported(OB_STRUCT_COLOR_AE_ROI, OB_PERMISSION_READ_WRITE)) { + auto config = OBRegionOfInterest(); + uint32_t data_size = sizeof(config); + device_->getStructuredData(OB_STRUCT_COLOR_AE_ROI, reinterpret_cast(&config), + &data_size); + if (color_ae_roi_left_ != -1) { + config.x0_left = (color_ae_roi_left_ < 0) ? 0 : color_ae_roi_left_; + config.x0_left = + (color_ae_roi_left_ > width_[COLOR] - 1) ? width_[COLOR] - 1 : config.x0_left; + } + if (color_ae_roi_top_ != -1) { + config.y0_top = (color_ae_roi_top_ < 0) ? 0 : color_ae_roi_top_; + config.y0_top = (color_ae_roi_top_ > height_[COLOR] - 1) ? height_[COLOR] - 1 : config.y0_top; + } + if (color_ae_roi_right_ != -1) { + config.x1_right = (color_ae_roi_right_ < 0) ? 0 : color_ae_roi_right_; + config.x1_right = + (color_ae_roi_right_ > width_[COLOR] - 1) ? width_[COLOR] - 1 : config.x1_right; + } + if (color_ae_roi_bottom_ != -1) { + config.y1_bottom = (color_ae_roi_bottom_ < 0) ? 0 : color_ae_roi_bottom_; + config.y1_bottom = + (color_ae_roi_bottom_ > height_[COLOR] - 1) ? height_[COLOR] - 1 : config.y1_bottom; + } + device_->setStructuredData(OB_STRUCT_COLOR_AE_ROI, reinterpret_cast(&config), + sizeof(config)); + device_->getStructuredData(OB_STRUCT_COLOR_AE_ROI, reinterpret_cast(&config), + &data_size); + RCLCPP_INFO_STREAM(logger_, "Setting color AE ROI to " + << config.x0_left << ", " << config.x1_right << ", " + << config.y0_top << ", " << config.y1_bottom); + } + color_roi_has_run = true; +} + +uint64_t OBCameraNode::getFrameTimestampUs(const std::shared_ptr &frame) { + if (frame == nullptr) { + RCLCPP_WARN(logger_, "getFrameTimestampUs: frame is nullptr, return 0"); + return 0; + } + if (time_domain_ == "device") { + return frame->getTimeStampUs(); + } else if (time_domain_ == "global") { + return frame->getGlobalTimeStampUs(); + } else { + return frame->getSystemTimeStampUs(); + } +} +void OBCameraNode::onNewFrameSetCallback(std::shared_ptr frame_set) { + if (!is_running_.load()) { + return; + } + if (!is_camera_node_initialized_.load()) { + return; + } + if (frame_set == nullptr) { + return; + } + try { + if (!tf_published_) { + publishStaticTransforms(); + tf_published_ = true; + } + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info); + auto depth_frame = frame_set->getFrame(OB_FRAME_DEPTH); + auto color_frame = frame_set->getFrame(OB_FRAME_COLOR); + auto left_ir_frame = frame_set->getFrame(OB_FRAME_IR_LEFT); + auto right_ir_frame = frame_set->getFrame(OB_FRAME_IR_RIGHT); + auto left_color_frame = frame_set->getFrame(OB_FRAME_COLOR_LEFT); + auto right_color_frame = frame_set->getFrame(OB_FRAME_COLOR_RIGHT); + auto ir_frame = frame_set->getFrame(OB_FRAME_IR); + if (depth_frame) { + setDisparitySearchOffset(); + setDepthAutoExposureROI(); + depth_frame = processDepthFrameFilter(depth_frame); + frame_set->pushFrame(depth_frame); + static bool depth_frame_info_printed = false; + if (!depth_frame_info_printed) { + auto profile = depth_frame->getStreamProfile()->as(); + RCLCPP_INFO_STREAM(logger_, "Depth Frame - Width: " << profile->getWidth() + << " Height: " << profile->getHeight() + << " fps: " << profile->getFps() + << " Format: " << profile->getFormat()); + depth_frame_info_printed = true; + } + fps_counter_depth_->tick(); + } + if (color_frame) { + setColorAutoExposureROI(); + color_frame = processColorFrameFilter(color_frame); + frame_set->pushFrame(color_frame); + static bool color_frame_info_printed = false; + if (!color_frame_info_printed) { + auto profile = color_frame->getStreamProfile()->as(); + RCLCPP_INFO_STREAM(logger_, "Color Frame - Width: " << profile->getWidth() + << " Height: " << profile->getHeight() + << " fps: " << profile->getFps() + << " Format: " << profile->getFormat()); + color_frame_info_printed = true; + } + fps_counter_color_->tick(); + } + if (left_color_frame) { + setColorAutoExposureROI(); + left_color_frame = processColorFrameFilter(left_color_frame); + frame_set->pushFrame(left_color_frame); + static bool left_color_frame_info_printed = false; + if (!left_color_frame_info_printed) { + auto profile = left_color_frame->getStreamProfile()->as(); + RCLCPP_INFO_STREAM( + logger_, "Left Color Frame - Width: " + << profile->getWidth() << " Height: " << profile->getHeight() + << " fps: " << profile->getFps() << " Format: " << profile->getFormat()); + left_color_frame_info_printed = true; + } + } + if (right_color_frame) { + right_color_frame = processColorFrameFilter(right_color_frame); + frame_set->pushFrame(right_color_frame); + static bool right_color_frame_info_printed = false; + if (!right_color_frame_info_printed) { + auto profile = right_color_frame->getStreamProfile()->as(); + RCLCPP_INFO_STREAM( + logger_, "Right Color Frame - Width: " + << profile->getWidth() << " Height: " << profile->getHeight() + << " fps: " << profile->getFps() << " Format: " << profile->getFormat()); + right_color_frame_info_printed = true; + } + } + if (left_ir_frame) { + left_ir_frame = processLeftIrFrameFilter(left_ir_frame); + frame_set->pushFrame(left_ir_frame); + static bool left_ir_frame_info_printed = false; + if (!left_ir_frame_info_printed) { + auto profile = left_ir_frame->getStreamProfile()->as(); + RCLCPP_INFO_STREAM( + logger_, "Left IR Frame - Width: " + << profile->getWidth() << " Height: " << profile->getHeight() + << " fps: " << profile->getFps() << " Format: " << profile->getFormat()); + left_ir_frame_info_printed = true; + } + fps_counter_left_ir_->tick(); + } + if (right_ir_frame) { + right_ir_frame = processRightIrFrameFilter(right_ir_frame); + frame_set->pushFrame(right_ir_frame); + static bool right_ir_frame_info_printed = false; + if (!right_ir_frame_info_printed) { + auto profile = right_ir_frame->getStreamProfile()->as(); + RCLCPP_INFO_STREAM( + logger_, "Right IR Frame - Width: " + << profile->getWidth() << " Height: " << profile->getHeight() + << " fps: " << profile->getFps() << " Format: " << profile->getFormat()); + right_ir_frame_info_printed = true; + } + fps_counter_right_ir_->tick(); + } + if (ir_frame) { + static bool ir_frame_info_printed = false; + if (!ir_frame_info_printed) { + auto profile = ir_frame->getStreamProfile()->as(); + RCLCPP_INFO_STREAM(logger_, "IR Frame - Width: " << profile->getWidth() + << " Height: " << profile->getHeight() + << " fps: " << profile->getFps() + << " Format: " << profile->getFormat()); + ir_frame_info_printed = true; + } + } + if (depth_registration_ && align_filter_ && depth_frame) { + if (auto new_frame = align_filter_->process(frame_set)) { + auto new_frame_set = new_frame->as(); + CHECK_NOTNULL(new_frame_set.get()); + frame_set = new_frame_set; + } else { + RCLCPP_ERROR(logger_, "Failed to align depth frame to color frame"); + return; + } + } else { + RCLCPP_DEBUG(logger_, + "Depth registration is disabled or align filter is null or depth frame is " + "null or color frame is null"); + } + + if (enable_stream_[COLOR] && color_frame) { + std::unique_lock lock(color_frame_queue_lock_); + color_frame_queue_.push(frame_set); + color_frame_queue_cv_.notify_all(); + } else { + publishPointCloud(frame_set); + } + + if (enable_stream_[COLOR_LEFT] && left_color_frame) { + std::unique_lock lock(left_color_frame_queue_lock_); + left_color_frame_queue_.push(frame_set); + left_color_frame_queue_cv_.notify_all(); + } + if (enable_stream_[COLOR_RIGHT] && right_color_frame) { + std::unique_lock lock(right_color_frame_queue_lock_); + right_color_frame_queue_.push(frame_set); + right_color_frame_queue_cv_.notify_all(); + } + + for (const auto &stream_index : IMAGE_STREAMS) { + if (enable_stream_[stream_index]) { + auto frame_type = STREAM_TYPE_TO_FRAME_TYPE.at(stream_index.first); + if (frame_type == OB_FRAME_COLOR || frame_type == OB_FRAME_COLOR_LEFT || + frame_type == OB_FRAME_COLOR_RIGHT) { + continue; + } + + auto frame = frame_set->getFrame(frame_type); + if (frame == nullptr) { + continue; + } + onNewFrameCallback(frame, stream_index); + } + } + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "onNewFrameSetCallback error: " << e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "onNewFrameSetCallback error: " << e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "onNewFrameSetCallback error: unknown error"); + } +} + +void OBCameraNode::onNewColorFrameCallback() { + while (enable_stream_[COLOR] && rclcpp::ok() && is_running_.load()) { + std::unique_lock lock(color_frame_queue_lock_); + color_frame_queue_cv_.wait( + lock, [this]() { return !color_frame_queue_.empty() || !(is_running_.load()); }); + + if (!rclcpp::ok() || !is_running_.load()) { + break; + } + std::shared_ptr frameSet = color_frame_queue_.front(); + is_color_frame_decoded_ = decodeColorFrameToBuffer(frameSet->colorFrame(), rgb_buffer_); + onNewFrameCallback(frameSet->colorFrame(), COLOR); + publishPointCloud(frameSet); + color_frame_queue_.pop(); + } + + RCLCPP_INFO_STREAM(logger_, "Color frame thread exit!"); +} + +void OBCameraNode::onNewLeftColorFrameCallback() { + while (enable_stream_[COLOR_LEFT] && rclcpp::ok() && is_running_.load()) { + std::unique_lock lock(left_color_frame_queue_lock_); + left_color_frame_queue_cv_.wait( + lock, [this]() { return !left_color_frame_queue_.empty() || !(is_running_.load()); }); + + if (!rclcpp::ok() || !is_running_.load()) { + break; + } + std::shared_ptr frameSet = left_color_frame_queue_.front(); + is_left_color_frame_decoded_ = + decodeColorFrameToBuffer(frameSet->getFrame(OB_FRAME_COLOR_LEFT), rgb_buffer_left_); + onNewFrameCallback(frameSet->getFrame(OB_FRAME_COLOR_LEFT), COLOR_LEFT); + left_color_frame_queue_.pop(); + } + RCLCPP_INFO_STREAM(logger_, "Left Color frame thread exit!"); +} + +void OBCameraNode::onNewRightColorFrameCallback() { + while (enable_stream_[COLOR_RIGHT] && rclcpp::ok() && is_running_.load()) { + std::unique_lock lock(right_color_frame_queue_lock_); + right_color_frame_queue_cv_.wait( + lock, [this]() { return !right_color_frame_queue_.empty() || !(is_running_.load()); }); + + if (!rclcpp::ok() || !is_running_.load()) { + break; + } + std::shared_ptr frameSet = right_color_frame_queue_.front(); + is_right_color_frame_decoded_ = + decodeColorFrameToBuffer(frameSet->getFrame(OB_FRAME_COLOR_RIGHT), rgb_buffer_right_); + onNewFrameCallback(frameSet->getFrame(OB_FRAME_COLOR_RIGHT), COLOR_RIGHT); + right_color_frame_queue_.pop(); + } + RCLCPP_INFO_STREAM(logger_, "Right Color frame thread exit!"); +} + +std::shared_ptr OBCameraNode::softwareDecodeColorFrame( + const std::shared_ptr &frame, const stream_index_pair &stream_index) { + if (frame == nullptr) { + return nullptr; + } + if (frame->getFormat() == OB_FORMAT_RGB || frame->getFormat() == OB_FORMAT_BGR) { + return frame; + } + if (frame->getFormat() == OB_FORMAT_RGBA || frame->getFormat() == OB_FORMAT_BGRA) { + return frame; + } + if (frame->getFormat() == OB_FORMAT_Y16 || frame->getFormat() == OB_FORMAT_Y8) { + return frame; + } + + ob::FormatConvertFilter *filter = &format_convert_filter_; + if (stream_index == COLOR_LEFT) { + filter = &format_convert_filter_left_; + } else if (stream_index == COLOR_RIGHT) { + filter = &format_convert_filter_right_; + } + + if (!setupFormatConvertType(frame->getFormat(), *filter)) { + RCLCPP_ERROR(logger_, "Unsupported color format: %d", frame->getFormat()); + return nullptr; + } + + std::shared_ptr color_frame; + try { + color_frame = filter->process(frame); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Format convert failed: " << e.getMessage()); + return nullptr; + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Format convert failed: " << e.what()); + return nullptr; + } catch (...) { + RCLCPP_ERROR(logger_, "Format convert failed: unknown error"); + return nullptr; + } + if (color_frame == nullptr) { + RCLCPP_ERROR_SKIPFIRST_THROTTLE(logger_, *(node_->get_clock()), 1000, + "Failed to convert frame to RGB format"); + return nullptr; + } + return color_frame; +} + +bool OBCameraNode::decodeColorFrameToBuffer(const std::shared_ptr &frame, + uint8_t *buffer) { + if (frame == nullptr) { + return false; + } + if (!buffer) { + return false; + } + + stream_index_pair stream_index = COLOR; + switch (frame->getType()) { + case OB_FRAME_COLOR: + stream_index = COLOR; + break; + case OB_FRAME_COLOR_LEFT: + stream_index = COLOR_LEFT; + break; + case OB_FRAME_COLOR_RIGHT: + stream_index = COLOR_RIGHT; + break; + default: + stream_index = COLOR; + break; + } + + bool has_subscriber = false; + if (image_publishers_.count(stream_index) && image_publishers_[stream_index]) { + has_subscriber = image_publishers_[stream_index]->get_subscription_count() > 0; + } + + if (frame->getType() == OB_FRAME_COLOR && enable_colored_point_cloud_ && + depth_registration_cloud_pub_ && + depth_registration_cloud_pub_->get_subscription_count() > 0) { + has_subscriber = true; + } + + if (metadata_publishers_.count(stream_index) && metadata_publishers_[stream_index] && + metadata_publishers_[stream_index]->get_subscription_count() > 0) { + has_subscriber = true; + } + if (camera_info_publishers_.count(stream_index) && camera_info_publishers_[stream_index] && + camera_info_publishers_[stream_index]->get_subscription_count() > 0) { + has_subscriber = true; + } + + if (!has_subscriber) { + return false; + } + + std::shared_ptr decoder; + if (stream_index == COLOR_LEFT) { + decoder = jpeg_decoder_left_; + } else if (stream_index == COLOR_RIGHT) { + decoder = jpeg_decoder_right_; + } else { + decoder = jpeg_decoder_; + } + bool is_decoded = false; + if (!frame) { + return false; + } + +#if defined(USE_RK_HW_DECODER) || defined(USE_NV_HW_DECODER) + if (frame && frame->getFormat() != OB_FORMAT_RGB888) { + if (frame->getFormat() == OB_FORMAT_MJPG && decoder) { + CHECK_NOTNULL(decoder.get()); + CHECK_NOTNULL(buffer); + auto video_frame = frame->as(); + bool ret = false; + if (video_frame && width_.count(stream_index) && height_.count(stream_index) && + static_cast(video_frame->getWidth()) == width_[stream_index] && + static_cast(video_frame->getHeight()) == height_[stream_index]) { + ret = decoder->decode(video_frame, buffer); + } + if (!ret) { + RCLCPP_ERROR_STREAM(logger_, "Decode frame failed"); + is_decoded = false; + + } else { + is_decoded = true; + } + } + } +#endif + if (!is_decoded) { + auto video_frame = softwareDecodeColorFrame(frame, stream_index); + if (!video_frame) { + RCLCPP_ERROR_STREAM(logger_, "Failed to convert frame to video frame"); + return false; + } + CHECK_NOTNULL(buffer); + memcpy(buffer, video_frame->getData(), video_frame->getDataSize()); + return true; + } + return true; +} + +std::shared_ptr OBCameraNode::decodeIRMJPGFrame( + const std::shared_ptr &frame) { + if (frame == nullptr) { + return nullptr; + } + if (frame->getFormat() == OB_FORMAT_MJPEG && + (frame->getType() == OB_FRAME_IR || frame->getType() == OB_FRAME_IR_LEFT || + frame->getType() == OB_FRAME_IR_RIGHT)) { + auto video_frame = frame->as(); + + cv::Mat mjpgMat(1, video_frame->getDataSize(), CV_8UC1, video_frame->getData()); + cv::Mat irRawMat = cv::imdecode(mjpgMat, cv::IMREAD_GRAYSCALE); + + std::shared_ptr irFrame = + ob::FrameFactory::createVideoFrame(video_frame->getType(), video_frame->getFormat(), + video_frame->getWidth(), video_frame->getHeight(), 0); + + uint32_t buffer_size = irRawMat.rows * irRawMat.cols * irRawMat.channels(); + + if (buffer_size > irFrame->getDataSize()) { + RCLCPP_ERROR_STREAM(logger_, + "Insufficient buffer size allocation,failed to decode ir mjpg frame!"); + return nullptr; + } + + memcpy(irFrame->getData(), irRawMat.data, buffer_size); + ob::FrameHelper::setFrameDeviceTimestamp(irFrame, video_frame->getTimeStampUs()); + ob::FrameHelper::setFrameDeviceTimestampUs(irFrame, video_frame->getTimeStampUs()); + ob::FrameHelper::setFrameSystemTimestamp(irFrame, video_frame->getSystemTimeStampUs()); + return irFrame; + } + + return frame; +} + +void OBCameraNode::onNewFrameCallback(const std::shared_ptr &frame, + const stream_index_pair &stream_index) { + if (frame == nullptr) { + return; + } + CHECK_NOTNULL(image_publishers_[stream_index]); + bool has_subscriber = image_publishers_[stream_index]->get_subscription_count() > 0; + has_subscriber = + has_subscriber || camera_info_publishers_[stream_index]->get_subscription_count() > 0; + has_subscriber = + has_subscriber || (metadata_publishers_.count(stream_index) && + metadata_publishers_[stream_index]->get_subscription_count() > 0); + if (!has_subscriber) { + return; + } + std::shared_ptr video_frame; + if (frame->getType() == OB_FRAME_COLOR || frame->getType() == OB_FRAME_COLOR_LEFT || + frame->getType() == OB_FRAME_COLOR_RIGHT) { + video_frame = frame->as(); + } else if (frame->getType() == OB_FRAME_DEPTH) { + video_frame = frame->as(); + } else if (frame->getType() == OB_FRAME_IR || frame->getType() == OB_FRAME_IR_LEFT || + frame->getType() == OB_FRAME_IR_RIGHT) { + video_frame = frame->as(); + + // interleave filter speckle or flood ir + if (interleave_frame_enable_ && interleave_skip_enable_) { + RCLCPP_DEBUG(logger_, "interleave filter skip interleave_skip_index_: %d", + interleave_skip_index_); + if (video_frame->getMetadataValue(OB_FRAME_METADATA_TYPE_HDR_SEQUENCE_INDEX) == + interleave_skip_index_) { + RCLCPP_DEBUG(logger_, "interleave filter skip frame type: %d", frame->getType()); + return; + } + } + } else { + RCLCPP_ERROR(logger_, "Unsupported frame type: %d", frame->getType()); + return; + } + if (!video_frame) { + RCLCPP_ERROR(logger_, "Failed to convert frame to video frame"); + return; + } + int width = static_cast(video_frame->getWidth()); + int height = static_cast(video_frame->getHeight()); + auto frame_timestamp = getFrameTimestampUs(frame); + auto timestamp = fromUsToROSTime(frame_timestamp); + if (!device_) { + RCLCPP_ERROR_STREAM(logger_, "device is null in onNewFrameCallback"); + return; + } + auto device_info = device_->getDeviceInfo(); + if (!device_info || !device_info.get()) { + RCLCPP_ERROR_STREAM(logger_, "device_info is null in onNewFrameCallback"); + return; + } + OBCameraIntrinsic intrinsic; + OBCameraDistortion distortion; + auto stream_profile = frame->getStreamProfile(); + CHECK_NOTNULL(stream_profile); + auto video_stream_profile = stream_profile->as(); + CHECK_NOTNULL(video_stream_profile); + intrinsic = video_stream_profile->getIntrinsic(); + distortion = video_stream_profile->getDistortion(); + if (pid_ == DABAI_MAX_PID) { + auto camera_params = pipeline_->getCameraParam(); + // use color param + intrinsic = camera_params.rgbIntrinsic; + distortion = camera_params.rgbDistortion; + } + std::string frame_id = optical_frame_id_[stream_index]; + if (depth_registration_ && stream_index == DEPTH) { + frame_id = depth_aligned_frame_id_[stream_index]; + } + sensor_msgs::msg::CameraInfo camera_info{}; + if (color_info_manager_ && color_info_manager_->isCalibrated() && stream_index == COLOR) { + camera_info = color_info_manager_->getCameraInfo(); + camera_info.header.stamp = timestamp; + camera_info.header.frame_id = frame_id; + camera_info.width = width; + camera_info.height = height; + } else if (ir_info_manager_ && ir_info_manager_->isCalibrated() && + (stream_index == INFRA1 || stream_index == INFRA2 || stream_index == DEPTH)) { + camera_info = ir_info_manager_->getCameraInfo(); + camera_info.header.stamp = timestamp; + camera_info.header.frame_id = frame_id; + camera_info.width = width; + camera_info.height = height; + } else { + camera_info = convertToCameraInfo(intrinsic, distortion, width); + camera_info.header.stamp = timestamp; + camera_info.header.frame_id = frame_id; + camera_info.width = width; + camera_info.height = height; + } + auto &image = images_[stream_index]; + if (stream_index == COLOR && enable_color_undistortion_) { + auto undistort_result = undistortImage(image, intrinsic, distortion); + sensor_msgs::msg::Image::UniquePtr undistorted_image_msg(new sensor_msgs::msg::Image()); + cv_bridge::CvImage(std_msgs::msg::Header(), encoding_[stream_index], undistort_result.image) + .toImageMsg(*undistorted_image_msg); + CHECK_NOTNULL(undistorted_image_msg.get()); + undistorted_image_msg->header.stamp = timestamp; + undistorted_image_msg->is_bigendian = false; + undistorted_image_msg->step = width * unit_step_size_[stream_index]; + undistorted_image_msg->header.frame_id = frame_id; + color_undistortion_publisher_->publish(std::move(undistorted_image_msg)); + // Update intrinsic with the new camera matrix from undistortion + camera_info.p.at(0) = undistort_result.new_intrinsic.fx; + camera_info.p.at(5) = undistort_result.new_intrinsic.fy; + camera_info.p.at(2) = undistort_result.new_intrinsic.cx; + camera_info.p.at(6) = undistort_result.new_intrinsic.cy; + } + if (frame->getType() == OB_FRAME_IR_RIGHT && enable_stream_[INFRA1]) { + auto stream_profile = frame->getStreamProfile(); + CHECK_NOTNULL(stream_profile); + auto video_stream_profile = stream_profile->as(); + CHECK_NOTNULL(video_stream_profile); + auto left_video_profile = stream_profile_[INFRA1]->as(); + CHECK_NOTNULL(left_video_profile); + auto ex = video_stream_profile->getExtrinsicTo(left_video_profile); + float fx = camera_info.k.at(0); + float fy = camera_info.k.at(4); + camera_info.p.at(3) = -fx * ex.trans[0] / 1000.0 + 0.0; + camera_info.p.at(7) = -fy * ex.trans[1] / 1000.0 + 0.0; + } + CHECK(camera_info_publishers_.count(stream_index) > 0); + camera_info_publishers_[stream_index]->publish(camera_info); + publishMetadata(frame, stream_index, camera_info.header); + CHECK_NOTNULL(image_publishers_[stream_index]); + if (image_publishers_[stream_index]->get_subscription_count() == 0) { + return; + } + if (image.empty() || image.cols != width || image.rows != height) { + image.create(height, width, image_format_[stream_index]); + } + if (frame->getType() == OB_FRAME_COLOR && !is_color_frame_decoded_) { + RCLCPP_ERROR(logger_, "color frame is not decoded"); + return; + } + if (frame->getType() == OB_FRAME_COLOR_LEFT && !is_left_color_frame_decoded_) { + RCLCPP_ERROR(logger_, "left color frame is not decoded"); + return; + } + if (frame->getType() == OB_FRAME_COLOR_RIGHT && !is_right_color_frame_decoded_) { + RCLCPP_ERROR(logger_, "right color frame is not decoded"); + return; + } + if (frame->getType() == OB_FRAME_COLOR && frame->format() != OB_FORMAT_Y8 && + frame->format() != OB_FORMAT_Y16 && frame->format() != OB_FORMAT_BGRA && + frame->format() != OB_FORMAT_RGBA && image_publishers_[COLOR]->get_subscription_count() > 0) { + memcpy(image.data, rgb_buffer_, video_frame->getWidth() * video_frame->getHeight() * 3); + } else if (frame->getType() == OB_FRAME_COLOR_LEFT && frame->format() != OB_FORMAT_Y8 && + frame->format() != OB_FORMAT_Y16 && frame->format() != OB_FORMAT_BGRA && + frame->format() != OB_FORMAT_RGBA && + image_publishers_[COLOR_LEFT]->get_subscription_count() > 0) { + memcpy(image.data, rgb_buffer_left_, video_frame->getWidth() * video_frame->getHeight() * 3); + } else if (frame->getType() == OB_FRAME_COLOR_RIGHT && frame->format() != OB_FORMAT_Y8 && + frame->format() != OB_FORMAT_Y16 && frame->format() != OB_FORMAT_BGRA && + frame->format() != OB_FORMAT_RGBA && + image_publishers_[COLOR_RIGHT]->get_subscription_count() > 0) { + memcpy(image.data, rgb_buffer_right_, video_frame->getWidth() * video_frame->getHeight() * 3); + } else { + memcpy(image.data, video_frame->getData(), video_frame->getDataSize()); + } + + if (stream_index == DEPTH) { + auto depth_scale = video_frame->as()->getValueScale(); + image = image * depth_scale; + } + sensor_msgs::msg::Image::UniquePtr image_msg(new sensor_msgs::msg::Image()); + + cv_bridge::CvImage(std_msgs::msg::Header(), encoding_[stream_index], image) + .toImageMsg(*image_msg); + CHECK_NOTNULL(image_msg.get()); + image_msg->header.stamp = timestamp; + image_msg->is_bigendian = false; + image_msg->step = width * unit_step_size_[stream_index]; + image_msg->header.frame_id = frame_id; + CHECK(image_publishers_.count(stream_index) > 0); + saveImageToFile(stream_index, image, *image_msg); + if (stream_index == COLOR) { + fps_delay_status_color_->tick(frame_timestamp); + } else if (stream_index == DEPTH) { + fps_delay_status_depth_->tick(frame_timestamp); + } + image_publishers_[stream_index]->publish(std::move(image_msg)); +} + +void OBCameraNode::publishMetadata(const std::shared_ptr &frame, + const stream_index_pair &stream_index, + const std_msgs::msg::Header &header) { + if (metadata_publishers_.count(stream_index) == 0) { + return; + } + auto metadata_publisher = metadata_publishers_[stream_index]; + if (metadata_publisher->get_subscription_count() == 0) { + return; + } + orbbec_camera_msgs::msg::Metadata metadata_msg; + metadata_msg.header = header; + nlohmann::json json_data; + + for (int i = 0; i < OB_FRAME_METADATA_TYPE_COUNT; i++) { + auto meta_data_type = static_cast(i); + std::string field_name = metaDataTypeToString(meta_data_type); + if (!frame->hasMetadata(meta_data_type)) { + continue; + } + int64_t value = frame->getMetadataValue(meta_data_type); + json_data[field_name] = value; + } + metadata_msg.json_data = json_data.dump(2); + metadata_publisher->publish(metadata_msg); +} + +void OBCameraNode::saveImageToFile(const stream_index_pair &stream_index, const cv::Mat &image, + const sensor_msgs::msg::Image &image_msg) { + if (save_images_[stream_index]) { + auto now = std::chrono::system_clock::now(); + auto in_time_t = std::chrono::system_clock::to_time_t(now); + auto us = + std::chrono::duration_cast(now.time_since_epoch()) % 1000000; + + std::stringstream ss; + ss << std::put_time(std::localtime(&in_time_t), "%Y%m%d_%H%M%S"); + ss << "_" << std::setw(6) << std::setfill('0') << us.count(); + auto current_path = std::filesystem::current_path().string(); + auto fps = fps_[stream_index]; + int index = save_images_count_[stream_index]; + std::string file_suffix = stream_index == COLOR ? ".png" : ".raw"; + std::string filename = current_path + "/image/" + stream_name_[stream_index] + "_" + + std::to_string(image_msg.width) + "x" + + std::to_string(image_msg.height) + "_" + std::to_string(fps) + "hz_" + + ss.str() + "_" + std::to_string(index) + file_suffix; + if (!std::filesystem::exists(current_path + "/image")) { + std::filesystem::create_directory(current_path + "/image"); + } + RCLCPP_INFO_STREAM(logger_, "Saving image to " << filename); + if (stream_index.first == OB_STREAM_COLOR) { + auto image_to_save = + cv_bridge::toCvCopy(image_msg, sensor_msgs::image_encodings::BGR8)->image; + cv::imwrite(filename, image_to_save); + } else if (stream_index.first == OB_STREAM_IR || stream_index.first == OB_STREAM_IR_LEFT || + stream_index.first == OB_STREAM_IR_RIGHT || stream_index.first == OB_STREAM_DEPTH) { + std::ofstream ofs(filename, std::ios::out | std::ios::binary); + if (!ofs.is_open()) { + RCLCPP_ERROR_STREAM(logger_, "Failed to open file: " << filename); + return; + } + if (image.isContinuous()) { + ofs.write(reinterpret_cast(image.data), image.total() * image.elemSize()); + } else { + int rows = image.rows; + int cols = image.cols * image.channels(); + for (int r = 0; r < rows; ++r) { + ofs.write(reinterpret_cast(image.ptr(r)), cols); + } + } + ofs.close(); + } else { + RCLCPP_ERROR_STREAM(logger_, "Unsupported stream type: " << stream_index.first); + } + if (++save_images_count_[stream_index] >= max_save_images_count_) { + save_images_[stream_index] = false; + } + } +} + +void OBCameraNode::onNewIMUFrameSyncOutputCallback(const std::shared_ptr &accelframe, + const std::shared_ptr &gryoframe) { + if (!is_camera_node_initialized_) { + return; + } + if (!imu_gyro_accel_publisher_) { + RCLCPP_ERROR_STREAM(logger_, "stream Accel Gryo publisher not initialized"); + return; + } + bool has_subscriber = imu_gyro_accel_publisher_->get_subscription_count() > 0; + has_subscriber = has_subscriber || imu_info_publishers_[GYRO]->get_subscription_count() > 0; + has_subscriber = has_subscriber || imu_info_publishers_[ACCEL]->get_subscription_count() > 0; + if (!has_subscriber) { + return; + } + auto imu_msg = sensor_msgs::msg::Imu(); + setDefaultIMUMessage(imu_msg); + + imu_msg.header.frame_id = optical_frame_id_[GYRO]; + auto frame_timestamp = getFrameTimestampUs(accelframe); + auto timestamp = fromUsToROSTime(frame_timestamp); + imu_msg.header.stamp = timestamp; + + auto gyro_info = createIMUInfo(GYRO); + gyro_info.header = imu_msg.header; + imu_info_publishers_[GYRO]->publish(gyro_info); + + auto accel_info = createIMUInfo(ACCEL); + imu_msg.header.frame_id = optical_frame_id_[ACCEL]; + accel_info.header = imu_msg.header; + imu_info_publishers_[ACCEL]->publish(accel_info); + + imu_msg.header.frame_id = accel_gyro_frame_id_; + + auto gyro_frame = gryoframe->as(); + auto gyroData = gyro_frame->getValue(); + imu_msg.angular_velocity.x = gyroData.x - gyro_info.bias[0]; + imu_msg.angular_velocity.y = gyroData.y - gyro_info.bias[1]; + imu_msg.angular_velocity.z = gyroData.z - gyro_info.bias[2]; + + auto accel_frame = accelframe->as(); + auto accelData = accel_frame->getValue(); + imu_msg.linear_acceleration.x = accelData.x - accel_info.bias[0]; + imu_msg.linear_acceleration.y = accelData.y - accel_info.bias[1]; + imu_msg.linear_acceleration.z = accelData.z - accel_info.bias[2]; + + imu_gyro_accel_publisher_->publish(imu_msg); +} + +void OBCameraNode::onNewIMUFrameCallback(const std::shared_ptr &frame, + const stream_index_pair &stream_index) { + if (!is_camera_node_initialized_) { + return; + } + if (!imu_publishers_.count(stream_index)) { + RCLCPP_ERROR_STREAM(logger_, + "stream " << stream_name_[stream_index] << " publisher not initialized"); + return; + } + bool has_subscriber = imu_publishers_[stream_index]->get_subscription_count() > 0; + has_subscriber = + has_subscriber || imu_info_publishers_[stream_index]->get_subscription_count() > 0; + if (!has_subscriber) { + return; + } + auto imu_msg = sensor_msgs::msg::Imu(); + setDefaultIMUMessage(imu_msg); + + imu_msg.header.frame_id = optical_frame_id_[stream_index]; + auto timestamp = fromUsToROSTime(frame->getTimeStampUs()); + imu_msg.header.stamp = timestamp; + + auto imu_info = createIMUInfo(stream_index); + imu_info.header = imu_msg.header; + imu_info_publishers_[stream_index]->publish(imu_info); + + if (frame->getType() == OB_FRAME_GYRO) { + auto gyro_frame = frame->as(); + auto data = gyro_frame->getValue(); + imu_msg.angular_velocity.x = data.x - imu_info.bias[0]; + imu_msg.angular_velocity.y = data.y - imu_info.bias[1]; + imu_msg.angular_velocity.z = data.z - imu_info.bias[2]; + } else if (frame->getType() == OB_FRAME_ACCEL) { + auto accel_frame = frame->as(); + auto data = accel_frame->getValue(); + imu_msg.linear_acceleration.x = data.x - imu_info.bias[0]; + imu_msg.linear_acceleration.y = data.y - imu_info.bias[1]; + imu_msg.linear_acceleration.z = data.z - imu_info.bias[2]; + } else { + RCLCPP_ERROR(logger_, "Unsupported IMU frame type"); + return; + } + imu_publishers_[stream_index]->publish(imu_msg); +} + +void OBCameraNode::setDefaultIMUMessage(sensor_msgs::msg::Imu &imu_msg) { + imu_msg.header.frame_id = "imu_link"; + imu_msg.orientation.x = 0.0; + imu_msg.orientation.y = 0.0; + imu_msg.orientation.z = 0.0; + imu_msg.orientation.w = 1.0; + + imu_msg.orientation_covariance = {-1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + imu_msg.linear_acceleration_covariance = { + linear_accel_cov_, 0.0, 0.0, 0.0, linear_accel_cov_, 0.0, 0.0, 0.0, linear_accel_cov_}; + imu_msg.angular_velocity_covariance = { + angular_vel_cov_, 0.0, 0.0, 0.0, angular_vel_cov_, 0.0, 0.0, 0.0, angular_vel_cov_}; +} + +sensor_msgs::msg::Imu OBCameraNode::createUnitIMUMessage(const IMUData &accel_data, + const IMUData &gyro_data) { + sensor_msgs::msg::Imu imu_msg; + rclcpp::Time timestamp(gyro_data.timestamp_); + imu_msg.header.stamp = timestamp; + imu_msg.angular_velocity.x = gyro_data.data_.x(); + imu_msg.angular_velocity.y = gyro_data.data_.y(); + imu_msg.angular_velocity.z = gyro_data.data_.z(); + + imu_msg.linear_acceleration.x = accel_data.data_.x(); + imu_msg.linear_acceleration.y = accel_data.data_.y(); + imu_msg.linear_acceleration.z = accel_data.data_.z(); + return imu_msg; +} + +std::optional OBCameraNode::findDefaultCameraParam() { + auto camera_params = device_->getCalibrationCameraParamList(); + for (size_t i = 0; i < camera_params->count(); i++) { + auto param = camera_params->getCameraParam(i); + int depth_w = param.depthIntrinsic.width; + int depth_h = param.depthIntrinsic.height; + int color_w = param.rgbIntrinsic.width; + int color_h = param.rgbIntrinsic.height; + if ((depth_w * height_[DEPTH] == depth_h * width_[DEPTH]) && + (color_w * height_[COLOR] == color_h * width_[COLOR])) { + return param; + } + } + return {}; +} + +std::optional OBCameraNode::getDepthCameraParam() { + auto camera_params = device_->getCalibrationCameraParamList(); + for (size_t i = 0; i < camera_params->count(); i++) { + auto param = camera_params->getCameraParam(i); + int depth_w = param.depthIntrinsic.width; + int depth_h = param.depthIntrinsic.height; + if (depth_w == width_[DEPTH] && depth_h == height_[DEPTH]) { + RCLCPP_INFO_STREAM(logger_, "getCameraDepthParam w: " << depth_w << ",h:" << depth_h); + return param; + } + } + + for (size_t i = 0; i < camera_params->count(); i++) { + auto param = camera_params->getCameraParam(i); + int depth_w = param.depthIntrinsic.width; + int depth_h = param.depthIntrinsic.height; + if (depth_w * height_[DEPTH] == depth_h * width_[DEPTH]) { + RCLCPP_INFO_STREAM(logger_, "getCameraDepthParam w: " << depth_w << ",h:" << depth_h); + return param; + } + } + return {}; +} + +std::optional OBCameraNode::getColorCameraParam() { + auto camera_params = device_->getCalibrationCameraParamList(); + for (size_t i = 0; i < camera_params->count(); i++) { + auto param = camera_params->getCameraParam(i); + int color_w = param.rgbIntrinsic.width; + int color_h = param.rgbIntrinsic.height; + if (color_w == width_[COLOR] && color_h == height_[COLOR]) { + RCLCPP_INFO_STREAM(logger_, "getColorCameraParam w: " << color_w << ",h:" << color_h); + return param; + } + } + + for (size_t i = 0; i < camera_params->count(); i++) { + auto param = camera_params->getCameraParam(i); + int color_w = param.rgbIntrinsic.width; + int color_h = param.rgbIntrinsic.height; + if (color_w * height_[COLOR] == color_h * width_[COLOR]) { + RCLCPP_INFO_STREAM(logger_, "getColorCameraParam w: " << color_w << ",h:" << color_h); + return param; + } + } + return {}; +} + +void OBCameraNode::publishStaticTF(const rclcpp::Time &t, const tf2::Vector3 &trans, + const tf2::Quaternion &q, const std::string &from, + const std::string &to) { + geometry_msgs::msg::TransformStamped msg; + msg.header.stamp = t; + msg.header.frame_id = from; + msg.child_frame_id = to; + msg.transform.translation.x = trans[2] / 1000.0; + msg.transform.translation.y = -trans[0] / 1000.0; + msg.transform.translation.z = -trans[1] / 1000.0; + msg.transform.rotation.x = q.getX(); + msg.transform.rotation.y = q.getY(); + msg.transform.rotation.z = q.getZ(); + msg.transform.rotation.w = q.getW(); + static_tf_msgs_.push_back(msg); +} + +void OBCameraNode::calcAndPublishStaticTransform() { + tf2::Quaternion quaternion_optical, zero_rot; + zero_rot.setRPY(0.0, 0.0, 0.0); + quaternion_optical.setRPY(-M_PI / 2, 0.0, -M_PI / 2); + tf2::Vector3 zero_trans(0, 0, 0); + auto base_stream_profile = stream_profile_[base_stream_]; + auto device_info = device_->getDeviceInfo(); + CHECK_NOTNULL(device_info); + if (!base_stream_profile) { + RCLCPP_ERROR_STREAM(logger_, "Failed to get base stream profile"); + return; + } + CHECK_NOTNULL(base_stream_profile.get()); + for (const auto &item : stream_profile_) { + auto stream_index = item.first; + + auto stream_profile = item.second; + if (!stream_profile) { + continue; + } + OBExtrinsic ex; + try { + ex = stream_profile->getExtrinsicTo(base_stream_profile); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to get " << stream_name_[stream_index] + << " extrinsic: " << e.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + + auto Q = rotationMatrixToQuaternion(ex.rot); + Q = quaternion_optical * Q * quaternion_optical.inverse(); + tf2::Vector3 trans(ex.trans[0], ex.trans[1], ex.trans[2]); + auto timestamp = node_->now(); + if (stream_index.first != base_stream_.first) { + if (stream_index.first == OB_STREAM_IR_RIGHT && base_stream_.first == OB_STREAM_DEPTH) { + trans[0] = std::abs(trans[0]); // because left and right ir calibration is error + } + publishStaticTF(timestamp, trans, Q, frame_id_[base_stream_], frame_id_[stream_index]); + } + publishStaticTF(timestamp, zero_trans, quaternion_optical, frame_id_[stream_index], + optical_frame_id_[stream_index]); + RCLCPP_INFO_STREAM(logger_, "Publishing static transform from " << stream_name_[stream_index] + << " to " + << stream_name_[base_stream_]); + RCLCPP_INFO_STREAM(logger_, "Translation " << trans[0] << ", " << trans[1] << ", " << trans[2]); + RCLCPP_INFO_STREAM(logger_, "Rotation " << Q.getX() << ", " << Q.getY() << ", " << Q.getZ() + << ", " << Q.getW()); + } + + if ((pid_ == FEMTO_BOLT_PID || pid_ == FEMTO_MEGA_PID) && enable_stream_[DEPTH] && + enable_stream_[COLOR]) { + // calc depth to color + + CHECK_NOTNULL(stream_profile_[COLOR]); + auto depth_to_color_extrinsics = base_stream_profile->getExtrinsicTo(stream_profile_[COLOR]); + auto Q = rotationMatrixToQuaternion(depth_to_color_extrinsics.rot); + Q = quaternion_optical * Q * quaternion_optical.inverse(); + publishStaticTF(node_->now(), zero_trans, Q, camera_link_frame_id_, frame_id_[base_stream_]); + } else { + publishStaticTF(node_->now(), zero_trans, zero_rot, camera_link_frame_id_, + frame_id_[base_stream_]); + } + + if (enable_stream_[DEPTH] && enable_stream_[COLOR] && enable_publish_extrinsic_) { + static const char *frame_id = "depth_to_color_extrinsics"; + OBExtrinsic ex; + try { + ex = base_stream_profile->getExtrinsicTo(stream_profile_[COLOR]); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, + "Failed to get " << frame_id << " extrinsic: " << e.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + depth_to_other_extrinsics_[COLOR] = ex; + auto ex_msg = obExtrinsicsToMsg(ex, frame_id); + CHECK_NOTNULL(depth_to_other_extrinsics_publishers_[COLOR]); + depth_to_other_extrinsics_publishers_[COLOR]->publish(ex_msg); + } + + if (enable_stream_[DEPTH] && enable_stream_[INFRA0] && enable_publish_extrinsic_) { + static const char *frame_id = "depth_to_ir_extrinsics"; + OBExtrinsic ex; + try { + ex = base_stream_profile->getExtrinsicTo(stream_profile_[INFRA0]); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, + "Failed to get " << frame_id << " extrinsic: " << e.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + depth_to_other_extrinsics_[INFRA0] = ex; + auto ex_msg = obExtrinsicsToMsg(ex, frame_id); + CHECK_NOTNULL(depth_to_other_extrinsics_publishers_[INFRA0]); + depth_to_other_extrinsics_publishers_[INFRA0]->publish(ex_msg); + } + if (enable_stream_[DEPTH] && enable_stream_[INFRA1] && enable_publish_extrinsic_) { + static const char *frame_id = "depth_to_left_ir_extrinsics"; + OBExtrinsic ex; + try { + ex = base_stream_profile->getExtrinsicTo(stream_profile_[INFRA1]); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, + "Failed to get " << frame_id << " extrinsic: " << e.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + depth_to_other_extrinsics_[INFRA1] = ex; + auto ex_msg = obExtrinsicsToMsg(ex, frame_id); + CHECK_NOTNULL(depth_to_other_extrinsics_publishers_[INFRA1]); + depth_to_other_extrinsics_publishers_[INFRA1]->publish(ex_msg); + } + if (enable_stream_[DEPTH] && enable_stream_[INFRA2] && enable_publish_extrinsic_) { + static const char *frame_id = "depth_to_right_ir_extrinsics"; + OBExtrinsic ex; + try { + ex = base_stream_profile->getExtrinsicTo(stream_profile_[INFRA2]); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, + "Failed to get " << frame_id << " extrinsic: " << e.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + ex.trans[0] = -std::abs(ex.trans[0]); + depth_to_other_extrinsics_[INFRA2] = ex; + auto ex_msg = obExtrinsicsToMsg(ex, frame_id); + CHECK_NOTNULL(depth_to_other_extrinsics_publishers_[INFRA2]); + depth_to_other_extrinsics_publishers_[INFRA2]->publish(ex_msg); + } + if (enable_stream_[DEPTH] && enable_stream_[ACCEL] && enable_publish_extrinsic_) { + static const char *frame_id = "depth_to_accel_extrinsics"; + OBExtrinsic ex; + try { + ex = base_stream_profile->getExtrinsicTo(stream_profile_[ACCEL]); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, + "Failed to get " << frame_id << " extrinsic: " << e.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + depth_to_other_extrinsics_[ACCEL] = ex; + auto ex_msg = obExtrinsicsToMsg(ex, frame_id); + CHECK_NOTNULL(depth_to_other_extrinsics_publishers_[ACCEL]); + depth_to_other_extrinsics_publishers_[ACCEL]->publish(ex_msg); + } + if (enable_stream_[DEPTH] && enable_stream_[GYRO] && enable_publish_extrinsic_) { + static const char *frame_id = "depth_to_gyro_extrinsics"; + OBExtrinsic ex; + try { + ex = base_stream_profile->getExtrinsicTo(stream_profile_[GYRO]); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, + "Failed to get " << frame_id << " extrinsic: " << e.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + depth_to_other_extrinsics_[GYRO] = ex; + auto ex_msg = obExtrinsicsToMsg(ex, frame_id); + CHECK_NOTNULL(depth_to_other_extrinsics_publishers_[GYRO]); + depth_to_other_extrinsics_publishers_[GYRO]->publish(ex_msg); + } + if (enable_stream_[COLOR_LEFT] && enable_stream_[COLOR_RIGHT] && enable_publish_extrinsic_) { + static const char *frame_id = "left_color_to_right_color_extrinsics"; + OBExtrinsic ex; + try { + ex = stream_profile_[COLOR_LEFT]->getExtrinsicTo(stream_profile_[COLOR_RIGHT]); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, + "Failed to get " << frame_id << " extrinsic: " << e.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + depth_to_other_extrinsics_[COLOR_LEFT] = ex; + auto ex_msg = obExtrinsicsToMsg(ex, frame_id); + CHECK_NOTNULL(depth_to_other_extrinsics_publishers_[COLOR_LEFT]); + depth_to_other_extrinsics_publishers_[COLOR_LEFT]->publish(ex_msg); + } + if (enable_sync_output_accel_gyro_) { + tf2::Quaternion zero_rot; + zero_rot.setRPY(0.0, 0.0, 0.0); + tf2::Vector3 zero_trans(0, 0, 0); + publishStaticTF(node_->now(), zero_trans, zero_rot, optical_frame_id_[GYRO], + accel_gyro_frame_id_); + } +} + +void OBCameraNode::publishStaticTransforms() { + if (!publish_tf_) { + return; + } + static_tf_broadcaster_ = std::make_shared(node_); + dynamic_tf_broadcaster_ = std::make_shared(node_); + calcAndPublishStaticTransform(); + if (tf_publish_rate_ > 0) { + tf_thread_ = std::make_shared([this]() { publishDynamicTransforms(); }); + } else { + static_tf_broadcaster_->sendTransform(static_tf_msgs_); + } +} + +void OBCameraNode::publishDynamicTransforms() { + RCLCPP_WARN(logger_, "Publishing dynamic camera transforms (/tf) at %g Hz", tf_publish_rate_); + std::mutex mu; + std::unique_lock lock(mu); + while (rclcpp::ok() && is_running_) { + tf_cv_.wait_for(lock, std::chrono::milliseconds((int)(1000.0 / tf_publish_rate_)), + [this] { return (!(is_running_)); }); + { + rclcpp::Time t = node_->now(); + for (auto &msg : static_tf_msgs_) { + msg.header.stamp = t; + } + dynamic_tf_broadcaster_->sendTransform(static_tf_msgs_); + } + } +} + +template +T lerp(const T &a, const T &b, const double t) { + return a * (1.0 - t) + b * t; +} + +void OBCameraNode::FillImuDataLinearInterpolation(const IMUData &imu_data, + std::deque &imu_msgs) { + imu_history_.push_back(imu_data); + stream_index_pair steam_index(imu_data.stream_); + imu_msgs.clear(); + std::deque gyros_data; + IMUData accel0, accel1, current_imu; + while (!imu_history_.empty()) { + current_imu = imu_history_.front(); + imu_history_.pop_front(); + if (accel0.isSet() && current_imu.stream_ == ACCEL) { + accel0 = current_imu; + } else if (accel0.isSet() && current_imu.stream_ == ACCEL) { + accel1 = current_imu; + const double dt = accel1.timestamp_ - accel0.timestamp_; + while (!gyros_data.empty()) { + auto current_gyro = gyros_data.front(); + gyros_data.pop_front(); + const double alpha = (current_gyro.timestamp_ - accel0.timestamp_) / dt; + IMUData current_accel(ACCEL, lerp(accel0.data_, accel1.data_, alpha), + current_gyro.timestamp_); + imu_msgs.push_back((createUnitIMUMessage(current_accel, current_gyro))); + } + accel0 = accel1; + } else if (accel0.isSet() && current_imu.timestamp_ >= accel0.timestamp_ && + current_imu.stream_ == GYRO) { + gyros_data.push_back(current_imu); + } + } + imu_history_.push_back(current_imu); +} + +void OBCameraNode::FillImuDataCopy(const IMUData &imu_data, + std::deque &imu_msgs) { + stream_index_pair steam_index(imu_data.stream_); + if (steam_index == ACCEL) { + accel_data_ = imu_data; + return; + } + if (accel_data_.isSet()) { + return; + } + imu_msgs.push_back(createUnitIMUMessage(accel_data_, imu_data)); +} + +bool OBCameraNode::setupFormatConvertType(OBFormat format) { + return setupFormatConvertType(format, format_convert_filter_); +} + +bool OBCameraNode::setupFormatConvertType(OBFormat format, ob::FormatConvertFilter &filter) { + switch (format) { + case OB_FORMAT_RGB888: + return true; + case OB_FORMAT_I420: + filter.setFormatConvertType(FORMAT_I420_TO_RGB888); + break; + case OB_FORMAT_MJPG: + filter.setFormatConvertType(FORMAT_MJPEG_TO_RGB888); + break; + case OB_FORMAT_YUYV: + filter.setFormatConvertType(FORMAT_YUYV_TO_RGB888); + break; + case OB_FORMAT_NV21: + filter.setFormatConvertType(FORMAT_NV21_TO_RGB888); + break; + case OB_FORMAT_NV12: + filter.setFormatConvertType(FORMAT_NV12_TO_RGB888); + break; + case OB_FORMAT_UYVY: + filter.setFormatConvertType(FORMAT_UYVY_TO_RGB888); + break; + default: + return false; + } + return true; +} + +bool OBCameraNode::isGemini335PID(uint32_t pid) { + return pid == GEMINI_335_PID || pid == GEMINI_330_PID || pid == GEMINI_336_PID || + pid == GEMINI_335L_PID || pid == GEMINI_330L_PID || pid == GEMINI_336L_PID || + pid == GEMINI_335LG_PID || pid == GEMINI_336LG_PID || pid == GEMINI_335LE_PID || + pid == GEMINI_336LE_PID || pid == CUSTOM_ADVANTECH_GEMINI_336_PID || + pid == CUSTOM_ADVANTECH_GEMINI_336L_PID || pid == GEMINI_338_PID; +} + +bool OBCameraNode::isGemini435LePID(uint32_t pid) { return pid == GEMINI_435Le_PID; } +bool OBCameraNode::isPublishMetaData(uint32_t pid) { + return isGemini335PID(pid) || isGemini435LePID(pid) || pid == GEMINI_305_PID; +} + +bool OBCameraNode::isDepthWorkModeDevices(uint32_t pid) { return pid == GEMINI_435Le_PID; } + +bool OBCameraNode::isnotLaserDevices(uint32_t pid) { return pid == GEMINI_305_PID; } + +orbbec_camera_msgs::msg::IMUInfo OBCameraNode::createIMUInfo( + const stream_index_pair &stream_index) { + orbbec_camera_msgs::msg::IMUInfo imu_info; + imu_info.header.frame_id = optical_frame_id_[stream_index]; + imu_info.header.stamp = node_->now(); + + if (stream_index == GYRO) { + auto gyro_profile = stream_profile_[stream_index]->as(); + auto gyro_intrinsics = gyro_profile->getIntrinsic(); + imu_info.noise_density = gyro_intrinsics.noiseDensity; + imu_info.random_walk = gyro_intrinsics.randomWalk; + imu_info.reference_temperature = gyro_intrinsics.referenceTemp; + imu_info.bias = {gyro_intrinsics.bias[0], gyro_intrinsics.bias[1], gyro_intrinsics.bias[2]}; + imu_info.scale_misalignment = { + gyro_intrinsics.scaleMisalignment[0], gyro_intrinsics.scaleMisalignment[1], + gyro_intrinsics.scaleMisalignment[2], gyro_intrinsics.scaleMisalignment[3], + gyro_intrinsics.scaleMisalignment[4], gyro_intrinsics.scaleMisalignment[5], + gyro_intrinsics.scaleMisalignment[6], gyro_intrinsics.scaleMisalignment[7], + gyro_intrinsics.scaleMisalignment[8]}; + imu_info.temperature_slope = { + gyro_intrinsics.tempSlope[0], gyro_intrinsics.tempSlope[1], gyro_intrinsics.tempSlope[2], + gyro_intrinsics.tempSlope[3], gyro_intrinsics.tempSlope[4], gyro_intrinsics.tempSlope[5], + gyro_intrinsics.tempSlope[6], gyro_intrinsics.tempSlope[7], gyro_intrinsics.tempSlope[8]}; + } else if (stream_index == ACCEL) { + auto accel_profile = stream_profile_[stream_index]->as(); + auto accel_intrinsics = accel_profile->getIntrinsic(); + imu_info.noise_density = accel_intrinsics.noiseDensity; + imu_info.random_walk = accel_intrinsics.randomWalk; + imu_info.reference_temperature = accel_intrinsics.referenceTemp; + imu_info.bias = {accel_intrinsics.bias[0], accel_intrinsics.bias[1], accel_intrinsics.bias[2]}; + imu_info.gravity = {accel_intrinsics.gravity[0], accel_intrinsics.gravity[1], + accel_intrinsics.gravity[2]}; + imu_info.scale_misalignment = { + accel_intrinsics.scaleMisalignment[0], accel_intrinsics.scaleMisalignment[1], + accel_intrinsics.scaleMisalignment[2], accel_intrinsics.scaleMisalignment[3], + accel_intrinsics.scaleMisalignment[4], accel_intrinsics.scaleMisalignment[5], + accel_intrinsics.scaleMisalignment[6], accel_intrinsics.scaleMisalignment[7], + accel_intrinsics.scaleMisalignment[8]}; + imu_info.temperature_slope = {accel_intrinsics.tempSlope[0], accel_intrinsics.tempSlope[1], + accel_intrinsics.tempSlope[2], accel_intrinsics.tempSlope[3], + accel_intrinsics.tempSlope[4], accel_intrinsics.tempSlope[5], + accel_intrinsics.tempSlope[6], accel_intrinsics.tempSlope[7], + accel_intrinsics.tempSlope[8]}; + } + + return imu_info; +} +void OBCameraNode::setFilterCallback(const std::shared_ptr &request, + std::shared_ptr &response) { + try { + RCLCPP_INFO_STREAM(logger_, "filter_name: " << request->filter_name << " filter_enable: " + << (request->filter_enable ? "true" : "false")); + auto it = std::remove_if(depth_filter_list_.begin(), depth_filter_list_.end(), + [&request](const std::shared_ptr &filter) { + return filter->getName() == request->filter_name; + }); + depth_filter_list_.erase(it, depth_filter_list_.end()); + if (request->filter_name == "DecimationFilter") { + auto decimation_filter = std::make_shared(); + decimation_filter->enable(request->filter_enable); + depth_filter_list_.push_back(decimation_filter); + if (request->filter_param.size() > 0) { + auto range = decimation_filter->getScaleRange(); + auto decimation_filter_scale = request->filter_param[0]; + if (decimation_filter_scale <= range.max && decimation_filter_scale >= range.min) { + RCLCPP_INFO_STREAM(logger_, + "Set decimation filter scale value to " << decimation_filter_scale); + decimation_filter->setScaleValue(decimation_filter_scale); + } + if (decimation_filter_scale != -1 && + (decimation_filter_scale < range.min || decimation_filter_scale > range.max)) { + RCLCPP_ERROR_STREAM(logger_, "Decimation filter scale value is out of range " + << range.min << " - " << range.max); + } + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + + } else if (request->filter_name == "HDRMerge") { + auto hdr_merge_filter = std::make_shared(); + hdr_merge_filter->enable(request->filter_enable); + depth_filter_list_.push_back(hdr_merge_filter); + if (request->filter_param.size() > 3) { + auto config = OBHdrConfig(); + config.enable = true; + config.exposure_1 = request->filter_param[0]; + config.gain_1 = request->filter_param[1]; + config.exposure_2 = request->filter_param[2]; + config.gain_2 = request->filter_param[3]; + device_->setStructuredData(OB_STRUCT_DEPTH_HDR_CONFIG, + reinterpret_cast(&config), sizeof(config)); + RCLCPP_INFO_STREAM(logger_, "Set HDR merge filter params: " + << "\nexposure_1: " << request->filter_param[0] + << "\ngain_1: " << request->filter_param[1] + << "\nexposure_2: " << request->filter_param[2] + << "\ngain_2: " << request->filter_param[3]); + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + + } else if (request->filter_name == "SequenceIdFilter") { + auto sequenced_filter = std::make_shared(); + sequenced_filter->enable(request->filter_enable); + depth_filter_list_.push_back(sequenced_filter); + if (request->filter_param.size() > 0) { + sequenced_filter->selectSequenceId(request->filter_param[0]); + RCLCPP_INFO_STREAM( + logger_, "Set sequenced filter selectSequenceId value to " << request->filter_param[0]); + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + + } else if (request->filter_name == "ThresholdFilter") { + auto threshold_filter = std::make_shared(); + threshold_filter->enable(request->filter_enable); + depth_filter_list_.push_back(threshold_filter); + if (request->filter_param.size() > 1) { + auto threshold_filter_min = request->filter_param[0]; + auto threshold_filter_max = request->filter_param[1]; + threshold_filter->setValueRange(threshold_filter_min, threshold_filter_max); + RCLCPP_INFO_STREAM(logger_, "Set threshold filter value range to " + << threshold_filter_min << " - " << threshold_filter_max); + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + + } else if (request->filter_name == "NoiseRemovalFilter") { + if (device_->isPropertySupported(OB_PROP_DEPTH_SOFT_FILTER_BOOL, OB_PERMISSION_READ_WRITE)) { + device_->setBoolProperty(OB_PROP_DEPTH_SOFT_FILTER_BOOL, request->filter_enable); + } + if (request->filter_param.size() > 1) { + if (device_->isPropertySupported(OB_PROP_DEPTH_MAX_DIFF_INT, OB_PERMISSION_WRITE)) { + auto default_noise_removal_filter_min_diff = + device_->getIntProperty(OB_PROP_DEPTH_MAX_DIFF_INT); + RCLCPP_INFO_STREAM(logger_, "default noise removal filter min diff: " + << default_noise_removal_filter_min_diff); + device_->setIntProperty(OB_PROP_DEPTH_MAX_DIFF_INT, request->filter_param[0]); + auto new_noise_removal_filter_min_diff = + device_->getIntProperty(OB_PROP_DEPTH_MAX_DIFF_INT); + RCLCPP_INFO_STREAM(logger_, "after set noise removal filter min diff: " + << new_noise_removal_filter_min_diff); + } + if (device_->isPropertySupported(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT, OB_PERMISSION_WRITE)) { + auto default_noise_removal_filter_max_size = + device_->getIntProperty(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT); + RCLCPP_INFO_STREAM(logger_, "default noise removal filter max size: " + << default_noise_removal_filter_max_size); + device_->setIntProperty(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT, request->filter_param[1]); + auto new_noise_removal_filter_max_size = + device_->getIntProperty(OB_PROP_DEPTH_MAX_SPECKLE_SIZE_INT); + RCLCPP_INFO_STREAM(logger_, "after set noise removal filter max size: " + << new_noise_removal_filter_max_size); + } + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + } else if (request->filter_name == "HardwareNoiseRemoval") { + if (device_->isPropertySupported(OB_PROP_HW_NOISE_REMOVE_FILTER_ENABLE_BOOL, + OB_PERMISSION_READ_WRITE)) { + device_->setBoolProperty(OB_PROP_HW_NOISE_REMOVE_FILTER_ENABLE_BOOL, + request->filter_enable); + if (request->filter_param.size() > 0 && + device_->isPropertySupported(OB_PROP_HW_NOISE_REMOVE_FILTER_THRESHOLD_FLOAT, + OB_PERMISSION_READ_WRITE)) { + if (request->filter_enable) { + device_->setFloatProperty(OB_PROP_HW_NOISE_REMOVE_FILTER_THRESHOLD_FLOAT, + request->filter_param[0]); + RCLCPP_INFO_STREAM(logger_, "Setting hardware noise removal filter threshold :" + << request->filter_param[0]); + } + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + } + } else if (request->filter_name == "SpatialAdvancedFilter") { + auto spatial_filter = std::make_shared(); + spatial_filter->enable(request->filter_enable); + depth_filter_list_.push_back(spatial_filter); + if (request->filter_param.size() > 3) { + OBSpatialAdvancedFilterParams params{}; + params.alpha = request->filter_param[0]; + params.disp_diff = request->filter_param[1]; + params.magnitude = request->filter_param[2]; + params.radius = request->filter_param[3]; + spatial_filter->setFilterParams(params); + RCLCPP_INFO_STREAM(logger_, "Set spatial filter params: " + << "\nalpha:" << params.alpha << "\nradius:" + << params.radius << "\ndisp_diff:" << params.disp_diff); + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + } else if (request->filter_name == "TemporalFilter") { + auto temporal_filter = std::make_shared(); + temporal_filter->enable(request->filter_enable); + depth_filter_list_.push_back(temporal_filter); + if (request->filter_param.size() > 1) { + temporal_filter->setDiffScale(request->filter_param[0]); + temporal_filter->setWeight(request->filter_param[1]); + RCLCPP_INFO_STREAM(logger_, "Set temporal filter value to " << request->filter_param[0] + << " - " + << request->filter_param[1]); + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + } else if (request->filter_name == "SpatialFastFilter") { + auto spatial_fast_filter = std::make_shared(); + spatial_fast_filter->enable(request->filter_enable); + depth_filter_list_.push_back(spatial_fast_filter); + if (request->filter_param.size() > 0) { + OBSpatialFastFilterParams params{}; + params.radius = request->filter_param[0]; + spatial_fast_filter->setFilterParams(params); + RCLCPP_INFO_STREAM(logger_, "Set SpatialFastFilter radius to " << params.radius); + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + + } else if (request->filter_name == "SpatialModerateFilter") { + auto spatial_moderate_filter = std::make_shared(); + spatial_moderate_filter->enable(request->filter_enable); + depth_filter_list_.push_back(spatial_moderate_filter); + if (request->filter_param.size() > 2) { + OBSpatialModerateFilterParams params{}; + params.disp_diff = request->filter_param[0]; + params.magnitude = request->filter_param[1]; + params.radius = request->filter_param[2]; + spatial_moderate_filter->setFilterParams(params); + RCLCPP_INFO_STREAM(logger_, "Set SpatialModerateFilter params: " + << "\ndisp_diff:" << params.disp_diff << "\nmagnitude:" + << params.magnitude << "\nradius:" << params.radius); + } else { + response->message = + "The filter switch setting is successful, but the filter parameter setting fails"; + return; + } + } else if (request->filter_name == "FalsePositiveFilter") { + auto false_positive_filter = std::make_shared(); + false_positive_filter->enable(request->filter_enable); + depth_filter_list_.push_back(false_positive_filter); + } else { + RCLCPP_INFO_STREAM(logger_, + request->filter_name + << "Cannot be set\n" + << "The filter_name value that can be set is " + "DecimationFilter, HDRMerge, SequenceIdFilter, ThresholdFilter, " + "NoiseRemovalFilter, HardwareNoiseRemoval, SpatialAdvancedFilter, " + "SpatialFastFilter, SpatialModerateFilter, FalsePositiveFilter and " + "TemporalFilter"); + return; + } + for (auto &filter : depth_filter_list_) { + std::cout << " - " << filter->getName() << ": " + << (filter->isEnabled() ? "enabled" : "disabled") << std::endl; + auto configSchemaVec = filter->getConfigSchemaVec(); + for (auto &configSchema : configSchemaVec) { + std::cout << " - {" << configSchema.name << ", " << configSchema.type << ", " + << configSchema.min << ", " << configSchema.max << ", " << configSchema.step + << ", " << configSchema.def << ", " << configSchema.desc << "}" << std::endl; + } + } + response->success = true; + } catch (const ob::Error &e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception &e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} +bool OBCameraNode::isWriteCustomerDataSuccess() const { + return write_customer_data_success_.load(); +} +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/src/ob_camera_node_driver.cpp b/dev_ws/src/orbbec_camera/src/ob_camera_node_driver.cpp new file mode 100644 index 0000000..0fd3f68 --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/ob_camera_node_driver.cpp @@ -0,0 +1,1550 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "orbbec_camera/ob_camera_node_driver.h" +#include "orbbec_camera/utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include // For std::put_time +#include + +std::string g_camera_name = "orbbec_camera"; // Assuming this is declared elsewhere +std::string g_time_domain = "global"; // Assuming this is declared elsewhere + +void signalHandler(int sig) { + // Prevent recursive signal handling + static std::atomic in_signal_handler{false}; + if (in_signal_handler.exchange(true)) { + // Already in signal handler, force exit immediately + _exit(sig); + } + + std::cout << "Received signal: " << sig << std::endl; + if (sig == SIGINT || sig == SIGTERM) { + static int signal_count = 0; + signal_count++; + + if (signal_count <= 3) { + rclcpp::shutdown(); + // Give some time for graceful shutdown + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } else if (signal_count >= 5) { + // Force exit after second signal + std::cout << "Force exit due to multiple signals" << std::endl; + _exit(sig); + } + in_signal_handler.store(false); + } else { + std::string log_dir = "Log/"; + + // get current time + std::time_t now = std::time(nullptr); + std::tm *local_time = std::localtime(&now); + + // format date and time to string, format as "2024_05_20_12_34_56" + std::ostringstream time_stream; + time_stream << std::put_time(local_time, "%Y_%m_%d_%H_%M_%S"); + + // generate log file name + std::string log_file_name = g_camera_name + "_crash_stack_trace_" + time_stream.str() + ".log"; + std::string log_file_path = log_dir + log_file_name; + + if (!std::filesystem::exists(log_dir)) { + std::filesystem::create_directories(log_dir); + } + + std::cout << "Log crash stack trace to " << log_file_path << std::endl; + std::ofstream log_file(log_file_path, std::ios::app); + + if (log_file.is_open()) { + log_file << "Received signal: " << sig << std::endl; + + backward::StackTrace st; + st.load_here(32); // Capture stack + backward::Printer p; + p.print(st, log_file); // Print stack to log file + } + + log_file.close(); + _exit(sig); // Use _exit instead of exit to avoid cleanup that may crash + } +} + +namespace orbbec_camera { +backward::SignalHandling OBCameraNodeDriver::sh; +OBCameraNodeDriver::OBCameraNodeDriver(const rclcpp::NodeOptions &node_options) + : Node("orbbec_camera_node", "/", node_options), + node_options_(node_options), + config_path_(ament_index_cpp::get_package_share_directory("orbbec_camera") + + "/config/OrbbecSDKConfig_v2.0.xml"), + logger_(this->get_logger()), + extension_path_(ament_index_cpp::get_package_prefix("orbbec_camera") + "/lib/extensions") { + node_name_ = "orbbec_camera_node"; + init(); +} + +OBCameraNodeDriver::OBCameraNodeDriver(const std::string &node_name, const std::string &ns, + const rclcpp::NodeOptions &node_options) + : Node(node_name, ns, node_options), + node_options_(node_options), + config_path_(ament_index_cpp::get_package_share_directory("orbbec_camera") + + "/config/OrbbecSDKConfig_v2.0.xml"), + logger_(this->get_logger()), + extension_path_(ament_index_cpp::get_package_prefix("orbbec_camera") + "/lib/extensions") { + node_name_ = node_name; + init(); +} + +OBCameraNodeDriver::~OBCameraNodeDriver() { + is_alive_.store(false); + + // First stop the camera node cleanly before stopping threads + if (ob_camera_node_) { + try { + ob_camera_node_->clean(); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception during camera node cleanup in destructor"); + } + ob_camera_node_->stopGmslTrigger(); + } + + // Stop timers that might access the device + if (sync_host_time_timer_) { + try { + sync_host_time_timer_->cancel(); + sync_host_time_timer_.reset(); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception during sync timer cleanup in destructor"); + } + } + + if (check_connect_timer_) { + try { + check_connect_timer_->cancel(); + check_connect_timer_.reset(); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception during check connect timer cleanup in destructor"); + } + } + + if (device_status_timer_) { + try { + device_status_timer_->cancel(); + device_status_timer_.reset(); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception during device status timer cleanup in destructor"); + } + } + + // Now stop threads + if (device_count_update_thread_ && device_count_update_thread_->joinable()) { + device_count_update_thread_->join(); + } + if (query_thread_ && query_thread_->joinable()) { + query_thread_->join(); + } + if (reset_device_thread_ && reset_device_thread_->joinable()) { + reset_device_cond_.notify_all(); + reset_device_thread_->join(); + } + if (ob_camera_node_) { + ob_camera_node_->stopGmslTrigger(); + } + + // Unregister device changed callback before destroying context + if (ctx_ && device_changed_callback_id_ != INVALID_CALLBACK_ID) { + try { + ctx_->unregisterDeviceChangedCallback(device_changed_callback_id_); + device_changed_callback_id_ = INVALID_CALLBACK_ID; + } catch (...) { + RCLCPP_WARN_STREAM(logger_, + "Exception during device changed callback unregister in destructor"); + } + } + + if (orb_device_lock_shm_fd_ != -1) { + close(orb_device_lock_shm_fd_); + orb_device_lock_shm_fd_ = -1; + } + shm_unlink(ORB_DEFAULT_LOCK_NAME.c_str()); +} + +void OBCameraNodeDriver::init() { + // Set signal handlers for crash reporting + signal(SIGSEGV, signalHandler); // segment fault + signal(SIGABRT, signalHandler); // abort + signal(SIGFPE, signalHandler); // float point exception + signal(SIGILL, signalHandler); // illegal instruction + signal(SIGINT, signalHandler); + signal(SIGTERM, signalHandler); + ob::Context::setExtensionsDirectory(extension_path_.c_str()); + g_camera_name = declare_parameter("camera_name", g_camera_name); + auto log_level_str = declare_parameter("log_level", "none"); + auto log_level = obLogSeverityFromString(log_level_str); + auto log_file_name = declare_parameter("log_file_name", ""); + std::string pwd_dir = std::getenv("PWD") ? std::getenv("PWD") : std::getenv("HOME"); + std::string log_path = pwd_dir + "/Log/" + g_camera_name; + // Set logger to console + ob::Context::setLoggerToConsole(log_level); + ob::Context::setLoggerToFile(log_level, log_path.c_str()); + // Set custom log file name if specified + if (!log_file_name.empty()) { + try { + ob::Context::setLoggerFileName(log_file_name); + RCLCPP_INFO_STREAM(logger_, "SDK log file name set to: " << log_file_name); + } catch (const ob::Error &e) { + RCLCPP_WARN_STREAM(logger_, "Failed to set SDK log file name: " << e.getMessage()); + } + } + // Force IP + force_ip_enable_ = declare_parameter("force_ip_enable", false); + force_ip_mac_ = declare_parameter("force_ip_mac", ""); + force_ip_address_ = declare_parameter("force_ip_address", "192.168.1.10"); + force_ip_subnet_mask_ = declare_parameter("force_ip_subnet_mask", "255.255.255.0"); + force_ip_gateway_ = declare_parameter("force_ip_gateway", "192.168.1.1"); + if (config_path_.empty()) { + ctx_ = std::make_unique(); + } else { + ctx_ = std::make_unique(config_path_.c_str()); + } + applyForceIpConfig(); + + device_type_ = declare_parameter("device_type", "camera"); + connection_delay_ = static_cast(declare_parameter("connection_delay", 100)); + enable_sync_host_time_ = declare_parameter("enable_sync_host_time", true); + double time_sync_period = declare_parameter("time_sync_period", 60.0); + time_sync_period_ = std::chrono::milliseconds((int)(time_sync_period * 1000)); + upgrade_firmware_ = declare_parameter("upgrade_firmware", ""); + g_time_domain = declare_parameter("time_domain", g_time_domain); + preset_firmware_path_ = + declare_parameter("preset_firmware_path", preset_firmware_path_); + orb_device_lock_shm_fd_ = shm_open(ORB_DEFAULT_LOCK_NAME.c_str(), O_CREAT | O_RDWR, 0666); + if (orb_device_lock_shm_fd_ < 0) { + RCLCPP_ERROR_STREAM(logger_, "Failed to open shared memory " << ORB_DEFAULT_LOCK_NAME); + return; + } + int ret = ftruncate(orb_device_lock_shm_fd_, sizeof(pthread_mutex_t)); + if (ret < 0) { + RCLCPP_ERROR_STREAM(logger_, "Failed to truncate shared memory " << ORB_DEFAULT_LOCK_NAME); + return; + } + orb_device_lock_shm_addr_ = + static_cast(mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, + orb_device_lock_shm_fd_, 0)); + if (orb_device_lock_shm_addr_ == MAP_FAILED) { + RCLCPP_ERROR_STREAM(logger_, "Failed to map shared memory " << ORB_DEFAULT_LOCK_NAME); + return; + } + reboot_device_srv_ = this->create_service( + "reboot_device", std::bind(&OBCameraNodeDriver::rebootDeviceCallback, this, + std::placeholders::_1, std::placeholders::_2)); + pthread_mutexattr_init(&orb_device_lock_attr_); + pthread_mutexattr_setpshared(&orb_device_lock_attr_, PTHREAD_PROCESS_SHARED); + orb_device_lock_ = (pthread_mutex_t *)orb_device_lock_shm_addr_; + pthread_mutex_init(orb_device_lock_, &orb_device_lock_attr_); + is_alive_.store(true); + // Initialize the reset device completion time to allow immediate device connection on startup + last_reset_device_completion_time_ = std::chrono::steady_clock::now() - std::chrono::seconds(10); + parameters_ = std::make_shared(this); + serial_number_ = declare_parameter("serial_number", ""); + device_num_ = static_cast(declare_parameter("device_num", 1)); + usb_port_ = declare_parameter("usb_port", ""); + net_device_ip_ = declare_parameter("net_device_ip", ""); + net_device_port_ = static_cast(declare_parameter("net_device_port", 0)); + enumerate_net_device_ = declare_parameter("enumerate_net_device", false); + uvc_backend_ = declare_parameter("uvc_backend", "libuvc"); + device_access_mode_str_ = declare_parameter("device_access_mode", "Default"); + device_access_mode_ = stringToAccessMode(device_access_mode_str_); + RCLCPP_INFO_STREAM(logger_, "Device access mode: " << device_access_mode_str_ << " (" + << device_access_mode_ << ")"); + if (uvc_backend_ == "libuvc") { + ctx_->setUvcBackendType(OB_UVC_BACKEND_TYPE_LIBUVC); + RCLCPP_INFO_STREAM(logger_, "setUvcBackendType:" << uvc_backend_); + } else if (uvc_backend_ == "v4l2") { + ctx_->setUvcBackendType(OB_UVC_BACKEND_TYPE_V4L2); + RCLCPP_INFO_STREAM(logger_, "setUvcBackendType:" << uvc_backend_); + } else { + ctx_->setUvcBackendType(OB_UVC_BACKEND_TYPE_LIBUVC); + RCLCPP_INFO_STREAM(logger_, "setUvcBackendType:" << uvc_backend_); + } + ctx_->enableNetDeviceEnumeration(enumerate_net_device_); + device_changed_callback_id_ = ctx_->registerDeviceChangedCallback( + [this](const std::shared_ptr &removed_list, + const std::shared_ptr &added_list) { + onDeviceDisconnected(removed_list); + onDeviceConnected(added_list); + }); + check_connect_timer_ = + this->create_wall_timer(std::chrono::milliseconds(1000), [this]() { checkConnectTimer(); }); + CHECK_NOTNULL(check_connect_timer_); + if (device_type_ == "camera") { + device_status_timer_ = + this->create_wall_timer(std::chrono::milliseconds(1000 / device_status_interval_hz), + [this]() { deviceStatusTimer(); }); + auto qos = rclcpp::QoS(1).transient_local(); + if (node_options_.use_intra_process_comms()) { + qos = rclcpp::QoS(1); + } + device_status_pub_ = + this->create_publisher("device_status", qos); + } + query_thread_ = std::make_shared([this]() { queryDevice(); }); + reset_device_thread_ = std::make_shared([this]() { resetDevice(); }); +} + +void OBCameraNodeDriver::onDeviceConnected(const std::shared_ptr &device_list) { + CHECK_NOTNULL(device_list); + { + RCLCPP_INFO_STREAM(logger_, "onDeviceConnected called"); + std::unique_lock reset_lock(reset_device_mutex_); + if (reset_device_flag_) { + RCLCPP_INFO_STREAM(logger_, "onDeviceConnected : device reset in progress, waiting..."); + reset_device_cond_.wait( + reset_lock, [this]() { return !reset_device_flag_ || !is_alive_ || !rclcpp::ok(); }); + if (!is_alive_) { + return; + } + RCLCPP_INFO_STREAM(logger_, + "onDeviceConnected : device reset completed, continuing connection"); + } + } + if (device_list->getCount() == 0) { + return; + } + + // Check if device is already connected or connecting + if (device_connected_.load() || device_connecting_.load()) { + RCLCPP_DEBUG_STREAM(logger_, "onDeviceConnected: device already connected or connecting"); + return; + } + + if (!device_) { + startDevice(device_list); + } +} + +void OBCameraNodeDriver::onDeviceDisconnected(const std::shared_ptr &device_list) { + CHECK_NOTNULL(device_list); + if (device_list->getCount() == 0) { + return; + } + RCLCPP_INFO_STREAM(logger_, "onDeviceDisconnected called"); + + // Check if device connection/initialization is in progress + if (device_connecting_.load()) { + RCLCPP_INFO_STREAM(logger_, + "onDeviceDisconnected: device connection/initialization in progress, " + "ignoring disconnect event"); + return; + } + + std::unique_lock reset_device_lock(reset_device_mutex_); + + std::lock_guard lock(device_lock_); + + if (!device_connected_.load()) { + RCLCPP_DEBUG_STREAM(logger_, "onDeviceDisconnected: device already disconnected"); + return; + } + + for (size_t i = 0; i < device_list->getCount(); i++) { + std::string uid = device_list->getUid(i); + std::string serial_number = device_list->getSerialNumber(i); + RCLCPP_INFO_STREAM(logger_, "device with " << uid << " disconnected"); + if (uid == device_unique_id_ || serial_number_ == serial_number) { + RCLCPP_INFO_STREAM(logger_, + "device with " << uid << " disconnected, notify reset device thread 1."); + reset_device_flag_ = true; + reset_device_cond_.notify_all(); + RCLCPP_INFO_STREAM(logger_, + "device with " << uid << " disconnected, notify reset device thread 2."); + break; + } + } +} + +OBLogSeverity OBCameraNodeDriver::obLogSeverityFromString(const std::string_view &log_level) { + if (log_level == "debug") { + return OBLogSeverity::OB_LOG_SEVERITY_DEBUG; + } else if (log_level == "info") { + return OBLogSeverity::OB_LOG_SEVERITY_INFO; + } else if (log_level == "warn") { + return OBLogSeverity::OB_LOG_SEVERITY_WARN; + } else if (log_level == "error") { + return OBLogSeverity::OB_LOG_SEVERITY_ERROR; + } else if (log_level == "fatal") { + return OBLogSeverity::OB_LOG_SEVERITY_FATAL; + } else { + return OBLogSeverity::OB_LOG_SEVERITY_NONE; + } +} + +void OBCameraNodeDriver::checkConnectTimer() { + if (!device_connected_.load()) { + RCLCPP_DEBUG_STREAM(logger_, + "checkConnectTimer: device " << serial_number_ << " not connected"); + return; + } else if (!ob_camera_node_ && !ob_lidar_node_) { + device_connected_.store(false); + } +} + +void OBCameraNodeDriver::queryDevice() { + while (is_alive_ && rclcpp::ok()) { + // Check if device reset is in progress before attempting to connect + { + std::unique_lock reset_lock(reset_device_mutex_); + if (reset_device_flag_) { + RCLCPP_INFO_STREAM(logger_, "queryDevice: device reset in progress, waiting..."); + reset_device_cond_.wait( + reset_lock, [this]() { return !reset_device_flag_ || !is_alive_ || !rclcpp::ok(); }); + if (!is_alive_ || !rclcpp::ok()) { + return; + } + RCLCPP_INFO_STREAM(logger_, "queryDevice: device reset completed, continuing connection"); + } + } + + // Check if connection is already in progress + if (device_connecting_.load()) { + RCLCPP_DEBUG_STREAM(logger_, + "queryDevice: device connection already in progress, waiting..."); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + continue; + } + + // If device is already connected, skip connection attempt + if (!device_connected_.load()) { + // Check if sufficient time has passed since last reset device completion + auto now = std::chrono::steady_clock::now(); + auto time_since_last_reset = std::chrono::duration_cast( + now - last_reset_device_completion_time_); + + if (time_since_last_reset.count() < 10) { + RCLCPP_DEBUG_STREAM( + logger_, + "queryDevice: Only " + << time_since_last_reset.count() + << " seconds since last reset completion, waiting before starting device..."); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + continue; + } + + if (!enumerate_net_device_ && !net_device_ip_.empty() && net_device_port_ != 0) { + connectNetDevice(net_device_ip_, net_device_port_); + } else { + auto device_list = ctx_->queryDeviceList(); + if (device_list->getCount() != 0) { + startDevice(device_list); + } + } + } + // Add a delay to prevent tight loop + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } +} + +void OBCameraNodeDriver::resetDevice() { + while (is_alive_ && rclcpp::ok()) { + { + std::unique_lock lock(reset_device_mutex_); + // Use a timeout to make the wait interruptible + auto timeout = std::chrono::milliseconds(1000); + bool notified = reset_device_cond_.wait_for( + lock, timeout, [this]() { return !is_alive_ || !rclcpp::ok() || reset_device_flag_; }); + + // Check if we should exit due to shutdown + if (!is_alive_ || !rclcpp::ok()) { + break; + } + + // If not notified by reset flag, continue waiting + if (!notified || !reset_device_flag_) { + continue; + } + + // Stop sync timer to prevent it from accessing the device during reset + if (sync_host_time_timer_) { + try { + sync_host_time_timer_->cancel(); + sync_host_time_timer_.reset(); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception during sync timer cleanup during reset"); + } + } + + RCLCPP_INFO_STREAM(logger_, "resetDevice : Reset device uid: " << device_unique_id_); + std::lock_guard device_lock(device_lock_); + { + // Mark device as disconnected immediately to prevent other threads from accessing it + device_connected_ = false; + device_connecting_ = false; // Clear connecting flag + + // Reset objects in order, with additional safety checks + if (ob_camera_node_) { + ob_camera_node_.reset(); + } else if (ob_lidar_node_) { + ob_lidar_node_.reset(); + } + + // Allow more time for internal SDK cleanup + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (device_) { + try { + RCLCPP_INFO_STREAM(logger_, "Resetting device_"); + // Force free any idle memory before device reset + if (ctx_) { + try { + ctx_->freeIdleMemory(); + } catch (...) { + // Ignore exceptions during memory cleanup + } + } + device_.reset(); + RCLCPP_INFO_STREAM(logger_, "device_ reset completed"); + } catch (const ob::Error &e) { + RCLCPP_WARN_STREAM(logger_, "OB Exception during device reset: " << e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_WARN_STREAM(logger_, "Standard exception during device reset: " << e.what()); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Unknown exception during device reset"); + } + } + + if (device_info_) { + try { + RCLCPP_INFO_STREAM(logger_, "Resetting device_info_"); + device_info_.reset(); + RCLCPP_INFO_STREAM(logger_, "device_info_ reset completed"); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception during device_info reset"); + } + } + + device_unique_id_.clear(); + } + reset_device_flag_ = false; + last_reset_device_completion_time_ = std::chrono::steady_clock::now(); + } + reset_device_cond_.notify_all(); + malloc_trim(0); + RCLCPP_INFO_STREAM(logger_, "Reset device uid: " << device_unique_id_ << " done"); + } +} + +void OBCameraNodeDriver::deviceStatusTimer() { + // Always publish device status regardless of device connection state + orbbec_camera_msgs::msg::DeviceStatus status_msg; + status_msg.header.stamp = this->now(); + status_msg.device_online = device_connected_.load(); + status_msg.header.frame_id = node_name_; + + // Initialize default values for when device is not connected + status_msg.connection_type = ""; + status_msg.calibration_from_factory = false; + status_msg.calibration_from_launch_param = false; + status_msg.customer_calibration_ready = false; + + // Flag to track if device communication error occurs + bool device_communication_error = false; + + // Only try to get device information if device is connected and stable + if (device_connected_.load() && !device_connecting_.load()) { + // Check if reset is in progress + std::unique_lock reset_lock(reset_device_mutex_, + std::try_to_lock); + if (reset_lock.owns_lock() && !reset_device_flag_) { + // Only get device-specific info if we have a valid camera node and device + if (ob_camera_node_) { + // Safely get color and depth status - these may access device + try { + ob_camera_node_->getColorStatus(status_msg); + ob_camera_node_->getDepthStatus(status_msg); + } catch (const ob::Error &e) { + std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error"; + if (error_msg.find("Device is deactivated") != std::string::npos || + error_msg.find("disconnected") != std::string::npos || + error_msg.find("Send control transfer failed") != std::string::npos) { + RCLCPP_WARN( + logger_, + "Device communication error in %s at line %d: %s - Device may be disconnected", + __FUNCTION__, __LINE__, error_msg.c_str()); + device_communication_error = true; + } else { + RCLCPP_ERROR(logger_, "Error in %s at line %d: %s", __FUNCTION__, __LINE__, + error_msg.c_str()); + } + } catch (const std::exception &e) { + RCLCPP_ERROR(logger_, "Exception in %s at line %d: %s", __FUNCTION__, __LINE__, e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Unknown exception in %s at line %d", __FUNCTION__, __LINE__); + } + + // These should be safe as they don't directly access hardware + status_msg.calibration_from_launch_param = ob_camera_node_->isParamCalibrated(); + } + + // Safely get connection type + try { + if (device_info_) { + status_msg.connection_type = device_info_->getConnectionType(); + } + } catch (const ob::Error &e) { + std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error"; + if (error_msg.find("Device is deactivated") != std::string::npos || + error_msg.find("disconnected") != std::string::npos || + error_msg.find("Send control transfer failed") != std::string::npos) { + RCLCPP_WARN( + logger_, + "Device communication error in %s at line %d: %s - Device may be disconnected", + __FUNCTION__, __LINE__, error_msg.c_str()); + device_communication_error = true; + } else { + RCLCPP_ERROR(logger_, "Error in %s at line %d: %s", __FUNCTION__, __LINE__, + error_msg.c_str()); + } + } catch (const std::exception &e) { + RCLCPP_ERROR(logger_, "Exception in %s at line %d: %s", __FUNCTION__, __LINE__, e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Unknown exception in %s at line %d", __FUNCTION__, __LINE__); + } + + // Safely get calibration info + try { + if (device_) { + auto camera_params = device_->getCalibrationCameraParamList(); + bool calibration_from_factory = (camera_params != nullptr && camera_params->count() > 0); + status_msg.calibration_from_factory = calibration_from_factory; + } + } catch (const ob::Error &e) { + std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error"; + if (error_msg.find("Device is deactivated") != std::string::npos || + error_msg.find("disconnected") != std::string::npos || + error_msg.find("Send control transfer failed") != std::string::npos) { + RCLCPP_WARN( + logger_, + "Device communication error in %s at line %d: %s - Device may be disconnected", + __FUNCTION__, __LINE__, error_msg.c_str()); + device_communication_error = true; + } else { + RCLCPP_ERROR(logger_, "Error in %s at line %d: %s", __FUNCTION__, __LINE__, + error_msg.c_str()); + } + } catch (const std::exception &e) { + RCLCPP_ERROR(logger_, "Exception in %s at line %d: %s", __FUNCTION__, __LINE__, e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Unknown exception in %s at line %d", __FUNCTION__, __LINE__); + } + + // Safely check user calibration readiness - this may also access device + // Only execute for 435LE devices (check by device name for network devices) + try { + if (device_info_ && ob_camera_node_) { + std::string device_name = device_info_->getName(); + if (device_name.find("435Le") != std::string::npos || + device_name.find("435LE") != std::string::npos) { + if (!ob_camera_node_->checkUserCalibrationReady()) { + status_msg.customer_calibration_ready = false; + } else { + status_msg.customer_calibration_ready = true; + } + } else { + // For non-435LE devices, set a default value or skip this check + status_msg.customer_calibration_ready = false; + } + } else { + status_msg.customer_calibration_ready = false; + } + } catch (const ob::Error &e) { + std::string error_msg = e.getMessage() ? e.getMessage() : "Unknown OB error"; + if (error_msg.find("Device is deactivated") != std::string::npos || + error_msg.find("disconnected") != std::string::npos || + error_msg.find("Send control transfer failed") != std::string::npos) { + RCLCPP_WARN( + logger_, + "Device communication error in %s at line %d: %s - Device may be disconnected", + __FUNCTION__, __LINE__, error_msg.c_str()); + device_communication_error = true; + } else { + RCLCPP_ERROR(logger_, "Error in %s at line %d: %s", __FUNCTION__, __LINE__, + error_msg.c_str()); + } + } catch (const std::exception &e) { + RCLCPP_ERROR(logger_, "Exception in %s at line %d: %s", __FUNCTION__, __LINE__, e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Unknown exception in %s at line %d", __FUNCTION__, __LINE__); + } + } + } + + // If device communication error occurred, set device_online to false + if (device_communication_error) { + status_msg.device_online = false; + } + + // if status_msg.connection_type is empty, set it to "unknown" + if (status_msg.connection_type.empty()) { + status_msg.connection_type = "unknown"; + status_msg.device_online = false; + } + + // Always publish the status message, regardless of device state + if (device_status_pub_) { + device_status_pub_->publish(status_msg); + } + // RCLCPP_INFO_STREAM(logger_, "deviceStatusTimer() "); +} +void OBCameraNodeDriver::rebootDeviceCallback( + const std::shared_ptr request, + std::shared_ptr response) { + (void)request; + (void)response; + + malloc_trim(0); + RCLCPP_INFO(logger_, "Reboot device service called"); + + struct timespec timeout; + clock_gettime(CLOCK_REALTIME, &timeout); + timeout.tv_sec += 15; + + int lock_result = pthread_mutex_timedlock(orb_device_lock_, &timeout); + if (lock_result != 0) { + RCLCPP_WARN(logger_, "Failed to acquire process lock for reboot: %s", strerror(lock_result)); + return; + } + + std::shared_ptr process_lock_guard( + nullptr, [this](int *) { pthread_mutex_unlock(orb_device_lock_); }); + + try { + std::unique_lock reset_lock(reset_device_mutex_); + reset_device_flag_ = true; + { + std::lock_guard device_lock(device_lock_); + + if (!device_connected_ || (!ob_camera_node_ && !ob_lidar_node_)) { + RCLCPP_INFO(logger_, "Device not connected"); + reset_device_flag_ = false; + } else { + std::string current_device_uid = device_unique_id_; + RCLCPP_INFO_STREAM(logger_, "Rebooting device with UID: " << current_device_uid); + if (ob_lidar_node_) { + ob_lidar_node_->rebootDevice(); + } else if (ob_camera_node_) { + ob_camera_node_->rebootDevice(); + } + } + } + if (reset_device_flag_) { + RCLCPP_INFO(logger_, "Device reboot initiated, waiting for reconnection"); + } + + } catch (std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to reboot device: " << e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to reboot device: unknown error"); + } + process_lock_guard.reset(); + if (reset_device_flag_) { + reset_device_cond_.notify_all(); + } + malloc_trim(0); + return; +} + +std::shared_ptr OBCameraNodeDriver::selectDevice( + const std::shared_ptr &list) { + std::shared_ptr device = nullptr; + if (!net_device_ip_.empty() && net_device_port_ != 0) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Connecting to device with net ip: " << net_device_ip_); + device = selectDeviceByNetIP(list, net_device_ip_); + } else if (!serial_number_.empty()) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Connecting to device with serial number: " << serial_number_); + device = selectDeviceBySerialNumber(list, serial_number_); + } else if (!usb_port_.empty()) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Connecting to device with usb port: " << usb_port_); + device = selectDeviceByUSBPort(list, usb_port_); + } else if (device_num_ == 1) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, "Connecting to the default device"); + return list->getDevice(0, device_access_mode_); + } + if (device == nullptr) { + RCLCPP_WARN_THROTTLE(logger_, *get_clock(), 5000, "Device with serial number %s not found", + serial_number_.c_str()); + device_connected_ = false; + return nullptr; + } + return device; +} + +std::shared_ptr OBCameraNodeDriver::selectDeviceBySerialNumber( + const std::shared_ptr &list, const std::string &serial_number) { + std::string lower_sn; + std::transform(serial_number.begin(), serial_number.end(), std::back_inserter(lower_sn), + [](auto ch) { return isalpha(ch) ? tolower(ch) : static_cast(ch); }); + for (size_t i = 0; i < list->getCount(); i++) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Before lock: Select device serial number: " << serial_number); + std::lock_guard lock(device_lock_); + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "After lock: Select device serial number: " << serial_number); + try { + auto pid = list->getPid(i); + if (isOpenNIDevice(pid)) { + // openNI device + auto device = list->getDevice(i); + auto device_info = device->getDeviceInfo(); + if (device_info->getSerialNumber() == serial_number) { + RCLCPP_INFO_STREAM_THROTTLE( + logger_, *get_clock(), 5000, + "Device serial number " << device_info->getSerialNumber() << " matched"); + return device; + } + } else { + std::string sn = list->getSerialNumber(i); + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, "Device serial number: " << sn); + if (sn == serial_number) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Device serial number " << sn << " matched"); + return list->getDevice(i, device_access_mode_); + } + } + } catch (ob::Error &e) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Failed to get device info " << e.getMessage()); + } catch (std::exception &e) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Failed to get device info " << e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, "Failed to get device info"); + } + } + return nullptr; +} + +std::shared_ptr OBCameraNodeDriver::selectDeviceByUSBPort( + const std::shared_ptr &list, const std::string &usb_port) { + try { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Before lock: Select device usb port: " << usb_port); + std::lock_guard lock(device_lock_); + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "After lock: Select device usb port: " << usb_port); + auto device = list->getDeviceByUid(usb_port.c_str(), device_access_mode_); + if (device) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "getDeviceByUid device usb port " << usb_port << " done"); + } else { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "getDeviceByUid device usb port " << usb_port << " failed"); + RCLCPP_ERROR_STREAM_THROTTLE( + logger_, *get_clock(), 5000, + "Please use script to get usb port: ros2 run orbbec_camera list_devices_node"); + } + return device; + } catch (ob::Error &e) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Failed to get device info " << e.getMessage()); + } catch (std::exception &e) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Failed to get device info " << e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, "Failed to get device info"); + } + + return nullptr; +} + +std::shared_ptr OBCameraNodeDriver::selectDeviceByNetIP( + const std::shared_ptr &list, const std::string &net_ip) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Before lock: Select device net ip: " << net_ip); + std::lock_guard lock(device_lock_); + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "After lock: Select device net ip: " << net_ip); + std::shared_ptr device = nullptr; + for (size_t i = 0; i < list->getCount(); i++) { + try { + if (std::string(list->getConnectionType(i)) != "Ethernet") { + continue; + } + if (list->getIpAddress(i) == nullptr) { + continue; + } + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "FindDeviceByNetIP device net ip " << list->getIpAddress(i)); + if (std::string(list->getIpAddress(i)) == net_ip) { + RCLCPP_INFO_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "getDeviceByNetIP device net ip " << net_ip << " done"); + return list->getDevice(i, device_access_mode_); + } + } catch (ob::Error &e) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Failed to get device info " << e.getMessage()); + continue; + } catch (std::exception &e) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, + "Failed to get device info " << e.what()); + continue; + } catch (...) { + RCLCPP_ERROR_STREAM_THROTTLE(logger_, *get_clock(), 5000, "Failed to get device info"); + continue; + } + } + + return nullptr; +} + +void OBCameraNodeDriver::initializeDevice(const std::shared_ptr &device) { + device_ = device; + updatePresetFirmware(preset_firmware_path_); + CHECK_NOTNULL(device_); + CHECK_NOTNULL(device_.get()); + if (ob_camera_node_) { + ob_camera_node_.reset(); + } else if (ob_lidar_node_) { + ob_lidar_node_.reset(); + } + int retry_count = 0; + constexpr int max_retries = 3; + bool initialized = false; + device_info_ = device_->getDeviceInfo(); + RCLCPP_INFO_STREAM(logger_, "Try to connect device via " << device_info_->connectionType()); + + while (retry_count < max_retries && !initialized) { + try { + if (device_type_ == "camera") { + ob_camera_node_ = std::make_unique(this, device_, parameters_, + node_options_.use_intra_process_comms()); + } else if (device_type_ == "lidar") { + ob_lidar_node_ = std::make_unique( + this, device_, parameters_, node_options_.use_intra_process_comms()); + } + + initialized = true; + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to initialize device (Attempt " + << retry_count + 1 << " of " << max_retries + << "): " << e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to initialize device (Attempt " << retry_count + 1 + << " of " << max_retries + << "): " << e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to initialize device (Attempt " + << retry_count + 1 << " of " << max_retries << ")"); + } + retry_count++; + } + + if (!initialized) { + RCLCPP_ERROR_STREAM(logger_, + "Device initialization failed after " << max_retries << " attempts."); + throw std::runtime_error("Device initialization failed after " + std::to_string(max_retries) + + " attempts."); + } + + device_connected_ = true; + device_info_ = device_->getDeviceInfo(); + serial_number_ = device_info_->getSerialNumber(); + CHECK_NOTNULL(device_info_.get()); + device_unique_id_ = device_info_->getUid(); + + if (enable_sync_host_time_ && !isOpenNIDevice(device_info_->pid()) && device_type_ == "camera") { + TRY_EXECUTE_BLOCK(device_->timerSyncWithHost()); + if (g_time_domain != "global") { + sync_host_time_timer_ = this->create_wall_timer(time_sync_period_, [this]() { + // Multiple safety checks before attempting time sync + if (!device_) { + RCLCPP_DEBUG_STREAM(logger_, "sync_host_time_timer_: device is null, skip time sync"); + return; + } + + // Check device connection status + if (!device_connected_.load()) { + RCLCPP_DEBUG_STREAM(logger_, + "sync_host_time_timer_: device not connected, skip time sync"); + return; + } + + // Check if device is in connecting state + if (device_connecting_.load()) { + RCLCPP_DEBUG_STREAM(logger_, "sync_host_time_timer_: device connecting, skip time sync"); + return; + } + + // Check if reset is in progress + { + std::unique_lock reset_lock(reset_device_mutex_, + std::try_to_lock); + if (!reset_lock.owns_lock() || reset_device_flag_) { + RCLCPP_DEBUG_STREAM(logger_, + "sync_host_time_timer_: device reset in progress, skip time sync"); + return; + } + } + + // Additional safety check with device lock + std::unique_lock device_lock(device_lock_, std::try_to_lock); + if (!device_lock.owns_lock()) { + RCLCPP_DEBUG_STREAM(logger_, + "sync_host_time_timer_: cannot acquire device lock, skip time sync"); + return; + } + + // Verify device is still valid after acquiring lock + if (!device_) { + RCLCPP_DEBUG_STREAM( + logger_, "sync_host_time_timer_: device became null after lock, skip time sync"); + return; + } + + RCLCPP_INFO_STREAM(logger_, "Sync device time with host"); + TRY_EXECUTE_BLOCK(device_->timerSyncWithHost()); + }); + } + } + + // Safely log device information - these calls can throw if device disconnects + TRY_EXECUTE_BLOCK({ + RCLCPP_INFO_STREAM(logger_, "Device " << device_info_->getName() << " connected"); + RCLCPP_INFO_STREAM(logger_, "Serial number: " << device_info_->getSerialNumber()); + RCLCPP_INFO_STREAM(logger_, "Firmware version: " << device_info_->getFirmwareVersion()); + RCLCPP_INFO_STREAM(logger_, "ROS Wrapper version: " << OB_ROS_VERSION_STR); + RCLCPP_INFO_STREAM(logger_, "SDK version: " << getObSDKVersion()); + RCLCPP_INFO_STREAM(logger_, "Hardware version: " << device_info_->getHardwareVersion()); + RCLCPP_INFO_STREAM(logger_, "usb connect type: " << device_info_->getConnectionType()); + }); + RCLCPP_INFO_STREAM(logger_, "device unique id: " << device_unique_id_); + RCLCPP_INFO_STREAM(logger_, "Current node pid: " << getpid()); + auto time_cost = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - start_time_); + RCLCPP_INFO_STREAM(logger_, "Start device cost " << time_cost.count() << " ms"); + + if (!upgrade_firmware_.empty()) { + // Check if this is a second update (reupdate scenario) + bool is_second_update = is_reupdating_.load(); + + if (is_second_update) { + RCLCPP_INFO(logger_, "Device reconnected, starting the second firmware update..."); + } else { + RCLCPP_INFO(logger_, "Starting firmware update from file: %s", upgrade_firmware_.c_str()); + } + + firmware_update_success_ = false; + need_reupdate_ = false; + + if (ob_camera_node_) { + TRY_EXECUTE_BLOCK({ + ob_camera_node_->withDeviceLock([&]() { + device_->updateFirmware( + upgrade_firmware_.c_str(), + std::bind(&OBCameraNodeDriver::firmwareUpdateCallback, this, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3), + false); + }); + }); + } else if (ob_lidar_node_) { + device_->updateFirmware( + upgrade_firmware_.c_str(), + std::bind(&OBCameraNodeDriver::firmwareUpdateCallback, this, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3), + false); + } + + if (need_reupdate_) { + // Some devices require a second update after reboot + RCLCPP_INFO(logger_, "The device will reboot and perform a second update automatically."); + // Set flag to indicate we're waiting for device to reboot for second update + is_reupdating_ = true; + // Keep upgrade_firmware_ path and wait for device to reconnect + // The second update will be triggered automatically when device reconnects + return; + } + + if (firmware_update_success_) { + if (is_second_update) { + RCLCPP_INFO(logger_, "Second firmware update completed successfully!"); + is_reupdating_ = false; + } else { + RCLCPP_INFO(logger_, "Firmware update completed successfully!"); + } + return; + } + } + + if (ob_camera_node_) { + ob_camera_node_->startIMU(); + ob_camera_node_->startStreams(); + } else if (ob_lidar_node_) { + ob_lidar_node_->startStreams(); + ob_lidar_node_->startIMU(); + } else { + RCLCPP_INFO_STREAM(logger_, "ob_camera_node_ is nullptr"); + } + +} // namespace orbbec_camera + +bool OBCameraNodeDriver::applyForceIpConfig() { + if (!force_ip_enable_) { + RCLCPP_DEBUG(logger_, "[ForceIP] Disabled, skip config"); + return false; + } + if (force_ip_success_) { + RCLCPP_DEBUG(logger_, "[ForceIP] Already applied, skip"); + return false; + } + + OBNetIpConfig config{}; + config.dhcp = force_ip_dhcp_ ? 1 : 0; + + if (config.dhcp == 0) { + RCLCPP_INFO(logger_, "[ForceIP] Static config mode"); + auto strToIp = [&](const std::string &s, uint8_t out[4]) -> bool { + std::stringstream ss(s); + std::string item; + int i = 0; + while (std::getline(ss, item, '.') && i < 4) { + int val = std::stoi(item); + if (val < 0 || val > 255) return false; + out[i++] = static_cast(val); + } + return i == 4; + }; + uint8_t ip[4], mask[4], gw[4]; + if (!strToIp(force_ip_address_, ip)) { + RCLCPP_ERROR(logger_, "[ForceIP] Invalid IP: %s", force_ip_address_.c_str()); + return false; + } + if (!strToIp(force_ip_subnet_mask_, mask)) { + RCLCPP_ERROR(logger_, "[ForceIP] Invalid Mask: %s", force_ip_subnet_mask_.c_str()); + return false; + } + if (!strToIp(force_ip_gateway_, gw)) { + RCLCPP_ERROR(logger_, "[ForceIP] Invalid Gateway: %s", force_ip_gateway_.c_str()); + return false; + } + std::memcpy(config.address, ip, 4); + std::memcpy(config.mask, mask, 4); + std::memcpy(config.gateway, gw, 4); + } + + force_ip_success_ = false; + try { + auto device_list = ctx_->queryDeviceList(); + uint32_t index = 0; + std::string mac; + if (!force_ip_mac_.empty()) { + mac = force_ip_mac_; + } else if (device_list->getCount() == 1) { + mac = device_list->getUid(index); + } else { + RCLCPP_ERROR(logger_, "[ForceIP] MAC address is empty"); + return false; + } + + if (ctx_->forceIp(mac.c_str(), config)) { + RCLCPP_INFO(logger_, "[ForceIP] Config applied. dhcp=%d ip=%s mask=%s gw=%s", config.dhcp, + force_ip_address_.c_str(), force_ip_subnet_mask_.c_str(), + force_ip_gateway_.c_str()); + force_ip_success_ = true; + } else { + RCLCPP_ERROR(logger_, "[ForceIP] Failed to apply config (SDK returned false)"); + } + } catch (const ob::Error &e) { + RCLCPP_ERROR(logger_, "[ForceIP] ob::Error: %s", e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR(logger_, "[ForceIP] std::exception: %s", e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "[ForceIP] Unknown error"); + } + + return force_ip_success_; +} + +void OBCameraNodeDriver::connectNetDevice(const std::string &net_device_ip, int net_device_port) { + if (net_device_ip.empty() || net_device_port == 0) { + RCLCPP_ERROR_STREAM(logger_, "Invalid net device ip or port"); + return; + } + + // Check if already connecting + bool expected = false; + if (!device_connecting_.compare_exchange_strong(expected, true)) { + RCLCPP_DEBUG_STREAM(logger_, "connectNetDevice: connection already in progress"); + return; + } + + // Use RAII to ensure connecting flag is cleared + std::shared_ptr connecting_guard(nullptr, + [this](int *) { device_connecting_.store(false); }); + + std::this_thread::sleep_for(std::chrono::milliseconds(connection_delay_)); + auto device = ctx_->createNetDevice(net_device_ip.c_str(), net_device_port, device_access_mode_); + if (device == nullptr) { + RCLCPP_ERROR_STREAM(logger_, "Failed to connect to net device " << net_device_ip); + return; + } + try { + initializeDevice(device); + if (!device_connected_) { + RCLCPP_ERROR_STREAM(logger_, "Failed to initialize net device " << net_device_ip); + } + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Exception during net device initialization: " << e.what()); + device_connected_ = false; + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Unknown exception during net device initialization"); + device_connected_ = false; + } +} + +void OBCameraNodeDriver::startDevice(const std::shared_ptr &list) { + if (device_connected_.load()) { + return; + } + + // Try to set connecting flag atomically + bool expected = false; + if (!device_connecting_.compare_exchange_strong(expected, true)) { + RCLCPP_DEBUG_STREAM(logger_, "startDevice: connection already in progress by another thread"); + return; + } + + // Use RAII to ensure connecting flag is cleared + std::shared_ptr connecting_guard(nullptr, [this](int *) { + device_connecting_.store(false); + RCLCPP_DEBUG_STREAM(logger_, "startDevice: connecting flag cleared"); + }); + + if (list->getCount() == 0) { + RCLCPP_WARN(logger_, "No device found"); + return; + } + + RCLCPP_INFO_THROTTLE(logger_, *get_clock(), 5000, "startDevice called"); + + start_time_ = std::chrono::high_resolution_clock::now(); + if (device_) { + device_.reset(); + } + std::this_thread::sleep_for(std::chrono::milliseconds(connection_delay_)); + int try_lock_count = 0; + int max_try_lock_count = 5; + + while (try_lock_count < max_try_lock_count) { + int try_lock_result = pthread_mutex_trylock(orb_device_lock_); + + if (try_lock_result == 0) { + // success get lock,break + break; + } else if (try_lock_result == EBUSY) { + RCLCPP_INFO_STREAM(logger_, "Device lock is held by another process, waiting 100ms"); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } else { + RCLCPP_ERROR_STREAM(logger_, "Failed to lock orb_device_lock_"); + return; // Not EBUSY, return + } + + try_lock_count++; + } + if (try_lock_count >= max_try_lock_count) { + RCLCPP_ERROR_STREAM(logger_, "Failed to lock orb_device_lock_"); + return; + } + + std::shared_ptr lock_holder(nullptr, + [this](int *) { pthread_mutex_unlock(orb_device_lock_); }); + bool start_device_failed = false; + try { + auto start_time = std::chrono::high_resolution_clock::now(); + auto device = selectDevice(list); + if (device == nullptr) { + device_connected_ = false; + return; + } + auto end_time = std::chrono::high_resolution_clock::now(); + auto time_cost = std::chrono::duration_cast(end_time - start_time); + RCLCPP_INFO_STREAM(logger_, "Select device cost " << time_cost.count() << " ms"); + start_time = std::chrono::high_resolution_clock::now(); + initializeDevice(device); + end_time = std::chrono::high_resolution_clock::now(); + time_cost = std::chrono::duration_cast(end_time - start_time); + RCLCPP_INFO_STREAM(logger_, "Initialize device cost " << time_cost.count() << " ms"); + + if (firmware_update_success_) { + firmware_update_success_ = false; + device_connected_ = false; + { + std::unique_lock reset_device_lock(reset_device_mutex_); + reset_device_flag_ = true; + } + reset_device_cond_.notify_all(); + return; + } + + auto pid = device->getDeviceInfo()->getPid(); + if (GEMINI_335LG_PID == pid) { + ob_camera_node_->startGmslTrigger(); + } + if (pid == GEMINI_305_PID) { + // Fixing 305 hot-swap not outputting power + ob_camera_node_->startStreams(); + } + } catch (ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to initialize device " << e.getMessage()); + start_device_failed = true; + } catch (std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to initialize device " << e.what()); + start_device_failed = true; + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to initialize device"); + start_device_failed = true; + } + if (start_device_failed) { + device_connected_ = false; + { + std::unique_lock reset_device_lock(reset_device_mutex_); + reset_device_flag_ = true; + } + reset_device_cond_.notify_all(); + } +} +void OBCameraNodeDriver::updatePresetFirmware(std::string path) { + if (path.empty()) { + return; + } else { + std::stringstream ss(path); + std::string path_segment; + std::vector paths; + OBFwUpdateState updateState = STAT_START; + bool firstCall = true; + + while (std::getline(ss, path_segment, ',')) { + paths.push_back(path_segment); + } + uint8_t index = 0; + uint8_t count = static_cast(paths.size()); + char(*filePaths)[OB_PATH_MAX] = new char[count][OB_PATH_MAX]; + RCLCPP_INFO_STREAM(this->get_logger(), "paths.cout : " << (uint32_t)count); + for (const auto &p : paths) { + strcpy(filePaths[index], p.c_str()); + RCLCPP_INFO_STREAM(this->get_logger(), + "path: " << (uint32_t)index << ":" << filePaths[index]); + index++; + } + RCLCPP_INFO_STREAM(this->get_logger(), + "Start to update optional depth preset, please wait a moment..."); + try { + device_->updateOptionalDepthPresets( + filePaths, count, + [this, &updateState, &firstCall](OBFwUpdateState state, const char *message, + uint8_t percent) { + updateState = state; + presetUpdateCallback(firstCall, state, message, percent); + // firstCall = false; + }); + + delete[] filePaths; + filePaths = nullptr; + if (updateState == STAT_DONE || updateState == STAT_DONE_WITH_DUPLICATES) { + RCLCPP_INFO_STREAM(this->get_logger(), "After updating the preset: "); + auto presetList = device_->getAvailablePresetList(); + RCLCPP_INFO_STREAM(this->get_logger(), "Preset count: " << presetList->getCount()); + for (uint32_t i = 0; i < presetList->getCount(); ++i) { + RCLCPP_INFO_STREAM(this->get_logger(), " - " << presetList->getName(i)); + } + RCLCPP_INFO_STREAM(this->get_logger(), + "Current preset: " << device_->getCurrentPresetName()); + std::string key = "PresetVer"; + if (device_->isExtensionInfoExist(key)) { + std::string value = device_->getExtensionInfo(key); + RCLCPP_INFO_STREAM(this->get_logger(), "Preset version: " << value); + } else { + RCLCPP_INFO_STREAM(this->get_logger(), "PresetVer: "); + } + } + } catch (ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to update Preset Firmware " << e.getMessage()); + } catch (std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to update Preset Firmware " << e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to update Preset Firmware"); + } + } +} +void OBCameraNodeDriver::presetUpdateCallback(bool firstCall, OBFwUpdateState state, + const char *message, uint8_t percent) { + if (!firstCall) { + std::cout << "\033[3F"; + } + + std::cout << "\033[K"; + std::cout << "Progress: " << static_cast(percent) << "%" << std::endl; + + std::cout << "\033[K"; + std::cout << "Status : "; + switch (state) { + case STAT_VERIFY_SUCCESS: + std::cout << "Image file verification success" << std::endl; + break; + case STAT_FILE_TRANSFER: + std::cout << "File transfer in progress" << std::endl; + break; + case STAT_DONE: + std::cout << "Update completed" << std::endl; + break; + case STAT_DONE_REBOOT_AND_REUPDATE: + std::cout << "Update completed, requires reboot and reupdate" << std::endl; + break; + case STAT_DONE_WITH_DUPLICATES: + std::cout << "Update completed, duplicated presets have been ignored" << std::endl; + break; + case STAT_IN_PROGRESS: + std::cout << "Update in progress" << std::endl; + break; + case STAT_START: + std::cout << "Starting the update" << std::endl; + break; + case STAT_VERIFY_IMAGE: + std::cout << "Verifying image file" << std::endl; + break; + default: + std::cout << "Unknown status or error" << std::endl; + break; + } + + std::cout << "\033[K"; + std::cout << "Message : " << message << std::endl << std::flush; +} +void OBCameraNodeDriver::firmwareUpdateCallback(OBFwUpdateState state, const char *message, + uint8_t percent) { + std::cout << "\033[K"; // Clear the current line + std::cout << "Progress: " << static_cast(percent) << "%" << std::endl; + + std::cout << "\033[K"; + std::cout << "Status : "; + switch (state) { + case STAT_VERIFY_SUCCESS: + std::cout << "Image file verification success" << std::endl; + break; + case STAT_FILE_TRANSFER: + std::cout << "File transfer in progress" << std::endl; + break; + case STAT_DONE: + std::cout << "Update completed" << std::endl; + break; + case STAT_DONE_REBOOT_AND_REUPDATE: + need_reupdate_ = true; + std::cout << "Update completed (requires reboot and reupdate)" << std::endl; + break; + case STAT_IN_PROGRESS: + std::cout << "Upgrade in progress" << std::endl; + break; + case STAT_START: + std::cout << "Starting the upgrade" << std::endl; + break; + case STAT_VERIFY_IMAGE: + std::cout << "Verifying image file" << std::endl; + break; + default: + std::cout << "Unknown status or error" << std::endl; + break; + } + + std::cout << "\033[K"; + std::cout << "Message : " << message << std::endl << std::flush; + if (state == STAT_DONE || state == STAT_DONE_REBOOT_AND_REUPDATE) { + RCLCPP_INFO(logger_, "Reboot device"); + + if (ob_camera_node_) { + // Don't call clean() here to avoid deadlock - just stop timers and reboot + // The resetDevice thread will handle proper cleanup when device disconnects + if (sync_host_time_timer_) { + try { + sync_host_time_timer_->cancel(); + sync_host_time_timer_.reset(); + } catch (...) { + RCLCPP_WARN_STREAM(logger_, "Exception during sync timer cleanup in firmware update"); + } + } + device_->reboot(); + } else if (ob_lidar_node_) { + ob_lidar_node_.reset(); + } + device_connected_ = false; + firmware_update_success_ = true; + if (state == STAT_DONE_REBOOT_AND_REUPDATE) { + // Keep upgrade_firmware_ path for second update + RCLCPP_INFO(logger_, "Firmware update requires a second update after reboot"); + } else { + upgrade_firmware_ = ""; + } + } +} + +OBDeviceAccessMode OBCameraNodeDriver::stringToAccessMode(const std::string &mode_str) { + std::string lower_mode; + std::transform(mode_str.begin(), mode_str.end(), std::back_inserter(lower_mode), + [](auto ch) { return tolower(ch); }); + + if (lower_mode == "ea") { + return OB_DEVICE_EXCLUSIVE_ACCESS; + } else if (lower_mode == "ca") { + return OB_DEVICE_CONTROL_ACCESS; + } else if (lower_mode == "mr") { + return OB_DEVICE_MONITOR_ACCESS; + } else if (lower_mode == "default") { + return OB_DEVICE_DEFAULT_ACCESS; + } else { + RCLCPP_WARN_STREAM(logger_, "Unknown access mode: " << mode_str << ", using default"); + return OB_DEVICE_DEFAULT_ACCESS; + } +} + +std::string OBCameraNodeDriver::accessModeToString(OBDeviceAccessMode mode) { + switch (mode) { + case OB_DEVICE_EXCLUSIVE_ACCESS: + return "EA"; + case OB_DEVICE_CONTROL_ACCESS: + return "CA"; + case OB_DEVICE_MONITOR_ACCESS: + return "MR"; + case OB_DEVICE_ACCESS_DENIED: + return "Denied"; + case OB_DEVICE_DEFAULT_ACCESS: + default: + return "Default"; + } +} +} // namespace orbbec_camera + +RCLCPP_COMPONENTS_REGISTER_NODE(orbbec_camera::OBCameraNodeDriver) diff --git a/dev_ws/src/orbbec_camera/src/ob_lidar_node.cpp b/dev_ws/src/orbbec_camera/src/ob_lidar_node.cpp new file mode 100644 index 0000000..27b2d7b --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/ob_lidar_node.cpp @@ -0,0 +1,1377 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "orbbec_camera/ob_lidar_node.h" +#include +#include +#include + +#include "orbbec_camera/utils.h" +#include +#include +#include "diagnostic_msgs/msg/diagnostic_status.hpp" +#include "libobsensor/hpp/Utils.hpp" + +namespace orbbec_camera { +namespace orbbec_lidar { +using namespace std::chrono_literals; + +OBLidarNode::OBLidarNode(rclcpp::Node *node, std::shared_ptr device, + std::shared_ptr parameters, bool use_intra_process) + : node_(node), + device_(std::move(device)), + parameters_(std::move(parameters)), + logger_(node->get_logger()), + use_intra_process_(use_intra_process) { + RCLCPP_INFO_STREAM(logger_, + "OBLidarNode: use_intra_process: " << (use_intra_process ? "ON" : "OFF")); + is_running_.store(true); + stream_name_[LIDAR] = "lidar"; + stream_name_[ACCEL] = "accel"; + stream_name_[GYRO] = "gyro"; + setupTopics(); + is_camera_node_initialized_ = true; +} + +template +void OBLidarNode::setAndGetNodeParameter( + T ¶m, const std::string ¶m_name, const T &default_value, + const rcl_interfaces::msg::ParameterDescriptor ¶meter_descriptor) { + try { + param = parameters_ + ->setParam(param_name, rclcpp::ParameterValue(default_value), + std::function(), parameter_descriptor) + .get(); + } catch (const rclcpp::ParameterTypeException &ex) { + RCLCPP_ERROR_STREAM(logger_, "Failed to set parameter: " << param_name << ". " << ex.what()); + throw; + } +} + +OBLidarNode::~OBLidarNode() noexcept { clean(); } + +void OBLidarNode::rebootDevice() { + RCLCPP_WARN_STREAM(logger_, "Reboot device"); + clean(); + if (device_) { + device_->reboot(); + RCLCPP_WARN_STREAM(logger_, "Reboot device DONE"); + } +} + +void OBLidarNode::clean() noexcept { + std::lock_guard lock(device_lock_); + RCLCPP_WARN_STREAM(logger_, "Do destroy ~OBLidarNode"); + is_running_.store(false); + RCLCPP_WARN_STREAM(logger_, "Stop tf thread"); + if (tf_thread_ && tf_thread_->joinable()) { + tf_thread_->join(); + } + RCLCPP_WARN_STREAM(logger_, "Stop color frame thread"); + RCLCPP_WARN_STREAM(logger_, "stop streams"); + stopStreams(); + stopIMU(); + RCLCPP_WARN_STREAM(logger_, "Destroy ~OBLidarNode DONE"); +} + +void OBLidarNode::setupTopics() { + try { + getParameters(); + setupDevices(); + selectBaseStream(); + setupProfiles(); + setupPublishers(); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to setup topics: " << e.getMessage()); + throw std::runtime_error(e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to setup topics: " << e.what()); + throw std::runtime_error(e.what()); + } catch (...) { + RCLCPP_ERROR(logger_, "Failed to setup topics"); + throw std::runtime_error("Failed to setup topics"); + } +} + +void OBLidarNode::getParameters() { + setAndGetNodeParameter(camera_name_, "camera_name", "lidar"); + for (auto stream_index : LIDAR_STREAMS) { + std::string param_name = stream_name_[stream_index] + "_format"; + setAndGetNodeParameter(format_str_[stream_index], param_name, format_str_[stream_index]); + format_[stream_index] = OBFormatFromString(format_str_[stream_index]); + param_name = stream_name_[stream_index] + "_rate"; + setAndGetNodeParameter(rate_int_[stream_index], param_name, 0); + rate_[stream_index] = OBScanRateFromInt(rate_int_[stream_index]); + RCLCPP_INFO_STREAM(logger_, "Input rate: " << magic_enum::enum_name(rate_[stream_index]) + << " Input format:" + << magic_enum::enum_name(format_[stream_index])); + param_name = stream_name_[stream_index] + "_frame_id"; + std::string default_frame_id = camera_name_ + "_" + stream_name_[stream_index] + "_frame"; + setAndGetNodeParameter(frame_id_[stream_index], param_name, default_frame_id); + std::string default_optical_frame_id = + camera_name_ + "_" + stream_name_[stream_index] + "_optical_frame"; + param_name = stream_name_[stream_index] + "_optical_frame_id"; + setAndGetNodeParameter(optical_frame_id_[stream_index], param_name, default_optical_frame_id); + } + setAndGetNodeParameter(enable_scan_to_point_, "enable_scan_to_point", false); + setAndGetNodeParameter(publish_tf_, "publish_tf", true); + setAndGetNodeParameter(tf_publish_rate_, "tf_publish_rate", 0.0); + setAndGetNodeParameter(time_domain_, "time_domain", "global"); + setAndGetNodeParameter(enable_heartbeat_, "enable_heartbeat", false); + setAndGetNodeParameter(echo_mode_, "echo_mode", ""); + setAndGetNodeParameter(point_cloud_qos_, "point_cloud_qos", "default"); + setAndGetNodeParameter(min_angle_, "min_angle", -135.0); + setAndGetNodeParameter(max_angle_, "max_angle", 135.0); + setAndGetNodeParameter(min_range_, "min_range", 0.05); + setAndGetNodeParameter(max_range_, "max_range", 30.0); + setAndGetNodeParameter(repetitive_scan_mode_, "repetitive_scan_mode", -1); + setAndGetNodeParameter(filter_level_, "filter_level", -1); + setAndGetNodeParameter(vertical_fov_, "vertical_fov", -1.0); + setAndGetNodeParameter(enable_imu_, "enable_imu", false); + setAndGetNodeParameter(imu_rate_, "imu_rate", "50hz"); + setAndGetNodeParameter(accel_range_, "accel_range", "2g"); + setAndGetNodeParameter(gyro_range_, "gyro_range", "1000dps"); + setAndGetNodeParameter(imu_qos_, "imu_qos", "default"); + setAndGetNodeParameter(liner_accel_cov_, "linear_accel_cov", 0.0003); + setAndGetNodeParameter(angular_vel_cov_, "angular_vel_cov", 0.02); + + // Multi-frame publishing parameter - only for LIDAR_POINT and LIDAR_SPHERE_POINT formats + setAndGetNodeParameter(publish_n_pkts_, "publish_n_pkts", 1); + if (publish_n_pkts_ < 1 || publish_n_pkts_ > 12000) { + RCLCPP_WARN_STREAM(logger_, "publish_n_pkts value " + << publish_n_pkts_ + << " is out of range [1, 12000], setting to 1"); + publish_n_pkts_ = 1; + } + if (publish_n_pkts_ > 1) + RCLCPP_INFO_STREAM( + logger_, "Multi-frame publishing enabled: " << publish_n_pkts_ << " frames will be merged"); + + // Setup IMU streams if enabled + if (enable_imu_) { + enable_stream_[ACCEL] = true; + enable_stream_[GYRO] = true; + + for (const auto &stream_index : HID_STREAMS) { + std::string param_name = camera_name_ + "_" + stream_name_[stream_index] + "_frame_id"; + std::string default_frame_id = camera_name_ + "_" + stream_name_[stream_index] + "_frame"; + setAndGetNodeParameter(frame_id_[stream_index], param_name, default_frame_id); + std::string default_optical_frame_id = + camera_name_ + "_" + stream_name_[stream_index] + "_optical_frame"; + param_name = stream_name_[stream_index] + "_optical_frame_id"; + setAndGetNodeParameter(optical_frame_id_[stream_index], param_name, default_optical_frame_id); + } + + // Set unified IMU frame ID + accel_gyro_frame_id_ = camera_name_ + "_imu_frame"; + } +} + +void OBLidarNode::setupDevices() { + auto sensor_list = device_->getSensorList(); + for (size_t i = 0; i < sensor_list->getCount(); i++) { + auto sensor = sensor_list->getSensor(i); + auto profiles = sensor->getStreamProfileList(); + for (size_t j = 0; j < profiles->getCount(); j++) { + auto profile = profiles->getProfile(j); + stream_index_pair sip{profile->getType(), 0}; + if (sensors_.find(sip) != sensors_.end()) { + continue; + } + sensors_[sip] = sensor; + } + } + for (const auto &[stream_index, enable] : enable_stream_) { + if (enable && sensors_.find(stream_index) == sensors_.end()) { + RCLCPP_INFO_STREAM(logger_, + magic_enum::enum_name(stream_index.first) + << "sensor isn't supported by current device! -- Skipping..."); + enable_stream_[stream_index] = false; + } + } + if (device_->isPropertySupported(OB_PROP_HEARTBEAT_BOOL, OB_PERMISSION_READ_WRITE)) { + RCLCPP_INFO_STREAM(logger_, "Setting heartbeat to " << (enable_heartbeat_ ? "ON" : "OFF")); + TRY_TO_SET_PROPERTY(setBoolProperty, OB_PROP_HEARTBEAT_BOOL, enable_heartbeat_); + } + if (!echo_mode_.empty() && + device_->isPropertySupported(OB_PROP_LIDAR_SPECIFIC_MODE_INT, OB_PERMISSION_READ_WRITE)) { + if (echo_mode_ == "Last Echo") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LIDAR_SPECIFIC_MODE_INT, 0); + } else if (echo_mode_ == "First Echo") { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LIDAR_SPECIFIC_MODE_INT, 1); + } + RCLCPP_INFO_STREAM( + logger_, "Setting echo mode to " + << (device_->getIntProperty(OB_PROP_LIDAR_SPECIFIC_MODE_INT) ? "First Echo" + : "Last Echo")); + } + if (repetitive_scan_mode_ != -1 && + device_->isPropertySupported(OB_PROP_LIDAR_REPETITIVE_SCAN_MODE_INT, + OB_PERMISSION_READ_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_LIDAR_REPETITIVE_SCAN_MODE_INT); + if (repetitive_scan_mode_ < range.min || repetitive_scan_mode_ > range.max) { + RCLCPP_ERROR(logger_, + "repetitive scan mode value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LIDAR_REPETITIVE_SCAN_MODE_INT, + repetitive_scan_mode_); + RCLCPP_INFO_STREAM(logger_, "Setting repetitive scan mode to " << device_->getIntProperty( + OB_PROP_LIDAR_REPETITIVE_SCAN_MODE_INT)); + } + } + if (filter_level_ != -1 && + device_->isPropertySupported(OB_PROP_LIDAR_TAIL_FILTER_LEVEL_INT, OB_PERMISSION_READ_WRITE)) { + auto range = device_->getIntPropertyRange(OB_PROP_LIDAR_TAIL_FILTER_LEVEL_INT); + if (filter_level_ < range.min || filter_level_ > range.max) { + RCLCPP_ERROR(logger_, "filter level value is out of range[%d,%d], please check the value", + range.min, range.max); + } else { + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LIDAR_TAIL_FILTER_LEVEL_INT, filter_level_); + TRY_TO_SET_PROPERTY(setIntProperty, OB_PROP_LIDAR_APPLY_CONFIGS_INT, 1); + RCLCPP_INFO_STREAM(logger_, "Setting filter level to " << device_->getIntProperty( + OB_PROP_LIDAR_TAIL_FILTER_LEVEL_INT)); + } + } + + if (vertical_fov_ != -1.0 && + device_->isPropertySupported(OB_PROP_LIDAR_MEMS_FOV_SIZE_FLOAT, OB_PERMISSION_READ_WRITE)) { + auto range = device_->getFloatPropertyRange(OB_PROP_LIDAR_MEMS_FOV_SIZE_FLOAT); + if (vertical_fov_ < range.min || vertical_fov_ > range.max) { + RCLCPP_ERROR(logger_, "vertical fov value is out of range[%f,%f], please check the value", + range.min, range.max); + } else { + TRY_TO_SET_PROPERTY(setFloatProperty, OB_PROP_LIDAR_MEMS_FOV_SIZE_FLOAT, vertical_fov_); + RCLCPP_INFO_STREAM(logger_, "Setting vertical fov to " << device_->getFloatProperty( + OB_PROP_LIDAR_MEMS_FOV_SIZE_FLOAT)); + } + } +} + +void OBLidarNode::setupProfiles() { + for (const auto &elem : LIDAR_STREAMS) { + if (enable_stream_[elem]) { + const auto &sensor = sensors_[elem]; + CHECK_NOTNULL(sensor.get()); + auto profiles = sensor->getStreamProfileList(); + CHECK_NOTNULL(profiles.get()); + CHECK(profiles->getCount() > 0); + for (size_t i = 0; i < profiles->getCount(); i++) { + auto base_profile = profiles->getProfile(i)->as(); + if (base_profile == nullptr) { + throw std::runtime_error("Failed to get profile " + std::to_string(i)); + } + auto profile = base_profile->as(); + if (profile == nullptr) { + throw std::runtime_error("Failed cast profile to LiDARStreamProfile"); + } + RCLCPP_DEBUG_STREAM(logger_, + "Sensor profile: " + << "stream_type: " << magic_enum::enum_name(profile->getType()) + << "Scan Rate: " << magic_enum::enum_name(profile->getScanRate()) + << "Format:" << magic_enum::enum_name(profile->getFormat())); + supported_profiles_[elem].emplace_back(profile); + } + std::shared_ptr selected_profile; + std::shared_ptr default_profile; + try { + if (rate_[elem] == OB_LIDAR_SCAN_UNKNOWN && format_[elem] == OB_FORMAT_UNKNOWN) { + selected_profile = profiles->getProfile(0)->as(); + } else { + selected_profile = profiles->getLiDARStreamProfile(rate_[elem], format_[elem]); + } + + } catch (const ob::Error &ex) { + RCLCPP_ERROR_STREAM( + logger_, "Failed to get " << stream_name_[elem] << " profile: " << ex.getMessage()); + RCLCPP_ERROR_STREAM(logger_, "Stream: " << magic_enum::enum_name(elem.first) + << ", Stream Index: " << elem.second + << ", Scan Rate: " << rate_[elem] + << "Format:" << format_[elem]); + RCLCPP_INFO_STREAM(logger_, "Available profiles:"); + printSensorProfiles(sensor); + RCLCPP_ERROR(logger_, "Because can not set this stream, so exit."); + exit(-1); + } + if (!selected_profile) { + RCLCPP_WARN_STREAM(logger_, "Given stream configuration is not supported by the device! " + << " Stream: " << magic_enum::enum_name(elem.first) + << ", Stream Index: " << elem.second + << ", Scan Rate: " << rate_[elem]); + if (default_profile) { + RCLCPP_WARN_STREAM(logger_, "Using default profile instead."); + RCLCPP_WARN_STREAM(logger_, "default scan Rate " + << magic_enum::enum_name(default_profile->getScanRate()) + << "default format:" + << magic_enum::enum_name(default_profile->getFormat())); + selected_profile = default_profile; + } else { + RCLCPP_ERROR_STREAM( + logger_, " NO default_profile found , Stream: " << magic_enum::enum_name(elem.first) + << " will be disable"); + enable_stream_[elem] = false; + } + } + CHECK_NOTNULL(selected_profile); + stream_profile_[elem] = selected_profile; + rate_[elem] = selected_profile->getScanRate(); + format_[elem] = selected_profile->getFormat(); + RCLCPP_INFO_STREAM(logger_, " stream " + << stream_name_[elem] << " is enabled - scan rate: " + << magic_enum::enum_name(selected_profile->getScanRate()) + << " format:" + << magic_enum::enum_name(selected_profile->getFormat())); + } + } + // IMU + for (const auto &stream_index : HID_STREAMS) { + if (!enable_stream_[stream_index]) { + continue; + } + try { + auto profile_list = sensors_[stream_index]->getStreamProfileList(); + if (stream_index == ACCEL) { + auto full_scale_range = fullAccelScaleRangeFromString(accel_range_); + auto sample_rate = sampleRateFromString(imu_rate_); + auto profile = profile_list->getAccelStreamProfile(full_scale_range, sample_rate); + stream_profile_[stream_index] = profile; + } else if (stream_index == GYRO) { + auto full_scale_range = fullGyroScaleRangeFromString(gyro_range_); + auto sample_rate = sampleRateFromString(imu_rate_); + auto profile = profile_list->getGyroStreamProfile(full_scale_range, sample_rate); + stream_profile_[stream_index] = profile; + } + RCLCPP_INFO_STREAM(logger_, "stream " << stream_name_[stream_index] << " full scale range " + << (stream_index == ACCEL ? accel_range_ : gyro_range_) + << " sample rate " << imu_rate_); + } catch (const ob::Error &e) { + RCLCPP_INFO_STREAM(logger_, "Failed to setup << " << stream_name_[stream_index] + << " profile: " << e.getMessage()); + enable_stream_[stream_index] = false; + stream_profile_[stream_index] = nullptr; + } + } +} + +void OBLidarNode::selectBaseStream() { + enable_stream_[LIDAR] = true; + if (enable_stream_[LIDAR]) { + base_stream_ = LIDAR; + } +} + +void OBLidarNode::printSensorProfiles(const std::shared_ptr &sensor) { + auto profiles = sensor->getStreamProfileList(); + for (size_t i = 0; i < profiles->getCount(); i++) { + auto origin_profile = profiles->getProfile(i); + if (sensor->getType() == OB_SENSOR_LIDAR) { + auto profile = origin_profile->as(); + RCLCPP_INFO_STREAM(logger_, "lidar scan rate: " + << profile->getScanRate() + << " format:" << magic_enum::enum_name(profile->getFormat())); + } else { + RCLCPP_INFO_STREAM(logger_, "unknown profile: " << magic_enum::enum_name(sensor->getType())); + } + } +} +void OBLidarNode::setupPublishers() { + auto point_cloud_qos_profile = getRMWQosProfileFromString(point_cloud_qos_); + if (use_intra_process_) { + point_cloud_qos_profile = rmw_qos_profile_default; + } + if (!enable_scan_to_point_ && format_[LIDAR] == OB_FORMAT_LIDAR_SCAN) { + scan_pub_ = node_->create_publisher( + "scan/points", rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(point_cloud_qos_profile), + point_cloud_qos_profile)); + } else if (enable_scan_to_point_ || format_[LIDAR] == OB_FORMAT_LIDAR_POINT || + format_[LIDAR] == OB_FORMAT_LIDAR_SPHERE_POINT) { + point_cloud_pub_ = node_->create_publisher( + "cloud/points", rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(point_cloud_qos_profile), + point_cloud_qos_profile)); + } + if (enable_imu_) { + std::string topic_name = "imu/sample"; + auto data_qos = getRMWQosProfileFromString(imu_qos_); + if (use_intra_process_) { + data_qos = rmw_qos_profile_default; + } + imu_publisher_ = node_->create_publisher( + topic_name, rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(data_qos), data_qos)); + } + auto extrinsics_qos = rclcpp::QoS(1).transient_local(); + if (use_intra_process_) { + extrinsics_qos = rclcpp::QoS(1); + } + if (enable_imu_) { + lidar_to_imu_extrinsics_publisher_ = + node_->create_publisher( + "/" + camera_name_ + "/lidar_to_imu", extrinsics_qos); + } +} + +void OBLidarNode::startStreams() { + if (pipeline_ != nullptr) { + pipeline_.reset(); + } + pipeline_ = std::make_unique(device_); + + try { + setupPipelineConfig(); + pipeline_->start(pipeline_config_, [this](const std::shared_ptr &frame_set) { + onNewFrameSetCallback(frame_set); + }); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to start pipeline: " << e.getMessage()); + setupPipelineConfig(); + pipeline_->start(pipeline_config_, [this](const std::shared_ptr &frame_set) { + onNewFrameSetCallback(frame_set); + }); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to start pipeline"); + throw std::runtime_error("Failed to start pipeline"); + } + pipeline_started_.store(true); +} + +void OBLidarNode::startIMU() { + if (!enable_imu_) { + return; + } + + if (imuPipeline_ != nullptr) { + imuPipeline_.reset(); + } + + imuPipeline_ = std::make_unique(device_); + if (imu_sync_output_start_) { + return; + } + + // ACCEL + auto accelProfiles = imuPipeline_->getStreamProfileList(OB_SENSOR_ACCEL); + auto accel_range = fullAccelScaleRangeFromString(accel_range_); + auto accel_rate = sampleRateFromString(imu_rate_); + auto accelProfile = accelProfiles->getAccelStreamProfile(accel_range, accel_rate); + + // GYRO + auto gyroProfiles = imuPipeline_->getStreamProfileList(OB_SENSOR_GYRO); + auto gyro_range = fullGyroScaleRangeFromString(gyro_range_); + auto gyro_rate = sampleRateFromString(imu_rate_); + auto gyroProfile = gyroProfiles->getGyroStreamProfile(gyro_range, gyro_rate); + + std::shared_ptr imuConfig = std::make_shared(); + imuConfig->enableStream(accelProfile); + imuConfig->enableStream(gyroProfile); + TRY_EXECUTE_BLOCK(imuPipeline_->enableFrameSync()); + imuPipeline_->start(imuConfig, [&](std::shared_ptr frame) { + auto frameSet = frame->as(); + auto aFrame = frameSet->getFrame(OB_FRAME_ACCEL); + auto gFrame = frameSet->getFrame(OB_FRAME_GYRO); + if (aFrame && gFrame) { + onNewIMUFrameCallback(aFrame, gFrame); + } + }); + + imu_sync_output_start_ = true; + if (!imu_sync_output_start_) { + RCLCPP_ERROR_STREAM( + logger_, "Failed to start IMU stream, please check the imu_rate and imu_range parameters."); + } else { + RCLCPP_INFO_STREAM(logger_, "Started IMU stream with accel range: " + << fullAccelScaleRangeToString(accel_range) + << ", gyro range: " << fullGyroScaleRangeToString(gyro_range) + << ", rate: " << sampleRateToString(accel_rate)); + } +} + +void OBLidarNode::stopStreams() { + if (!pipeline_started_ || !pipeline_) { + RCLCPP_INFO_STREAM(logger_, "pipeline not started or not exist, skip stop pipeline"); + return; + } + try { + pipeline_->stop(); + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop pipeline: " << e.getMessage()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop pipeline"); + } +} + +void OBLidarNode::stopIMU() { + if (!enable_imu_) { + return; + } + + if (!imu_sync_output_start_ || !imuPipeline_) { + RCLCPP_INFO_STREAM(logger_, "IMU pipeline not started or not exist, skip stop imu pipeline"); + return; + } + try { + imuPipeline_->stop(); + imu_sync_output_start_ = false; + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop IMU pipeline: " << e.getMessage()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "Failed to stop IMU pipeline"); + } +} + +void OBLidarNode::setupPipelineConfig() { + if (pipeline_config_) { + pipeline_config_.reset(); + } + pipeline_config_ = std::make_shared(); + for (const auto &stream_index : LIDAR_STREAMS) { + if (enable_stream_[stream_index]) { + RCLCPP_INFO_STREAM(logger_, "Enable " << stream_name_[stream_index] << " stream"); + auto profile = stream_profile_[stream_index]->as(); + + if (enable_stream_[stream_index]) { + auto video_profile = profile; + RCLCPP_INFO_STREAM(logger_, + "lidar profile: " << magic_enum::enum_name(video_profile->getScanRate()) + << " " + << magic_enum::enum_name(video_profile->getFormat())); + } + + RCLCPP_INFO_STREAM( + logger_, "Stream " << stream_name_[stream_index] + << " scan rate: " << magic_enum::enum_name(profile->getScanRate()) + << " format: " << magic_enum::enum_name(profile->getFormat())); + pipeline_config_->enableStream(stream_profile_[stream_index]); + } + } +} + +void OBLidarNode::onNewIMUFrameCallback(const std::shared_ptr &accelframe, + const std::shared_ptr &gryoframe) { + if (!is_camera_node_initialized_) { + return; + } + if (!imu_publisher_) { + RCLCPP_ERROR_STREAM(logger_, "IMU publisher not initialized"); + return; + } + + if (!tf_published_) { + publishStaticTransforms(); + tf_published_ = true; + } + + bool has_subscriber = imu_publisher_->get_subscription_count() > 0; + if (!has_subscriber) { + return; + } + + auto imu_msg = sensor_msgs::msg::Imu(); + setDefaultIMUMessage(imu_msg); + + imu_msg.header.frame_id = accel_gyro_frame_id_; + auto frame_timestamp = getFrameTimestampUs(accelframe); + auto timestamp = fromUsToROSTime(frame_timestamp); + imu_msg.header.stamp = timestamp; + + auto gyro_frame = gryoframe->as(); + auto gyroData = gyro_frame->getValue(); + + imu_msg.angular_velocity.x = -gyroData.x; + imu_msg.angular_velocity.y = gyroData.y; + imu_msg.angular_velocity.z = -gyroData.z; + + auto accel_frame = accelframe->as(); + auto accelData = accel_frame->getValue(); + imu_msg.linear_acceleration.x = -accelData.x; + imu_msg.linear_acceleration.y = accelData.y; + imu_msg.linear_acceleration.z = -accelData.z; + + imu_publisher_->publish(imu_msg); +} + +void OBLidarNode::onNewFrameSetCallback(std::shared_ptr frame_set) { + if (!is_running_.load()) { + return; + } + if (!is_camera_node_initialized_.load()) { + return; + } + if (frame_set == nullptr) { + return; + } + try { + RCLCPP_INFO_ONCE(logger_, "New frame received"); + if (!tf_published_ && !enable_imu_) { + publishStaticTransforms(); + tf_published_ = true; + } + + // Handle multi-frame publishing for LIDAR_POINT and LIDAR_SPHERE_POINT formats + if ((format_[LIDAR] == OB_FORMAT_LIDAR_POINT || + format_[LIDAR] == OB_FORMAT_LIDAR_SPHERE_POINT)) { + if (publish_n_pkts_ == 1) { + if (format_[LIDAR] == OB_FORMAT_LIDAR_POINT) { + publishPointCloud(frame_set); + return; + } else if (format_[LIDAR] == OB_FORMAT_LIDAR_SPHERE_POINT) { + publishSpherePointCloud(frame_set); + return; + } + } + std::lock_guard lock(frame_buffer_mutex_); + frame_buffer_.push_back(frame_set); + // If we have enough frames, publish merged point cloud + if (frame_buffer_.size() >= static_cast(publish_n_pkts_)) { + if (format_[LIDAR] == OB_FORMAT_LIDAR_POINT) { + publishMergedPointCloud(); + } else if (format_[LIDAR] == OB_FORMAT_LIDAR_SPHERE_POINT) { + publishMergedSpherePointCloud(); + } + frame_buffer_.clear(); + } + } else { + // Original single frame publishing logic + if (format_[LIDAR] == OB_FORMAT_LIDAR_SCAN && !enable_scan_to_point_) { + publishScan(frame_set); + } else if (format_[LIDAR] == OB_FORMAT_LIDAR_SCAN && enable_scan_to_point_) { + publishScanToPoint(frame_set); + } + } + } catch (const ob::Error &e) { + RCLCPP_ERROR_STREAM(logger_, "onNewFrameSetCallback error: " << e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(logger_, "onNewFrameSetCallback error: " << e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM(logger_, "onNewFrameSetCallback error: unknown error"); + } +} + +void OBLidarNode::publishScan(std::shared_ptr frame_set) { + (void)frame_set; + if (angle_increment_ == 0.0) { + angle_increment_ = getScanAngleIncrement(rate_[LIDAR]); + } + if (frame_set == nullptr) { + return; + } + // std::shared_ptr lidar_frame; + auto lidar_frame = frame_set->getFrame(OB_FRAME_LIDAR_POINTS); + auto *scans_data = reinterpret_cast(lidar_frame->getData()); + auto scan_count = lidar_frame->getDataSize() / sizeof(OBLiDARScanPoint); + auto frame_timestamp = getFrameTimestampUs(lidar_frame); + auto timestamp = fromUsToROSTime(frame_timestamp); + auto scan_msg = std::make_unique(); + scan_msg->header.stamp = timestamp; + scan_msg->header.frame_id = frame_id_[LIDAR]; + scan_msg->angle_min = 0.7853981852531433; + scan_msg->angle_max = 5.495169162750244; + scan_msg->angle_increment = angle_increment_; + scan_msg->time_increment = 1.0 / rate_int_[LIDAR] / scan_count; + scan_msg->scan_time = 1.0 / rate_int_[LIDAR]; + scan_msg->range_min = min_range_; + scan_msg->range_max = max_range_; + scan_msg->ranges.resize(scan_count); + scan_msg->intensities.resize(scan_count); + for (size_t i = 0; i < scan_count; ++i) { + if (scans_data->distance < min_range_ && scans_data->distance > max_range_) { + scans_data++; + continue; + } + scan_msg->ranges[i] = scans_data[i].distance / 1000.0; + scan_msg->intensities[i] = scans_data[i].intensity; + } + filterScan(*scan_msg); + scan_pub_->publish(std::move(scan_msg)); +} + +void OBLidarNode::publishScanToPoint(std::shared_ptr frame_set) { + (void)frame_set; + if (frame_set == nullptr) { + return; + } + if (angle_increment_ == 0.0) { + angle_increment_ = getScanAngleIncrement(rate_[LIDAR]); + } + auto lidar_frame = frame_set->getFrame(OB_FRAME_LIDAR_POINTS); + auto *scans_data = reinterpret_cast(lidar_frame->getData()); + auto scan_count = lidar_frame->getDataSize() / sizeof(OBLiDARScanPoint); + auto point_cloud_msg = std::make_unique(); + sensor_msgs::PointCloud2Modifier modifier(*point_cloud_msg); + modifier.setPointCloud2Fields(4, "x", 1, sensor_msgs::msg::PointField::FLOAT32, "y", 1, + sensor_msgs::msg::PointField::FLOAT32, "z", 1, + sensor_msgs::msg::PointField::FLOAT32, "intensity", 1, + sensor_msgs::msg::PointField::UINT8); + modifier.resize(scan_count); + auto frame_timestamp = getFrameTimestampUs(lidar_frame); + auto timestamp = fromUsToROSTime(frame_timestamp); + point_cloud_msg->header.stamp = timestamp; + point_cloud_msg->header.frame_id = frame_id_[LIDAR]; + point_cloud_msg->height = 1; + point_cloud_msg->width = scan_count; + point_cloud_msg->is_dense = true; + point_cloud_msg->is_bigendian = false; + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + point_cloud_msg->data.resize(point_cloud_msg->height * point_cloud_msg->row_step); + sensor_msgs::PointCloud2Iterator iter_x(*point_cloud_msg, "x"); + sensor_msgs::PointCloud2Iterator iter_y(*point_cloud_msg, "y"); + sensor_msgs::PointCloud2Iterator iter_z(*point_cloud_msg, "z"); + sensor_msgs::PointCloud2Iterator iter_intensity(*point_cloud_msg, "intensity"); + for (size_t i = 0; i < scan_count; ++i, ++iter_x, ++iter_y, ++iter_z, ++iter_intensity) { + double rad = 0.7853981852531433 + angle_increment_ * i; + *iter_x = static_cast(scans_data[i].distance * cos(rad) / 1000.0); + *iter_y = static_cast(scans_data[i].distance * sin(rad) / 1000.0); + *iter_z = static_cast(0.0); + *iter_intensity = static_cast(scans_data[i].intensity); + } + *point_cloud_msg = filterPointCloud(*point_cloud_msg); + point_cloud_pub_->publish(std::move(point_cloud_msg)); +} + +void OBLidarNode::publishPointCloud(std::shared_ptr frame_set) { + (void)frame_set; + if (frame_set == nullptr) { + return; + } + auto lidar_frame = frame_set->getFrame(OB_FRAME_LIDAR_POINTS); + auto *point_data = reinterpret_cast(lidar_frame->getData()); + auto point_count = lidar_frame->getDataSize() / sizeof(OBLiDARPoint); + auto frame_timestamp = getFrameTimestampUs(lidar_frame); + auto timestamp = fromUsToROSTime(frame_timestamp); + auto point_cloud_msg = std::make_unique(); + sensor_msgs::PointCloud2Modifier modifier(*point_cloud_msg); + modifier.setPointCloud2Fields(5, "x", 1, sensor_msgs::msg::PointField::FLOAT32, "y", 1, + sensor_msgs::msg::PointField::FLOAT32, "z", 1, + sensor_msgs::msg::PointField::FLOAT32, "intensity", 1, + sensor_msgs::msg::PointField::UINT8, "tag", 1, + sensor_msgs::msg::PointField::UINT8); + modifier.resize(point_count); + point_cloud_msg->header.stamp = timestamp; + point_cloud_msg->header.frame_id = frame_id_[LIDAR]; + point_cloud_msg->height = 1; + point_cloud_msg->width = point_count; + point_cloud_msg->is_dense = true; + point_cloud_msg->is_bigendian = false; + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + point_cloud_msg->data.resize(point_cloud_msg->height * point_cloud_msg->row_step); + sensor_msgs::PointCloud2Iterator iter_x(*point_cloud_msg, "x"); + sensor_msgs::PointCloud2Iterator iter_y(*point_cloud_msg, "y"); + sensor_msgs::PointCloud2Iterator iter_z(*point_cloud_msg, "z"); + sensor_msgs::PointCloud2Iterator iter_intensity(*point_cloud_msg, "intensity"); + sensor_msgs::PointCloud2Iterator iter_tag(*point_cloud_msg, "tag"); + for (size_t i = 0; i < point_count; + ++i, ++iter_x, ++iter_y, ++iter_z, ++iter_intensity, ++iter_tag) { + *iter_x = static_cast(point_data[i].x / 1000.0); + *iter_y = static_cast(point_data[i].y / 1000.0); + *iter_z = static_cast(point_data[i].z / 1000.0); + *iter_intensity = point_data[i].reflectivity; + *iter_tag = point_data[i].tag; + } + *point_cloud_msg = filterPointCloud(*point_cloud_msg); + point_cloud_pub_->publish(std::move(point_cloud_msg)); +} + +void OBLidarNode::publishSpherePointCloud(std::shared_ptr frame_set) { + (void)frame_set; + if (frame_set == nullptr) { + return; + } + auto lidar_frame = frame_set->getFrame(OB_FRAME_LIDAR_POINTS); + auto *point_data = reinterpret_cast(lidar_frame->getData()); + auto point_count = lidar_frame->getDataSize() / sizeof(OBLiDARSpherePoint); + auto result_point = spherePointToPoint(point_data, point_count); + auto frame_timestamp = getFrameTimestampUs(lidar_frame); + auto timestamp = fromUsToROSTime(frame_timestamp); + auto point_cloud_msg = std::make_unique(); + sensor_msgs::PointCloud2Modifier modifier(*point_cloud_msg); + modifier.setPointCloud2Fields(5, "x", 1, sensor_msgs::msg::PointField::FLOAT32, "y", 1, + sensor_msgs::msg::PointField::FLOAT32, "z", 1, + sensor_msgs::msg::PointField::FLOAT32, "intensity", 1, + sensor_msgs::msg::PointField::UINT8, "tag", 1, + sensor_msgs::msg::PointField::UINT8); + modifier.resize(point_count); + point_cloud_msg->header.stamp = timestamp; + point_cloud_msg->header.frame_id = frame_id_[LIDAR]; + point_cloud_msg->height = 1; + point_cloud_msg->width = point_count; + point_cloud_msg->is_dense = true; + point_cloud_msg->is_bigendian = false; + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + point_cloud_msg->data.resize(point_cloud_msg->height * point_cloud_msg->row_step); + sensor_msgs::PointCloud2Iterator iter_x(*point_cloud_msg, "x"); + sensor_msgs::PointCloud2Iterator iter_y(*point_cloud_msg, "y"); + sensor_msgs::PointCloud2Iterator iter_z(*point_cloud_msg, "z"); + sensor_msgs::PointCloud2Iterator iter_intensity(*point_cloud_msg, "intensity"); + sensor_msgs::PointCloud2Iterator iter_tag(*point_cloud_msg, "tag"); + for (size_t i = 0; i < point_count; + ++i, ++iter_x, ++iter_y, ++iter_z, ++iter_intensity, ++iter_tag) { + *iter_x = static_cast(result_point[i].x / 1000.0); + *iter_y = static_cast(result_point[i].y / 1000.0); + *iter_z = static_cast(result_point[i].z / 1000.0); + *iter_intensity = result_point[i].reflectivity; + *iter_tag = result_point[i].tag; + } + *point_cloud_msg = filterPointCloud(*point_cloud_msg); + point_cloud_pub_->publish(std::move(point_cloud_msg)); +} + +void OBLidarNode::publishMergedPointCloud() { + if (frame_buffer_.empty()) { + return; + } + + // Calculate total point count across all frames + size_t total_point_count = 0; + std::vector> frame_data; + std::vector frame_timestamps; + + for (const auto &fs : frame_buffer_) { + auto lidar_frame = fs->getFrame(OB_FRAME_LIDAR_POINTS); + if (lidar_frame) { + auto *point_data = reinterpret_cast(lidar_frame->getData()); + auto point_count = lidar_frame->getDataSize() / sizeof(OBLiDARPoint); + frame_data.emplace_back(point_data, point_count); + frame_timestamps.push_back(getFrameTimestampUs(lidar_frame)); + total_point_count += point_count; + } + } + + if (total_point_count == 0) { + return; + } + + // Create merged point cloud message with offset_time field + auto point_cloud_msg = std::make_unique(); + sensor_msgs::PointCloud2Modifier modifier(*point_cloud_msg); + modifier.setPointCloud2Fields( + 6, "x", 1, sensor_msgs::msg::PointField::FLOAT32, "y", 1, + sensor_msgs::msg::PointField::FLOAT32, "z", 1, sensor_msgs::msg::PointField::FLOAT32, + "intensity", 1, sensor_msgs::msg::PointField::UINT8, "tag", 1, + sensor_msgs::msg::PointField::UINT8, "offset_time", 1, sensor_msgs::msg::PointField::UINT32); + modifier.resize(total_point_count); + + // Use the timestamp of the latest frame as the header timestamp + auto timestamp = fromUsToROSTime(frame_timestamps.front()); + point_cloud_msg->header.stamp = timestamp; + point_cloud_msg->header.frame_id = frame_id_[LIDAR]; + point_cloud_msg->height = 1; + point_cloud_msg->width = total_point_count; + point_cloud_msg->is_dense = true; + point_cloud_msg->is_bigendian = false; + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + point_cloud_msg->data.resize(point_cloud_msg->height * point_cloud_msg->row_step); + + // Create iterators + sensor_msgs::PointCloud2Iterator iter_x(*point_cloud_msg, "x"); + sensor_msgs::PointCloud2Iterator iter_y(*point_cloud_msg, "y"); + sensor_msgs::PointCloud2Iterator iter_z(*point_cloud_msg, "z"); + sensor_msgs::PointCloud2Iterator iter_intensity(*point_cloud_msg, "intensity"); + sensor_msgs::PointCloud2Iterator iter_tag(*point_cloud_msg, "tag"); + sensor_msgs::PointCloud2Iterator iter_offset_time(*point_cloud_msg, "offset_time"); + + // Calculate frame time interval based on lidar rate + double frame_interval_us = 1000000.0 / static_cast(rate_int_[LIDAR]); + + // Merge all frames with per-point timestamps + for (size_t frame_idx = 0; frame_idx < frame_data.size(); ++frame_idx) { + auto [point_data, point_count] = frame_data[frame_idx]; + uint64_t frame_timestamp_us = frame_timestamps[frame_idx]; + + // Calculate time increment per point within this frame (uniform sampling) + double point_time_increment_us = frame_interval_us / static_cast(point_count); + + // RCLCPP_INFO_STREAM(logger_, "Frame1 " << frame_idx << ": point_count = " << point_count + // << ", frame_timestamp_us = " << frame_timestamp_us + // << ", point_time_increment_us = " << + // point_time_increment_us); + for (size_t i = 0; i < point_count; + ++i, ++iter_x, ++iter_y, ++iter_z, ++iter_intensity, ++iter_tag, ++iter_offset_time) { + *iter_x = static_cast(point_data[i].x / 1000.0); + *iter_y = static_cast(point_data[i].y / 1000.0); + *iter_z = static_cast(point_data[i].z / 1000.0); + *iter_intensity = point_data[i].reflectivity; + *iter_tag = point_data[i].tag; + + // Calculate per-point offset time in nanoseconds relative to point cloud header timestamp + double point_timestamp_us = + static_cast(frame_timestamp_us) + (i * point_time_increment_us); + uint64_t header_timestamp_us = frame_timestamps[0]; // First frame timestamp + *iter_offset_time = + static_cast((point_timestamp_us - static_cast(header_timestamp_us)) * + 1000.0); // Convert to nanoseconds + } + } + + *point_cloud_msg = filterPointCloud(*point_cloud_msg); + point_cloud_pub_->publish(std::move(point_cloud_msg)); +} + +void OBLidarNode::publishMergedSpherePointCloud() { + if (frame_buffer_.empty()) { + return; + } + + // Calculate total point count across all frames + size_t total_point_count = 0; + std::vector> frame_data; + std::vector frame_timestamps; + + for (const auto &fs : frame_buffer_) { + auto lidar_frame = fs->getFrame(OB_FRAME_LIDAR_POINTS); + if (lidar_frame) { + auto *point_data = reinterpret_cast(lidar_frame->getData()); + auto point_count = lidar_frame->getDataSize() / sizeof(OBLiDARSpherePoint); + frame_data.emplace_back(point_data, point_count); + frame_timestamps.push_back(getFrameTimestampUs(lidar_frame)); + total_point_count += point_count; + } + } + + if (total_point_count == 0) { + return; + } + + // Create merged point cloud message with timestamp field + auto point_cloud_msg = std::make_unique(); + sensor_msgs::PointCloud2Modifier modifier(*point_cloud_msg); + modifier.setPointCloud2Fields( + 6, "x", 1, sensor_msgs::msg::PointField::FLOAT32, "y", 1, + sensor_msgs::msg::PointField::FLOAT32, "z", 1, sensor_msgs::msg::PointField::FLOAT32, + "intensity", 1, sensor_msgs::msg::PointField::UINT8, "tag", 1, + sensor_msgs::msg::PointField::UINT8, "offset_time", 1, sensor_msgs::msg::PointField::UINT32); + modifier.resize(total_point_count); + + // Use the timestamp of the latest frame as the header timestamp + auto timestamp = fromUsToROSTime(frame_timestamps.front()); + point_cloud_msg->header.stamp = timestamp; + point_cloud_msg->header.frame_id = frame_id_[LIDAR]; + point_cloud_msg->height = 1; + point_cloud_msg->width = total_point_count; + point_cloud_msg->is_dense = true; + point_cloud_msg->is_bigendian = false; + point_cloud_msg->row_step = point_cloud_msg->width * point_cloud_msg->point_step; + point_cloud_msg->data.resize(point_cloud_msg->height * point_cloud_msg->row_step); + + // Create iterators + sensor_msgs::PointCloud2Iterator iter_x(*point_cloud_msg, "x"); + sensor_msgs::PointCloud2Iterator iter_y(*point_cloud_msg, "y"); + sensor_msgs::PointCloud2Iterator iter_z(*point_cloud_msg, "z"); + sensor_msgs::PointCloud2Iterator iter_intensity(*point_cloud_msg, "intensity"); + sensor_msgs::PointCloud2Iterator iter_tag(*point_cloud_msg, "tag"); + sensor_msgs::PointCloud2Iterator iter_offset_time(*point_cloud_msg, "offset_time"); + + // Calculate frame time interval based on lidar rate + double frame_interval_us = 1000000.0 / static_cast(rate_int_[LIDAR]); + + // Merge all frames with per-point timestamps + for (size_t frame_idx = 0; frame_idx < frame_data.size(); ++frame_idx) { + auto [sphere_point_data, point_count] = frame_data[frame_idx]; + uint64_t frame_timestamp_us = frame_timestamps[frame_idx]; + + // Convert sphere points to cartesian points + auto result_point = spherePointToPoint(sphere_point_data, point_count); + + // Calculate time increment per point within this frame (uniform sampling) + double point_time_increment_us = frame_interval_us / static_cast(point_count); + + // RCLCPP_INFO_STREAM(logger_, "Frame " << frame_idx << ": point_count = " << point_count + // << ", frame_timestamp_us = " << frame_timestamp_us + // << ", point_time_increment_us = " << + // point_time_increment_us); + + for (size_t i = 0; i < point_count; + ++i, ++iter_x, ++iter_y, ++iter_z, ++iter_intensity, ++iter_tag, ++iter_offset_time) { + *iter_x = static_cast(result_point[i].x / 1000.0); + *iter_y = static_cast(result_point[i].y / 1000.0); + *iter_z = static_cast(result_point[i].z / 1000.0); + *iter_intensity = result_point[i].reflectivity; + *iter_tag = result_point[i].tag; + + // Calculate per-point offset time in nanoseconds relative to point cloud header timestamp + double point_timestamp_us = + static_cast(frame_timestamp_us) + (i * point_time_increment_us); + uint64_t header_timestamp_us = frame_timestamps[0]; // First frame timestamp + *iter_offset_time = + static_cast((point_timestamp_us - static_cast(header_timestamp_us)) * + 1000.0); // Convert to nanoseconds + } + } + + *point_cloud_msg = filterPointCloud(*point_cloud_msg); + point_cloud_pub_->publish(std::move(point_cloud_msg)); +} + +uint64_t OBLidarNode::getFrameTimestampUs(const std::shared_ptr &frame) { + if (frame == nullptr) { + RCLCPP_WARN(logger_, "getFrameTimestampUs: frame is nullptr, return 0"); + return 0; + } + if (time_domain_ == "device") { + return frame->getTimeStampUs(); + } else if (time_domain_ == "global") { + return frame->getGlobalTimeStampUs(); + } else { + return frame->getSystemTimeStampUs(); + } +} + +std::vector OBLidarNode::spherePointToPoint(OBLiDARSpherePoint *sphere_point, + uint32_t point_count) { + std::vector point_cloud; + point_cloud.resize(point_count); + OBLiDARPoint *point_data = point_cloud.data(); + for (uint32_t i = 0; i < point_count; ++i) { + double theta_rad = sphere_point->theta * M_PI / 180.0f; // to unit rad + double phi_rad = sphere_point->phi * M_PI / 180.0f; // to unit rad + auto distance = sphere_point->distance; + auto x = static_cast(distance * cos(theta_rad) * cos(phi_rad)); + auto y = static_cast(distance * sin(theta_rad) * cos(phi_rad)); + auto z = static_cast(distance * sin(phi_rad)); + if (std::isfinite(x) && std::isfinite(y) && std::isfinite(y)) { + // point: convert to opengl point + point_data->x = x; + point_data->y = y; + point_data->z = z; + point_data->reflectivity = sphere_point->reflectivity; + point_data->tag = sphere_point->tag; + ++point_data; + } + ++sphere_point; + } + return point_cloud; +} + +void OBLidarNode::filterScan(sensor_msgs::msg::LaserScan &scan) { + double current_angle = scan.angle_min; + double max_angle = deg2rad(max_angle_); + double min_angle = deg2rad(min_angle_); + // map to 0 - 2 * M_PI + max_angle = std::fmod(max_angle + M_PI, 2 * M_PI); + if (max_angle < 0) { + max_angle += 2 * M_PI; + } + + min_angle = std::fmod(min_angle + M_PI, 2 * M_PI); + if (min_angle < 0) { + min_angle += 2 * M_PI; + } + if (min_angle > max_angle) { + std::swap(min_angle, max_angle); + } + for (size_t i = 0; i < scan.ranges.size(); ++i, current_angle += scan.angle_increment) { + bool is_angle_in_range = (current_angle >= min_angle && current_angle <= max_angle); + + bool is_range_in_range = (scan.ranges[i] >= min_range_ && scan.ranges[i] <= max_range_); + + if (!(is_angle_in_range && is_range_in_range)) { + scan.ranges[i] = 0; + scan.intensities[i] = 0; + } + } +} +sensor_msgs::msg::PointCloud2 OBLidarNode::filterPointCloud( + sensor_msgs::msg::PointCloud2 &point_cloud) const { + // Initialize the filtered point cloud + sensor_msgs::msg::PointCloud2 filtered_point_cloud; + filtered_point_cloud.header = point_cloud.header; + filtered_point_cloud.height = point_cloud.height; + filtered_point_cloud.width = point_cloud.width; + filtered_point_cloud.is_dense = point_cloud.is_dense; + filtered_point_cloud.is_bigendian = point_cloud.is_bigendian; + filtered_point_cloud.fields = point_cloud.fields; + filtered_point_cloud.point_step = point_cloud.point_step; + + // Convert filter angles from degrees to radians and normalize to [0, 2蟺] + double max_angle = deg2rad(max_angle_); + double min_angle = deg2rad(min_angle_); + max_angle = std::fmod(max_angle + M_PI, 2 * M_PI); + min_angle = std::fmod(min_angle + M_PI, 2 * M_PI); + if (min_angle < 0) { + min_angle += 2 * M_PI; + } + if (max_angle < 0) { + max_angle += 2 * M_PI; + } + + // Swap angles if min is greater than max + if (min_angle > max_angle) { + std::swap(min_angle, max_angle); + } + + // Reserve space for filtered point cloud data + filtered_point_cloud.data.reserve(point_cloud.data.size()); + + // Create iterators for each field + sensor_msgs::PointCloud2Iterator iter_x(point_cloud, "x"); + sensor_msgs::PointCloud2Iterator iter_y(point_cloud, "y"); + sensor_msgs::PointCloud2Iterator iter_z(point_cloud, "z"); + + // Process each point + for (size_t i = 0; i < point_cloud.height * point_cloud.width; + ++i, ++iter_x, ++iter_y, ++iter_z) { + float x = *iter_x; + float y = *iter_y; + float z = *iter_z; + + // Calculate distance from origin + float distance = std::sqrt(x * x + y * y + z * z); + + // Calculate angle and normalize to [0, 2蟺] + float angle = std::atan2(y, x); + angle = std::fmod(angle + 2 * M_PI, 2 * M_PI); + + // Check if point is within both angle and range limits + bool is_angle_in_range = (angle >= min_angle && angle <= max_angle); + bool is_range_in_range = (distance >= min_range_ && distance <= max_range_); + + if (is_angle_in_range && is_range_in_range) { + // Keep points within the specified range + filtered_point_cloud.data.insert(filtered_point_cloud.data.end(), + point_cloud.data.begin() + i * point_cloud.point_step, + point_cloud.data.begin() + (i + 1) * point_cloud.point_step); + } else { + // Fill zero values for filtered out points + filtered_point_cloud.data.insert(filtered_point_cloud.data.end(), point_cloud.point_step, 0); + } + } + + // Update row step and resize data + filtered_point_cloud.row_step = filtered_point_cloud.width * filtered_point_cloud.point_step; + filtered_point_cloud.data.resize(filtered_point_cloud.height * filtered_point_cloud.row_step); + + return filtered_point_cloud; +} + +void OBLidarNode::publishStaticTransforms() { + if (!publish_tf_) { + return; + } + static_tf_broadcaster_ = std::make_shared(node_); + dynamic_tf_broadcaster_ = std::make_shared(node_); + calcAndPublishStaticTransform(); + if (tf_publish_rate_ > 0) { + tf_thread_ = std::make_shared([this]() { publishDynamicTransforms(); }); + } else { + static_tf_broadcaster_->sendTransform(static_tf_msgs_); + } +} + +void OBLidarNode::calcAndPublishStaticTransform() { + tf2::Quaternion quaternion_optical, zero_rot; + zero_rot.setRPY(0.0, 0.0, 0.0); + quaternion_optical.setRPY(-M_PI / 2, 0.0, -M_PI / 2); + tf2::Vector3 zero_trans(0, 0, 0); + auto base_stream_profile = stream_profile_[base_stream_]; + if (!base_stream_profile) { + RCLCPP_ERROR_STREAM(logger_, "Failed to get base stream profile"); + return; + } + CHECK_NOTNULL(base_stream_profile.get()); + // for (const auto &item : stream_profile_) { + // auto stream_index = item.first; + + // auto stream_profile = item.second; + // if (!stream_profile) { + // continue; + // } + // OBExtrinsic ex; + // try { + // ex = stream_profile->getExtrinsicTo(base_stream_profile); + // } catch (const ob::Error &e) { + // RCLCPP_ERROR_STREAM(logger_, "Failed to get " << stream_name_[stream_index] + // << " extrinsic: " << e.getMessage()); + // ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + // } + + // auto Q = rotationMatrixToQuaternion(ex.rot); + // Q = quaternion_optical * Q * quaternion_optical.inverse(); + // tf2::Vector3 trans(ex.trans[0], ex.trans[1], ex.trans[2]); + // auto timestamp = node_->now(); + // if (stream_index.first != base_stream_.first) { + // publishStaticTF(timestamp, trans, Q, frame_id_[base_stream_], frame_id_[stream_index]); + // } + // publishStaticTF(timestamp, zero_trans, quaternion_optical, frame_id_[stream_index], + // optical_frame_id_[stream_index]); + // RCLCPP_INFO_STREAM(logger_, "Publishing static transform from " << + // stream_name_[stream_index] + // << " to " + // << + // stream_name_[base_stream_]); + // RCLCPP_INFO_STREAM(logger_, "Translation " << trans[0] << ", " << trans[1] << ", " << + // trans[2]); RCLCPP_INFO_STREAM(logger_, "Rotation " << Q.getX() << ", " << Q.getY() << ", " + // << Q.getZ() + // << ", " << Q.getW()); + // } + if (enable_imu_) { + static const char *frame_id = "lidar_to_imu_extrinsics"; + OBExtrinsic ex; + try { + // Try to get extrinsic from ACCEL first + ex = base_stream_profile->getExtrinsicTo(stream_profile_[ACCEL]); + + // Verify if GYRO has the same extrinsic (they should be identical for the same IMU) + try { + auto gyro_ex = base_stream_profile->getExtrinsicTo(stream_profile_[GYRO]); + // Check if ACCEL and GYRO extrinsics are identical + bool extrinsics_match = true; + for (int i = 0; i < 9; i++) { + if (std::abs(ex.rot[i] - gyro_ex.rot[i]) > 1e-6) { + extrinsics_match = false; + break; + } + } + for (int i = 0; i < 3; i++) { + if (std::abs(ex.trans[i] - gyro_ex.trans[i]) > 1e-6) { + extrinsics_match = false; + break; + } + } + + if (!extrinsics_match) { + RCLCPP_WARN_STREAM(logger_, "ACCEL and GYRO have different extrinsics, using ACCEL"); + } else { + RCLCPP_DEBUG_STREAM(logger_, "ACCEL and GYRO extrinsics are identical"); + } + } catch (const ob::Error &e) { + RCLCPP_WARN_STREAM(logger_, + "Could not get GYRO extrinsic for verification: " << e.getMessage()); + } + + } catch (const ob::Error &e) { + RCLCPP_WARN_STREAM(logger_, "Failed to get ACCEL extrinsic, trying GYRO: " << e.getMessage()); + try { + ex = base_stream_profile->getExtrinsicTo(stream_profile_[GYRO]); + RCLCPP_INFO_STREAM(logger_, "Using GYRO extrinsic for IMU"); + } catch (const ob::Error &e2) { + RCLCPP_ERROR_STREAM( + logger_, "Failed to get " + << frame_id << " extrinsic from both ACCEL and GYRO: " << e2.getMessage()); + ex = OBExtrinsic({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0}}); + } + } + lidar_to_imu_extrinsic_ = ex; + auto ex_msg = obExtrinsicsToMsg(ex, frame_id); + CHECK_NOTNULL(lidar_to_imu_extrinsics_publisher_); + lidar_to_imu_extrinsics_publisher_->publish(ex_msg); + + // Publish static TF from lidar to IMU + auto Q = rotationMatrixToQuaternion(ex.rot); + Q = quaternion_optical * Q * quaternion_optical.inverse(); + tf2::Vector3 trans(ex.trans[0], ex.trans[1], ex.trans[2]); + auto timestamp = node_->now(); + publishStaticTF(timestamp, trans, Q, frame_id_[base_stream_], accel_gyro_frame_id_); + + RCLCPP_INFO_STREAM(logger_, "Publishing static transform from " + << frame_id_[base_stream_] << " to " << accel_gyro_frame_id_); + RCLCPP_INFO_STREAM(logger_, "Translation " << trans[0] << ", " << trans[1] << ", " << trans[2]); + RCLCPP_INFO_STREAM(logger_, "Rotation " << Q.getX() << ", " << Q.getY() << ", " << Q.getZ() + << ", " << Q.getW()); + } +} + +orbbec_camera_msgs::msg::IMUInfo OBLidarNode::createIMUInfo(const stream_index_pair &stream_index) { + orbbec_camera_msgs::msg::IMUInfo imu_info; + imu_info.header.frame_id = optical_frame_id_[stream_index]; + imu_info.header.stamp = node_->now(); + + if (stream_index == GYRO) { + auto gyro_profile = stream_profile_[stream_index]->as(); + auto gyro_intrinsics = gyro_profile->getIntrinsic(); + imu_info.noise_density = gyro_intrinsics.noiseDensity; + imu_info.random_walk = gyro_intrinsics.randomWalk; + imu_info.reference_temperature = gyro_intrinsics.referenceTemp; + imu_info.bias = {gyro_intrinsics.bias[0], gyro_intrinsics.bias[1], gyro_intrinsics.bias[2]}; + imu_info.scale_misalignment = { + gyro_intrinsics.scaleMisalignment[0], gyro_intrinsics.scaleMisalignment[1], + gyro_intrinsics.scaleMisalignment[2], gyro_intrinsics.scaleMisalignment[3], + gyro_intrinsics.scaleMisalignment[4], gyro_intrinsics.scaleMisalignment[5], + gyro_intrinsics.scaleMisalignment[6], gyro_intrinsics.scaleMisalignment[7], + gyro_intrinsics.scaleMisalignment[8]}; + imu_info.temperature_slope = { + gyro_intrinsics.tempSlope[0], gyro_intrinsics.tempSlope[1], gyro_intrinsics.tempSlope[2], + gyro_intrinsics.tempSlope[3], gyro_intrinsics.tempSlope[4], gyro_intrinsics.tempSlope[5], + gyro_intrinsics.tempSlope[6], gyro_intrinsics.tempSlope[7], gyro_intrinsics.tempSlope[8]}; + } else if (stream_index == ACCEL) { + auto accel_profile = stream_profile_[stream_index]->as(); + auto accel_intrinsics = accel_profile->getIntrinsic(); + imu_info.noise_density = accel_intrinsics.noiseDensity; + imu_info.random_walk = accel_intrinsics.randomWalk; + imu_info.reference_temperature = accel_intrinsics.referenceTemp; + imu_info.bias = {accel_intrinsics.bias[0], accel_intrinsics.bias[1], accel_intrinsics.bias[2]}; + imu_info.gravity = {accel_intrinsics.gravity[0], accel_intrinsics.gravity[1], + accel_intrinsics.gravity[2]}; + imu_info.scale_misalignment = { + accel_intrinsics.scaleMisalignment[0], accel_intrinsics.scaleMisalignment[1], + accel_intrinsics.scaleMisalignment[2], accel_intrinsics.scaleMisalignment[3], + accel_intrinsics.scaleMisalignment[4], accel_intrinsics.scaleMisalignment[5], + accel_intrinsics.scaleMisalignment[6], accel_intrinsics.scaleMisalignment[7], + accel_intrinsics.scaleMisalignment[8]}; + imu_info.temperature_slope = {accel_intrinsics.tempSlope[0], accel_intrinsics.tempSlope[1], + accel_intrinsics.tempSlope[2], accel_intrinsics.tempSlope[3], + accel_intrinsics.tempSlope[4], accel_intrinsics.tempSlope[5], + accel_intrinsics.tempSlope[6], accel_intrinsics.tempSlope[7], + accel_intrinsics.tempSlope[8]}; + } + + return imu_info; +} +void OBLidarNode::setDefaultIMUMessage(sensor_msgs::msg::Imu &imu_msg) { + imu_msg.header.frame_id = "imu_link"; + imu_msg.orientation.x = 0.0; + imu_msg.orientation.y = 0.0; + imu_msg.orientation.z = 0.0; + imu_msg.orientation.w = 1.0; + + imu_msg.orientation_covariance = {-1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + imu_msg.linear_acceleration_covariance = { + liner_accel_cov_, 0.0, 0.0, 0.0, liner_accel_cov_, 0.0, 0.0, 0.0, liner_accel_cov_}; + imu_msg.angular_velocity_covariance = { + angular_vel_cov_, 0.0, 0.0, 0.0, angular_vel_cov_, 0.0, 0.0, 0.0, angular_vel_cov_}; +} +void OBLidarNode::publishStaticTF(const rclcpp::Time &t, const tf2::Vector3 &trans, + const tf2::Quaternion &q, const std::string &from, + const std::string &to) { + geometry_msgs::msg::TransformStamped msg; + msg.header.stamp = t; + msg.header.frame_id = from; + msg.child_frame_id = to; + msg.transform.translation.x = trans[2] / 1000.0; + msg.transform.translation.y = -trans[0] / 1000.0; + msg.transform.translation.z = -trans[1] / 1000.0; + msg.transform.rotation.x = q.getX(); + msg.transform.rotation.y = q.getY(); + msg.transform.rotation.z = q.getZ(); + msg.transform.rotation.w = q.getW(); + static_tf_msgs_.push_back(msg); +} + +void OBLidarNode::publishDynamicTransforms() { + RCLCPP_WARN(logger_, "Publishing dynamic camera transforms (/tf) at %g Hz", tf_publish_rate_); + std::mutex mu; + std::unique_lock lock(mu); + while (rclcpp::ok() && is_running_) { + tf_cv_.wait_for(lock, std::chrono::milliseconds((int)(1000.0 / tf_publish_rate_)), + [this] { return (!(is_running_)); }); + { + rclcpp::Time t = node_->now(); + for (auto &msg : static_tf_msgs_) { + msg.header.stamp = t; + } + dynamic_tf_broadcaster_->sendTransform(static_tf_msgs_); + } + } +} + +} // namespace orbbec_lidar +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/src/rk_mpp_decoder.cpp b/dev_ws/src/orbbec_camera/src/rk_mpp_decoder.cpp new file mode 100644 index 0000000..8a755cd --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/rk_mpp_decoder.cpp @@ -0,0 +1,237 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "orbbec_camera/rk_mpp_decoder.h" +#include +#include + +namespace orbbec_camera { + +RKJPEGDecoder::RKJPEGDecoder(int width, int height) : JPEGDecoder(width, height) { + rgb_buffer_ = new uint8_t[width_ * height_ * 3]; + MPP_RET ret = mpp_create(&mpp_ctx_, &mpp_api_); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), "mpp_create failed, ret = " << ret); + throw std::runtime_error("mpp_create failed"); + } + MpiCmd mpi_cmd = MPP_CMD_BASE; + MppParam mpp_param = nullptr; + + mpi_cmd = MPP_DEC_SET_PARSER_SPLIT_MODE; + mpp_param = &need_split_; + ret = mpp_api_->control(mpp_ctx_, mpi_cmd, mpp_param); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "mpp_api_->control failed, ret = " << ret); + throw std::runtime_error("mpp_api_->control failed"); + } + ret = mpp_init(mpp_ctx_, MPP_CTX_DEC, MPP_VIDEO_CodingMJPEG); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), "mpp_init failed, ret = " << ret); + throw std::runtime_error("mpp_init failed"); + } + MppFrameFormat fmt = MPP_FMT_YUV420SP_VU; + mpp_param = &fmt; + ret = mpp_api_->control(mpp_ctx_, MPP_DEC_SET_OUTPUT_FORMAT, mpp_param); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "mpp_api_->control failed, ret = " << ret); + throw std::runtime_error("mpp_api_->control failed"); + } + ret = mpp_frame_init(&mpp_frame_); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "mpp_frame_init failed, ret = " << ret); + throw std::runtime_error("mpp_frame_init failed"); + } + ret = mpp_buffer_group_get_internal(&mpp_frame_group_, MPP_BUFFER_TYPE_ION); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "mpp_buffer_group_get_internal failed, ret = " << ret); + throw std::runtime_error("mpp_buffer_group_get_internal failed"); + } + ret = mpp_buffer_group_get_internal(&mpp_packet_group_, MPP_BUFFER_TYPE_ION); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "mpp_buffer_group_get_internal failed, ret = " << ret); + throw std::runtime_error("mpp_buffer_group_get_internal failed"); + } + RK_U32 hor_stride = MPP_ALIGN(width_, 16); + RK_U32 ver_stride = MPP_ALIGN(height_, 16); + ret = mpp_buffer_get(mpp_frame_group_, &mpp_frame_buffer_, hor_stride * ver_stride * 4); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "mpp_buffer_get failed, ret = " << ret); + throw std::runtime_error("mpp_buffer_get failed"); + } + mpp_frame_set_buffer(mpp_frame_, mpp_frame_buffer_); + ret = mpp_buffer_get(mpp_packet_group_, &mpp_packet_buffer_, width_ * height_ * 3); + if (ret != MPP_OK) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "mpp_buffer_get failed, ret = " << ret); + throw std::runtime_error("mpp_buffer_get failed"); + } + mpp_packet_init_with_buffer(&mpp_packet_, mpp_packet_buffer_); + data_buffer_ = (uint8_t *)mpp_buffer_get_ptr(mpp_packet_buffer_); +} + +RKJPEGDecoder::~RKJPEGDecoder() { + if (mpp_frame_buffer_) { + mpp_buffer_put(mpp_frame_buffer_); + mpp_frame_buffer_ = nullptr; + } + if (mpp_packet_buffer_) { + mpp_buffer_put(mpp_packet_buffer_); + mpp_packet_buffer_ = nullptr; + } + if (mpp_frame_group_) { + mpp_buffer_group_put(mpp_frame_group_); + mpp_frame_group_ = nullptr; + } + if (mpp_packet_group_) { + mpp_buffer_group_put(mpp_packet_group_); + mpp_packet_group_ = nullptr; + } + if (mpp_frame_) { + mpp_frame_deinit(&mpp_frame_); + mpp_frame_ = nullptr; + } + if (mpp_packet_) { + mpp_packet_deinit(&mpp_packet_); + mpp_packet_ = nullptr; + } + if (mpp_ctx_) { + mpp_destroy(mpp_ctx_); + mpp_ctx_ = nullptr; + } + if (rgb_buffer_) { + delete[] rgb_buffer_; + } +} + +bool RKJPEGDecoder::mppFrame2RGB(const MppFrame frame, uint8_t *data) { + int width = mpp_frame_get_width(frame); + int height = mpp_frame_get_height(frame); + MppBuffer buffer = mpp_frame_get_buffer(frame); + CHECK_EQ(width, width_); + CHECK_EQ(height, height_); + CHECK_NOTNULL(data); + CHECK_EQ(width, width_); + CHECK_EQ(height, height_); + memset(data, 0, width * height * 3); + auto buffer_ptr = mpp_buffer_get_ptr(buffer); +#if defined(USE_LIBYUV) + auto *y = (const uint8_t *)buffer_ptr; + auto *uv = y + width * height; + int ret = libyuv::NV12ToRGB24(y, width, uv, width, data, width * 3, width, height); + if (ret) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), "libyuv error " << ret); + return false; + } + return true; +#else + rga_info_t src_info; + rga_info_t dst_info; + // NOTE: memset to zero is MUST + memset(&src_info, 0, sizeof(rga_info_t)); + memset(&dst_info, 0, sizeof(rga_info_t)); + src_info.fd = -1; + src_info.mmuFlag = 1; + src_info.virAddr = buffer_ptr; + src_info.format = RK_FORMAT_YCbCr_420_SP; + dst_info.fd = -1; + dst_info.mmuFlag = 1; + dst_info.virAddr = data; + dst_info.format = RK_FORMAT_BGR_888; + rga_set_rect(&src_info.rect, 0, 0, width, height, width, height, RK_FORMAT_YCbCr_420_SP); + rga_set_rect(&dst_info.rect, 0, 0, width, height, width, height, RK_FORMAT_BGR_888); + int ret = c_RkRgaBlit(&src_info, &dst_info, nullptr); + if (ret) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "c_RkRgaBlit error " << ret << " errno " << strerror(errno)); + return false; + } + return true; +#endif +} + +bool RKJPEGDecoder::decode(const std::shared_ptr &frame, uint8_t *dest) { + MPP_RET ret = MPP_OK; + memset(data_buffer_, 0, width_ * height_ * 3); + memcpy(data_buffer_, frame->data(), frame->dataSize()); + mpp_packet_set_pos(mpp_packet_, data_buffer_); + mpp_packet_set_length(mpp_packet_, frame->dataSize()); + mpp_packet_set_eos(mpp_packet_); + CHECK_NOTNULL(mpp_ctx_); + ret = mpp_api_->poll(mpp_ctx_, MPP_PORT_INPUT, MPP_POLL_BLOCK); + if (ret != MPP_OK) { + RCLCPP_ERROR(rclcpp::get_logger("rk_mpp_decoder"), "mpp poll failed %d", ret); + return false; + } + ret = mpp_api_->dequeue(mpp_ctx_, MPP_PORT_INPUT, &mpp_task_); + if (ret != MPP_OK) { + RCLCPP_ERROR(rclcpp::get_logger("rk_mpp_decoder"), "mpp dequeue failed %d", ret); + return false; + } + mpp_task_meta_set_packet(mpp_task_, KEY_INPUT_PACKET, mpp_packet_); + mpp_task_meta_set_frame(mpp_task_, KEY_OUTPUT_FRAME, mpp_frame_); + ret = mpp_api_->enqueue(mpp_ctx_, MPP_PORT_INPUT, mpp_task_); + if (ret != MPP_OK) { + RCLCPP_ERROR(rclcpp::get_logger("rk_mpp_decoder"), "mpp enqueue failed %d", ret); + return false; + } + ret = mpp_api_->poll(mpp_ctx_, MPP_PORT_OUTPUT, MPP_POLL_BLOCK); + if (ret != MPP_OK) { + RCLCPP_ERROR(rclcpp::get_logger("rk_mpp_decoder"), "mpp poll failed %d", ret); + return false; + } + ret = mpp_api_->dequeue(mpp_ctx_, MPP_PORT_OUTPUT, &mpp_task_); + if (ret != MPP_OK) { + RCLCPP_ERROR(rclcpp::get_logger("rk_mpp_decoder"), "mpp dequeue failed %d", ret); + return false; + } + if (mpp_task_) { + MppFrame output_frame = nullptr; + mpp_task_meta_get_frame(mpp_task_, KEY_OUTPUT_FRAME, &output_frame); + if (mpp_frame_) { + int width = mpp_frame_get_width(mpp_frame_); + int height = mpp_frame_get_height(mpp_frame_); + if (width != width_ || height != height_) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), + "mpp frame size error " << width << " " << height); + return false; + } + if (!mppFrame2RGB(mpp_frame_, rgb_buffer_)) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("rk_mpp_decoder"), "mpp frame to rgb error"); + return false; + } + if (mpp_frame_get_eos(output_frame)) { + RCLCPP_INFO_STREAM(rclcpp::get_logger("rk_mpp_decoder"), "mpp frame get eos"); + } + } + ret = mpp_api_->enqueue(mpp_ctx_, MPP_PORT_OUTPUT, mpp_task_); + if (ret != MPP_OK) { + RCLCPP_ERROR(rclcpp::get_logger("rk_mpp_decoder"), "mpp enqueue failed %d", ret); + return false; + } + CHECK_NOTNULL(dest); + memcpy(dest, rgb_buffer_, width_ * height_ * 3); + return true; + } + return false; +} + +} // namespace orbbec_camera \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera/src/ros_param_backend.cpp b/dev_ws/src/orbbec_camera/src/ros_param_backend.cpp new file mode 100644 index 0000000..0e172df --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/ros_param_backend.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "orbbec_camera/ros_param_backend.h" +namespace orbbec_camera { +ParametersBackend::ParametersBackend(rclcpp::Node *node) + : node_(node), logger_(node_->get_logger()) {} + +ParametersBackend::~ParametersBackend() { + if (ros_callback_) { + node_->remove_on_set_parameters_callback( + (rclcpp::node_interfaces::OnSetParametersCallbackHandle *)(ros_callback_.get())); + ros_callback_.reset(); + } +} + +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/src/ros_service.cpp b/dev_ws/src/orbbec_camera/src/ros_service.cpp new file mode 100644 index 0000000..d4fe970 --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/ros_service.cpp @@ -0,0 +1,1515 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "orbbec_camera/ob_camera_node.h" +#include +#include +#include + +#include "orbbec_camera/utils.h" +namespace orbbec_camera { + +void OBCameraNode::setupCameraCtrlServices() { + using std_srvs::srv::SetBool; + for (auto stream_index : IMAGE_STREAMS) { + if (!enable_stream_[stream_index]) { + continue; + } + auto stream_name = stream_name_[stream_index]; + std::string service_name = "get_" + stream_name + "_exposure"; + get_exposure_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + getExposureCallback(request, response, stream_index); + }); + + service_name = "set_" + stream_name + "_exposure"; + set_exposure_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + setExposureCallback(request, response, stream_index); + }); + service_name = "get_" + stream_name + "_gain"; + get_gain_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + getGainCallback(request, response, stream_index); + }); + + service_name = "set_" + stream_name + "_gain"; + set_gain_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + setGainCallback(request, response, stream_index); + }); + service_name = "set_" + stream_name + "_auto_exposure"; + set_auto_exposure_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + setAutoExposureCallback(request, response, stream_index); + }); + + service_name = "set_" + stream_name + "_ae_roi"; + set_ae_roi_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + setAeRoiCallback(request, response, stream_index); + }); + + service_name = "toggle_" + stream_name; + + toggle_sensor_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + toggleSensorCallback(request, response, stream_index); + }); + service_name = "set_" + stream_name + "_mirror"; + set_mirror_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + setMirrorCallback(request, response, stream_index); + }); + service_name = "set_" + stream_name + "_flip"; + set_flip_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + setFlipCallback(request, response, stream_index); + }); + service_name = "set_" + stream_name + "_rotation"; + set_rotation_srv_[stream_index] = node_->create_service( + service_name, + [this, stream_index = stream_index](const std::shared_ptr request, + std::shared_ptr response) { + setRotationCallback(request, response, stream_index); + }); + } + set_fan_work_mode_srv_ = node_->create_service( + "set_fan_work_mode", [this](const std::shared_ptr request, + std::shared_ptr response) { + setFanWorkModeCallback(request, response); + }); + set_floor_enable_srv_ = node_->create_service( + "set_floor_enable", [this](const std::shared_ptr request_header, + const std::shared_ptr request, + std::shared_ptr response) { + setFloorEnableCallback(request_header, request, response); + }); + set_laser_enable_srv_ = node_->create_service( + "set_laser_enable", [this](const std::shared_ptr request_header, + const std::shared_ptr request, + std::shared_ptr response) { + setLaserEnableCallback(request_header, request, response); + }); + set_ldp_enable_srv_ = node_->create_service( + "set_ldp_enable", [this](const std::shared_ptr request_header, + const std::shared_ptr request, + std::shared_ptr response) { + setLdpEnableCallback(request_header, request, response); + }); + get_ldp_status_srv_ = node_->create_service( + "get_ldp_status", [this](const std::shared_ptr request_header, + const std::shared_ptr request, + std::shared_ptr response) { + (void)request_header; + getLdpStatusCallback(request, response); + }); + get_laser_status_srv_ = node_->create_service( + "get_laser_status", [this](const std::shared_ptr request_header, + const std::shared_ptr request, + std::shared_ptr response) { + (void)request_header; + getLaserStatusCallback(request, response); + }); + set_ptp_config_srv_ = node_->create_service( + "set_ptp_config", [this](const std::shared_ptr request_header, + const std::shared_ptr request, + std::shared_ptr response) { + setPtpConfigCallback(request_header, request, response); + }); + get_ptp_config_srv_ = node_->create_service( + "get_ptp_config", [this](const std::shared_ptr request_header, + const std::shared_ptr request, + std::shared_ptr response) { + (void)request_header; + getPtpConfigCallback(request, response); + }); + + get_white_balance_srv_ = node_->create_service( + "get_white_balance", [this](const std::shared_ptr request, + std::shared_ptr response) { + getWhiteBalanceCallback(request, response); + }); + + set_white_balance_srv_ = node_->create_service( + "set_white_balance", [this](const std::shared_ptr request, + std::shared_ptr response) { + setWhiteBalanceCallback(request, response); + }); + get_auto_white_balance_srv_ = node_->create_service( + "get_auto_white_balance", [this](const std::shared_ptr request, + std::shared_ptr response) { + getAutoWhiteBalanceCallback(request, response); + }); + set_auto_white_balance_srv_ = node_->create_service( + "set_auto_white_balance", [this](const std::shared_ptr request, + std::shared_ptr response) { + setAutoWhiteBalanceCallback(request, response); + }); + get_device_srv_ = node_->create_service( + "get_device_info", [this](const std::shared_ptr request, + std::shared_ptr response) { + getDeviceInfoCallback(request, response); + }); + get_sdk_version_srv_ = node_->create_service( + "get_sdk_version", + [this](const std::shared_ptr request, + std::shared_ptr response) { getSDKVersion(request, response); }); + save_images_srv_ = node_->create_service( + "save_images", [this](const std::shared_ptr request, + std::shared_ptr response) { + saveImageCallback(request, response); + }); + save_point_cloud_srv_ = node_->create_service( + "save_point_cloud", [this](const std::shared_ptr request, + std::shared_ptr response) { + savePointCloudCallback(request, response); + }); + switch_ir_camera_srv_ = node_->create_service( + "switch_ir", [this](const std::shared_ptr request, + std::shared_ptr response) { + switchIRCameraCallback(request, response); + }); + set_ir_long_exposure_srv_ = node_->create_service( + "set_ir_long_exposure", [this](const std::shared_ptr request, + std::shared_ptr response) { + setIRLongExposureCallback(request, response); + }); + get_lrm_measure_distance_srv_ = node_->create_service( + "get_lrm_measure_distance", [this](const std::shared_ptr request, + std::shared_ptr response) { + getLrmMeasureDistanceCallback(request, response); + }); + set_reset_timestamp_srv_ = node_->create_service( + "set_reset_timestamp", [this](const std::shared_ptr request, + std::shared_ptr response) { + setRESETTimestampCallback(request, response); + }); + set_interleaver_laser_sync_srv_ = node_->create_service( + "set_sync_interleaverlaser", [this](const std::shared_ptr request, + std::shared_ptr response) { + setSYNCInterleaveLaserCallback(request, response); + }); + set_sync_host_time_srv_ = node_->create_service( + "set_sync_hosttime", [this](const std::shared_ptr request, + std::shared_ptr response) { + setSYNCHostimeCallback(request, response); + }); + send_software_trigger_srv_ = node_->create_service( + "send_software_trigger", [this](const std::shared_ptr request, + std::shared_ptr response) { + sendSoftwareTriggerCallback(request, response); + }); + if (device_->getDeviceInfo()->getPid() == GEMINI_435Le_PID) { + write_customerdata_srv_ = node_->create_service( + "write_customer_data", [this](const std::shared_ptr request, + std::shared_ptr response) { + writeCustomerDataCallback(request, response); + }); + read_customerdata_srv_ = node_->create_service( + "read_customer_data", [this](const std::shared_ptr request, + std::shared_ptr response) { + readCustomerDataCallback(request, response); + }); + set_user_calib_params_srv_ = node_->create_service( + "set_user_calib_params", [this](const std::shared_ptr request, + std::shared_ptr response) { + setUserCalibParamsCallback(request, response); + }); + get_user_calib_params_srv_ = node_->create_service( + "get_user_calib_params", [this](const std::shared_ptr request, + std::shared_ptr response) { + getUserCalibParamsCallback(request, response); + }); + } + set_ae_mode_srv_ = node_->create_service( + "set_ae_mode", [this](const std::shared_ptr request, + std::shared_ptr response) { + setAEModeCallback(request, response); + }); + set_sports_mode_srv_ = node_->create_service( + "set_sports_mode", [this](const std::shared_ptr request, + std::shared_ptr response) { + setSportsModeCallback(request, response); + }); + set_streams_enable_srv_ = node_->create_service( + "set_streams_enable", [this](const std::shared_ptr request, + std::shared_ptr response) { + setStreamsEnableCallback(request, response); + }); + get_streams_enable_srv_ = node_->create_service( + "get_streams_enable", [this](const std::shared_ptr request, + std::shared_ptr response) { + getStreamsEnableCallback(request, response); + }); + set_point_cloud_decimation_srv_ = node_->create_service( + "set_point_cloud_decimation", [this](const std::shared_ptr request, + std::shared_ptr response) { + setPointCloudDecimationCallback(request, response); + }); + get_point_cloud_decimation_srv_ = node_->create_service( + "get_point_cloud_decimation", [this](const std::shared_ptr request, + std::shared_ptr response) { + getPointCloudDecimationCallback(request, response); + }); +} + +void OBCameraNode::getPointCloudDecimationCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + response->data = point_cloud_decimation_filter_factor_; + response->success = true; + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setPointCloudDecimationCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + if (!request) { + response->success = false; + response->message = "Invalid request"; + return; + } + + if (request->data <= 0 || request->data > 8) { + response->success = false; + response->message = "Decimation factor must be between 1 and 8"; + RCLCPP_WARN_STREAM(logger_, "Invalid decimation factor: " << request->data); + return; + } + + try { + point_cloud_decimation_filter_factor_ = request->data; + RCLCPP_INFO_STREAM(logger_, "Set point_cloud_decimation_filter_factor to " + << point_cloud_decimation_filter_factor_); + response->success = true; + response->message = "Point cloud decimation factor updated successfully"; + } catch (const std::exception& e) { + response->success = false; + response->message = std::string("Failed to set decimation factor: ") + e.what(); + RCLCPP_ERROR_STREAM(logger_, response->message); + } +} + +void OBCameraNode::setStreamsEnableCallback( + const std::shared_ptr request, + std::shared_ptr response) { + try { + if (request->data) { + startStreams(); + response->success = true; + response->message = "streams started"; + } else { + stopStreams(); + response->success = true; + response->message = "streams stopped"; + } + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::getStreamsEnableCallback( + const std::shared_ptr request, + std::shared_ptr response) { + (void)request; + try { + response->data = pipeline_started_.load(); + response->success = true; + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setExposureCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + auto stream = stream_index.first; + try { + switch (stream) { + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR_RIGHT: + case OB_STREAM_IR: + device_->setIntProperty(OB_PROP_IR_EXPOSURE_INT, request->data); + break; + case OB_STREAM_DEPTH: + device_->setIntProperty(OB_PROP_DEPTH_EXPOSURE_INT, request->data); + break; + case OB_STREAM_COLOR: + case OB_STREAM_COLOR_LEFT: + case OB_STREAM_COLOR_RIGHT: + device_->setIntProperty(OB_PROP_COLOR_EXPOSURE_INT, request->data); + break; + default: + RCLCPP_ERROR(logger_, "%s NOT a video stream", __FUNCTION__); + break; + } + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + RCLCPP_ERROR(logger_, "%s unknown error %d", __FUNCTION__, __LINE__); + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::getGainCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + (void)request; + auto stream = stream_index.first; + try { + switch (stream) { + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR_RIGHT: + case OB_STREAM_IR: + response->data = device_->getIntProperty(OB_PROP_IR_GAIN_INT); + break; + case OB_STREAM_DEPTH: + response->data = device_->getIntProperty(OB_PROP_DEPTH_GAIN_INT); + break; + case OB_STREAM_COLOR: + case OB_STREAM_COLOR_LEFT: + case OB_STREAM_COLOR_RIGHT: + response->data = device_->getIntProperty(OB_PROP_COLOR_GAIN_INT); + break; + default: + RCLCPP_ERROR(logger_, " %s NOT a video stream", __FUNCTION__); + break; + } + response->success = true; + } catch (ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setGainCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + auto stream = stream_index.first; + OBPropertyID prop_id = OB_PROP_IR_GAIN_INT; + try { + switch (stream) { + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR_RIGHT: + case OB_STREAM_IR: + prop_id = OB_PROP_IR_GAIN_INT; + break; + case OB_STREAM_DEPTH: + prop_id = OB_PROP_DEPTH_GAIN_INT; + break; + case OB_STREAM_COLOR: + case OB_STREAM_COLOR_LEFT: + case OB_STREAM_COLOR_RIGHT: + prop_id = OB_PROP_COLOR_GAIN_INT; + break; + default: + RCLCPP_ERROR(logger_, "%s NOT a video stream", __FUNCTION__); + response->success = false; + response->message = "NOT a video stream"; + return; + } + auto range = device_->getIntPropertyRange(prop_id); + if (request->data < range.min || request->data > range.max) { + response->success = false; + RCLCPP_INFO_STREAM(logger_, "set gain value out of range"); + response->message = "value out of range"; + return; + } + device_->setIntProperty(prop_id, request->data); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setAeRoiCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + auto stream = stream_index.first; + if (device_->getDeviceInfo()->getPid() == GEMINI_305_PID && + (stream != OB_STREAM_COLOR && ae_mode_ == "colorbased")) { + response->success = false; + response->message = "AE MODE is colorbased, other sensors setting is not supported"; + return; + } + if (device_->getDeviceInfo()->getPid() == GEMINI_305_PID && + (stream != OB_STREAM_DEPTH && ae_mode_ == "depthbased")) { + response->success = false; + response->message = "AE MODE is depthbased, other sensors sensor setting is not supported"; + return; + } + auto config = OBRegionOfInterest(); + uint32_t data_size = sizeof(config); + try { + switch (stream) { + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR_RIGHT: + case OB_STREAM_IR: + case OB_STREAM_DEPTH: + config.x0_left = (static_cast(request->data_param[0]) < 0) + ? 0 + : static_cast(request->data_param[0]); + config.x0_left = (static_cast(request->data_param[0]) > width_[DEPTH] - 1) + ? width_[DEPTH] - 1 + : config.x0_left; + config.y0_top = (static_cast(request->data_param[2]) < 0) + ? 0 + : static_cast(request->data_param[2]); + config.y0_top = (static_cast(request->data_param[2]) > height_[DEPTH] - 1) + ? height_[DEPTH] - 1 + : config.y0_top; + config.x1_right = (static_cast(request->data_param[1]) < 0) + ? 0 + : static_cast(request->data_param[1]); + config.x1_right = (static_cast(request->data_param[1]) > width_[DEPTH] - 1) + ? width_[DEPTH] - 1 + : config.x1_right; + config.y1_bottom = (static_cast(request->data_param[3]) < 0) + ? 0 + : static_cast(request->data_param[3]); + config.y1_bottom = (static_cast(request->data_param[3]) > height_[DEPTH] - 1) + ? height_[DEPTH] - 1 + : config.y1_bottom; + device_->setStructuredData(OB_STRUCT_DEPTH_AE_ROI, + reinterpret_cast(&config), sizeof(config)); + device_->getStructuredData(OB_STRUCT_DEPTH_AE_ROI, reinterpret_cast(&config), + &data_size); + RCLCPP_INFO_STREAM( + logger_, "set depth AE ROI : " + << "[Left: " << config.x0_left << ", Right: " << config.x1_right + << ", Top: " << config.y0_top << ", Bottom: " << config.y1_bottom << " ]"); + break; + case OB_STREAM_COLOR: + case OB_STREAM_COLOR_LEFT: + case OB_STREAM_COLOR_RIGHT: + config.x0_left = (static_cast(request->data_param[0]) < 0) + ? 0 + : static_cast(request->data_param[0]); + config.x0_left = (static_cast(request->data_param[0]) > width_[COLOR] - 1) + ? width_[COLOR] - 1 + : config.x0_left; + config.y0_top = (static_cast(request->data_param[2]) < 0) + ? 0 + : static_cast(request->data_param[2]); + config.y0_top = (static_cast(request->data_param[2]) > height_[COLOR] - 1) + ? height_[COLOR] - 1 + : config.y0_top; + config.x1_right = (static_cast(request->data_param[1]) < 0) + ? 0 + : static_cast(request->data_param[1]); + config.x1_right = (static_cast(request->data_param[1]) > width_[COLOR] - 1) + ? width_[COLOR] - 1 + : config.x1_right; + config.y1_bottom = (static_cast(request->data_param[3]) < 0) + ? 0 + : static_cast(request->data_param[3]); + config.y1_bottom = (static_cast(request->data_param[3]) > height_[COLOR] - 1) + ? height_[COLOR] - 1 + : config.y1_bottom; + device_->setStructuredData(OB_STRUCT_COLOR_AE_ROI, + reinterpret_cast(&config), sizeof(config)); + device_->getStructuredData(OB_STRUCT_COLOR_AE_ROI, reinterpret_cast(&config), + &data_size); + RCLCPP_INFO_STREAM( + logger_, "set color AE ROI : " + << "[Left: " << config.x0_left << ", Right: " << config.x1_right + << ", Top: " << config.y0_top << ", Bottom: " << config.y1_bottom << " ]"); + break; + default: + RCLCPP_ERROR(logger_, "%s NOT a video stream", __FUNCTION__); + response->success = false; + response->message = "NOT a video stream"; + return; + } + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::getWhiteBalanceCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + response->data = device_->getIntProperty(OB_PROP_COLOR_WHITE_BALANCE_INT); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setWhiteBalanceCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + try { + auto range = device_->getIntPropertyRange(OB_PROP_COLOR_WHITE_BALANCE_INT); + if (request->data < range.min || request->data > range.max) { + response->success = false; + RCLCPP_INFO_STREAM(logger_, "set white balance value out of range"); + response->message = "value out of range"; + return; + } + bool auto_white_balance = device_->getBoolProperty(OB_PROP_COLOR_AUTO_WHITE_BALANCE_BOOL); + if (auto_white_balance) { + RCLCPP_WARN(logger_, "auto white balance is enabled, set white balance will be ignored"); + response->success = false; + response->message = "auto white balance is enabled"; + return; + } + device_->setIntProperty(OB_PROP_COLOR_WHITE_BALANCE_INT, request->data); + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::getAutoWhiteBalanceCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + response->data = device_->getBoolProperty(OB_PROP_COLOR_AUTO_WHITE_BALANCE_BOOL); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setAutoWhiteBalanceCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + try { + device_->setBoolProperty(OB_PROP_COLOR_AUTO_WHITE_BALANCE_BOOL, request->data); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setAutoExposureCallback( + const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + auto stream = stream_index.first; + OBPropertyID prop_id = OB_PROP_IR_AUTO_EXPOSURE_BOOL; + try { + switch (stream) { + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR_RIGHT: + case OB_STREAM_IR: + prop_id = OB_PROP_IR_AUTO_EXPOSURE_BOOL; + break; + case OB_STREAM_DEPTH: + prop_id = OB_PROP_DEPTH_AUTO_EXPOSURE_BOOL; + break; + case OB_STREAM_COLOR: + case OB_STREAM_COLOR_LEFT: + case OB_STREAM_COLOR_RIGHT: + prop_id = OB_PROP_COLOR_AUTO_EXPOSURE_BOOL; + break; + default: + RCLCPP_ERROR(logger_, "%s NOT a video stream", __FUNCTION__); + response->success = false; + response->message = "NOT a video stream"; + return; + } + auto range = device_->getIntPropertyRange(prop_id); + if (request->data < range.min || request->data > range.max) { + response->success = false; + RCLCPP_INFO_STREAM(logger_, "set auto exposure value out of range"); + response->message = "value out of range"; + return; + } + device_->setIntProperty(prop_id, request->data); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setFanWorkModeCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)response; + bool fan_mode = request->data; + try { + device_->setBoolProperty(OB_PROP_FAN_WORK_MODE_INT, fan_mode); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setFloorEnableCallback( + const std::shared_ptr& request_header, + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request_header; + (void)response; + bool floor_enable = request->data; + try { + device_->setBoolProperty(OB_PROP_FLOOD_BOOL, floor_enable); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setLaserEnableCallback( + const std::shared_ptr& request_header, + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request_header; + (void)response; + int laser_enable = request->data ? 1 : 0; + try { + if (device_->isPropertySupported(OB_PROP_LASER_CONTROL_INT, OB_PERMISSION_READ_WRITE)) { + device_->setIntProperty(OB_PROP_LASER_CONTROL_INT, laser_enable); + } else if (device_->isPropertySupported(OB_PROP_LASER_BOOL, OB_PERMISSION_READ_WRITE)) { + device_->setIntProperty(OB_PROP_LASER_BOOL, laser_enable); + } + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::setLdpEnableCallback( + const std::shared_ptr& request_header, + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request_header; + (void)response; + bool ldp_enable = request->data; + try { + if (device_->isPropertySupported(OB_PROP_LASER_CONTROL_INT, OB_PERMISSION_READ_WRITE)) { + auto laser_enable = device_->getIntProperty(OB_PROP_LASER_CONTROL_INT); + device_->setBoolProperty(OB_PROP_LDP_BOOL, ldp_enable); + device_->setIntProperty(OB_PROP_LASER_CONTROL_INT, laser_enable); + } else if (device_->isPropertySupported(OB_PROP_LASER_BOOL, OB_PERMISSION_READ_WRITE)) { + if (!ldp_enable) { + auto laser_enable = device_->getIntProperty(OB_PROP_LASER_BOOL); + device_->setBoolProperty(OB_PROP_LDP_BOOL, ldp_enable); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + device_->setIntProperty(OB_PROP_LASER_BOOL, laser_enable); + } else { + device_->setBoolProperty(OB_PROP_LDP_BOOL, ldp_enable); + } + } + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::getExposureCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + (void)request; + auto stream = stream_index.first; + try { + switch (stream) { + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR_RIGHT: + case OB_STREAM_IR: + response->data = device_->getIntProperty(OB_PROP_IR_EXPOSURE_INT); + break; + case OB_STREAM_DEPTH: + response->data = device_->getIntProperty(OB_PROP_DEPTH_EXPOSURE_INT); + break; + case OB_STREAM_COLOR: + case OB_STREAM_COLOR_LEFT: + case OB_STREAM_COLOR_RIGHT: + response->data = device_->getIntProperty(OB_PROP_COLOR_EXPOSURE_INT); + break; + default: + RCLCPP_ERROR(logger_, " %s NOT a video stream", __FUNCTION__); + break; + } + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::getDeviceInfoCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + auto device_info = device_->getDeviceInfo(); + response->info.name = device_info->getName(); + response->info.serial_number = device_info->getSerialNumber(); + response->info.firmware_version = device_info->getFirmwareVersion(); + response->info.supported_min_sdk_version = device_info->getSupportedMinSdkVersion(); + response->info.current_sdk_version = getObSDKVersion(); + response->info.hardware_version = device_info->getHardwareVersion(); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::getSDKVersion(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + auto device_info = device_->getDeviceInfo(); + nlohmann::json data; + data["firmware_version"] = device_info->getFirmwareVersion(); + data["supported_min_sdk_version"] = device_info->getSupportedMinSdkVersion(); + data["ros_sdk_version"] = OB_ROS_VERSION_STR; + data["ob_sdk_version"] = getObSDKVersion(); + response->data = data.dump(2); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::setMirrorCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + (void)request; + auto stream = stream_index.first; + try { + switch (stream) { + case OB_STREAM_IR_RIGHT: + device_->setBoolProperty(OB_PROP_IR_RIGHT_MIRROR_BOOL, request->data); + break; + case OB_STREAM_IR_LEFT: + case OB_STREAM_IR: + device_->setBoolProperty(OB_PROP_IR_MIRROR_BOOL, request->data); + break; + case OB_STREAM_DEPTH: + device_->setBoolProperty(OB_PROP_DEPTH_MIRROR_BOOL, request->data); + break; + case OB_STREAM_COLOR: + device_->setBoolProperty(OB_PROP_COLOR_MIRROR_BOOL, request->data); + break; + case OB_STREAM_COLOR_LEFT: + device_->setBoolProperty(OB_PROP_COLOR_LEFT_MIRROR_BOOL, request->data); + break; + case OB_STREAM_COLOR_RIGHT: + device_->setBoolProperty(OB_PROP_COLOR_RIGHT_MIRROR_BOOL, request->data); + break; + default: + RCLCPP_ERROR(logger_, " %s NOT a video stream", __FUNCTION__); + break; + } + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::setFlipCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + (void)request; + auto stream = stream_index.first; + try { + switch (stream) { + case OB_STREAM_IR_RIGHT: + device_->setBoolProperty(OB_PROP_IR_RIGHT_FLIP_BOOL, request->data); + break; + case OB_STREAM_IR_LEFT: + device_->setBoolProperty(OB_PROP_IR_FLIP_BOOL, request->data); + break; + case OB_STREAM_IR: + device_->setBoolProperty(OB_PROP_IR_FLIP_BOOL, request->data); + break; + case OB_STREAM_DEPTH: + device_->setBoolProperty(OB_PROP_DEPTH_FLIP_BOOL, request->data); + break; + case OB_STREAM_COLOR: + device_->setBoolProperty(OB_PROP_COLOR_FLIP_BOOL, request->data); + break; + case OB_STREAM_COLOR_LEFT: + device_->setBoolProperty(OB_PROP_COLOR_LEFT_FLIP_BOOL, request->data); + break; + case OB_STREAM_COLOR_RIGHT: + device_->setBoolProperty(OB_PROP_COLOR_RIGHT_FLIP_BOOL, request->data); + break; + default: + RCLCPP_ERROR(logger_, " %s NOT a video stream", __FUNCTION__); + break; + } + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::setRotationCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + (void)request; + auto stream = stream_index.first; + try { + switch (stream) { + case OB_STREAM_IR_RIGHT: + device_->setIntProperty(OB_PROP_IR_RIGHT_ROTATE_INT, request->data); + break; + case OB_STREAM_IR_LEFT: + device_->setIntProperty(OB_PROP_IR_ROTATE_INT, request->data); + break; + case OB_STREAM_IR: + device_->setIntProperty(OB_PROP_IR_ROTATE_INT, request->data); + break; + case OB_STREAM_DEPTH: + device_->setIntProperty(OB_PROP_DEPTH_ROTATE_INT, request->data); + break; + case OB_STREAM_COLOR: + device_->setIntProperty(OB_PROP_COLOR_ROTATE_INT, request->data); + break; + case OB_STREAM_COLOR_LEFT: + device_->setIntProperty(OB_PROP_COLOR_LEFT_ROTATE_INT, request->data); + break; + case OB_STREAM_COLOR_RIGHT: + device_->setIntProperty(OB_PROP_COLOR_RIGHT_ROTATE_INT, request->data); + break; + default: + RCLCPP_ERROR(logger_, " %s NOT a video stream", __FUNCTION__); + break; + } + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::getLdpStatusCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + response->data = device_->getBoolProperty(OB_PROP_LDP_STATUS_BOOL); + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::getLaserStatusCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + if (device_->isPropertySupported(OB_PROP_LASER_CONTROL_INT, OB_PERMISSION_READ_WRITE)) { + response->data = device_->getBoolProperty(OB_PROP_LASER_CONTROL_INT); + } else if (device_->isPropertySupported(OB_PROP_LASER_BOOL, OB_PERMISSION_READ_WRITE)) { + response->data = device_->getBoolProperty(OB_PROP_LASER_BOOL); + } + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::setPtpConfigCallback( + const std::shared_ptr& request_header, + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request_header; + + try { + if (!device_->isPropertySupported(OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL, + OB_PERMISSION_READ_WRITE)) { + response->success = false; + RCLCPP_ERROR(logger_, "OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL not supported or not writable"); + return; + } + device_->setBoolProperty(OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL, request->data); + response->success = true; + } catch (const ob::Error& e) { + response->success = false; + response->message = e.getMessage(); + } catch (const std::exception& e) { + response->success = false; + response->message = e.what(); + } catch (...) { + response->success = false; + response->message = "unknown error"; + } +} + +void OBCameraNode::getPtpConfigCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + response->data = device_->getBoolProperty(OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL); + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::getLrmMeasureDistanceCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + response->data = device_->getIntProperty(OB_PROP_LDP_MEASURE_DISTANCE_INT); + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::toggleSensorCallback(const std::shared_ptr& request, + std::shared_ptr& response, + const stream_index_pair& stream_index) { + std::string msg; + if (request->data) { + if (enable_stream_[stream_index]) { + msg = stream_name_[stream_index] + " Already ON"; + } + RCLCPP_INFO_STREAM(logger_, "toggling sensor " << stream_name_[stream_index] << " ON"); + + } else { + if (!enable_stream_[stream_index]) { + msg = stream_name_[stream_index] + " Already OFF"; + } + RCLCPP_INFO_STREAM(logger_, "toggling sensor " << stream_name_[stream_index] << " OFF"); + } + if (!msg.empty()) { + RCLCPP_ERROR_STREAM(logger_, msg); + response->success = true; + response->message = msg; + return; + } + response->success = toggleSensor(stream_index, request->data, response->message); +} + +bool OBCameraNode::toggleSensor(const stream_index_pair& stream_index, bool enabled, + std::string& msg) { + std::lock_guard lock(device_lock_); + try { + pipeline_->stop(); + enable_stream_[stream_index] = enabled; + setupProfiles(); + startStreams(); + return true; + } catch (const ob::Error& e) { + msg = e.getMessage(); + return false; + } catch (const std::exception& e) { + msg = e.what(); + return false; + } catch (...) { + msg = "unknown error"; + return false; + } +} + +void OBCameraNode::saveImageCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + (void)response; + for (const auto& stream_index : IMAGE_STREAMS) { + if (enable_stream_[stream_index]) { + save_images_[stream_index] = true; + save_images_count_[stream_index] = 0; + } + } +} + +void OBCameraNode::savePointCloudCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + (void)response; + if (enable_point_cloud_) { + save_point_cloud_ = true; + } + if (enable_colored_point_cloud_) { + save_colored_point_cloud_ = true; + } +} + +void OBCameraNode::switchIRCameraCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + if (request->data != "left" && request->data != "right") { + response->success = false; + response->message = "invalid ir camera name"; + return; + } + try { + int data = request->data == "left" ? 0 : 1; + device_->setIntProperty(OB_PROP_IR_CHANNEL_DATA_SOURCE_INT, data); + response->success = true; + return; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} +void OBCameraNode::setIRLongExposureCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + try { + device_->setBoolProperty(OB_PROP_IR_LONG_EXPOSURE_BOOL, request->data); + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::setRESETTimestampCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + device_->setBoolProperty(OB_PROP_TIMER_RESET_TRIGGER_OUT_ENABLE_BOOL, true); + device_->setBoolProperty(OB_PROP_TIMER_RESET_SIGNAL_BOOL, true); + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} +void OBCameraNode::setSYNCInterleaveLaserCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + device_->setIntProperty(OB_PROP_FRAME_INTERLEAVE_LASER_PATTERN_SYNC_DELAY_INT, request->data); + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} +void OBCameraNode::setSYNCHostimeCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + device_->timerSyncWithHost(); + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +void OBCameraNode::sendSoftwareTriggerCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + try { + if (request->data) { + device_->triggerCapture(); + } + response->success = true; + } catch (const ob::Error& e) { + response->message = e.getMessage(); + response->success = false; + } catch (const std::exception& e) { + response->message = e.what(); + response->success = false; + } catch (...) { + response->message = "unknown error"; + response->success = false; + } +} + +bool OBCameraNode::writeCustomerData(const std::string& data) { + if (data.empty()) return false; + + std::string md5_value = calcMD5(data); + uint32_t data_len_net = htonl(static_cast(data.size())); + std::string len_bytes(reinterpret_cast(&data_len_net), sizeof(data_len_net)); + + std::string write_buffer = len_bytes + md5_value + data; + device_->writeCustomerData(write_buffer.c_str(), write_buffer.size()); + + std::vector read_buffer(write_buffer.size() + 8); + uint32_t read_len = 0; + device_->readCustomerData(read_buffer.data(), &read_len); + + if (read_len < sizeof(uint32_t) + 32) return false; + + uint32_t read_data_len_net = 0; + memcpy(&read_data_len_net, read_buffer.data(), sizeof(uint32_t)); + uint32_t read_data_len = ntohl(read_data_len_net); + + std::string md5_read(reinterpret_cast(read_buffer.data() + sizeof(uint32_t)), 32); + std::string data_read(reinterpret_cast(read_buffer.data() + sizeof(uint32_t) + 32), + read_data_len); + + return calcMD5(data_read) == md5_read; +} + +bool OBCameraNode::readCustomerData(std::string& out_data) { + std::vector read_buffer(40960); + uint32_t read_len = 0; + device_->readCustomerData(read_buffer.data(), &read_len); + if (read_len < sizeof(uint32_t) + 32) { + return false; + } + uint32_t read_data_len_net = 0; + memcpy(&read_data_len_net, read_buffer.data(), sizeof(uint32_t)); + uint32_t read_data_len = ntohl(read_data_len_net); + std::string md5_read(reinterpret_cast(read_buffer.data() + sizeof(uint32_t)), 32); + std::string data_read(reinterpret_cast(read_buffer.data() + sizeof(uint32_t) + 32), + read_data_len); + if (calcMD5(data_read) == md5_read) { + out_data = std::move(data_read); + return true; + } else { + return false; + } +} + +void OBCameraNode::writeCustomerDataCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + if (request->data.empty()) { + response->success = false; + response->message = "data empty"; + return; + } + + try { + if (writeCustomerData(request->data)) { + write_customer_data_success_ = true; + response->success = true; + response->message = "write and verify success"; + user_calibration_ready_ = true; + } else { + write_customer_data_success_ = false; + response->success = false; + response->message = "write failed: MD5 mismatch or read too short"; + user_calibration_ready_ = false; + } + } catch (...) { + response->success = false; + response->message = "write exception"; + } +} + +void OBCameraNode::readCustomerDataCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + std::string data; + if (readCustomerData(data)) { + response->success = true; + response->data = std::move(data); + response->message = "read success"; + } else { + response->success = false; + response->message = "read failed: MD5 mismatch or data too short"; + } + } catch (...) { + response->success = false; + response->message = "read exception"; + } +} +void OBCameraNode::setUserCalibParamsCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + try { + std::ostringstream ss; + for (const auto& v : request->k) ss << v << " "; + for (const auto& v : request->d) ss << v << " "; + for (const auto& v : request->rotation) ss << v << " "; + for (const auto& v : request->translation) ss << v << " "; + std::string serialized_data = ss.str(); + if (writeCustomerData(serialized_data)) { + response->success = true; + response->message = "write and verify success"; + } else { + response->success = false; + response->message = "write failed"; + } + } catch (...) { + response->success = false; + response->message = "exception occurred"; + } +} +void OBCameraNode::getUserCalibParamsCallback( + const std::shared_ptr& request, + std::shared_ptr& response) { + (void)request; + try { + std::string data_read; + if (!readCustomerData(data_read)) { + response->success = false; + response->message = "read failed"; + return; + } + std::istringstream ss(data_read); + for (size_t i = 0; i < 9; ++i) ss >> response->k[i]; + for (size_t i = 0; i < 8; ++i) ss >> response->d[i]; + for (size_t i = 0; i < 9; ++i) ss >> response->rotation[i]; + for (size_t i = 0; i < 3; ++i) ss >> response->translation[i]; + response->success = true; + response->message = "read success"; + } catch (...) { + response->success = false; + response->message = "exception occurred"; + } +} +void OBCameraNode::setAEModeCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + try { + if (device_->isPropertySupported(OB_PROP_DEVICE_AE_REFERENCE_INT, OB_PERMISSION_WRITE) && + (request->data == "depthbased" || request->data == "colorbased")) { + device_->setIntProperty(OB_PROP_DEVICE_AE_REFERENCE_INT, + request->data == "depthbased" ? 0 : 1); + ae_mode_ = request->data; + response->success = true; + response->message = "set AE mode success"; + } else { + response->success = false; + response->message = "set AE mode failed"; + } + } catch (...) { + response->success = false; + response->message = "exception occurred"; + } +} +void OBCameraNode::setSportsModeCallback(const std::shared_ptr& request, + std::shared_ptr& response) { + try { + if (device_->isPropertySupported(OB_PROP_DEVICE_AE_STRATEGY_INT, OB_PERMISSION_WRITE)) { + device_->setIntProperty(OB_PROP_DEVICE_AE_STRATEGY_INT, request->data ? 1 : 0); + response->success = true; + response->message = "set sports mode success"; + } else { + response->success = false; + response->message = "set sports mode failed"; + } + } catch (...) { + response->success = false; + response->message = "exception occurred"; + } +} +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/src/synced_imu_publisher.cpp b/dev_ws/src/orbbec_camera/src/synced_imu_publisher.cpp new file mode 100644 index 0000000..f17f7db --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/synced_imu_publisher.cpp @@ -0,0 +1,69 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#include "orbbec_camera/utils.h" +#include "orbbec_camera/synced_imu_publisher.h" +#include + +namespace orbbec_camera { +SyncedImuPublisher::SyncedImuPublisher( + rclcpp::Publisher::SharedPtr imu_publisher, size_t queue_size) + : imu_publisher_(imu_publisher), queue_size_(queue_size) {} + +SyncedImuPublisher::~SyncedImuPublisher() { publishPendingMessages(); } + +void SyncedImuPublisher::publish(const sensor_msgs::msg::Imu &imu_msg) { + std::unique_lock lock(mutex_); + auto sub_num = imu_publisher_->get_subscription_count(); + if (sub_num == 0 || !is_enabled_) { + return; + } + if (is_paused_) { + while (queue_.size() >= queue_size_) { + queue_.pop(); + } + queue_.push(imu_msg); + } else { + imu_publisher_->publish(imu_msg); + } +} + +void SyncedImuPublisher::pause() { + std::unique_lock lock(mutex_); + is_paused_ = true; +} + +void SyncedImuPublisher::resume() { + std::unique_lock lock(mutex_); + is_paused_ = false; + publishPendingMessages(); +} + +void SyncedImuPublisher::setQueueSize(size_t queue_size) { + std::unique_lock lock(mutex_); + queue_size_ = queue_size; +} + +void SyncedImuPublisher::enable(bool enable) { is_enabled_ = enable; } + +void SyncedImuPublisher::publishPendingMessages() { + std::unique_lock lock(mutex_); + while (!queue_.empty()) { + imu_publisher_->publish(queue_.front()); + queue_.pop(); + } +} + +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/src/utils.cpp b/dev_ws/src/orbbec_camera/src/utils.cpp new file mode 100644 index 0000000..a1a504a --- /dev/null +++ b/dev_ws/src/orbbec_camera/src/utils.cpp @@ -0,0 +1,1019 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include +#include "orbbec_camera/utils.h" +#include +#include "orbbec_camera/constants.h" +namespace orbbec_camera { +sensor_msgs::msg::CameraInfo convertToCameraInfo(OBCameraIntrinsic intrinsic, + OBCameraDistortion distortion, int width) { + (void)width; + sensor_msgs::msg::CameraInfo info; + info.distortion_model = getDistortionModels(distortion); + info.width = intrinsic.width; + info.height = intrinsic.height; + info.d.resize(8, 0.0); + info.d[0] = distortion.k1; + info.d[1] = distortion.k2; + info.d[2] = distortion.p1; + info.d[3] = distortion.p2; + info.d[4] = distortion.k3; + info.d[5] = distortion.k4; + info.d[6] = distortion.k5; + info.d[7] = distortion.k6; + bool all_zero = std::all_of(info.d.begin(), info.d.end(), [](double val) { return val == 0.0; }); + info.roi.do_rectify = all_zero; + + info.k.fill(0.0); + info.k[0] = intrinsic.fx; + info.k[2] = intrinsic.cx; + info.k[4] = intrinsic.fy; + info.k[5] = intrinsic.cy; + info.k[8] = 1.0; + + info.r.fill(0.0); + info.r[0] = 1; + info.r[4] = 1; + info.r[8] = 1; + + info.p.fill(0.0); + info.p[0] = info.k[0]; + info.p[2] = info.k[2]; + info.p[5] = info.k[4]; + info.p[6] = info.k[5]; + info.p[10] = 1.0; + return info; +} + +void saveRGBPointsToPly(const std::shared_ptr &frame, const std::string &fileName) { + size_t point_size = frame->getDataSize() / sizeof(OBColorPoint); + FILE *fp = fopen(fileName.c_str(), "wb+"); + std::shared_ptr fp_guard(nullptr, [&fp](int *) { + fflush(fp); + fclose(fp); + }); + fprintf(fp, "ply\n"); + fprintf(fp, "format ascii 1.0\n"); + fprintf(fp, "element vertex %zu\n", point_size); + fprintf(fp, "property float x\n"); + fprintf(fp, "property float y\n"); + fprintf(fp, "property float z\n"); + fprintf(fp, "property uchar red\n"); + fprintf(fp, "property uchar green\n"); + fprintf(fp, "property uchar blue\n"); + fprintf(fp, "end_header\n"); + + const auto *points = (OBColorPoint *)frame->getData(); + CHECK_NOTNULL(points); + for (size_t i = 0; i < point_size; i++) { + fprintf(fp, "%.3f %.3f %.3f %d %d %d\n", points[i].x, points[i].y, points[i].z, + (int)points[i].r, (int)points[i].g, (int)points[i].b); + } +} + +void saveRGBPointCloudMsgToPly(const sensor_msgs::msg::PointCloud2::UniquePtr &msg, + const std::string &fileName) { + FILE *fp = fopen(fileName.c_str(), "wb+"); + CHECK_NOTNULL(fp); + CHECK_NOTNULL(msg); + + sensor_msgs::PointCloud2ConstIterator iter_x(*msg, "x"); + sensor_msgs::PointCloud2ConstIterator iter_y(*msg, "y"); + sensor_msgs::PointCloud2ConstIterator iter_z(*msg, "z"); + + // First, count the actual number of valid points + size_t valid_points = 0; + for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) { + if (!std::isnan(*iter_x) && !std::isnan(*iter_y) && !std::isnan(*iter_z)) { + ++valid_points; + } + } + + // Reset the iterators + iter_x = sensor_msgs::PointCloud2ConstIterator(*msg, "x"); + iter_y = sensor_msgs::PointCloud2ConstIterator(*msg, "y"); + iter_z = sensor_msgs::PointCloud2ConstIterator(*msg, "z"); + sensor_msgs::PointCloud2ConstIterator iter_r(*msg, "r"); + sensor_msgs::PointCloud2ConstIterator iter_g(*msg, "g"); + sensor_msgs::PointCloud2ConstIterator iter_b(*msg, "b"); + + fprintf(fp, "ply\n"); + fprintf(fp, "format ascii 1.0\n"); + fprintf(fp, "element vertex %zu\n", valid_points); + fprintf(fp, "property float x\n"); + fprintf(fp, "property float y\n"); + fprintf(fp, "property float z\n"); + fprintf(fp, "property uchar red\n"); + fprintf(fp, "property uchar green\n"); + fprintf(fp, "property uchar blue\n"); + fprintf(fp, "end_header\n"); + + for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z, ++iter_r, ++iter_g, ++iter_b) { + if (!std::isnan(*iter_x) && !std::isnan(*iter_y) && !std::isnan(*iter_z)) { + fprintf(fp, "%.3f %.3f %.3f %d %d %d\n", *iter_x, *iter_y, *iter_z, (int)*iter_r, + (int)*iter_g, (int)*iter_b); + } + } + + fflush(fp); + fclose(fp); +} + +void saveDepthPointsToPly(const sensor_msgs::msg::PointCloud2::UniquePtr &msg, + const std::string &fileName) { + FILE *fp = fopen(fileName.c_str(), "wb+"); + CHECK_NOTNULL(fp); + CHECK_NOTNULL(msg); + sensor_msgs::PointCloud2ConstIterator iter_x(*msg, "x"); + sensor_msgs::PointCloud2ConstIterator iter_y(*msg, "y"); + sensor_msgs::PointCloud2ConstIterator iter_z(*msg, "z"); + + // First, count the actual number of valid points + size_t valid_points = 0; + for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) { + if (!std::isnan(*iter_x) && !std::isnan(*iter_y) && !std::isnan(*iter_z)) { + ++valid_points; + } + } + + // Reset the iterators + iter_x = sensor_msgs::PointCloud2ConstIterator(*msg, "x"); + iter_y = sensor_msgs::PointCloud2ConstIterator(*msg, "y"); + iter_z = sensor_msgs::PointCloud2ConstIterator(*msg, "z"); + + fprintf(fp, "ply\n"); + fprintf(fp, "format ascii 1.0\n"); + fprintf(fp, "element vertex %zu\n", valid_points); + fprintf(fp, "property float x\n"); + fprintf(fp, "property float y\n"); + fprintf(fp, "property float z\n"); + fprintf(fp, "end_header\n"); + + for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) { + if (!std::isnan(*iter_x) && !std::isnan(*iter_y) && !std::isnan(*iter_z)) { + fprintf(fp, "%.3f %.3f %.3f\n", *iter_x, *iter_y, *iter_z); + } + } + + fflush(fp); + fclose(fp); +} + +void savePointsToPly(const std::shared_ptr &frame, const std::string &fileName) { + size_t point_size = frame->getDataSize() / sizeof(OBPoint); + FILE *fp = fopen(fileName.c_str(), "wb+"); + std::shared_ptr fp_guard(nullptr, [&fp](int *) { + fflush(fp); + fclose(fp); + }); + CHECK_NOTNULL(fp); + CHECK_NOTNULL(frame); + fprintf(fp, "ply\n"); + fprintf(fp, "format ascii 1.0\n"); + fprintf(fp, "element vertex %zu\n", point_size); + fprintf(fp, "property float x\n"); + fprintf(fp, "property float y\n"); + fprintf(fp, "property float z\n"); + fprintf(fp, "end_header\n"); + + const auto *points = (OBPoint *)frame->getData(); + CHECK_NOTNULL(points); + for (size_t i = 0; i < point_size; i++) { + fprintf(fp, "%.3f %.3f %.3f\n", points[i].x, points[i].y, points[i].z); + } +} + +tf2::Quaternion rotationMatrixToQuaternion(const float rotation[9]) { + Eigen::Matrix3f m; + m << rotation[0], rotation[1], rotation[2], rotation[3], rotation[4], rotation[5], rotation[6], + rotation[7], rotation[8]; + Eigen::Quaternionf q(m); + return {q.x(), q.y(), q.z(), q.w()}; +} + +std::ostream &operator<<(std::ostream &os, const OBCameraParam &rhs) { + auto depth_intrinsic = rhs.depthIntrinsic; + auto rgb_intrinsic = rhs.rgbIntrinsic; + os << "=====depth intrinsic=====\n"; + os << "fx : " << depth_intrinsic.fx << "\n"; + os << "fy : " << depth_intrinsic.fy << "\n"; + os << "cx : " << depth_intrinsic.cx << "\n"; + os << "cy : " << depth_intrinsic.cy << "\n"; + os << "width : " << depth_intrinsic.width << "\n"; + os << "height : " << depth_intrinsic.height << "\n"; + os << "=====rgb intrinsic=====\n"; + os << "fx : " << rgb_intrinsic.fx << "\n"; + os << "fy : " << rgb_intrinsic.fy << "\n"; + os << "cx : " << rgb_intrinsic.cx << "\n"; + os << "cy : " << rgb_intrinsic.cy << "\n"; + os << "width : " << rgb_intrinsic.width << "\n"; + os << "height : " << rgb_intrinsic.height << "\n"; + return os; +} + +orbbec_camera_msgs::msg::Extrinsics obExtrinsicsToMsg(const OBD2CTransform &extrinsics, + const std::string &frame_id) { + orbbec_camera_msgs::msg::Extrinsics msg; + for (int i = 0; i < 9; ++i) { + msg.rotation[i] = extrinsics.rot[i]; + if (i < 3) { + msg.translation[i] = extrinsics.trans[i] / 1000.0; + } + } + + msg.header.frame_id = frame_id; + return msg; +} + +rclcpp::Time fromMsToROSTime(uint64_t ms) { + auto total = static_cast(ms * 1e6); + uint64_t sec = total / 1000000000; + uint64_t nano_sec = total % 1000000000; + rclcpp::Time stamp(sec, nano_sec); + return stamp; +} + +rclcpp::Time fromUsToROSTime(uint64_t us) { + auto total = static_cast(us * 1e3); + uint64_t sec = total / 1000000000; + uint64_t nano_sec = total % 1000000000; + rclcpp::Time stamp(sec, nano_sec); + return stamp; +} + +std::string getObSDKVersion() { + std::string major = std::to_string(ob::Version::getMajor()); + std::string minor = std::to_string(ob::Version::getMinor()); + std::string patch = std::to_string(ob::Version::getPatch()); + std::string version = major + "." + minor + "." + patch; + return version; +} + +OBFormat OBFormatFromString(const std::string &format) { + if (format.empty()) { + return OB_FORMAT_UNKNOWN; + } + std::string fixed_format; + std::transform(format.begin(), format.end(), std::back_inserter(fixed_format), + [](const auto ch) { return std::isalpha(ch) ? toupper(ch) : ch; }); + std::cout << "OBFormatFromString: " << fixed_format << std::endl; + if (fixed_format == "MJPG") { + return OB_FORMAT_MJPG; + } else if (fixed_format == "MJPEG") { + return OB_FORMAT_MJPEG; + } else if (fixed_format == "YUYV") { + return OB_FORMAT_YUYV; + } else if (fixed_format == "YUYV2") { + return OB_FORMAT_YUY2; + } else if (fixed_format == "UYVY") { + return OB_FORMAT_UYVY; + } else if (fixed_format == "NV12") { + return OB_FORMAT_NV12; + } else if (fixed_format == "NV21") { + return OB_FORMAT_NV21; + } else if (fixed_format == "H264") { + return OB_FORMAT_H264; + } else if (fixed_format == "H265") { + return OB_FORMAT_H265; + } else if (fixed_format == "Y16") { + return OB_FORMAT_Y16; + } else if (fixed_format == "Y8") { + return OB_FORMAT_Y8; + } else if (fixed_format == "Y10") { + return OB_FORMAT_Y10; + } else if (fixed_format == "Y11") { + return OB_FORMAT_Y11; + } else if (fixed_format == "Y12") { + return OB_FORMAT_Y12; + } else if (fixed_format == "GRAY") { + return OB_FORMAT_GRAY; + } else if (fixed_format == "HEVC") { + return OB_FORMAT_HEVC; + } else if (fixed_format == "I420") { + return OB_FORMAT_I420; + } else if (fixed_format == "ACCEL") { + return OB_FORMAT_ACCEL; + } else if (fixed_format == "GYRO") { + return OB_FORMAT_GYRO; + } else if (fixed_format == "POINT") { + return OB_FORMAT_POINT; + } else if (fixed_format == "RGB_POINT") { + return OB_FORMAT_RGB_POINT; + } else if (fixed_format == "REL") { + return OB_FORMAT_RLE; + } else if (fixed_format == "RGB888" || fixed_format == "RGB") { + return OB_FORMAT_RGB888; + } else if (fixed_format == "BGR") { + return OB_FORMAT_BGR; + } else if (fixed_format == "Y14") { + return OB_FORMAT_Y14; + } else if (fixed_format == "BGRA") { + return OB_FORMAT_BGRA; + } else if (fixed_format == "COMPRESSED") { + return OB_FORMAT_COMPRESSED; + } else if (fixed_format == "RVL") { + return OB_FORMAT_RVL; + } else if (fixed_format == "Z16") { + return OB_FORMAT_Z16; + } else if (fixed_format == "YV12") { + return OB_FORMAT_YV12; + } else if (fixed_format == "BA81") { + return OB_FORMAT_BA81; + } else if (fixed_format == "RGBA") { + return OB_FORMAT_RGBA; + } else if (fixed_format == "BYR2") { + return OB_FORMAT_BYR2; + } else if (fixed_format == "RW16") { + return OB_FORMAT_RW16; + } else if (fixed_format == "Y12C4") { + return OB_FORMAT_Y12C4; + } else if (fixed_format == "LIDAR_POINT") { + return OB_FORMAT_LIDAR_POINT; + } else if (fixed_format == "LIDAR_SPHERE_POINT") { + return OB_FORMAT_LIDAR_SPHERE_POINT; + } else if (fixed_format == "LIDAR_SCAN") { + return OB_FORMAT_LIDAR_SCAN; + } else if (fixed_format == "LIDAR_CALIBRATION") { + return OB_FORMAT_LIDAR_CALIBRATION; + } + // else if (fixed_format == "DISP16") { + // return OB_FORMAT_DISP16; + // } + else { + return OB_FORMAT_UNKNOWN; + } +} + +OBLiDARScanRate OBScanRateFromInt(const int rate) { + std::cout << "OBScanRateFromInt: " << rate << std::endl; + if (rate == 5) { + return OB_LIDAR_SCAN_5HZ; + } else if (rate == 10) { + return OB_LIDAR_SCAN_10HZ; + } else if (rate == 15) { + return OB_LIDAR_SCAN_15HZ; + } else if (rate == 20) { + return OB_LIDAR_SCAN_20HZ; + } else if (rate == 25) { + return OB_LIDAR_SCAN_25HZ; + } else if (rate == 30) { + return OB_LIDAR_SCAN_30HZ; + } else if (rate == 40) { + return OB_LIDAR_SCAN_40HZ; + } else { + return OB_LIDAR_SCAN_UNKNOWN; + } +} + +std::string OBFormatToString(const OBFormat &format) { + switch (format) { + case OB_FORMAT_MJPG: + return "MJPG"; + case OB_FORMAT_YUYV: + return "YUYV"; + case OB_FORMAT_YUY2: + return "YUYV2"; + case OB_FORMAT_UYVY: + return "UYVY"; + case OB_FORMAT_NV12: + return "NV12"; + case OB_FORMAT_NV21: + return "NV21"; + case OB_FORMAT_H264: + return "H264"; + case OB_FORMAT_H265: + return "H265"; + case OB_FORMAT_Y16: + return "Y16"; + case OB_FORMAT_Y8: + return "Y8"; + case OB_FORMAT_Y10: + return "Y10"; + case OB_FORMAT_Y11: + return "Y11"; + case OB_FORMAT_Y12: + return "Y12"; + case OB_FORMAT_GRAY: + return "GRAY"; + case OB_FORMAT_HEVC: + return "HEVC"; + case OB_FORMAT_I420: + return "I420"; + case OB_FORMAT_ACCEL: + return "ACCEL"; + case OB_FORMAT_GYRO: + return "GYRO"; + case OB_FORMAT_POINT: + return "POINT"; + case OB_FORMAT_RGB_POINT: + return "RGB_POINT"; + case OB_FORMAT_RLE: + return "REL"; + case OB_FORMAT_RGB888: + return "RGB888"; + case OB_FORMAT_BGR: + return "BGR"; + case OB_FORMAT_Y14: + return "Y14"; + case OB_FORMAT_BGRA: + return "BGRA"; + case OB_FORMAT_COMPRESSED: + return "COMPRESSED"; + case OB_FORMAT_RVL: + return "RVL"; + case OB_FORMAT_Z16: + return "Z16"; + case OB_FORMAT_YV12: + return "YV12"; + case OB_FORMAT_BA81: + return "BA81"; + case OB_FORMAT_RGBA: + return "RGBA"; + case OB_FORMAT_BYR2: + return "BYR2"; + case OB_FORMAT_RW16: + return "RW16"; + case OB_FORMAT_Y12C4: + return "Y12C4"; + // case OB_FORMAT_DISP16: + // return "DISP16"; + default: + return "UNKNOWN"; + } +} + +std::ostream &operator<<(std::ostream &os, const OBFormat &rhs) { + os << OBFormatToString(rhs); + return os; +} + +std::string ObDeviceTypeToString(const OBDeviceType &type) { + switch (type) { + case OBDeviceType::OB_STRUCTURED_LIGHT_BINOCULAR_CAMERA: + return "structured light binocular camera"; + case OBDeviceType::OB_STRUCTURED_LIGHT_MONOCULAR_CAMERA: + return "structured light monocular camera"; + case OBDeviceType::OB_TOF_CAMERA: + return "tof camera"; + default: + // 澶勭悊鍏朵粬鏈瑙佺殑鎯呭喌 + break; + } + return "unknown technology camera"; +} + +rmw_qos_profile_t getRMWQosProfileFromString(const std::string &str_qos) { + std::string upper_str_qos = str_qos; + std::transform(upper_str_qos.begin(), upper_str_qos.end(), upper_str_qos.begin(), ::toupper); + if (upper_str_qos == "SYSTEM_DEFAULT") { + return rmw_qos_profile_system_default; + } else if (upper_str_qos == "DEFAULT") { + return rmw_qos_profile_default; + } else if (upper_str_qos == "PARAMETER_EVENTS") { + return rmw_qos_profile_parameter_events; + } else if (upper_str_qos == "SERVICES_DEFAULT") { + return rmw_qos_profile_services_default; + } else if (upper_str_qos == "PARAMETERS") { + return rmw_qos_profile_parameters; + } else if (upper_str_qos == "SENSOR_DATA") { + return rmw_qos_profile_sensor_data; + } else { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("astra_camera"), + "Invalid QoS profile: " << upper_str_qos << ". Using default QoS profile."); + return rmw_qos_profile_default; + } +} + +bool isOpenNIDevice(int pid) { + static const std::vector OPENNI_DEVICE_PIDS = { + 0x0300, 0x0301, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0407, 0x0601, 0x060b, 0x060e, + 0x060f, 0x0610, 0x0613, 0x0614, 0x0616, 0x0617, 0x0618, 0x061b, 0x062b, 0x062c, 0x062d, + 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063a, 0x0650, 0x0651, + 0x0654, 0x0655, 0x0656, 0x0657, 0x0658, 0x0659, 0x065a, 0x065b, 0x065c, 0x065d, 0x0698, + 0x0699, 0x069a, 0x055c, 0x065e, 0x069a, 0x069f, 0x06a0, 0x069e}; + + return std::any_of(OPENNI_DEVICE_PIDS.begin(), OPENNI_DEVICE_PIDS.end(), + [pid](int pid_openni) { return pid == pid_openni; }); +} + +OB_DEPTH_PRECISION_LEVEL depthPrecisionLevelFromString( + const std::string &depth_precision_level_str) { + if (depth_precision_level_str == "1mm") { + return OB_PRECISION_1MM; + } else if (depth_precision_level_str == "0.8mm") { + return OB_PRECISION_0MM8; + } else if (depth_precision_level_str == "0.4mm") { + return OB_PRECISION_0MM4; + } else if (depth_precision_level_str == "0.2mm") { + return OB_PRECISION_0MM2; + } else if (depth_precision_level_str == "0.1mm") { + return OB_PRECISION_0MM1; + } else { + return OB_PRECISION_0MM8; + } +} + +float depthPrecisionFromString(const std::string &depth_precision_level_str) { + // covert 0.8mm to 0.8 + if (depth_precision_level_str.size() < 2) { + RCLCPP_WARN_STREAM(rclcpp::get_logger("utils"), + "Invalid depth precision level: " << depth_precision_level_str + << ". Using default precision level 1mm"); + return 1.0; + } + std::string depth_precision_level_str_num = + depth_precision_level_str.substr(0, depth_precision_level_str.size() - 2); + return std::stof(depth_precision_level_str_num); +} + +OBMultiDeviceSyncMode OBSyncModeFromString(const std::string &mode) { + if (mode == "FREE_RUN") { + return OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN; + } else if (mode == "STANDALONE") { + return OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_STANDALONE; + } else if (mode == "PRIMARY") { + return OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_PRIMARY; + } else if (mode == "SECONDARY") { + return OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_SECONDARY; + } else if (mode == "SECONDARY_SYNCED") { + return OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_SECONDARY_SYNCED; + } else if (mode == "SOFTWARE_TRIGGERING") { + return OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING; + } else if (mode == "HARDWARE_TRIGGERING") { + return OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING; + } else { + return OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN; + } +} + +OB_SAMPLE_RATE sampleRateFromString(std::string &sample_rate) { + // covert to lower case + std::transform(sample_rate.begin(), sample_rate.end(), sample_rate.begin(), ::tolower); + if (sample_rate == "1.5625hz") { + return OB_SAMPLE_RATE_1_5625_HZ; + } else if (sample_rate == "3.125hz") { + return OB_SAMPLE_RATE_3_125_HZ; + } else if (sample_rate == "6.25hz") { + return OB_SAMPLE_RATE_6_25_HZ; + } else if (sample_rate == "12.5hz") { + return OB_SAMPLE_RATE_12_5_HZ; + } else if (sample_rate == "25hz") { + return OB_SAMPLE_RATE_25_HZ; + } else if (sample_rate == "50hz") { + return OB_SAMPLE_RATE_50_HZ; + } else if (sample_rate == "100hz") { + return OB_SAMPLE_RATE_100_HZ; + } else if (sample_rate == "200hz") { + return OB_SAMPLE_RATE_200_HZ; + } else if (sample_rate == "500hz") { + return OB_SAMPLE_RATE_500_HZ; + } else if (sample_rate == "1khz") { + return OB_SAMPLE_RATE_1_KHZ; + } else if (sample_rate == "2khz") { + return OB_SAMPLE_RATE_2_KHZ; + } else if (sample_rate == "4khz") { + return OB_SAMPLE_RATE_4_KHZ; + } else if (sample_rate == "8khz") { + return OB_SAMPLE_RATE_8_KHZ; + } else if (sample_rate == "16khz") { + return OB_SAMPLE_RATE_16_KHZ; + } else if (sample_rate == "32khz") { + return OB_SAMPLE_RATE_32_KHZ; + } else { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("utils"), "Unknown OB_SAMPLE_RATE: " << sample_rate); + return OB_SAMPLE_RATE_100_HZ; + } +} + +std::string sampleRateToString(const OB_SAMPLE_RATE &sample_rate) { + switch (sample_rate) { + case OB_SAMPLE_RATE_1_5625_HZ: + return "1.5625hz"; + case OB_SAMPLE_RATE_3_125_HZ: + return "3.125hz"; + case OB_SAMPLE_RATE_6_25_HZ: + return "6.25hz"; + case OB_SAMPLE_RATE_12_5_HZ: + return "12.5hz"; + case OB_SAMPLE_RATE_25_HZ: + return "25hz"; + case OB_SAMPLE_RATE_50_HZ: + return "50hz"; + case OB_SAMPLE_RATE_100_HZ: + return "100hz"; + case OB_SAMPLE_RATE_200_HZ: + return "200hz"; + case OB_SAMPLE_RATE_500_HZ: + return "500hz"; + case OB_SAMPLE_RATE_1_KHZ: + return "1khz"; + case OB_SAMPLE_RATE_2_KHZ: + return "2khz"; + case OB_SAMPLE_RATE_4_KHZ: + return "4khz"; + case OB_SAMPLE_RATE_8_KHZ: + return "8khz"; + case OB_SAMPLE_RATE_16_KHZ: + return "16khz"; + case OB_SAMPLE_RATE_32_KHZ: + return "32khz"; + default: + return "100hz"; + } +} + +std::ostream &operator<<(std::ostream &os, const OB_SAMPLE_RATE &rhs) { + os << sampleRateToString(rhs); + return os; +} + +OB_GYRO_FULL_SCALE_RANGE fullGyroScaleRangeFromString(std::string &full_scale_range) { + std::transform(full_scale_range.begin(), full_scale_range.end(), full_scale_range.begin(), + ::tolower); + if (full_scale_range == "16dps") { + return OB_GYRO_FS_16dps; + } else if (full_scale_range == "31dps") { + return OB_GYRO_FS_31dps; + } else if (full_scale_range == "62dps") { + return OB_GYRO_FS_62dps; + } else if (full_scale_range == "125dps") { + return OB_GYRO_FS_125dps; + } else if (full_scale_range == "250dps") { + return OB_GYRO_FS_250dps; + } else if (full_scale_range == "500dps") { + return OB_GYRO_FS_500dps; + } else if (full_scale_range == "1000dps") { + return OB_GYRO_FS_1000dps; + } else if (full_scale_range == "2000dps") { + return OB_GYRO_FS_2000dps; + } else { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("utils"), + "Unknown OB_GYRO_FULL_SCALE_RANGE: " << full_scale_range); + return OB_GYRO_FS_2000dps; + } +} + +std::string fullGyroScaleRangeToString(const OB_GYRO_FULL_SCALE_RANGE &full_scale_range) { + switch (full_scale_range) { + case OB_GYRO_FS_16dps: + return "16dps"; + case OB_GYRO_FS_31dps: + return "31dps"; + case OB_GYRO_FS_62dps: + return "62dps"; + case OB_GYRO_FS_125dps: + return "125dps"; + case OB_GYRO_FS_250dps: + return "250dps"; + case OB_GYRO_FS_500dps: + return "500dps"; + case OB_GYRO_FS_1000dps: + return "1000dps"; + case OB_GYRO_FS_2000dps: + return "2000dps"; + default: + return "16dps"; + } +} + +std::ostream &operator<<(std::ostream &os, const OB_GYRO_FULL_SCALE_RANGE &rhs) { + os << fullGyroScaleRangeToString(rhs); + return os; +} + +OBAccelFullScaleRange fullAccelScaleRangeFromString(std::string &full_scale_range) { + std::transform(full_scale_range.begin(), full_scale_range.end(), full_scale_range.begin(), + ::tolower); + if (full_scale_range == "2g") { + return OB_ACCEL_FS_2g; + } else if (full_scale_range == "4g") { + return OB_ACCEL_FS_4g; + } else if (full_scale_range == "8g") { + return OB_ACCEL_FS_8g; + } else if (full_scale_range == "16g") { + return OB_ACCEL_FS_16g; + } else if (full_scale_range == "3g") { + return OB_ACCEL_FS_3g; + } else if (full_scale_range == "6g") { + return OB_ACCEL_FS_6g; + } else if (full_scale_range == "12g") { + return OB_ACCEL_FS_12g; + } else if (full_scale_range == "24g") { + return OB_ACCEL_FS_24g; + } else { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("utils"), + "Unknown OB_ACCEL_FULL_SCALE_RANGE: " << full_scale_range); + return OB_ACCEL_FS_16g; + } +} + +std::string fullAccelScaleRangeToString(const OBAccelFullScaleRange &full_scale_range) { + switch (full_scale_range) { + case OB_ACCEL_FS_2g: + return "2g"; + case OB_ACCEL_FS_4g: + return "4g"; + case OB_ACCEL_FS_8g: + return "8g"; + case OB_ACCEL_FS_16g: + return "16g"; + case OB_ACCEL_FS_3g: + return "3g"; + case OB_ACCEL_FS_6g: + return "6g"; + case OB_ACCEL_FS_12g: + return "12g"; + case OB_ACCEL_FS_24g: + return "24g"; + default: + return "2g"; + } +} + +std::ostream &operator<<(std::ostream &os, const OBAccelFullScaleRange &rhs) { + os << fullAccelScaleRangeToString(rhs); + return os; +} + +std::string parseUsbPort(const std::string &line) { + std::string port_id; + std::regex usb_regex("(?:[^ ]+/usb[0-9]+[0-9./-]*/){0,1}([0-9.-]+)(:){0,1}[^ ]*", + std::regex_constants::ECMAScript); + std::smatch base_match; + bool found_usb = std::regex_match(line, base_match, usb_regex); + + if (found_usb) { + port_id = base_match[1].str(); + std::cout << "USB port_id: " << port_id << std::endl; + + if (base_match[2].str().empty()) { + std::regex end_regex(".+(-[0-9]+$)", std::regex_constants::ECMAScript); + bool found_end = std::regex_match(port_id, base_match, end_regex); + + if (found_end) { + port_id = port_id.substr(0, port_id.size() - base_match[1].str().size()); + std::cout << "Modified USB port_id: " << port_id << std::endl; + } + } + + return port_id; + } + + std::regex gmsl_regex("(gmsl[0-9]+)(?:-[0-9]+)*(-[0-9]+)$", std::regex_constants::ECMAScript); + bool found_gmsl = std::regex_match(line, base_match, gmsl_regex); + + if (found_gmsl) { + port_id = base_match[1].str() + base_match[2].str(); + std::cout << "Parsed GMSL Port ID: " << port_id << std::endl; + return port_id; + } + + return ""; +} + +bool isValidJPEG(const std::shared_ptr &frame) { + if (frame->getDataSize() < 2) { // Checking both start and end markers, so minimal size is 4 + return false; + } + + const auto *data = static_cast(frame->getData()); + + // Check for JPEG start marker + if (data[0] != 0xFF || data[1] != 0xD8) { + return false; + } + return true; +} + +std::string metaDataTypeToString(const OBFrameMetadataType &meta_data_type) { + switch (meta_data_type) { + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_TIMESTAMP: + return "frame_timestamp"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_SENSOR_TIMESTAMP: + return "sensor_timestamp"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_FRAME_NUMBER: + return "frame_number"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_AUTO_EXPOSURE: + return "auto_exposure"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_EXPOSURE: + return "exposure"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_GAIN: + return "gain"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_AUTO_WHITE_BALANCE: + return "auto_white_balance"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_WHITE_BALANCE: + return "white_balance"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_BRIGHTNESS: + return "brightness"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_CONTRAST: + return "contrast"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_SATURATION: + return "saturation"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_SHARPNESS: + return "sharpness"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_BACKLIGHT_COMPENSATION: + return "backlight_compensation"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_HUE: + return "hue"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_GAMMA: + return "gamma"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_POWER_LINE_FREQUENCY: + return "power_line_frequency"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_LOW_LIGHT_COMPENSATION: + return "low_light_compensation"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_MANUAL_WHITE_BALANCE: + return "manual_white_balance"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_ACTUAL_FRAME_RATE: + return "actual_frame_rate"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_FRAME_RATE: + return "frame_rate"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_AE_ROI_LEFT: + return "ae_roi_left"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_AE_ROI_TOP: + return "ae_roi_top"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_AE_ROI_RIGHT: + return "ae_roi_right"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_AE_ROI_BOTTOM: + return "ae_roi_bottom"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_EXPOSURE_PRIORITY: + return "exposure_priority"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_HDR_SEQUENCE_NAME: + return "hdr_sequence_name"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_HDR_SEQUENCE_SIZE: + return "hdr_sequence_size"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_HDR_SEQUENCE_INDEX: + return "hdr_sequence_index"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_LASER_POWER: + return "frame_laser_power"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_LASER_POWER_MODE: + return "frame_laser_power_mode"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_EMITTER_MODE: + return "frame_emitter_mode"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_GPIO_INPUT_DATA: + return "gpio_input_data"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_DISPARITY_SEARCH_OFFSET: + return "disparity_search_offset"; + case OBFrameMetadataType::OB_FRAME_METADATA_TYPE_DISPARITY_SEARCH_RANGE: + return "disparity search range"; + default: + return "unknown_field"; + } +} + +std::ostream &operator<<(std::ostream &os, const OBFrameMetadataType &rhs) { + os << metaDataTypeToString(rhs); + return os; +} + +OBHoleFillingMode holeFillingModeFromString(const std::string &hole_filling_mode) { + if (hole_filling_mode == "FILL_TOP") { + return OB_HOLE_FILL_TOP; + } else if (hole_filling_mode == "FILL_NEAREST") { + return OB_HOLE_FILL_NEAREST; + } else if (hole_filling_mode == "FILL_FAREST") { + return OB_HOLE_FILL_FAREST; + } else { + return OB_HOLE_FILL_NEAREST; + } +} + +bool isGemini2R(int pid) { + if (pid == GEMINI2R_PID || pid == GEMINI2RL_PID) { + return true; + } + if (pid == GEMINI2R_PID2 || pid == GEMINI2RL_PID2) { + return true; + } + return false; +} + +OBStreamType obStreamTypeFromString(const std::string &stream_type) { + std::string upper_stream_type = stream_type; + std::transform(upper_stream_type.begin(), upper_stream_type.end(), upper_stream_type.begin(), + ::toupper); + if (upper_stream_type == "VIDEO") { + return OB_STREAM_VIDEO; + } else if (upper_stream_type == "IR") { + return OB_STREAM_IR; + } else if (upper_stream_type == "COLOR") { + return OB_STREAM_COLOR; + } else if (upper_stream_type == "DEPTH") { + return OB_STREAM_DEPTH; + } else if (upper_stream_type == "ACCEL") { + return OB_STREAM_ACCEL; + } else if (upper_stream_type == "GYRO") { + return OB_STREAM_GYRO; + } else if (upper_stream_type == "IR_LEFT") { + return OB_STREAM_IR_LEFT; + } else if (upper_stream_type == "IR_RIGHT") { + return OB_STREAM_IR_RIGHT; + } else if (upper_stream_type == "RAW_PHASE") { + return OB_STREAM_RAW_PHASE; + } else { + return OB_STREAM_UNKNOWN; + } +} + +UndistortedImageResult undistortImage(const cv::Mat &image, const OBCameraIntrinsic &intrinsic, + const OBCameraDistortion &distortion) { + UndistortedImageResult result; + cv::Mat camera_matrix = cv::Mat::eye(3, 3, CV_64F); + camera_matrix.at(0, 0) = intrinsic.fx; + camera_matrix.at(1, 1) = intrinsic.fy; + camera_matrix.at(0, 2) = intrinsic.cx; + camera_matrix.at(1, 2) = intrinsic.cy; + + // Create the distortion coefficients matrix using the extended distortion model + cv::Mat dist_coeffs = (cv::Mat_(8, 1) << distortion.k1, distortion.k2, distortion.p1, + distortion.p2, distortion.k3, distortion.k4, distortion.k5, distortion.k6); + cv::Size image_size(image.cols, image.rows); + cv::Mat new_camera_matrix = + cv::getOptimalNewCameraMatrix(camera_matrix, dist_coeffs, image_size, 0.0, image_size); + // Undistort the image using the new camera matrix + cv::undistort(image, result.image, camera_matrix, dist_coeffs, new_camera_matrix); + // Update the intrinsic parameters with the new camera matrix + result.new_intrinsic = intrinsic; // Copy original values first + result.new_intrinsic.fx = new_camera_matrix.at(0, 0); + result.new_intrinsic.fy = new_camera_matrix.at(1, 1); + result.new_intrinsic.cx = new_camera_matrix.at(0, 2); + result.new_intrinsic.cy = new_camera_matrix.at(1, 2); + result.new_intrinsic.width = image.cols; + result.new_intrinsic.height = image.rows; + return result; +} +std::string getDistortionModels(OBCameraDistortion distortion) { + switch (distortion.model) { + case OB_DISTORTION_NONE: + return sensor_msgs::distortion_models::PLUMB_BOB; + case OB_DISTORTION_MODIFIED_BROWN_CONRADY: + return sensor_msgs::distortion_models::PLUMB_BOB; + case OB_DISTORTION_INVERSE_BROWN_CONRADY: + return sensor_msgs::distortion_models::PLUMB_BOB; + case OB_DISTORTION_BROWN_CONRADY: + return sensor_msgs::distortion_models::PLUMB_BOB; + case OB_DISTORTION_BROWN_CONRADY_K6: + return sensor_msgs::distortion_models::PLUMB_BOB; + case OB_DISTORTION_KANNALA_BRANDT4: + return sensor_msgs::distortion_models::EQUIDISTANT; + default: + return sensor_msgs::distortion_models::PLUMB_BOB; + } +} + +std::string calcMD5(const std::string &data) { + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int digest_len = 0; + + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); + EVP_DigestUpdate(ctx, data.data(), data.size()); + EVP_DigestFinal_ex(ctx, digest, &digest_len); + EVP_MD_CTX_free(ctx); + + std::stringstream ss; + ss << std::hex << std::setfill('0'); + for (unsigned int i = 0; i < digest_len; ++i) ss << std::setw(2) << (int)digest[i]; + return ss.str(); +} +double getScanAngleIncrement(OBLiDARScanRate fps) { + switch (fps) { + case OB_LIDAR_SCAN_15HZ: + return deg2rad(0.075); + case OB_LIDAR_SCAN_20HZ: + return deg2rad(0.1); + case OB_LIDAR_SCAN_25HZ: + return deg2rad(0.125); + case OB_LIDAR_SCAN_30HZ: + return deg2rad(0.15); + case OB_LIDAR_SCAN_40HZ: + return deg2rad(0.2); + default: + return deg2rad(0.1); + } +} + +double deg2rad(double deg) { return deg * M_PI / 180.0; } + +double rad2deg(double rad) { + double angle_degrees = rad * (180.0 / M_PI); + if (angle_degrees < 0) { + angle_degrees += 360.0; + } + return angle_degrees; +} + +} // namespace orbbec_camera diff --git a/dev_ws/src/orbbec_camera/tools/list_depth_work_mode.cpp b/dev_ws/src/orbbec_camera/tools/list_depth_work_mode.cpp new file mode 100644 index 0000000..1c1eef0 --- /dev/null +++ b/dev_ws/src/orbbec_camera/tools/list_depth_work_mode.cpp @@ -0,0 +1,39 @@ +/******************************************************************************* +* Copyright (c) 2023 Orbbec 3D Technology, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#include + +int main() { + std::shared_ptr pipeline = std::make_shared(); + auto device = pipeline->getDevice(); + if (!device) { + std::cout << "No device found" << std::endl; + return -1; + } + if (!device->isPropertySupported(OB_STRUCT_CURRENT_DEPTH_ALG_MODE, OB_PERMISSION_READ_WRITE)) { + std::cout << "Current device not support depth work mode!" << std::endl; + return -1; + } + auto current_depth_mode = device->getCurrentDepthWorkMode(); + std::cout << "current depth mode: " << current_depth_mode.name << std::endl; + auto depth_mode_list = device->getDepthWorkModeList(); + std::cout << "depth mode list: " << std::endl; + for (uint32_t i = 0; i < depth_mode_list->count(); i++) { + std::cout << "depth_mode_list[" << i << "]: " << (*depth_mode_list)[i].name; + + std::cout << std::endl; + } + return 0; +} diff --git a/dev_ws/src/orbbec_camera/tools/list_devices_node.cpp b/dev_ws/src/orbbec_camera/tools/list_devices_node.cpp new file mode 100644 index 0000000..a9583e6 --- /dev/null +++ b/dev_ws/src/orbbec_camera/tools/list_devices_node.cpp @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2023 Orbbec 3D Technology, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +#include + +#include +#include + +int main() { + try { + ob::Context::setLoggerSeverity(OBLogSeverity::OB_LOG_SEVERITY_OFF); + auto context = std::make_unique(); + auto list = context->queryDeviceList(); + for (size_t i = 0; i < list->deviceCount(); i++) { + if (std::string(list->getConnectionType(i)) != "Ethernet") { + std::string serial = list->serialNumber(i); + std::string uid = list->uid(i); + auto usb_port = orbbec_camera::parseUsbPort(uid); + auto connection_type = list->getConnectionType(i); + std::stringstream pid_hex; + pid_hex << std::hex << std::setw(4) << std::setfill('0') << list->getPid(i); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), + "- Name: " << list->getName(i) << ", PID: 0x" << pid_hex.str() + << ", SN/ID: " << serial + << ", Connection: " << connection_type); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), "serial: " << serial); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), "usb port: " << usb_port); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), + "usb connect type: " << connection_type); + std::cout << std::endl; + } else { + std::string serial = list->serialNumber(i); + auto connection_type = list->getConnectionType(i); + auto ip_address = list->getIpAddress(i); + std::stringstream pid_hex; + pid_hex << std::hex << std::setw(4) << std::setfill('0') << list->getPid(i); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), + "- Name: " << list->getName(i) << ", PID: 0x" << pid_hex.str() + << ", SN/ID: " << serial + << ", Connection: " << connection_type); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), "serial: " << serial); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), "ip address: " << ip_address); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), + "usb connect type: " << connection_type); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), + "MAC address: " << list->getUid(i)); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), + "subnet mask: " << list->getSubnetMask(i)); + RCLCPP_INFO_STREAM(rclcpp::get_logger("list_device_node"), + "gateway: " << list->getGateway(i)); + std::cout << std::endl; + } + } + } catch (ob::Error &e) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), e.getMessage()); + } catch (const std::exception &e) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), e.what()); + } catch (...) { + RCLCPP_ERROR_STREAM(rclcpp::get_logger("list_device_node"), "unknown error"); + } + return 0; +} diff --git a/dev_ws/src/orbbec_camera_msgs/CMakeLists.txt b/dev_ws/src/orbbec_camera_msgs/CMakeLists.txt new file mode 100644 index 0000000..a862e98 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.8) +project(orbbec_camera_msgs) + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +find_package(ament_cmake REQUIRED) +find_package(rosidl_default_generators REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(std_msgs REQUIRED) +# uncomment the following section in order to fill in +# further dependencies manually. +# find_package( REQUIRED) + +rosidl_generate_interfaces( + ${PROJECT_NAME} + "msg/DeviceInfo.msg" + "msg/DeviceStatus.msg" + "msg/Extrinsics.msg" + "msg/Metadata.msg" + "msg/IMUInfo.msg" + "msg/RGBD.msg" + "srv/GetBool.srv" + "srv/GetDeviceInfo.srv" + "srv/GetCameraInfo.srv" + "srv/GetInt32.srv" + "srv/GetString.srv" + "srv/SetFilter.srv" + "srv/SetInt32.srv" + "srv/SetString.srv" + "srv/SetArrays.srv" + "srv/GetUserCalibParams.srv" + "srv/SetUserCalibParams.srv" + DEPENDENCIES + sensor_msgs + std_msgs +) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + # the following line skips the linter which checks for copyrights + # uncomment the line when a copyright and license is not present in all source files + #set(ament_cmake_copyright_FOUND TRUE) + # the following line skips cpplint (only works in a git repo) + # uncomment the line when this package is not in a git repo + #set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() diff --git a/dev_ws/src/orbbec_camera_msgs/msg/DeviceInfo.msg b/dev_ws/src/orbbec_camera_msgs/msg/DeviceInfo.msg new file mode 100644 index 0000000..4a03571 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/msg/DeviceInfo.msg @@ -0,0 +1,7 @@ +std_msgs/Header header +string name +string serial_number +string firmware_version +string supported_min_sdk_version +string current_sdk_version +string hardware_version diff --git a/dev_ws/src/orbbec_camera_msgs/msg/DeviceStatus.msg b/dev_ws/src/orbbec_camera_msgs/msg/DeviceStatus.msg new file mode 100644 index 0000000..9066254 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/msg/DeviceStatus.msg @@ -0,0 +1,32 @@ +std_msgs/Header header + +# --- Color stream --- +float64 color_frame_rate_cur +float64 color_frame_rate_avg +float64 color_frame_rate_min +float64 color_frame_rate_max + +float64 color_delay_ms_cur +float64 color_delay_ms_avg +float64 color_delay_ms_min +float64 color_delay_ms_max + +# --- Depth stream --- +float64 depth_frame_rate_cur +float64 depth_frame_rate_avg +float64 depth_frame_rate_min +float64 depth_frame_rate_max + +float64 depth_delay_ms_cur +float64 depth_delay_ms_avg +float64 depth_delay_ms_min +float64 depth_delay_ms_max + +# --- Device info --- +bool device_online +string connection_type # e.g. "USB2.0", "USB3.0", "GigE" + +# --- Calibration status --- +bool customer_calibration_ready +bool calibration_from_factory +bool calibration_from_launch_param diff --git a/dev_ws/src/orbbec_camera_msgs/msg/Extrinsics.msg b/dev_ws/src/orbbec_camera_msgs/msg/Extrinsics.msg new file mode 100644 index 0000000..6482a0e --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/msg/Extrinsics.msg @@ -0,0 +1,3 @@ +std_msgs/Header header +float64[9] rotation +float64[3] translation diff --git a/dev_ws/src/orbbec_camera_msgs/msg/IMUInfo.msg b/dev_ws/src/orbbec_camera_msgs/msg/IMUInfo.msg new file mode 100644 index 0000000..5f748ff --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/msg/IMUInfo.msg @@ -0,0 +1,9 @@ +std_msgs/Header header +float64 noise_density +float64 random_walk +float64 reference_temperature +float64[3] bias +float64[3] gravity +float64[9] scale_misalignment +float64[9] temperature_slope + diff --git a/dev_ws/src/orbbec_camera_msgs/msg/Metadata.msg b/dev_ws/src/orbbec_camera_msgs/msg/Metadata.msg new file mode 100644 index 0000000..0c49959 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/msg/Metadata.msg @@ -0,0 +1,2 @@ +std_msgs/Header header +string json_data diff --git a/dev_ws/src/orbbec_camera_msgs/msg/RGBD.msg b/dev_ws/src/orbbec_camera_msgs/msg/RGBD.msg new file mode 100644 index 0000000..faa44ce --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/msg/RGBD.msg @@ -0,0 +1,6 @@ +# RGBD Message +std_msgs/Header header +sensor_msgs/CameraInfo rgb_camera_info +sensor_msgs/CameraInfo depth_camera_info +sensor_msgs/Image rgb +sensor_msgs/Image depth diff --git a/dev_ws/src/orbbec_camera_msgs/package.xml b/dev_ws/src/orbbec_camera_msgs/package.xml new file mode 100644 index 0000000..b714e3c --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/package.xml @@ -0,0 +1,23 @@ + + + + orbbec_camera_msgs + 2.7.6 + A package containing orbbec camera messages definitions. + Joe Dong + Apache-2.0 + + ament_cmake + + ament_lint_auto + ament_lint_common + rosidl_default_generators + sensor_msgs + std_msgs + rosidl_default_runtime + sensor_msgs + rosidl_interface_packages + + ament_cmake + + diff --git a/dev_ws/src/orbbec_camera_msgs/srv/GetBool.srv b/dev_ws/src/orbbec_camera_msgs/srv/GetBool.srv new file mode 100644 index 0000000..ccfce7d --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/GetBool.srv @@ -0,0 +1,4 @@ +--- +bool data +bool success +string message diff --git a/dev_ws/src/orbbec_camera_msgs/srv/GetCameraInfo.srv b/dev_ws/src/orbbec_camera_msgs/srv/GetCameraInfo.srv new file mode 100644 index 0000000..64b5d0f --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/GetCameraInfo.srv @@ -0,0 +1,2 @@ +--- +sensor_msgs/CameraInfo info diff --git a/dev_ws/src/orbbec_camera_msgs/srv/GetDeviceInfo.srv b/dev_ws/src/orbbec_camera_msgs/srv/GetDeviceInfo.srv new file mode 100644 index 0000000..32f711d --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/GetDeviceInfo.srv @@ -0,0 +1,4 @@ +--- +DeviceInfo info +bool success +string message \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera_msgs/srv/GetInt32.srv b/dev_ws/src/orbbec_camera_msgs/srv/GetInt32.srv new file mode 100644 index 0000000..6621dd8 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/GetInt32.srv @@ -0,0 +1,4 @@ +--- +int32 data +bool success +string message diff --git a/dev_ws/src/orbbec_camera_msgs/srv/GetString.srv b/dev_ws/src/orbbec_camera_msgs/srv/GetString.srv new file mode 100644 index 0000000..ac7ad61 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/GetString.srv @@ -0,0 +1,4 @@ +--- +string data +bool success +string message diff --git a/dev_ws/src/orbbec_camera_msgs/srv/GetUserCalibParams.srv b/dev_ws/src/orbbec_camera_msgs/srv/GetUserCalibParams.srv new file mode 100644 index 0000000..159dc4e --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/GetUserCalibParams.srv @@ -0,0 +1,7 @@ +--- +float64[9] k #Intrinsic camera matrix for the raw (distorted) images +float64[8] d #The distortion parameters +float64[9] rotation #Extrinsic rotation matrix +float64[3] translation #Extrinsic translation vector +bool success +string message diff --git a/dev_ws/src/orbbec_camera_msgs/srv/SetArrays.srv b/dev_ws/src/orbbec_camera_msgs/srv/SetArrays.srv new file mode 100644 index 0000000..79d458a --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/SetArrays.srv @@ -0,0 +1,5 @@ +bool enable +float32[] data_param +--- +bool success +string message \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera_msgs/srv/SetFilter.srv b/dev_ws/src/orbbec_camera_msgs/srv/SetFilter.srv new file mode 100644 index 0000000..4fc24ab --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/SetFilter.srv @@ -0,0 +1,6 @@ +string filter_name +bool filter_enable +float32[] filter_param +--- +bool success +string message \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera_msgs/srv/SetInt32.srv b/dev_ws/src/orbbec_camera_msgs/srv/SetInt32.srv new file mode 100644 index 0000000..f6ad672 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/SetInt32.srv @@ -0,0 +1,4 @@ +int32 data +--- +bool success +string message \ No newline at end of file diff --git a/dev_ws/src/orbbec_camera_msgs/srv/SetString.srv b/dev_ws/src/orbbec_camera_msgs/srv/SetString.srv new file mode 100644 index 0000000..b0de4d8 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/SetString.srv @@ -0,0 +1,4 @@ +string data +--- +bool success +string message diff --git a/dev_ws/src/orbbec_camera_msgs/srv/SetUserCalibParams.srv b/dev_ws/src/orbbec_camera_msgs/srv/SetUserCalibParams.srv new file mode 100644 index 0000000..0903ce1 --- /dev/null +++ b/dev_ws/src/orbbec_camera_msgs/srv/SetUserCalibParams.srv @@ -0,0 +1,7 @@ +float64[9] k #Intrinsic camera matrix for the raw (distorted) images +float64[8] d #The distortion parameters +float64[9] rotation #Extrinsic rotation matrix +float64[3] translation #Extrinsic translation vector +--- +bool success +string message diff --git a/dev_ws/src/origintank_base/CMakeLists.txt b/dev_ws/src/origintank_base/CMakeLists.txt new file mode 100644 index 0000000..ffdb440 --- /dev/null +++ b/dev_ws/src/origintank_base/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.5) +project(origintank_base) + +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(tf2 REQUIRED) +find_package(nav_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(tf2_ros REQUIRED) + +include_directories(include) + +install( + DIRECTORY launch + DESTINATION share/${PROJECT_NAME} +) + +add_executable(${PROJECT_NAME} + src/main.cpp + src/origintank_base.cpp +) + +ament_target_dependencies(${PROJECT_NAME} + rclcpp + geometry_msgs + sensor_msgs + nav_msgs + tf2 + tf2_ros +) + +install(TARGETS + ${PROJECT_NAME} + DESTINATION lib/${PROJECT_NAME} +) + +ament_package() diff --git a/dev_ws/src/origintank_base/include/origintank_base/origintank_base.h b/dev_ws/src/origintank_base/include/origintank_base/origintank_base.h new file mode 100644 index 0000000..a442083 --- /dev/null +++ b/dev_ws/src/origintank_base/include/origintank_base/origintank_base.h @@ -0,0 +1,137 @@ +#ifndef ORIGINTANK_BASE__ORIGINTANK_BASE_H_ +#define ORIGINTANK_BASE__ORIGINTANK_BASE_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "geometry_msgs/msg/twist.hpp" +#include "nav_msgs/msg/odometry.hpp" +#include "rclcpp/rclcpp.hpp" +#include "sensor_msgs/msg/imu.hpp" +#include "sensor_msgs/msg/range.hpp" +#include "tf2/LinearMath/Quaternion.h" +#include "tf2_ros/transform_broadcaster.h" + +using std::placeholders::_1; + +class CCodbotBase : public rclcpp::Node +{ +public: + CCodbotBase(); + bool init(); + void GetParams(); + void SetGorgePro(const char * serial_num); + int set_serial(int fd, int nSpeed, int nBits, char nEvent, int nStop); + void DiffCallBack(const geometry_msgs::msg::Twist::SharedPtr cmd_input); + void AckerCallBack(const geometry_msgs::msg::Twist::SharedPtr cmd_input); + void MecanumCallBack(const geometry_msgs::msg::Twist::SharedPtr cmd_input); + static void * MyReadThread(void * pt); + static void * MyWriteThread(void * th); + void ReceiveUpdate(int data_len, unsigned char * data_type, unsigned char new_buff); + bool CheckRawData(unsigned char * raw_data, int data_num, int current_code); + void tf_pub_callback(); + void PublishUltrasonicRange(uint16_t raw_distance); + +public: + rclcpp::Publisher::SharedPtr odom_pub; + +private: + rclcpp::Publisher::SharedPtr imu_pub; + rclcpp::Publisher::SharedPtr ultrasonic_pub; + rclcpp::Subscription::SharedPtr cmd_sub; + + std::string cmd_port; + std::string cmd_topic; + std::string imu_topic; + std::string imu_frame; + std::string baud_rate; + std::string ultrasonic_topic; + std::string ultrasonic_frame; + int debug_num {0}; + double coeff_odom_x {1.131}; + double coeff_odom_y {1.077}; + double ultrasonic_min_range_m_ {0.03}; + double ultrasonic_max_range_m_ {4.0}; + double ultrasonic_unit_scale_m_ {0.01}; + double ultrasonic_field_of_view_rad_ {0.26}; + + const std::string alltype[4] = {"A100", "D100", "T100", "M100"}; + std::string current_type; + std::string feedback_type; + std::shared_ptr tf_publisher_; + rclcpp::TimerBase::SharedPtr timer_; + +private: + pthread_t th_base_write {}; + + struct BaseReader + { + int serialNum {-1}; + unsigned char carVelRaw[13] = {0}; + unsigned char motorVelRaw[12] = {0}; + unsigned char batteryRaw[5] = {0}; + unsigned char imuRpyRaw[13] = {0}; + unsigned char imuRaw[34] = {0}; + unsigned char carTypeRaw[5] = {0}; + unsigned char ultrasonicRaw[6] = {0}; + + unsigned char writebuff[13] = {0xcd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + int nread {0}; + int nwrite {0}; + std::atomic_bool recv_update_flag {false}; + std::atomic_bool send_update_flag {false}; + } baseCommunication; + + struct BaseData + { + float vx {0.0F}; + float vy {0.0F}; + float yaw {0.0F}; + float v1 {0.0F}; + float v2 {0.0F}; + float v3 {0.0F}; + float v4 {0.0F}; + float init_yaw {0.0F}; + float curr_orien {0.0F}; + float angler_speed {0.0F}; + } currentBaseData; + +public: + std::string odom_frame; + std::string odom_topic; + std::string odom_child_frame; + + struct OdomData + { + float speed_ratio = 1.2941F; + float wheel_distance = 0.19F; + float encode_sampling_time = 0.04F; + float cmd_vel_linear_max {0.3F}; + float cmd_vel_linear_min {0.0F}; + float cmd_vel_anglar_max {2.0F}; + float cmd_vel_anglar_min {0.0F}; + float cmd_vel_angle_max {25.0F}; + float cmd_vel_angle_min {0.0F}; + + float position_x = 0.0F; + float position_y = 0.0F; + float twist_x = 0.0F; + float twist_y = 0.0F; + float twist_th = 0.0F; + float oriention = 0.0F; + bool update_flag = false; + } myOdomData; +}; + +#endif // ORIGINTANK_BASE__ORIGINTANK_BASE_H_ diff --git a/dev_ws/src/origintank_base/launch/origintank_base.launch.py b/dev_ws/src/origintank_base/launch/origintank_base.launch.py new file mode 100644 index 0000000..d6e17d6 --- /dev/null +++ b/dev_ws/src/origintank_base/launch/origintank_base.launch.py @@ -0,0 +1,75 @@ +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node + + +def generate_launch_description(): + cmd_port = LaunchConfiguration('cmd_port') + baud_rate = LaunchConfiguration('baud_rate') + + origintank_base_node = Node( + package='origintank_base', + executable='origintank_base', + name='origintank_base', + output='screen', + parameters=[{ + 'debug_num': 0, + 'baud_rate': baud_rate, + 'cmd_port': cmd_port, + 'coeff_odom_x': 1.131, + 'coeff_odom_y': 1.077, + 'cmd_vel_linear_max': 0.4, + 'cmd_vel_linear_min': 0.0, + 'cmd_vel_anglar_max': 2.0, + 'cmd_vel_anglar_min': 0.0, + 'cmd_vel_angle_max': 25.0, + 'cmd_vel_angle_min': 0.0, + 'current_type': 'M100', + 'cmd_vel_topic': '/cmd_vel', + 'odom_topic': '/odom', + 'imu_topic': '/imu', + 'imu_frame': 'imu_link', + 'odom_frame': 'odom', + 'odom_child_frame': 'base_footprint', + 'ultrasonic_topic': '/ultrasonic/front/range', + 'ultrasonic_frame': 'ultrasonic_front_link', + 'ultrasonic_min_range_m': 0.03, + 'ultrasonic_max_range_m': 4.0, + 'ultrasonic_unit_scale_m': 0.01, + 'ultrasonic_field_of_view_rad': 0.26, + }] + ) + + base_tf = Node( + package='tf2_ros', + executable='static_transform_publisher', + arguments=['--x', '0.0', '--y', '0.0', '--z', '0.05', + '--roll', '0.0', '--pitch', '0.0', '--yaw', '0.0', + '--frame-id', 'base_footprint', '--child-frame-id', 'base_link'] + ) + + imu_tf = Node( + package='tf2_ros', + executable='static_transform_publisher', + arguments=['--x', '0.0', '--y', '0.0', '--z', '0.0', + '--roll', '0.0', '--pitch', '0.0', '--yaw', '0.0', + '--frame-id', 'base_link', '--child-frame-id', 'imu_link'] + ) + + ultrasonic_tf = Node( + package='tf2_ros', + executable='static_transform_publisher', + arguments=['--x', '0.18', '--y', '0.0', '--z', '0.10', + '--roll', '0.0', '--pitch', '0.0', '--yaw', '0.0', + '--frame-id', 'base_link', '--child-frame-id', 'ultrasonic_front_link'] + ) + + return LaunchDescription([ + DeclareLaunchArgument('cmd_port', default_value='/dev/ttyUSB0'), + DeclareLaunchArgument('baud_rate', default_value='B115200'), + origintank_base_node, + base_tf, + imu_tf, + ultrasonic_tf, + ]) diff --git a/dev_ws/src/origintank_base/package.xml b/dev_ws/src/origintank_base/package.xml new file mode 100644 index 0000000..1506b6a --- /dev/null +++ b/dev_ws/src/origintank_base/package.xml @@ -0,0 +1,27 @@ + + + + origintank_base + 0.1.0 + OriginTank base driver for RDK X5 mission project. + codbot + Apache-2.0 + + ament_cmake + + rclcpp + geometry_msgs + tf2 + nav_msgs + sensor_msgs + tf2_ros + + ament_lint_auto + ament_lint_common + + ros2launch + + + ament_cmake + + diff --git a/dev_ws/src/origintank_base/src/main.cpp b/dev_ws/src/origintank_base/src/main.cpp new file mode 100644 index 0000000..3345246 --- /dev/null +++ b/dev_ws/src/origintank_base/src/main.cpp @@ -0,0 +1,10 @@ +#include "rclcpp/rclcpp.hpp" +#include "../include/origintank_base/origintank_base.h" + +int main(int argc, char ** argv) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} diff --git a/dev_ws/src/origintank_base/src/origintank_base.cpp b/dev_ws/src/origintank_base/src/origintank_base.cpp new file mode 100644 index 0000000..c04ceef --- /dev/null +++ b/dev_ws/src/origintank_base/src/origintank_base.cpp @@ -0,0 +1,787 @@ +#include "../include/origintank_base/origintank_base.h" + +#include +#include +#include +#include +#include + +using namespace std::chrono_literals; + +CCodbotBase::CCodbotBase() +: Node("origintank_base") +{ + init(); +} + +bool CCodbotBase::init() +{ + GetParams(); + + if (current_type == alltype[0]) { + RCLCPP_INFO(get_logger(), "Current chassis type is ackerman"); + cmd_sub = this->create_subscription( + cmd_topic, 10, std::bind(&CCodbotBase::AckerCallBack, this, _1)); + } else if (current_type == alltype[1] || current_type == alltype[2]) { + RCLCPP_INFO(get_logger(), "Current chassis type is differential/tank"); + cmd_sub = this->create_subscription( + cmd_topic, 10, std::bind(&CCodbotBase::DiffCallBack, this, _1)); + } else if (current_type == alltype[3]) { + RCLCPP_INFO(get_logger(), "Current chassis type is mecanum"); + cmd_sub = this->create_subscription( + cmd_topic, 10, std::bind(&CCodbotBase::MecanumCallBack, this, _1)); + } else { + RCLCPP_ERROR(get_logger(), "can not find %s chassis", current_type.c_str()); + return false; + } + + imu_pub = this->create_publisher(imu_topic, 10); + odom_pub = this->create_publisher(odom_topic, 10); + ultrasonic_pub = this->create_publisher(ultrasonic_topic, 10); + tf_publisher_ = std::make_shared(*this); + timer_ = this->create_wall_timer(50ms, std::bind(&CCodbotBase::tf_pub_callback, this)); + + SetGorgePro(cmd_port.c_str()); + if (baseCommunication.serialNum < 0) { + return false; + } + + pthread_t th_base_read {}; + int th_read_status = pthread_create(&th_base_read, nullptr, MyReadThread, this); + if (0 != th_read_status) { + RCLCPP_ERROR(get_logger(), "can't create base read thread: %d", th_read_status); + return false; + } + + int th_write_status = pthread_create(&th_base_write, nullptr, MyWriteThread, this); + if (0 != th_write_status) { + RCLCPP_ERROR(get_logger(), "can't create base write thread: %d", th_write_status); + return false; + } + + return true; +} + +void CCodbotBase::GetParams() +{ + this->declare_parameter("cmd_port", "/dev/ttyUSB0"); + cmd_port = this->get_parameter("cmd_port").as_string(); + + this->declare_parameter("baud_rate", "B115200"); + baud_rate = this->get_parameter("baud_rate").as_string(); + + this->declare_parameter("cmd_vel_topic", "/cmd_vel"); + cmd_topic = this->get_parameter("cmd_vel_topic").as_string(); + + this->declare_parameter("odom_topic", "/odom"); + odom_topic = this->get_parameter("odom_topic").as_string(); + + this->declare_parameter("odom_frame", "odom"); + odom_frame = this->get_parameter("odom_frame").as_string(); + + this->declare_parameter("odom_child_frame", "base_footprint"); + odom_child_frame = this->get_parameter("odom_child_frame").as_string(); + + this->declare_parameter("imu_topic", "/imu"); + imu_topic = this->get_parameter("imu_topic").as_string(); + + this->declare_parameter("imu_frame", "imu_link"); + imu_frame = this->get_parameter("imu_frame").as_string(); + + this->declare_parameter("ultrasonic_topic", "/ultrasonic/front/range"); + ultrasonic_topic = this->get_parameter("ultrasonic_topic").as_string(); + + this->declare_parameter("ultrasonic_frame", "ultrasonic_front_link"); + ultrasonic_frame = this->get_parameter("ultrasonic_frame").as_string(); + + this->declare_parameter("ultrasonic_min_range_m", 0.03); + ultrasonic_min_range_m_ = this->get_parameter("ultrasonic_min_range_m").as_double(); + + this->declare_parameter("ultrasonic_max_range_m", 4.0); + ultrasonic_max_range_m_ = this->get_parameter("ultrasonic_max_range_m").as_double(); + + this->declare_parameter("ultrasonic_unit_scale_m", 0.01); + ultrasonic_unit_scale_m_ = this->get_parameter("ultrasonic_unit_scale_m").as_double(); + + this->declare_parameter("ultrasonic_field_of_view_rad", 0.26); + ultrasonic_field_of_view_rad_ = + this->get_parameter("ultrasonic_field_of_view_rad").as_double(); + + this->declare_parameter("debug_num", 0); + this->get_parameter("debug_num", debug_num); + + this->declare_parameter("coeff_odom_x", 1.131); + coeff_odom_x = this->get_parameter("coeff_odom_x").as_double(); + + this->declare_parameter("coeff_odom_y", 1.077); + coeff_odom_y = this->get_parameter("coeff_odom_y").as_double(); + + this->declare_parameter("current_type", "M100"); + current_type = this->get_parameter("current_type").as_string(); + + this->declare_parameter("cmd_vel_linear_max", 0.3); + myOdomData.cmd_vel_linear_max = this->get_parameter("cmd_vel_linear_max").as_double(); + + this->declare_parameter("cmd_vel_linear_min", 0.0); + myOdomData.cmd_vel_linear_min = this->get_parameter("cmd_vel_linear_min").as_double(); + + this->declare_parameter("cmd_vel_anglar_max", 2.0); + myOdomData.cmd_vel_anglar_max = this->get_parameter("cmd_vel_anglar_max").as_double(); + + this->declare_parameter("cmd_vel_anglar_min", 0.0); + myOdomData.cmd_vel_anglar_min = this->get_parameter("cmd_vel_anglar_min").as_double(); + + this->declare_parameter("cmd_vel_angle_max", 25.0); + myOdomData.cmd_vel_angle_max = this->get_parameter("cmd_vel_angle_max").as_double(); + + this->declare_parameter("cmd_vel_angle_min", 0.0); + myOdomData.cmd_vel_angle_min = this->get_parameter("cmd_vel_angle_min").as_double(); +} + +void CCodbotBase::SetGorgePro(const char * serial_num) +{ + baseCommunication.serialNum = open(serial_num, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (-1 == baseCommunication.serialNum) { + RCLCPP_ERROR(get_logger(), "Open %s serial port failed: %s", serial_num, strerror(errno)); + return; + } + + struct termios my_options; + if (0 != tcgetattr(baseCommunication.serialNum, &my_options)) { + RCLCPP_ERROR(get_logger(), "Get serial port attribute failed: %s", strerror(errno)); + close(baseCommunication.serialNum); + baseCommunication.serialNum = -1; + return; + } + + tcflush(baseCommunication.serialNum, TCIFLUSH); + cfsetispeed(&my_options, B115200); + cfsetospeed(&my_options, B115200); + + my_options.c_cflag |= (CLOCAL | CREAD); + my_options.c_cflag &= ~CSIZE; + my_options.c_cflag |= CS8; + my_options.c_cflag &= ~PARENB; + my_options.c_cflag &= ~CSTOPB; + my_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + my_options.c_oflag &= ~OPOST; + my_options.c_iflag &= ~(IXON | IXOFF | IXANY); + my_options.c_iflag &= ~(INLCR | ICRNL | IGNCR); + my_options.c_cc[VTIME] = 0; + my_options.c_cc[VMIN] = 0; + + if (0 != tcsetattr(baseCommunication.serialNum, TCSANOW, &my_options)) { + RCLCPP_ERROR(get_logger(), "Set %s serial port failed: %s", serial_num, strerror(errno)); + close(baseCommunication.serialNum); + baseCommunication.serialNum = -1; + return; + } + + RCLCPP_INFO(get_logger(), "Serial port %s opened at 115200", serial_num); +} + +int CCodbotBase::set_serial(int fd, int nSpeed, int nBits, char nEvent, int nStop) +{ + struct termios newttys1, oldttys1; + if (tcgetattr(fd, &oldttys1) != 0) { + perror("Setup IMU Serial"); + return -1; + } + + memset(&newttys1, 0, sizeof(newttys1)); + newttys1.c_cflag |= (CLOCAL | CREAD); + + switch (nBits) { + case 7: + newttys1.c_cflag |= CS7; + break; + case 8: + default: + newttys1.c_cflag |= CS8; + break; + } + + switch (nEvent) { + case 'O': + newttys1.c_cflag |= PARENB; + newttys1.c_iflag |= (INPCK | ISTRIP); + newttys1.c_cflag |= PARODD; + break; + case 'E': + newttys1.c_cflag |= PARENB; + newttys1.c_iflag |= (INPCK | ISTRIP); + newttys1.c_cflag &= ~PARODD; + break; + case 'N': + default: + newttys1.c_cflag &= ~PARENB; + break; + } + + switch (nSpeed) { + case 2400: + cfsetispeed(&newttys1, B2400); + cfsetospeed(&newttys1, B2400); + break; + case 4800: + cfsetispeed(&newttys1, B4800); + cfsetospeed(&newttys1, B4800); + break; + case 9600: + cfsetispeed(&newttys1, B9600); + cfsetospeed(&newttys1, B9600); + break; + case 230400: + cfsetispeed(&newttys1, B230400); + cfsetospeed(&newttys1, B230400); + break; + case 460800: + cfsetispeed(&newttys1, B460800); + cfsetospeed(&newttys1, B460800); + break; + case 115200: + default: + cfsetispeed(&newttys1, B115200); + cfsetospeed(&newttys1, B115200); + break; + } + + if (nStop == 1) { + newttys1.c_cflag &= ~CSTOPB; + } else if (nStop == 2) { + newttys1.c_cflag |= CSTOPB; + } + + newttys1.c_cc[VTIME] = 0; + newttys1.c_cc[VMIN] = 0; + tcflush(fd, TCIFLUSH); + + newttys1.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + newttys1.c_oflag &= ~OPOST; + newttys1.c_iflag &= ~(INLCR | ICRNL | IGNCR); + + if ((tcsetattr(fd, TCSANOW, &newttys1)) != 0) { + perror("IMU com set error"); + exit(1); + } + + return 0; +} + +void CCodbotBase::DiffCallBack(const geometry_msgs::msg::Twist::SharedPtr cmd_input) +{ + float linear_speed = cmd_input->linear.x; + float angular_speed = cmd_input->angular.z; + + double linear_sign = 0.0; + if (linear_speed > 0) { + linear_sign = 1.0; + } else if (linear_speed < 0) { + linear_sign = -1.0; + } + linear_speed = std::min(std::abs(linear_speed), myOdomData.cmd_vel_linear_max); + if (linear_sign != 0.0) { + linear_speed = std::max(std::abs(linear_speed), myOdomData.cmd_vel_linear_min); + } + linear_speed = linear_sign * linear_speed; + + double angular_sign = 0.0; + if (angular_speed > 0) { + angular_sign = 1.0; + } else if (angular_speed < 0) { + angular_sign = -1.0; + } + angular_speed = std::min(std::abs(angular_speed), myOdomData.cmd_vel_anglar_max); + if (angular_sign != 0.0) { + angular_speed = std::max(std::abs(angular_speed), myOdomData.cmd_vel_anglar_min); + } + angular_speed = angular_sign * angular_speed; + + while (baseCommunication.send_update_flag.load()) { + } + + baseCommunication.writebuff[0] = 0xCD; + baseCommunication.writebuff[1] = 0x0A; + baseCommunication.writebuff[2] = 0x01; + if (linear_speed >= 0) { + baseCommunication.writebuff[3] = 0x00; + } else { + baseCommunication.writebuff[3] = 0x01; + linear_speed = -linear_speed; + } + baseCommunication.writebuff[4] = (static_cast(linear_speed * 1000) >> 8) & 0xff; + baseCommunication.writebuff[5] = static_cast(linear_speed * 1000) & 0xff; + + baseCommunication.writebuff[6] = 0x00; + baseCommunication.writebuff[7] = 0x00; + baseCommunication.writebuff[8] = 0x00; + + if (angular_speed > 0) { + baseCommunication.writebuff[9] = 0x00; + } else { + baseCommunication.writebuff[9] = 0x01; + angular_speed *= -1; + } + + baseCommunication.writebuff[10] = (static_cast(angular_speed * 100) >> 8) & 0xff; + baseCommunication.writebuff[11] = static_cast(angular_speed * 100) & 0xff; + baseCommunication.writebuff[12] = 0x00; + for (int i = 2; i < 12; i++) { + baseCommunication.writebuff[12] ^= baseCommunication.writebuff[i]; + } + + baseCommunication.send_update_flag.store(true); +} + +void CCodbotBase::AckerCallBack(const geometry_msgs::msg::Twist::SharedPtr cmd_input) +{ + float linear_x = cmd_input->linear.x; + float angle = static_cast(cmd_input->angular.z * 180.0 / M_PI); + + double linear_sign = 0.0; + if (linear_x > 0) { + linear_sign = 1.0; + } else if (linear_x < 0) { + linear_sign = -1.0; + } + linear_x = std::min(std::abs(linear_x), myOdomData.cmd_vel_linear_max); + if (linear_sign != 0.0) { + linear_x = std::max(std::abs(linear_x), myOdomData.cmd_vel_linear_min); + } + linear_x = linear_sign * linear_x; + + double angle_sign = 0.0; + if (angle > 0) { + angle_sign = 1.0; + } else if (angle < 0) { + angle_sign = -1.0; + } + angle = std::min(std::abs(angle), myOdomData.cmd_vel_angle_max); + if (angle_sign != 0.0) { + angle = std::max(std::abs(angle), myOdomData.cmd_vel_angle_min); + } + angle = (linear_sign != 0.0) ? static_cast(angle_sign * linear_sign * angle) + : static_cast(angle_sign * angle); + + while (baseCommunication.send_update_flag.load()) { + } + + baseCommunication.writebuff[0] = 0xCD; + baseCommunication.writebuff[1] = 0x0A; + baseCommunication.writebuff[2] = 0x01; + if (linear_x >= 0) { + baseCommunication.writebuff[3] = 0x00; + } else { + baseCommunication.writebuff[3] = 0x01; + linear_x *= -1; + } + + baseCommunication.writebuff[4] = (static_cast(linear_x * 1000) >> 8) & 0xff; + baseCommunication.writebuff[5] = static_cast(linear_x * 1000) & 0xff; + baseCommunication.writebuff[6] = 0x00; + baseCommunication.writebuff[7] = 0x00; + baseCommunication.writebuff[8] = 0x00; + + if (angle >= 0) { + baseCommunication.writebuff[9] = 0x00; + } else { + baseCommunication.writebuff[9] = 0x01; + angle *= -1; + } + + baseCommunication.writebuff[10] = (static_cast(angle) >> 8) & 0xff; + baseCommunication.writebuff[11] = static_cast(angle) & 0xff; + baseCommunication.writebuff[12] = 0x00; + for (int i = 2; i < 12; i++) { + baseCommunication.writebuff[12] ^= baseCommunication.writebuff[i]; + } + + baseCommunication.send_update_flag.store(true); +} + +void CCodbotBase::MecanumCallBack(const geometry_msgs::msg::Twist::SharedPtr cmd_input) +{ + float linear_x_speed = cmd_input->linear.x; + float linear_y_speed = cmd_input->linear.y; + float angular_speed = cmd_input->angular.z; + + float linear_max_limit = myOdomData.cmd_vel_linear_max; + float angular_max_limit = myOdomData.cmd_vel_anglar_max; + linear_x_speed = std::max(-linear_max_limit, std::min(linear_x_speed, linear_max_limit)); + linear_y_speed = std::max(-linear_max_limit, std::min(linear_y_speed, linear_max_limit)); + angular_speed = std::max(-angular_max_limit, std::min(angular_speed, angular_max_limit)); + + while (baseCommunication.send_update_flag.load()) { + } + + baseCommunication.writebuff[0] = 0xCD; + baseCommunication.writebuff[1] = 0x0A; + baseCommunication.writebuff[2] = 0x01; + if (linear_x_speed >= 0) { + baseCommunication.writebuff[3] = 0x00; + } else { + baseCommunication.writebuff[3] = 0x01; + linear_x_speed = -linear_x_speed; + } + baseCommunication.writebuff[4] = (static_cast(linear_x_speed * 1000) >> 8) & 0xff; + baseCommunication.writebuff[5] = static_cast(linear_x_speed * 1000) & 0xff; + + if (linear_y_speed >= 0) { + baseCommunication.writebuff[6] = 0x00; + } else { + baseCommunication.writebuff[6] = 0x01; + linear_y_speed = -linear_y_speed; + } + baseCommunication.writebuff[7] = (static_cast(linear_y_speed * 1000) >> 8) & 0xff; + baseCommunication.writebuff[8] = static_cast(linear_y_speed * 1000) & 0xff; + + if (angular_speed > 0) { + baseCommunication.writebuff[9] = 0x00; + } else { + baseCommunication.writebuff[9] = 0x01; + angular_speed *= -1; + } + + baseCommunication.writebuff[10] = (static_cast(angular_speed * 100) >> 8) & 0xff; + baseCommunication.writebuff[11] = static_cast(angular_speed * 100) & 0xff; + baseCommunication.writebuff[12] = 0x00; + for (int i = 2; i < 12; i++) { + baseCommunication.writebuff[12] ^= baseCommunication.writebuff[i]; + } + + baseCommunication.send_update_flag.store(true); +} + +void * CCodbotBase::MyReadThread(void * pt) +{ + auto * pt_read = static_cast(pt); + unsigned char read_buff = 0; + double dt = 1.0 / 50.0; + double previous_time = rclcpp::Clock().now().seconds(); + bool init_yaw_flag = false; + + while (true) { + int nread = read(pt_read->baseCommunication.serialNum, &read_buff, 1); + if (nread <= 0) { + usleep(1000); + continue; + } + + pt_read->ReceiveUpdate(13, pt_read->baseCommunication.carVelRaw, read_buff); + pt_read->ReceiveUpdate(12, pt_read->baseCommunication.motorVelRaw, read_buff); + pt_read->ReceiveUpdate(5, pt_read->baseCommunication.batteryRaw, read_buff); + pt_read->ReceiveUpdate(13, pt_read->baseCommunication.imuRpyRaw, read_buff); + pt_read->ReceiveUpdate(34, pt_read->baseCommunication.imuRaw, read_buff); + pt_read->ReceiveUpdate(5, pt_read->baseCommunication.carTypeRaw, read_buff); + pt_read->ReceiveUpdate(6, pt_read->baseCommunication.ultrasonicRaw, read_buff); + + if ((0xfd == pt_read->baseCommunication.carVelRaw[0]) && + (0x0a == pt_read->baseCommunication.carVelRaw[1]) && + (0x02 == pt_read->baseCommunication.carVelRaw[2])) + { + if (pt_read->CheckRawData(pt_read->baseCommunication.carVelRaw, 13, 2)) { + double current_time = rclcpp::Clock().now().seconds(); + dt = current_time - previous_time; + previous_time = current_time; + if (dt <= 0.0) { + dt = 1.0 / 50.0; + } + + pt_read->currentBaseData.vx = + (pt_read->baseCommunication.carVelRaw[3] > 0 ? -1.0F : 1.0F) * + ((pt_read->baseCommunication.carVelRaw[4] * 256 + + pt_read->baseCommunication.carVelRaw[5]) / 1000.0F); + pt_read->currentBaseData.vy = + (pt_read->baseCommunication.carVelRaw[6] > 0 ? -1.0F : 1.0F) * + ((pt_read->baseCommunication.carVelRaw[7] * 256 + + pt_read->baseCommunication.carVelRaw[8]) / 1000.0F); + pt_read->currentBaseData.angler_speed = + (pt_read->baseCommunication.carVelRaw[9] > 0 ? -1.0F : 1.0F) * + ((pt_read->baseCommunication.carVelRaw[10] * 256 + + pt_read->baseCommunication.carVelRaw[11]) / 100.0F); + + if (std::abs(pt_read->currentBaseData.vx) <= 0.01F) { + pt_read->currentBaseData.vx = 0.0F; + } + if (std::abs(pt_read->currentBaseData.vy) <= 0.01F) { + pt_read->currentBaseData.vy = 0.0F; + } + if (std::abs(pt_read->currentBaseData.angler_speed) <= 0.01F) { + pt_read->currentBaseData.angler_speed = 0.0F; + } + pt_read->baseCommunication.recv_update_flag.store(true); + } + } + + if ((0xfd == pt_read->baseCommunication.motorVelRaw[0]) && + (0x09 == pt_read->baseCommunication.motorVelRaw[1]) && + (0x03 == pt_read->baseCommunication.motorVelRaw[2])) + { + if (pt_read->CheckRawData(pt_read->baseCommunication.motorVelRaw, 12, 3)) { + pt_read->currentBaseData.v1 = + ((pt_read->baseCommunication.motorVelRaw[3] << 8) + + pt_read->baseCommunication.motorVelRaw[4]) / 1000.0F; + pt_read->currentBaseData.v2 = + ((pt_read->baseCommunication.motorVelRaw[5] << 8) + + pt_read->baseCommunication.motorVelRaw[6]) / 1000.0F; + pt_read->currentBaseData.v3 = + ((pt_read->baseCommunication.motorVelRaw[7] << 8) + + pt_read->baseCommunication.motorVelRaw[8]) / 1000.0F; + pt_read->currentBaseData.v4 = + ((pt_read->baseCommunication.motorVelRaw[9] << 8) + + pt_read->baseCommunication.motorVelRaw[10]) / 1000.0F; + } + } + + if ((0xfd == pt_read->baseCommunication.batteryRaw[0]) && + (0x02 == pt_read->baseCommunication.batteryRaw[1]) && + (0x04 == pt_read->baseCommunication.batteryRaw[2])) + { + if (pt_read->CheckRawData(pt_read->baseCommunication.batteryRaw, 5, 4)) { + float battery = pt_read->baseCommunication.batteryRaw[3] * 0.1F; + if (battery < 10.0F) { + RCLCPP_WARN_THROTTLE( + pt_read->get_logger(), *pt_read->get_clock(), 5000, + "Battery is low, please charge: %.1fV", battery); + } + } + } + + if ((0xfd == pt_read->baseCommunication.imuRpyRaw[0]) && + (0x0a == pt_read->baseCommunication.imuRpyRaw[1]) && + (0x05 == pt_read->baseCommunication.imuRpyRaw[2])) + { + if (pt_read->CheckRawData(pt_read->baseCommunication.imuRpyRaw, 13, 5)) { + pt_read->currentBaseData.yaw = + ((pt_read->baseCommunication.imuRpyRaw[9] > 0 ? -1.0F : 1.0F) * + ((pt_read->baseCommunication.imuRpyRaw[10] * 256 + + pt_read->baseCommunication.imuRpyRaw[11]) / 100.0F)) * M_PI / 180.0F; + + if (pt_read->currentBaseData.yaw < 0) { + pt_read->currentBaseData.yaw += static_cast(2.0 * M_PI); + } + if (!init_yaw_flag) { + pt_read->currentBaseData.init_yaw = pt_read->currentBaseData.yaw; + pt_read->currentBaseData.curr_orien = 0.0F; + init_yaw_flag = true; + } else { + pt_read->currentBaseData.curr_orien = + -(pt_read->currentBaseData.yaw - pt_read->currentBaseData.init_yaw); + if (pt_read->currentBaseData.curr_orien > M_PI) { + pt_read->currentBaseData.curr_orien -= static_cast(2.0 * M_PI); + } + if (pt_read->currentBaseData.curr_orien < -M_PI) { + pt_read->currentBaseData.curr_orien += static_cast(2.0 * M_PI); + } + } + } + } + + if ((0xfd == pt_read->baseCommunication.imuRaw[0]) && + (0x1f == pt_read->baseCommunication.imuRaw[1]) && + (0x06 == pt_read->baseCommunication.imuRaw[2])) + { + if (pt_read->CheckRawData(pt_read->baseCommunication.imuRaw, 34, 6)) { + sensor_msgs::msg::Imu imu_data; + imu_data.header.stamp = pt_read->now(); + imu_data.header.frame_id = pt_read->imu_frame; + + imu_data.angular_velocity.x = -1.0 * + ((pt_read->baseCommunication.imuRaw[3] > 0 ? -1.0 : 1.0) * + (((pt_read->baseCommunication.imuRaw[4] << 8) + + pt_read->baseCommunication.imuRaw[5]) / 1000.0)); + imu_data.angular_velocity.y = + (pt_read->baseCommunication.imuRaw[6] > 0 ? -1.0 : 1.0) * + (((pt_read->baseCommunication.imuRaw[7] << 8) + + pt_read->baseCommunication.imuRaw[8]) / 1000.0); + imu_data.angular_velocity.z = + (pt_read->baseCommunication.imuRaw[9] > 0 ? -1.0 : 1.0) * + (((pt_read->baseCommunication.imuRaw[10] << 8) + + pt_read->baseCommunication.imuRaw[11]) / 1000.0); + imu_data.angular_velocity_covariance = {1e4, 0, 0, 0, 1e4, 0, 0, 0, 1e4}; + + imu_data.linear_acceleration.x = -1.0 * + ((pt_read->baseCommunication.imuRaw[12] > 0 ? -1.0 : 1.0) * + (((pt_read->baseCommunication.imuRaw[13] << 8) + + pt_read->baseCommunication.imuRaw[14]) / 1000.0)); + imu_data.linear_acceleration.y = + (pt_read->baseCommunication.imuRaw[15] > 0 ? -1.0 : 1.0) * + (((pt_read->baseCommunication.imuRaw[16] << 8) + + pt_read->baseCommunication.imuRaw[17]) / 1000.0); + imu_data.linear_acceleration.z = + (pt_read->baseCommunication.imuRaw[18] > 0 ? -1.0 : 1.0) * + (((pt_read->baseCommunication.imuRaw[19] << 8) + + pt_read->baseCommunication.imuRaw[20]) / 1000.0); + imu_data.linear_acceleration_covariance = {1e6, 0, 0, 0, 1e6, 0, 0, 0, 1e6}; + + tf2::Quaternion q; + q.setRPY(0.0, 0.0, pt_read->currentBaseData.curr_orien); + imu_data.orientation.w = q.w(); + imu_data.orientation.x = q.x(); + imu_data.orientation.y = q.y(); + imu_data.orientation.z = q.z(); + imu_data.orientation_covariance = {1e-8, 0, 0, 0, 1e-8, 0, 0, 0, 1e-8}; + + pt_read->imu_pub->publish(imu_data); + } + } + + if ((0xfd == pt_read->baseCommunication.carTypeRaw[0]) && + (0x02 == pt_read->baseCommunication.carTypeRaw[1]) && + (0x07 == pt_read->baseCommunication.carTypeRaw[2])) + { + if (pt_read->CheckRawData(pt_read->baseCommunication.carTypeRaw, 5, 7)) { + pt_read->feedback_type = std::to_string(pt_read->baseCommunication.carTypeRaw[3]); + } + } + + if ((0xfd == pt_read->baseCommunication.ultrasonicRaw[0]) && + (0x03 == pt_read->baseCommunication.ultrasonicRaw[1]) && + (0x08 == pt_read->baseCommunication.ultrasonicRaw[2])) + { + if (pt_read->CheckRawData(pt_read->baseCommunication.ultrasonicRaw, 6, 8)) { + uint16_t raw_distance = + static_cast((pt_read->baseCommunication.ultrasonicRaw[3] << 8) | + pt_read->baseCommunication.ultrasonicRaw[4]); + pt_read->PublishUltrasonicRange(raw_distance); + } + } + + if (pt_read->baseCommunication.recv_update_flag.load()) { + pt_read->myOdomData.update_flag = false; + if (pt_read->myOdomData.oriention > 2 * M_PI) { + pt_read->myOdomData.oriention -= static_cast(2 * M_PI); + } + if (pt_read->myOdomData.oriention < -2 * M_PI) { + pt_read->myOdomData.oriention += static_cast(2 * M_PI); + } + + double delta_x = pt_read->coeff_odom_x * dt * + ((pt_read->currentBaseData.vx * std::cos(pt_read->myOdomData.oriention)) - + (pt_read->currentBaseData.vy * std::sin(pt_read->myOdomData.oriention))); + double delta_y = pt_read->coeff_odom_y * dt * + ((pt_read->currentBaseData.vx * std::sin(pt_read->myOdomData.oriention)) + + (pt_read->currentBaseData.vy * std::cos(pt_read->myOdomData.oriention))); + pt_read->myOdomData.position_x += static_cast(delta_x); + pt_read->myOdomData.position_y += static_cast(delta_y); + pt_read->myOdomData.twist_x = pt_read->currentBaseData.vx; + pt_read->myOdomData.twist_y = pt_read->currentBaseData.vy; + pt_read->myOdomData.twist_th = pt_read->currentBaseData.angler_speed; + pt_read->myOdomData.oriention = pt_read->currentBaseData.curr_orien; + pt_read->baseCommunication.recv_update_flag.store(false); + pt_read->myOdomData.update_flag = true; + } + } +} + +void CCodbotBase::ReceiveUpdate(int data_len, unsigned char * data_type, unsigned char new_buff) +{ + for (int i = 0; i < data_len - 1; i++) { + data_type[i] = data_type[i + 1]; + } + data_type[data_len - 1] = new_buff; +} + +bool CCodbotBase::CheckRawData(unsigned char * raw_data, int data_num, int current_code) +{ + unsigned char check_num = 0; + for (int i = 2; i < (data_num - 1); i++) { + check_num ^= raw_data[i]; + } + + if ((debug_num >> (current_code - 1)) & 0x01) { + std::cout << "\033[32m#" << current_code << " "; + for (int i = 0; i < data_num; ++i) { + printf("%02x ", raw_data[i]); + } + std::cout << "\033[0m" << std::endl; + } + + if (check_num == raw_data[data_num - 1]) { + return true; + } + + RCLCPP_WARN(get_logger(), "frame %d xor check failed", current_code); + return false; +} + +void * CCodbotBase::MyWriteThread(void * th) +{ + auto * pt_write = static_cast(th); + while (true) { + if (pt_write->baseCommunication.send_update_flag.load()) { + if (pt_write->debug_num & 0x01) { + std::cout << "\033[32m#1 "; + for (int i = 0; i < 13; ++i) { + printf("%02x ", pt_write->baseCommunication.writebuff[i]); + } + std::cout << "\033[0m" << std::endl; + } + pt_write->baseCommunication.nwrite = + write(pt_write->baseCommunication.serialNum, pt_write->baseCommunication.writebuff, 13); + pt_write->baseCommunication.send_update_flag.store(false); + } else { + usleep(1000); + } + } +} + +void CCodbotBase::PublishUltrasonicRange(uint16_t raw_distance) +{ + sensor_msgs::msg::Range range_msg; + range_msg.header.stamp = now(); + range_msg.header.frame_id = ultrasonic_frame; + range_msg.radiation_type = sensor_msgs::msg::Range::ULTRASOUND; + range_msg.field_of_view = ultrasonic_field_of_view_rad_; + range_msg.min_range = ultrasonic_min_range_m_; + range_msg.max_range = ultrasonic_max_range_m_; + + double range_m = static_cast(raw_distance) * ultrasonic_unit_scale_m_; + if (range_m < ultrasonic_min_range_m_) { + range_m = ultrasonic_min_range_m_; + } + if (range_m > ultrasonic_max_range_m_) { + range_m = ultrasonic_max_range_m_; + } + range_msg.range = static_cast(range_m); + ultrasonic_pub->publish(range_msg); +} + +void CCodbotBase::tf_pub_callback() +{ + if (!myOdomData.update_flag) { + return; + } + + geometry_msgs::msg::TransformStamped odom_trans; + geometry_msgs::msg::Quaternion trans_quat; + tf2::Quaternion odom_quat; + nav_msgs::msg::Odometry odom; + + odom_quat.setRPY(0.0, 0.0, myOdomData.oriention); + trans_quat.x = odom_quat.x(); + trans_quat.y = odom_quat.y(); + trans_quat.z = odom_quat.z(); + trans_quat.w = odom_quat.w(); + + odom_trans.header.stamp = now(); + odom_trans.header.frame_id = odom_frame; + odom_trans.child_frame_id = odom_child_frame; + odom_trans.transform.translation.x = myOdomData.position_x; + odom_trans.transform.translation.y = myOdomData.position_y; + odom_trans.transform.translation.z = 0.0; + odom_trans.transform.rotation = trans_quat; + tf_publisher_->sendTransform(odom_trans); + + odom.header.stamp = now(); + odom.header.frame_id = odom_frame; + odom.child_frame_id = odom_child_frame; + odom.pose.pose.position.x = myOdomData.position_x; + odom.pose.pose.position.y = myOdomData.position_y; + odom.pose.pose.position.z = 0.0; + odom.pose.pose.orientation = trans_quat; + odom.twist.twist.linear.x = myOdomData.twist_x; + odom.twist.twist.linear.y = myOdomData.twist_y; + odom.twist.twist.angular.z = myOdomData.twist_th; + odom_pub->publish(odom); +} diff --git a/dev_ws/src/origintank_bringup/CMakeLists.txt b/dev_ws/src/origintank_bringup/CMakeLists.txt new file mode 100644 index 0000000..936ad0b --- /dev/null +++ b/dev_ws/src/origintank_bringup/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.5) +project(origintank_bringup) + +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(nav_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(joy_linux REQUIRED) +find_package(teleop_twist_joy REQUIRED) +find_package(origintank_base REQUIRED) + +install( + DIRECTORY launch param config + DESTINATION share/${PROJECT_NAME} +) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + # the following line skips the linter which checks for copyrights + # uncomment the line when a copyright and license is not present in all source files + #set(ament_cmake_copyright_FOUND TRUE) + # the following line skips cpplint (only works in a git repo) + # uncomment the line when this package is not in a git repo + #set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() \ No newline at end of file diff --git a/dev_ws/src/origintank_bringup/config/joy.yaml b/dev_ws/src/origintank_bringup/config/joy.yaml new file mode 100644 index 0000000..19b1822 --- /dev/null +++ b/dev_ws/src/origintank_bringup/config/joy.yaml @@ -0,0 +1,78 @@ + +# Teleop configuration for origintank Controller joystick using the x-pad configuration. +# Left thumb-stick up/down for velocity, left/right for twist +# Left shoulder button for enable +# Right shoulder button for enable-turbo +# +# L1 R1 +# L2 R2 +# _=====_ _=====_ +# / _____ \ / _____ \ +# +.-'_____'-.------------------------------.-'_____'-.+ +# / | | '. (SHARE) (OPTIONS) .' | _ | \ +# / ___| /|\ |___ \ / ___| /_\ |___ \ (Y) +# / | | | ; ; | _ _ || +# | | <--- ---> | | | ||_| (_)|| (X) (B) +# | |___ | ___| ; ; |___ ___|| +# |\ | \|/ | / _ ____ _ \ | (X) | /| (A) +# | \ |_____| .','" "', (HOME) ,'" "', '. |_____| .' | +# | '-.______.-' / \ / \ '-._____.-' | +# | | LJ |--------| RJ | | +# | /\ / \ /\ | +# | / '.___.' '.___.' \ | +# | / \ | +# \ / \ / +# \________/ \_________/ +# +# ^ x +# | +# | +# y <-----+ Accelerometer axes +# \ +# \ +# > z (out) +# +# BUTTON Value +# A 0 +# B 1 +# Y 2 +# X 3 +# L1 4 +# L2 6 +# R1 5 +# R2 7 +# Share 8 +# Options 9 +# Home 10 +# L3 11 +# R3 12 +# +# AXIS Value +# Left Horiz. 0 +# Left Vert. 1 +# Right Horiz. 3 +# Right Vert. 4 +# L2 2 +# R2 5 +# D-pad Horiz. 6 +# D-pad Vert. 7 + + +teleop_twist_joy_node: + ros__parameters: + axis_linear: + x: 1 + scale_linear: + x: 0.2 + scale_linear_turbo: + x: 0.5 + + axis_angular: + yaw: 0 + scale_angular: + yaw: 0.5 + scale_angular_turbo: + yaw: 1.9 + + enable_button: 8 # L1 shoulder button + enable_turbo_button: 10 # R1 shoulder button \ No newline at end of file diff --git a/dev_ws/src/origintank_bringup/launch/camera.launch.py b/dev_ws/src/origintank_bringup/launch/camera.launch.py new file mode 100644 index 0000000..5781742 --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/camera.launch.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 + +# Copyright (c) 2024, www.guyuehome.com +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration, TextSubstitution +from launch_ros.actions import Node +from launch.actions import IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from ament_index_python import get_package_share_directory +from ament_index_python.packages import get_package_prefix +import os + +def generate_launch_description(): + config_file_path = os.path.join( + get_package_prefix('hobot_usb_cam'), + "lib/hobot_usb_cam/config/usb_camera_calibration.yaml") + print("config_file_path is ", config_file_path) + + return LaunchDescription([ + DeclareLaunchArgument( + 'usb_camera_calibration_file_path', + default_value=TextSubstitution(text=str(config_file_path)), + description='camera calibration file path'), + IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_shm'), + 'launch/hobot_shm.launch.py')) + ), + + Node( + package='hobot_usb_cam', + executable='hobot_usb_cam', + name='hobot_usb_cam', + parameters=[ + {"camera_calibration_file_path": LaunchConfiguration( + 'usb_camera_calibration_file_path')}, + {"image_height": 480}, + {"image_width": 640}, + {"io_method":'mmap'}, + {"pixel_format": 'mjpeg2rgb'}, + {"video_device": '/dev/video8'}, + {"zero_copy":False} + ], + arguments=['--ros-args', '--log-level', 'warn'] + ) + ]) diff --git a/dev_ws/src/origintank_bringup/launch/camera_internal.launch.py b/dev_ws/src/origintank_bringup/launch/camera_internal.launch.py new file mode 100644 index 0000000..8879372 --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/camera_internal.launch.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 + +# Copyright (c) 2024, www.guyuehome.com +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration, TextSubstitution +from launch_ros.actions import Node +from launch.actions import IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from ament_index_python import get_package_share_directory +from ament_index_python.packages import get_package_prefix +import os + +def generate_launch_description(): + config_file_path = os.path.join( + get_package_prefix('hobot_usb_cam'), + "lib/hobot_usb_cam/config/usb_camera_calibration.yaml") + print("config_file_path is ", config_file_path) + + return LaunchDescription([ + DeclareLaunchArgument( + 'usb_camera_calibration_file_path', + default_value=TextSubstitution(text=str(config_file_path)), + description='camera calibration file path'), + # 启动零拷贝环境配置node + IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_shm'), + 'launch/hobot_shm.launch.py')) + ), + + Node( + package='hobot_usb_cam', + executable='hobot_usb_cam', + name='hobot_usb_cam', + parameters=[ + {"camera_calibration_file_path": LaunchConfiguration( + 'usb_camera_calibration_file_path')}, + {"image_height": 480}, + {"image_width": 640}, + {"io_method":'mmap'}, + {"pixel_format": 'mjpeg'}, + {"video_device": '/dev/video8'}, + {"zero_copy":True} + ], + arguments=['--ros-args', '--log-level', 'warn'] + ) + ]) diff --git a/dev_ws/src/origintank_bringup/launch/camera_websoket_display.launch.py b/dev_ws/src/origintank_bringup/launch/camera_websoket_display.launch.py new file mode 100644 index 0000000..23fc6b3 --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/camera_websoket_display.launch.py @@ -0,0 +1,120 @@ +#!/usr/bin/python3 + +# Copyright (c) 2024, www.guyuehome.com +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from launch import LaunchDescription +from launch_ros.actions import Node + +from launch.actions import IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from ament_index_python import get_package_share_directory +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration + +model_path = "/opt/tros/humble/lib/mono2d_body_detection/config/multitask_body_head_face_hand_kps_960x544.hbm" + + +def generate_launch_description(): + print("浣跨敤USB鎽勫儚澶�") + # 浣跨敤USB鎽勫儚澶村彂甯冨浘鍍� + usb_cam_device_arg = DeclareLaunchArgument( + 'device', + default_value='/dev/video0', + description='USB鎽勫儚澶磋澶�') + + usb_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_usb_cam'), + 'launch/hobot_usb_cam.launch.py')), + launch_arguments={ + 'usb_image_width': '640', + 'usb_image_height': '480', + 'usb_video_device': LaunchConfiguration('device') + }.items() + ) + + # jpeg->nv12 + nv12_codec_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_codec'), + 'launch/hobot_codec_decode.launch.py')), + launch_arguments={ + 'codec_in_mode': 'ros', + 'codec_out_mode': 'shared_mem', + 'codec_sub_topic': '/image', + 'codec_pub_topic': '/hbmem_img' + }.items() + ) + + # web + web_smart_topic_arg = DeclareLaunchArgument( + 'smart_topic', + default_value='/hobot_mono2d_body_detection', + description='WebSocket鏅鸿兘璇濋') + web_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('websocket'), + 'launch/websocket.launch.py')), + launch_arguments={ + 'websocket_image_topic': '/image', + 'websocket_smart_topic': LaunchConfiguration('smart_topic') + }.items() + ) + + # mono2d浜轰綋妫�娴� + mono2d_body_pub_topic_arg = DeclareLaunchArgument( + 'mono2d_body_pub_topic', + default_value='/hobot_mono2d_body_detection', + description='mono2d浜轰綋AI娑堟伅鍙戝竷璇濋') + mono2d_body_det_node = Node( + package='mono2d_body_detection', + executable='mono2d_body_detection', + output='screen', + parameters=[ + {"ai_msg_pub_topic_name": LaunchConfiguration( + 'mono2d_body_pub_topic'), + "model_file_name": model_path + } + ], + arguments=['--ros-args', '--log-level', 'warn'] + ) + + shared_mem_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_shm'), + 'launch/hobot_shm.launch.py')) + ) + + return LaunchDescription([ + usb_cam_device_arg, + # 鍚姩闆舵嫹璐濈幆澧冮厤缃妭鐐� + shared_mem_node, + # 鍥惧儚鍙戝竷 + usb_node, + # 鍥惧儚缂栬В鐮� + nv12_codec_node, + # 浜轰綋妫�娴� + mono2d_body_pub_topic_arg, + mono2d_body_det_node, + # Web鏄剧ず + web_smart_topic_arg, + web_node + ]) \ No newline at end of file diff --git a/dev_ws/src/origintank_bringup/launch/joy_teleop.launch.py b/dev_ws/src/origintank_bringup/launch/joy_teleop.launch.py new file mode 100644 index 0000000..9adb09b --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/joy_teleop.launch.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +# Copyright 2021 Clearpath Robotics, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @author Roni Kreinin (rkreinin@clearpathrobotics.com) + +from ament_index_python.packages import get_package_share_directory + +from launch import LaunchDescription +from launch.actions.declare_launch_argument import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution + +from launch_ros.actions import Node + + +def generate_launch_description(): + pkg_origintank_bringup = get_package_share_directory('origintank_bringup') + + joy_config_cmd = DeclareLaunchArgument( + 'joy_config', + default_value=PathJoinSubstitution( + [pkg_origintank_bringup, 'config', 'joy.yaml']), + description='origintank Joy teleop param file' + ) + + joy_config = LaunchConfiguration('joy_config') + + joy_node = Node( + package='joy_linux', + executable='joy_linux_node', + name='joy_linux_node' + ) + + teleop_twist_joy_node = Node( + package='teleop_twist_joy', + executable='teleop_node', + name='teleop_twist_joy_node', + parameters=[joy_config] + ) + + ld = LaunchDescription() + ld.add_action(joy_config_cmd) + ld.add_action(joy_node) + ld.add_action(teleop_twist_joy_node) + + return ld \ No newline at end of file diff --git a/dev_ws/src/origintank_bringup/launch/orbbec_gemini2.launch.py b/dev_ws/src/origintank_bringup/launch/orbbec_gemini2.launch.py new file mode 100644 index 0000000..ee32363 --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/orbbec_gemini2.launch.py @@ -0,0 +1,31 @@ +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration +from ament_index_python.packages import get_package_share_directory +import os + + +def generate_launch_description(): + orbbec_share = get_package_share_directory("orbbec_camera") + upstream_launch = os.path.join(orbbec_share, "launch", "gemini2.launch.py") + + return LaunchDescription([ + DeclareLaunchArgument("camera_name", default_value="camera"), + DeclareLaunchArgument("serial_number", default_value=""), + DeclareLaunchArgument("usb_port", default_value=""), + DeclareLaunchArgument("enable_point_cloud", default_value="false"), + DeclareLaunchArgument("enable_colored_point_cloud", default_value="false"), + DeclareLaunchArgument("depth_registration", default_value="true"), + IncludeLaunchDescription( + PythonLaunchDescriptionSource(upstream_launch), + launch_arguments={ + "camera_name": LaunchConfiguration("camera_name"), + "serial_number": LaunchConfiguration("serial_number"), + "usb_port": LaunchConfiguration("usb_port"), + "enable_point_cloud": LaunchConfiguration("enable_point_cloud"), + "enable_colored_point_cloud": LaunchConfiguration("enable_colored_point_cloud"), + "depth_registration": LaunchConfiguration("depth_registration"), + }.items(), + ), + ]) diff --git a/dev_ws/src/origintank_bringup/launch/origintank_bringup.launch.py b/dev_ws/src/origintank_bringup/launch/origintank_bringup.launch.py new file mode 100644 index 0000000..bfdcc8d --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/origintank_bringup.launch.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 + +# Copyright (c) 2024, www.guyuehome.com +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import launch +import launch_ros.actions +from ament_index_python.packages import get_package_share_directory + +def generate_launch_description(): + ld = launch.LaunchDescription([ + launch.actions.DeclareLaunchArgument(name='use_lidar', default_value='false'), + launch.actions.DeclareLaunchArgument(name='use_camera', default_value='false'), + + # Include origintank_base launch file + launch.actions.IncludeLaunchDescription( + launch.launch_description_sources.PythonLaunchDescriptionSource( + os.path.join(get_package_share_directory('origintank_base'), + 'launch/origintank_base.launch.py')) + ), + + # Include joystick teleop launch file + #launch.actions.IncludeLaunchDescription( + # launch.launch_description_sources.PythonLaunchDescriptionSource( + # os.path.join(get_package_share_directory('origintank_bringup'), + # 'launch/joy_teleop.launch.py')) + #), + + # Include lidar launch file based on condition + launch.actions.IncludeLaunchDescription( + launch.launch_description_sources.PythonLaunchDescriptionSource( + os.path.join(get_package_share_directory('origintank_bringup'), + 'launch','vp100.launch.py')), + condition=launch.conditions.IfCondition( + launch.substitutions.LaunchConfiguration('use_lidar'))), + + # Include camera launch file based on condition + launch.actions.IncludeLaunchDescription( + launch.launch_description_sources.PythonLaunchDescriptionSource( + os.path.join(get_package_share_directory('origintank_bringup'), + 'launch','camera.launch.py')), + condition=launch.conditions.IfCondition( + launch.substitutions.LaunchConfiguration('use_camera'))) + ]) + return ld + + +if __name__ == '__main__': + generate_launch_description() \ No newline at end of file diff --git a/dev_ws/src/origintank_bringup/launch/rdk_x5_auto_mission.launch.py b/dev_ws/src/origintank_bringup/launch/rdk_x5_auto_mission.launch.py new file mode 100644 index 0000000..6363faa --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/rdk_x5_auto_mission.launch.py @@ -0,0 +1,128 @@ +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.conditions import IfCondition +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node + + +def generate_launch_description(): + use_usb_camera = LaunchConfiguration('use_usb_camera') + use_depth_detector = LaunchConfiguration('use_depth_detector') + use_arm_controller = LaunchConfiguration('use_arm_controller') + use_orbbec_camera = LaunchConfiguration('use_orbbec_camera') + image_topic = LaunchConfiguration('image_topic') + depth_topic = LaunchConfiguration('depth_topic') + depth_info_topic = LaunchConfiguration('depth_info_topic') + + mission_cfg = os.path.join( + get_package_share_directory('mission_manager'), "config", "mission_manager.yaml" + ) + signal_cfg = os.path.join( + get_package_share_directory('signal_board_detector'), "config", "signal_board_detector.yaml" + ) + depth_cfg = os.path.join( + get_package_share_directory('depth_target_detector'), "config", "depth_target_detector.yaml" + ) + arm_cfg = os.path.join( + get_package_share_directory('lerobot_arm_controller'), "config", "lerobot_arm_controller.yaml" + ) + + base_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join(get_package_share_directory('origintank_base'), "launch", "origintank_base.launch.py") + ), + launch_arguments={ + "cmd_port": LaunchConfiguration('cmd_port'), + "baud_rate": LaunchConfiguration('baud_rate'), + }.items(), + ) + + usb_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join(get_package_share_directory('origintank_bringup'), "launch", "usb_camera_rdk_x5.launch.py") + ), + launch_arguments={ + "use_hobot_usb_cam": LaunchConfiguration('use_hobot_usb_cam'), + "usb_video_device": LaunchConfiguration('usb_video_device'), + "usb_width": LaunchConfiguration('usb_width'), + "usb_height": LaunchConfiguration('usb_height'), + "image_topic": image_topic, + }.items(), + condition=IfCondition(use_usb_camera), + ) + + orbbec_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join(get_package_share_directory('origintank_bringup'), "launch", "orbbec_gemini2.launch.py") + ), + launch_arguments={ + "camera_name": "camera", + "enable_point_cloud": "false", + "enable_colored_point_cloud": "false", + "depth_registration": "true", + }.items(), + condition=IfCondition(use_orbbec_camera), + ) + + signal_detector = Node( + package='signal_board_detector', + executable='signal_board_detector', + name='signal_board_detector', + output='screen', + parameters=[signal_cfg, {'image_topic': image_topic}], + condition=IfCondition(use_usb_camera), + ) + + depth_detector = Node( + package='depth_target_detector', + executable='depth_target_detector', + name='depth_target_detector', + output='screen', + parameters=[depth_cfg, {'depth_topic': depth_topic, 'camera_info_topic': depth_info_topic}], + condition=IfCondition(use_depth_detector), + ) + + arm_controller = Node( + package='lerobot_arm_controller', + executable='lerobot_arm_controller', + name='lerobot_arm_controller', + output='screen', + parameters=[arm_cfg, {'port': LaunchConfiguration('arm_port')}], + condition=IfCondition(use_arm_controller), + ) + + mission_node = Node( + package='mission_manager', + executable='mission_manager', + name='mission_manager', + output='screen', + parameters=[mission_cfg], + ) + + return LaunchDescription([ + DeclareLaunchArgument('cmd_port', default_value='/dev/ttyUSB0'), + DeclareLaunchArgument('baud_rate', default_value='B115200'), + DeclareLaunchArgument('use_usb_camera', default_value='true'), + DeclareLaunchArgument('use_orbbec_camera', default_value='true'), + DeclareLaunchArgument('use_depth_detector', default_value='true'), + DeclareLaunchArgument('use_arm_controller', default_value='true'), + DeclareLaunchArgument('use_hobot_usb_cam', default_value='true'), + DeclareLaunchArgument('usb_video_device', default_value='/dev/video0'), + DeclareLaunchArgument('usb_width', default_value='640'), + DeclareLaunchArgument('usb_height', default_value='480'), + DeclareLaunchArgument('image_topic', default_value='/image_raw'), + DeclareLaunchArgument('depth_topic', default_value='/camera/depth/image_raw'), + DeclareLaunchArgument('depth_info_topic', default_value='/camera/depth/camera_info'), + DeclareLaunchArgument('arm_port', default_value='/dev/ttyUSB2'), + base_launch, + usb_launch, + orbbec_launch, + signal_detector, + depth_detector, + arm_controller, + mission_node, + ]) diff --git a/dev_ws/src/origintank_bringup/launch/usb_camera_rdk_x5.launch.py b/dev_ws/src/origintank_bringup/launch/usb_camera_rdk_x5.launch.py new file mode 100644 index 0000000..8bc5803 --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/usb_camera_rdk_x5.launch.py @@ -0,0 +1,89 @@ +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.conditions import IfCondition +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration, PythonExpression, TextSubstitution +from launch_ros.actions import Node +from ament_index_python.packages import get_package_prefix, get_package_share_directory +import os + + +def generate_launch_description(): + use_hobot = LaunchConfiguration('use_hobot_usb_cam') + device = LaunchConfiguration('usb_video_device') + width = LaunchConfiguration('usb_width') + height = LaunchConfiguration('usb_height') + image_topic = LaunchConfiguration('image_topic') + + have_hobot = True + try: + config_file_path = os.path.join( + get_package_prefix('hobot_usb_cam'), + 'lib/hobot_usb_cam/config/usb_camera_calibration.yaml' + ) + shm_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join(get_package_share_directory('hobot_shm'), 'launch/hobot_shm.launch.py') + ), + condition=IfCondition(use_hobot) + ) + hobot_cam = Node( + package='hobot_usb_cam', + executable='hobot_usb_cam', + name='hobot_usb_cam', + output='screen', + parameters=[{ + 'camera_calibration_file_path': TextSubstitution(text=str(config_file_path)), + 'image_height': height, + 'image_width': width, + 'io_method': 'mmap', + 'pixel_format': 'mjpeg2rgb', + 'video_device': device, + 'zero_copy': False, + }], + remappings=[('/image', image_topic)], + condition=IfCondition(use_hobot), + arguments=['--ros-args', '--log-level', 'warn'] + ) + except Exception: + have_hobot = False + shm_launch = None + hobot_cam = None + + generic_condition = IfCondition(PythonExpression([ + "'", use_hobot, "' == 'false'" + ])) if have_hobot else None + + generic_cam_kwargs = dict( + package='usb_cam', + executable='usb_cam_node_exe', + name='usb_cam', + output='screen', + parameters=[{ + 'video_device': device, + 'image_width': width, + 'image_height': height, + 'pixel_format': 'mjpeg', + 'camera_frame_id': 'usb_camera_link', + 'io_method': 'mmap', + }], + remappings=[('/image_raw', image_topic)], + ) + if generic_condition is not None: + generic_cam_kwargs['condition'] = generic_condition + generic_cam = Node(**generic_cam_kwargs) + + actions = [ + DeclareLaunchArgument('use_hobot_usb_cam', default_value='true'), + DeclareLaunchArgument('usb_video_device', default_value='/dev/video0'), + DeclareLaunchArgument('usb_width', default_value='640'), + DeclareLaunchArgument('usb_height', default_value='480'), + DeclareLaunchArgument('image_topic', default_value='/image_raw'), + ] + + if shm_launch is not None: + actions.append(shm_launch) + if hobot_cam is not None: + actions.append(hobot_cam) + actions.append(generic_cam) + return LaunchDescription(actions) diff --git a/dev_ws/src/origintank_bringup/launch/vp100.launch.py b/dev_ws/src/origintank_bringup/launch/vp100.launch.py new file mode 100644 index 0000000..6b8e587 --- /dev/null +++ b/dev_ws/src/origintank_bringup/launch/vp100.launch.py @@ -0,0 +1,57 @@ +#!/usr/bin/python3 + +# Copyright (c) 2022, www.guyuehome.com +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_index_python.packages import get_package_share_directory + +from launch import LaunchDescription +from launch_ros.actions import LifecycleNode +from launch_ros.actions import Node +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch.actions import LogInfo + +import lifecycle_msgs.msg +import os + +def generate_launch_description(): + share_dir = get_package_share_directory('vp100_ros2') + parameter_file = LaunchConfiguration('params_file') + node_name = 'vp100_ros2_node' + + params_declare = DeclareLaunchArgument('params_file', + default_value=os.path.join( + share_dir, 'params', 'vp100.yaml'), + description='FPath to the ROS2 parameters file to use.') + + driver_node = LifecycleNode(package='vp100_ros2', + executable='vp100_ros2_node', # Changed from node_executable to executable + name='vp100_ros2_node', + output='screen', + emulate_tty=True, + parameters=[parameter_file], + namespace='/', + ) + tf2_node = Node(package='tf2_ros', + executable='static_transform_publisher', # Changed from node_executable to executable + name='static_tf_pub_laser', # Changed from node_name to name + arguments=['0', '0', '0.02','0', '0', '0', '1','base_link','laser_link'], + ) + + return LaunchDescription([ + params_declare, + driver_node, + tf2_node, + ]) \ No newline at end of file diff --git a/dev_ws/src/origintank_bringup/package.xml b/dev_ws/src/origintank_bringup/package.xml new file mode 100644 index 0000000..b4f8071 --- /dev/null +++ b/dev_ws/src/origintank_bringup/package.xml @@ -0,0 +1,33 @@ + + + + origintank_bringup + 0.0.0 + origintank bringup scripts with origintank_base + GuYueHome + Apache 2.0 + + ament_cmake + rclcpp + origintank_base + sensor_msgs + geometry_msgs + tf2_ros + joy_linux + teleop_twist_joy + nav_msgs + nav2_msgs + tf2 + mission_manager + signal_board_detector + depth_target_detector + lerobot_arm_controller + orbbec_camera + + ament_lint_auto + ament_lint_common + + + ament_cmake + + \ No newline at end of file diff --git a/dev_ws/src/origintank_bringup/param/ydlidar.yaml b/dev_ws/src/origintank_bringup/param/ydlidar.yaml new file mode 100644 index 0000000..ab64f89 --- /dev/null +++ b/dev_ws/src/origintank_bringup/param/ydlidar.yaml @@ -0,0 +1,23 @@ +ydlidar_ros2_driver_node: + ros__parameters: + port: /dev/ydlidar + frame_id: laser_link + ignore_array: "" + baudrate: 115200 + lidar_type: 1 + device_type: 0 + sample_rate: 3 + abnormal_check_count: 4 + resolution_fixed: true + reversion: false + inverted: true + auto_reconnect: true + isSingleChannel: true + intensity: false + support_motor_dtr: false + angle_max: 180.0 + angle_min: -180.0 + range_max: 12.0 + range_min: 0.01 + frequency: 8.0 + invalid_range_is_inf: false diff --git a/dev_ws/src/raw_material_detector/config/raw_material_detector.yaml b/dev_ws/src/raw_material_detector/config/raw_material_detector.yaml new file mode 100644 index 0000000..ab326d7 --- /dev/null +++ b/dev_ws/src/raw_material_detector/config/raw_material_detector.yaml @@ -0,0 +1,27 @@ +raw_material_detector: + ros__parameters: + color_topic: "/camera/color/image_raw" + depth_topic: "/camera/depth/image_raw" + camera_info_topic: "/camera/depth/camera_info" + + green_h_min: 35 + green_h_max: 90 + green_s_min: 60 + green_v_min: 40 + min_contour_area: 180.0 + max_contour_area: 80000.0 + min_aspect_ratio: 0.40 + max_aspect_ratio: 2.50 + + roi_x_ratio: 0.05 + roi_y_ratio: 0.05 + roi_w_ratio: 0.90 + roi_h_ratio: 0.90 + min_depth_m: 0.08 + max_depth_m: 0.80 + depth_patch_radius_px: 6 + max_depth_age_sec: 0.50 + + stable_frames: 3 + stable_position_tolerance_m: 0.025 + publish_compatible_depth_target: true diff --git a/dev_ws/src/raw_material_detector/launch/raw_material_detector.launch.py b/dev_ws/src/raw_material_detector/launch/raw_material_detector.launch.py new file mode 100644 index 0000000..f63ebb0 --- /dev/null +++ b/dev_ws/src/raw_material_detector/launch/raw_material_detector.launch.py @@ -0,0 +1,23 @@ +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch_ros.actions import Node + + +def generate_launch_description(): + config = os.path.join( + get_package_share_directory('raw_material_detector'), + 'config', + 'raw_material_detector.yaml', + ) + return LaunchDescription([ + Node( + package='raw_material_detector', + executable='raw_material_detector', + name='raw_material_detector', + output='screen', + parameters=[config], + ) + ]) + diff --git a/dev_ws/src/raw_material_detector/package.xml b/dev_ws/src/raw_material_detector/package.xml new file mode 100644 index 0000000..9ee4909 --- /dev/null +++ b/dev_ws/src/raw_material_detector/package.xml @@ -0,0 +1,23 @@ + + + + raw_material_detector + 0.1.0 + Gemini 2 green raw material detector for the logistics challenge. + SK + Apache-2.0 + + rclpy + geometry_msgs + sensor_msgs + std_msgs + cv_bridge + python3-opencv + python3-numpy + ros2launch + + + ament_python + + + diff --git a/dev_ws/src/raw_material_detector/raw_material_detector/__init__.py b/dev_ws/src/raw_material_detector/raw_material_detector/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dev_ws/src/raw_material_detector/raw_material_detector/__init__.py @@ -0,0 +1 @@ + diff --git a/dev_ws/src/raw_material_detector/raw_material_detector/__pycache__/raw_material_detector_node.cpython-313.pyc b/dev_ws/src/raw_material_detector/raw_material_detector/__pycache__/raw_material_detector_node.cpython-313.pyc new file mode 100644 index 0000000..169bdfc Binary files /dev/null and b/dev_ws/src/raw_material_detector/raw_material_detector/__pycache__/raw_material_detector_node.cpython-313.pyc differ diff --git a/dev_ws/src/raw_material_detector/raw_material_detector/raw_material_detector_node.py b/dev_ws/src/raw_material_detector/raw_material_detector/raw_material_detector_node.py new file mode 100644 index 0000000..1156cc9 --- /dev/null +++ b/dev_ws/src/raw_material_detector/raw_material_detector/raw_material_detector_node.py @@ -0,0 +1,330 @@ +from collections import deque +from typing import Optional, Tuple + +import cv2 +import numpy as np +import rclpy +from cv_bridge import CvBridge +from geometry_msgs.msg import PointStamped +from rclpy.node import Node +from rclpy.qos import qos_profile_sensor_data +from sensor_msgs.msg import CameraInfo, Image +from std_msgs.msg import Bool, String + + +class RawMaterialDetector(Node): + def __init__(self) -> None: + super().__init__('raw_material_detector') + self._declare_parameters() + self._load_parameters() + + self.bridge = CvBridge() + self.latest_depth: Optional[np.ndarray] = None + self.latest_depth_header = None + self.latest_depth_time = None + self.fx = None + self.fy = None + self.cx = None + self.cy = None + self.history = deque(maxlen=max(self.stable_frames, 2)) + self.last_status_time = None + + self.point_pub = self.create_publisher(PointStamped, '/raw_material/point', 10) + self.point3d_pub = self.create_publisher(PointStamped, '/raw_material/point3d', 10) + self.visible_pub = self.create_publisher(Bool, '/raw_material/visible', 10) + self.stable_pub = self.create_publisher(Bool, '/raw_material/stable', 10) + self.debug_pub = self.create_publisher(Image, '/raw_material/debug_image', 10) + self.mask_pub = self.create_publisher(Image, '/raw_material/mask_image', 10) + self.status_pub = self.create_publisher(String, '/raw_material/status', 10) + self.compatible_pub = self.create_publisher(PointStamped, '/depth_target/point3d', 10) + + self.create_subscription( + Image, self.color_topic, self.on_color, qos_profile_sensor_data + ) + self.create_subscription( + Image, self.depth_topic, self.on_depth, qos_profile_sensor_data + ) + self.create_subscription( + CameraInfo, self.camera_info_topic, self.on_camera_info, qos_profile_sensor_data + ) + + def _declare_parameters(self) -> None: + defaults = { + 'color_topic': '/camera/color/image_raw', + 'depth_topic': '/camera/depth/image_raw', + 'camera_info_topic': '/camera/depth/camera_info', + 'green_h_min': 35, + 'green_h_max': 90, + 'green_s_min': 60, + 'green_v_min': 40, + 'min_contour_area': 180.0, + 'max_contour_area': 80000.0, + 'min_aspect_ratio': 0.40, + 'max_aspect_ratio': 2.50, + 'roi_x_ratio': 0.05, + 'roi_y_ratio': 0.05, + 'roi_w_ratio': 0.90, + 'roi_h_ratio': 0.90, + 'min_depth_m': 0.08, + 'max_depth_m': 0.80, + 'depth_patch_radius_px': 6, + 'max_depth_age_sec': 0.50, + 'stable_frames': 5, + 'stable_position_tolerance_m': 0.025, + 'publish_compatible_depth_target': True, + } + for name, value in defaults.items(): + self.declare_parameter(name, value) + + def _load_parameters(self) -> None: + get = self.get_parameter + self.color_topic = str(get('color_topic').value) + self.depth_topic = str(get('depth_topic').value) + self.camera_info_topic = str(get('camera_info_topic').value) + self.green_h_min = int(get('green_h_min').value) + self.green_h_max = int(get('green_h_max').value) + self.green_s_min = int(get('green_s_min').value) + self.green_v_min = int(get('green_v_min').value) + self.min_contour_area = float(get('min_contour_area').value) + self.max_contour_area = float(get('max_contour_area').value) + self.min_aspect_ratio = float(get('min_aspect_ratio').value) + self.max_aspect_ratio = float(get('max_aspect_ratio').value) + self.roi_x_ratio = float(get('roi_x_ratio').value) + self.roi_y_ratio = float(get('roi_y_ratio').value) + self.roi_w_ratio = float(get('roi_w_ratio').value) + self.roi_h_ratio = float(get('roi_h_ratio').value) + self.min_depth_m = float(get('min_depth_m').value) + self.max_depth_m = float(get('max_depth_m').value) + self.depth_patch_radius_px = int(get('depth_patch_radius_px').value) + self.max_depth_age_sec = float(get('max_depth_age_sec').value) + self.stable_frames = int(get('stable_frames').value) + self.stable_position_tolerance_m = float(get('stable_position_tolerance_m').value) + self.publish_compatible_depth_target = bool(get('publish_compatible_depth_target').value) + + def on_camera_info(self, msg: CameraInfo) -> None: + if len(msg.k) >= 9: + self.fx = float(msg.k[0]) + self.fy = float(msg.k[4]) + self.cx = float(msg.k[2]) + self.cy = float(msg.k[5]) + + def on_depth(self, msg: Image) -> None: + depth = self.bridge.imgmsg_to_cv2(msg) + if depth.ndim != 2: + return + if depth.dtype == np.uint16: + depth = depth.astype(np.float32) / 1000.0 + else: + depth = depth.astype(np.float32) + self.latest_depth = depth + self.latest_depth_header = msg.header + self.latest_depth_time = self.get_clock().now() + + def publish_bool(self, publisher, value: bool) -> None: + msg = Bool() + msg.data = value + publisher.publish(msg) + + def publish_status(self, text: str, force: bool = False) -> None: + now = self.get_clock().now() + if not force and self.last_status_time is not None: + age = (now - self.last_status_time).nanoseconds / 1e9 + if age < 1.0: + return + msg = String() + msg.data = text + self.status_pub.publish(msg) + self.get_logger().info(text) + self.last_status_time = now + + def publish_not_visible( + self, + frame: Optional[np.ndarray], + header=None, + reason: str = 'not_found', + ) -> None: + self.history.clear() + self.publish_bool(self.visible_pub, False) + self.publish_bool(self.stable_pub, False) + self.publish_status(f'not_visible:{reason}') + if frame is not None: + cv2.putText(frame, f'not found: {reason}', (20, 35), + cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) + debug = self.bridge.cv2_to_imgmsg(frame, encoding='bgr8') + if header is not None: + debug.header = header + self.debug_pub.publish(debug) + + def depth_is_fresh(self) -> bool: + if self.latest_depth_time is None: + return False + age = (self.get_clock().now() - self.latest_depth_time).nanoseconds / 1e9 + return age <= self.max_depth_age_sec + + def depth_at_color_pixel( + self, + color_x: int, + color_y: int, + color_shape: Tuple[int, int], + ) -> Optional[Tuple[int, int, float]]: + if self.latest_depth is None: + return None + color_h, color_w = color_shape + depth_h, depth_w = self.latest_depth.shape + depth_x = int(round(color_x * depth_w / max(color_w, 1))) + depth_y = int(round(color_y * depth_h / max(color_h, 1))) + radius = max(1, self.depth_patch_radius_px) + x0 = max(0, depth_x - radius) + x1 = min(depth_w, depth_x + radius + 1) + y0 = max(0, depth_y - radius) + y1 = min(depth_h, depth_y + radius + 1) + patch = self.latest_depth[y0:y1, x0:x1] + valid = patch[ + np.isfinite(patch) + & (patch >= self.min_depth_m) + & (patch <= self.max_depth_m) + ] + if valid.size < 5: + return None + return depth_x, depth_y, float(np.median(valid)) + + def is_stable(self) -> bool: + if len(self.history) < self.stable_frames: + return False + points = np.asarray(list(self.history)[-self.stable_frames:], dtype=np.float32) + spread = np.max(points, axis=0) - np.min(points, axis=0) + return bool(np.max(spread) <= self.stable_position_tolerance_m) + + def on_color(self, msg: Image) -> None: + frame = self.bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8') + if self.latest_depth is None: + self.publish_not_visible(frame, msg.header, 'no_depth_image') + return + if not self.depth_is_fresh(): + self.publish_not_visible(frame, msg.header, 'depth_image_stale') + return + if any(value is None for value in (self.fx, self.fy, self.cx, self.cy)): + self.publish_not_visible(frame, msg.header, 'no_depth_camera_info') + return + + height, width = frame.shape[:2] + x0 = max(0, int(width * self.roi_x_ratio)) + y0 = max(0, int(height * self.roi_y_ratio)) + x1 = min(width, x0 + int(width * self.roi_w_ratio)) + y1 = min(height, y0 + int(height * self.roi_h_ratio)) + hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) + mask = cv2.inRange( + hsv, + (self.green_h_min, self.green_s_min, self.green_v_min), + (self.green_h_max, 255, 255), + ) + roi_mask = np.zeros_like(mask) + roi_mask[y0:y1, x0:x1] = mask[y0:y1, x0:x1] + kernel = np.ones((5, 5), np.uint8) + roi_mask = cv2.morphologyEx(roi_mask, cv2.MORPH_OPEN, kernel) + roi_mask = cv2.morphologyEx(roi_mask, cv2.MORPH_CLOSE, kernel) + mask_msg = self.bridge.cv2_to_imgmsg(roi_mask, encoding='mono8') + mask_msg.header = msg.header + self.mask_pub.publish(mask_msg) + + contours, _ = cv2.findContours(roi_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + candidates = [] + for contour in contours: + area = float(cv2.contourArea(contour)) + if not self.min_contour_area <= area <= self.max_contour_area: + continue + x, y, w, h = cv2.boundingRect(contour) + aspect = float(w) / float(max(h, 1)) + if not self.min_aspect_ratio <= aspect <= self.max_aspect_ratio: + continue + candidates.append((area, contour, x, y, w, h)) + + if not candidates: + mask_pixels = int(np.count_nonzero(roi_mask)) + if contours: + largest_area = max(float(cv2.contourArea(contour)) for contour in contours) + reason = ( + f'green_contours_rejected,mask_pixels={mask_pixels},' + f'largest_area={largest_area:.1f}' + ) + else: + reason = f'no_green_pixels,mask_pixels={mask_pixels}' + self.publish_not_visible(frame, msg.header, reason) + return + + area, contour, x, y, box_w, box_h = max(candidates, key=lambda item: item[0]) + moments = cv2.moments(contour) + if abs(moments['m00']) < 1e-6: + self.publish_not_visible(frame, msg.header, 'invalid_green_contour_moment') + return + color_x = int(round(moments['m10'] / moments['m00'])) + color_y = int(round(moments['m01'] / moments['m00'])) + depth_result = self.depth_at_color_pixel(color_x, color_y, (height, width)) + if depth_result is None: + self.publish_not_visible( + frame, + msg.header, + f'no_valid_depth_at_green_target,min={self.min_depth_m:.2f},' + f'max={self.max_depth_m:.2f}', + ) + return + depth_x, depth_y, distance = depth_result + + assert self.fx is not None and self.fy is not None + assert self.cx is not None and self.cy is not None + x_cam = (depth_x - self.cx) * distance / self.fx + y_cam = (depth_y - self.cy) * distance / self.fy + z_cam = distance + + normalized_x = (color_x - width / 2.0) / max(width / 2.0, 1.0) + normalized_y = (color_y - height / 2.0) / max(height / 2.0, 1.0) + point = PointStamped() + point.header = msg.header + point.point.x = distance + point.point.y = float(normalized_x) + point.point.z = float(normalized_y) + self.point_pub.publish(point) + + point3d = PointStamped() + point3d.header = self.latest_depth_header + point3d.point.x = float(x_cam) + point3d.point.y = float(y_cam) + point3d.point.z = float(z_cam) + self.point3d_pub.publish(point3d) + + self.history.append((x_cam, y_cam, z_cam)) + stable = self.is_stable() + self.publish_bool(self.visible_pub, True) + self.publish_bool(self.stable_pub, stable) + if stable and self.publish_compatible_depth_target: + self.compatible_pub.publish(point3d) + self.publish_status( + f'detected:stable={stable},distance={distance:.3f},' + f'area={area:.1f},pixel=({color_x},{color_y})' + ) + + color = (0, 255, 0) if stable else (0, 200, 255) + cv2.rectangle(frame, (x, y), (x + box_w, y + box_h), color, 2) + cv2.circle(frame, (color_x, color_y), 6, color, 2) + label = f'raw d={distance:.3f}m area={area:.0f} stable={stable}' + cv2.putText(frame, label, (max(5, x), max(25, y - 8)), + cv2.FONT_HERSHEY_SIMPLEX, 0.60, color, 2) + debug = self.bridge.cv2_to_imgmsg(frame, encoding='bgr8') + debug.header = msg.header + self.debug_pub.publish(debug) + + +def main() -> None: + rclpy.init() + node = RawMaterialDetector() + try: + rclpy.spin(node) + except KeyboardInterrupt: + pass + finally: + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/dev_ws/src/raw_material_detector/resource/raw_material_detector b/dev_ws/src/raw_material_detector/resource/raw_material_detector new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dev_ws/src/raw_material_detector/resource/raw_material_detector @@ -0,0 +1 @@ + diff --git a/dev_ws/src/raw_material_detector/setup.cfg b/dev_ws/src/raw_material_detector/setup.cfg new file mode 100644 index 0000000..c8e281b --- /dev/null +++ b/dev_ws/src/raw_material_detector/setup.cfg @@ -0,0 +1,5 @@ +[develop] +script_dir=$base/lib/raw_material_detector +[install] +install_scripts=$base/lib/raw_material_detector + diff --git a/dev_ws/src/raw_material_detector/setup.py b/dev_ws/src/raw_material_detector/setup.py new file mode 100644 index 0000000..8bea8b4 --- /dev/null +++ b/dev_ws/src/raw_material_detector/setup.py @@ -0,0 +1,29 @@ +from setuptools import setup + + +package_name = 'raw_material_detector' + + +setup( + name=package_name, + version='0.1.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', ['launch/raw_material_detector.launch.py']), + ('share/' + package_name + '/config', ['config/raw_material_detector.yaml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='SK', + maintainer_email='sk@example.com', + description='Gemini 2 color and depth detector for green raw material blocks.', + license='Apache-2.0', + entry_points={ + 'console_scripts': [ + 'raw_material_detector = raw_material_detector.raw_material_detector_node:main', + ], + }, +) + diff --git a/dev_ws/src/signal_board_detector/config/signal_board_detector.yaml b/dev_ws/src/signal_board_detector/config/signal_board_detector.yaml new file mode 100644 index 0000000..0d1695a --- /dev/null +++ b/dev_ws/src/signal_board_detector/config/signal_board_detector.yaml @@ -0,0 +1,7 @@ +signal_board_detector: + ros__parameters: + image_topic: "/image_raw" + busy_yellow_ratio: 0.45 + idle_yellow_ratio_min: 0.03 + idle_yellow_ratio_max: 0.28 + min_contour_area: 1200.0 diff --git a/dev_ws/src/signal_board_detector/launch/signal_board_detector.launch.py b/dev_ws/src/signal_board_detector/launch/signal_board_detector.launch.py new file mode 100644 index 0000000..14eec78 --- /dev/null +++ b/dev_ws/src/signal_board_detector/launch/signal_board_detector.launch.py @@ -0,0 +1,20 @@ +from launch import LaunchDescription +from launch_ros.actions import Node +from ament_index_python.packages import get_package_share_directory +import os + + +def generate_launch_description(): + config = os.path.join( + get_package_share_directory('signal_board_detector'), + 'config', 'signal_board_detector.yaml' + ) + return LaunchDescription([ + Node( + package='signal_board_detector', + executable='signal_board_detector', + name='signal_board_detector', + output='screen', + parameters=[config], + ) + ]) diff --git a/dev_ws/src/signal_board_detector/package.xml b/dev_ws/src/signal_board_detector/package.xml new file mode 100644 index 0000000..b80cd9d --- /dev/null +++ b/dev_ws/src/signal_board_detector/package.xml @@ -0,0 +1,23 @@ + + + + signal_board_detector + 0.1.0 + USB camera based signal board detector. + OpenAI + Apache-2.0 + + + rclpy + sensor_msgs + std_msgs + cv_bridge + + python3-opencv + python3-numpy + ros2launch + + + ament_python + + diff --git a/dev_ws/src/signal_board_detector/resource/signal_board_detector b/dev_ws/src/signal_board_detector/resource/signal_board_detector new file mode 100644 index 0000000..e69de29 diff --git a/dev_ws/src/signal_board_detector/setup.cfg b/dev_ws/src/signal_board_detector/setup.cfg new file mode 100644 index 0000000..f271e10 --- /dev/null +++ b/dev_ws/src/signal_board_detector/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/signal_board_detector +[install] +install_scripts=$base/lib/signal_board_detector diff --git a/dev_ws/src/signal_board_detector/setup.py b/dev_ws/src/signal_board_detector/setup.py new file mode 100644 index 0000000..f6c89cf --- /dev/null +++ b/dev_ws/src/signal_board_detector/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup + +package_name = 'signal_board_detector' + +setup( + name=package_name, + version='0.1.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', ['launch/signal_board_detector.launch.py']), + ('share/' + package_name + '/config', ['config/signal_board_detector.yaml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='OpenAI', + maintainer_email='openai@example.com', + description='USB camera based signal board detector', + license='Apache-2.0', + entry_points={ + 'console_scripts': [ + 'signal_board_detector = signal_board_detector.signal_board_detector_node:main', + ], + }, +) diff --git a/dev_ws/src/signal_board_detector/signal_board_detector/__init__.py b/dev_ws/src/signal_board_detector/signal_board_detector/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dev_ws/src/signal_board_detector/signal_board_detector/signal_board_detector_node.py b/dev_ws/src/signal_board_detector/signal_board_detector/signal_board_detector_node.py new file mode 100644 index 0000000..7b32595 --- /dev/null +++ b/dev_ws/src/signal_board_detector/signal_board_detector/signal_board_detector_node.py @@ -0,0 +1,95 @@ +import cv2 +import numpy as np +import rclpy +from cv_bridge import CvBridge +from rclpy.node import Node +from sensor_msgs.msg import Image +from std_msgs.msg import String + + +class SignalBoardDetector(Node): + def __init__(self) -> None: + super().__init__('signal_board_detector') + self.declare_parameter('image_topic', '/image_raw') + self.declare_parameter('busy_yellow_ratio', 0.45) + self.declare_parameter('idle_yellow_ratio_min', 0.03) + self.declare_parameter('idle_yellow_ratio_max', 0.28) + self.declare_parameter('min_contour_area', 1200.0) + + image_topic = self.get_parameter('image_topic').value + self.busy_yellow_ratio = float(self.get_parameter('busy_yellow_ratio').value) + self.idle_yellow_ratio_min = float(self.get_parameter('idle_yellow_ratio_min').value) + self.idle_yellow_ratio_max = float(self.get_parameter('idle_yellow_ratio_max').value) + self.min_contour_area = float(self.get_parameter('min_contour_area').value) + + self.bridge = CvBridge() + self.result_pub = self.create_publisher(String, '/signal_board/result', 10) + self.debug_pub = self.create_publisher(Image, '/signal_board/debug_image', 10) + self.create_subscription(Image, image_topic, self.on_image, 10) + + def publish_result(self, result: str) -> None: + msg = String() + msg.data = result + self.result_pub.publish(msg) + + def detect_shape(self, contour) -> str: + peri = cv2.arcLength(contour, True) + approx = cv2.approxPolyDP(contour, 0.04 * peri, True) + vertices = len(approx) + if vertices == 3: + return 'triangle' + if vertices == 4: + return 'square' + return 'star' + + def on_image(self, msg: Image) -> None: + frame = self.bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8') + hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) + + yellow_mask = cv2.inRange(hsv, (15, 80, 80), (40, 255, 255)) + gray_mask = cv2.inRange(hsv, (0, 0, 40), (180, 50, 220)) + + kernel = np.ones((5, 5), np.uint8) + yellow_mask = cv2.morphologyEx(yellow_mask, cv2.MORPH_OPEN, kernel) + yellow_mask = cv2.morphologyEx(yellow_mask, cv2.MORPH_CLOSE, kernel) + gray_mask = cv2.morphologyEx(gray_mask, cv2.MORPH_OPEN, kernel) + + total_pixels = frame.shape[0] * frame.shape[1] + yellow_ratio = float(np.count_nonzero(yellow_mask)) / float(max(total_pixels, 1)) + gray_ratio = float(np.count_nonzero(gray_mask)) / float(max(total_pixels, 1)) + + result = 'unknown' + contours, _ = cv2.findContours(yellow_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + contours = [c for c in contours if cv2.contourArea(c) >= self.min_contour_area] + + if yellow_ratio >= self.busy_yellow_ratio: + result = 'busy' + elif self.idle_yellow_ratio_min <= yellow_ratio <= self.idle_yellow_ratio_max and gray_ratio > 0.15 and contours: + contour = max(contours, key=cv2.contourArea) + shape = self.detect_shape(contour) + result = f'idle_{shape}' + x, y, w, h = cv2.boundingRect(contour) + cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) + cv2.putText(frame, result, (x, max(30, y - 10)), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2) + else: + cv2.putText(frame, result, (20, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2) + + cv2.putText(frame, f'yellow={yellow_ratio:.3f}', (20, 65), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 2) + self.publish_result(result) + debug_msg = self.bridge.cv2_to_imgmsg(frame, encoding='bgr8') + debug_msg.header = msg.header + self.debug_pub.publish(debug_msg) + + +def main() -> None: + rclpy.init() + node = SignalBoardDetector() + try: + rclpy.spin(node) + finally: + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/dev_ws/src/supply_pickup_manager/README.md b/dev_ws/src/supply_pickup_manager/README.md new file mode 100644 index 0000000..f8a96af --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/README.md @@ -0,0 +1,223 @@ +# 绗簩闃舵锛氬す鐖牴閮� Gemini 2 + LeArm 鎶撳彇 + +Gemini 2 瀹夎鍦ㄥす鐖牴閮ㄥ苟涓庡す鐖钩琛岋紝鍥犳绗簩闃舵浣跨敤 LeArm 鐨� 6 鍙锋棆杞� +鑸垫満鏀瑰彉鐩告満瑙嗛噹锛屼笉鍐嶆棆杞簳鐩橈紝涔熶笉渚濊禆 `/imu`銆� + +```text +绛夊緟绗竴闃舵 ARRIVED锛堟垨鎵嬪姩寮�濮嬶級 + -> 璇诲彇 LeArm 褰撳墠鑸垫満6鑴夊浣滀负鎵弿涓績 + -> 鑸垫満6鎸夌浉瀵瑰亸绉婚�愮偣鎵弿 + -> Gemini 2妫�娴嬬ǔ瀹氱豢鑹叉柟鍧� + -> 鏍规嵁鍥惧儚姘村钩璇樊寰皟鑸垫満6锛屼娇鏂瑰潡灞呬腑 + -> model.yaml棰勬祴鑸垫満6/5/4/3鎶撳彇濮挎�� + -> 寮犲紑澶圭埅銆佹帴杩戙�佸す鍙栥�佹姮鍗� + -> 绉诲姩鍒板乏骞冲彴銆佹澗寮�銆佸洖瀹夊叏濮挎�� +``` + +鏈寘鏂板 `learm_stage2_controller`锛岀洿鎺ヤ娇鐢� `arm_plane_calib/learm_test.py` +涓獙璇佽繃鐨� `55 55 + CMD=3` 澶氳埖鏈哄崗璁�傚畠涓嶄細鍚姩鎴栦慨鏀瑰師 +`lerobot_arm_controller`銆� + +## 瀹夊叏闂ㄧ + +榛樿閰嶇疆涓嶄細椹卞姩鐪熷疄鏈烘鑷傦細 + +```yaml +simulation: true +hardware_motion_enabled: false +poses_calibrated: false +enable_pick_after_center: false +``` + +闂ㄧ鍒嗕负涓夊眰锛� + +1. `hardware_motion_enabled=false`锛氱湡瀹炰覆鍙e彧鑳借鍙栬埖鏈轰綅缃紝涓嶈兘杩愬姩锛� +2. `enable_pick_after_center=false`锛氬彧鎵弿鍜屽眳涓紝涓嶆墽琛屾姄鍙栵紱 +3. `poses_calibrated=false`锛氬嵆浣挎敹鍒版姄鍙栧懡浠わ紝鐪熷疄鎺у埗鍣ㄤ篃鎷掔粷鎵ц瀹屾暣鎶撳彇銆� + +`home_pulses`銆乣left_platform_pulses`銆乣grasp_offsets`銆乣lift_offsets` 褰撳墠鏄� +鍗犱綅鍊硷紝涓嶈兘鐩存帴鐢ㄤ簬鐪熸満瀹屾暣鎶撳彇銆� + +## 缂栬瘧 + +```bash +cd /root/dev_ws +source /opt/ros/humble/setup.bash +colcon build --packages-select raw_material_detector supply_pickup_manager +source install/setup.bash +``` + +涓嶈浣跨敤 `--symlink-install`銆傜浜岄樁娈典笉鍐嶉渶瑕佺紪璇� +`lerobot_arm_controller`銆� + +## 娴嬭瘯涓�锛氬畬鏁撮�昏緫浠跨湡 + +浠跨湡涓嶄細鎵撳紑鏈烘鑷備覆鍙c�傜敱浜庣浉鏈轰笉浼氶殢浠跨湡鑸垫満瀹為檯杞姩锛屽簲鍏堟妸缁挎柟鍧楁斁鍦� +Gemini 2 褰撳墠瑙嗛噹鍐咃細 + +```bash +ros2 launch supply_pickup_manager stage2_supply_pickup.launch.py \ + start_gemini2:=true \ + arm_simulation:=true \ + enable_pick_after_center:=true \ + auto_start_on_supply_arrival:=false +``` + +鎵嬪姩寮�濮嬶細 + +```bash +ros2 topic pub --once /supply_pickup/start std_msgs/msg/Bool "{data: true}" +``` + +瑙傚療锛� + +```bash +ros2 topic echo /supply_pickup/status +ros2 topic echo /learm_stage2/status +ros2 topic echo /raw_material/visible +ros2 topic echo /raw_material/stable +ros2 topic echo /raw_material/point3d +ros2 topic echo /raw_material/status +``` + +姝e父鐘舵�佷负锛� + +```text +WAIT_SUPPLY_ARRIVAL -> SEARCH_RAW -> CENTER_RAW -> WAIT_ARM -> COMPLETE +``` + +## 娴嬭瘯浜岋細鍙繛鎺ョ湡鏈哄苟璇诲彇鑸垫満 + +杩欎釜鍛戒护涓嶄細鍏佽鏈烘鑷傝繍鍔細 + +```bash +ros2 launch supply_pickup_manager stage2_supply_pickup.launch.py \ + start_gemini2:=true \ + arm_port:=/dev/ttyUSB1 \ + arm_baud_rate:=9600 \ + arm_simulation:=false \ + hardware_motion_enabled:=false \ + enable_pick_after_center:=false \ + auto_start_on_supply_arrival:=false +``` + +鐪嬪埌浠ヤ笅鐘舵�佹墠璇存槑涓插彛銆佹尝鐗圭巼鍜屽洖璇诲崗璁甯革細 + +```text +ready:servo6=... +``` + +璇诲彇鍏ㄩ儴鑸垫満浣嶇疆锛� + +```bash +ros2 topic pub --once /learm_stage2/command std_msgs/msg/String \ + "{data: read_positions}" +``` + +缁撴灉浼氬彂甯冧负锛� + +```text +positions:1=...,2=...,3=...,4=...,5=...,6=... +``` + +## 娴嬭瘯涓夛細鍙祴璇曡埖鏈�6鎵弿鍜岃瑙夊眳涓� + +绗竴娆¢檺鍒跺湪鍚姩浣嶇疆姝h礋30鑴夊锛� + +```bash +ros2 launch supply_pickup_manager stage2_supply_pickup.launch.py \ + start_gemini2:=true \ + arm_port:=/dev/ttyUSB1 \ + arm_baud_rate:=9600 \ + arm_simulation:=false \ + hardware_motion_enabled:=true \ + poses_calibrated:=false \ + enable_pick_after_center:=false \ + auto_start_on_supply_arrival:=false \ + max_scan_offset:=30 +``` + +纭澶圭埅銆佺浉鏈哄拰绾跨紗閮芥湁瓒冲绌洪棿锛屽啀鎵嬪姩寮�濮嬨�傛壘鍒板苟灞呬腑鍚庝細鎶ュ憡 +`COMPLETE:scan test complete`锛屼笉浼氭姄鍙栥�� + +濡傛灉灞呬腑鏃舵柟鍧楀弽鑰屽悜鍥惧儚杈圭紭绉诲姩锛屽仠姝㈡祴璇曞苟鍙嶈浆鏂瑰悜锛� + +```bash +pan_direction_sign:=-1.0 +``` + +## 灏忔鏍囧畾濮挎�� + +鎺у埗鍣ㄦ敮鎸佷竴娆℃渶澶�40鑴夊鐨勭浉瀵圭偣鍔紝渚嬪璁�6鍙疯埖鏈哄鍔�10锛� + +```bash +ros2 topic pub --once /learm_stage2/command std_msgs/msg/String \ + "{data: 'jog:6:+10'}" +``` + +璁�4鍙疯埖鏈哄噺灏�10锛� + +```bash +ros2 topic pub --once /learm_stage2/command std_msgs/msg/String \ + "{data: 'jog:4:-10'}" +``` + +姣忔鐐瑰姩鍚庢墽琛� `read_positions`銆備緷娆¤褰曪細 + +- 鏈烘鑷傚畨鍏ㄦ敹鎷㈢姸鎬侊細`home_pulses`锛岄『搴忎负 `[6,5,4,3]`锛� +- 澶圭埅浣嶄簬宸﹀钩鍙颁笂鏂圭殑鐘舵�侊細`left_platform_pulses`锛� +- 妯″瀷棰勬祴濮挎�佷笅闄嶅埌鍙す鍙栭珮搴︽墍闇�澧為噺锛歚grasp_offsets`锛� +- 澶逛綇鍚庢姮鍗囨墍闇�澧為噺锛歚lift_offsets`銆� + +鍦ㄦ柟鍧楀凡缁忕ǔ瀹氬眳涓椂锛屽彲浠ュ厛鍙绠椼�佷笉鎵ц鏈烘鑷傚Э鎬侊細 + +```bash +ros2 topic pub --once /learm_stage2/command std_msgs/msg/String \ + "{data: preview_target}" +``` + +鎺у埗鍣ㄤ細杩斿洖 `prediction:6=...,5=...,4=...,3=...`锛岃鍛戒护涓嶄細杩愬姩浠讳綍鑸垫満銆� + +鎶婂疄娴嬪�煎啓鍏� `config/learm_stage2.yaml`锛岀‘璁ゆ満姊伴檺浣嶅拰绾跨紗瀹夊叏鍚庯紝鎵嶈兘灏嗭細 + +```text +poses_calibrated:=true +enable_pick_after_center:=true +``` + +鍚屾椂鍚敤銆� + +## 鍐茬獊绋嬪簭 + +杩愯鏈樁娈垫椂涓嶈鍚屾椂鍚姩锛� + +- `lerobot_arm_controller`锛氫細浜夋姠 `/dev/ttyUSB1`锛� +- `depth_target_detector`锛氫細鍙戝竷鍙︿竴璺洰鏍囷紱 +- `mission_manager` 鎴� `rdk_x5_auto_mission.launch.py`锛氫細鍙戝竷鍏朵粬浠诲姟鍛戒护銆� + +鏄剧ず鎺у埗鍣ㄤ笉鍙備笌绗簩闃舵銆� + +## `visible=false` 鐨勮瘖鏂� + +鏂扮増妫�娴嬪櫒浼氬湪 `/raw_material/status` 涓粰鍑哄叿浣撳師鍥狅細 + +- `no_depth_image`锛氭病鏈夋敹鍒版繁搴﹀浘锛� +- `depth_image_stale`锛氬僵鑹插浘鍜屾繁搴﹀浘鏃堕棿宸繃澶э紱 +- `no_depth_camera_info`锛氭病鏈夋敹鍒版繁搴︾浉鏈哄唴鍙傦紱 +- `no_green_pixels`锛欻SV闃堝�煎唴娌℃湁缁胯壊鍍忕礌锛� +- `green_contours_rejected`锛氭娴嬪埌缁胯壊锛屼絾闈㈢Н鎴栭暱瀹芥瘮涓嶇鍚堣姹傦紱 +- `no_valid_depth_at_green_target`锛氱豢鍧椾綅缃病鏈夋湁鏁堟繁搴︼紱 +- `detected:stable=...`锛氬凡妫�娴嬪埌鐩爣銆� + +缁胯壊浜屽�煎浘鍙戝竷鍦� `/raw_material/mask_image`锛屾爣娉ㄥ浘鍙戝竷鍦� +`/raw_material/debug_image`銆傚鏋滅姸鎬佷负 `no_green_pixels`锛屽彲鍏堝皾璇曟斁瀹斤細 + +```bash +green_h_min:=30 green_h_max:=100 green_s_min:=30 green_v_min:=25 +``` + +濡傛灉鐘舵�佷负 `green_contours_rejected` 涓� `largest_area` 灏忎簬180锛屽彲澧炲姞锛� + +```bash +min_contour_area:=60.0 +``` diff --git a/dev_ws/src/supply_pickup_manager/config/learm_plane_model.yaml b/dev_ws/src/supply_pickup_manager/config/learm_plane_model.yaml new file mode 100644 index 0000000..a49ce1f --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/config/learm_plane_model.yaml @@ -0,0 +1,37 @@ +feature_order: +- '1' +- x +- y +- x2 +- xy +- y2 +weights: +- - 511.28515454089643 + - 821.2615901131778 + - 265.21874233385535 + - 398.5549181928104 +- - -771.8329814607213 + - 52.76710377195036 + - 237.64443893556836 + - -114.8132656337159 +- - 362.52663422740244 + - -580.4727764870705 + - -26.751203474622418 + - -1877.4142059960259 +- - 680.0875101829623 + - 7153.497267194028 + - 5925.331927860114 + - 1758.558407685675 +- - -4993.565252238856 + - 4809.674284044076 + - 17834.265848385203 + - -12695.665144123212 +- - 5570.783049089005 + - 3393.015647299803 + - 30196.06155860567 + - -33269.65533447665 +cmd_dim: 4 +sample_count: 9 +mae_per_dim: [17.308270436659697, 9.353204865258602, 23.274954237277775, 26.493102071291403] +rmse_per_dim: [20.835859382625955, 12.3444244473184, 28.89964968573881, 35.21007477027654] +z_ref_median: 0.34400000000000003 diff --git a/dev_ws/src/supply_pickup_manager/config/learm_stage2.yaml b/dev_ws/src/supply_pickup_manager/config/learm_stage2.yaml new file mode 100644 index 0000000..7c9cde4 --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/config/learm_stage2.yaml @@ -0,0 +1,39 @@ +learm_stage2_controller: + ros__parameters: + simulation: true + port: "/dev/ttyUSB1" + baud_rate: 9600 + serial_timeout_sec: 0.10 + startup_wait_sec: 3.0 + require_readback: true + + # Real serial motion is blocked unless this is explicitly enabled. + hardware_motion_enabled: false + # Real pickup is additionally blocked until all poses below are measured. + poses_calibrated: false + model_path: "" + target_timeout_sec: 1.0 + + command_topic: "/learm_stage2/command" + status_topic: "/learm_stage2/status" + target_topic: "/raw_material/point3d" + + pan_servo_id: 6 + simulation_pan_pulse: 500 + servo_min_pulse: 125 + servo_max_pulse: 875 + scan_move_time_ms: 650 + arm_move_time_ms: 900 + motion_settle_sec: 0.35 + max_jog_delta_pulse: 40 + + claw_servo_id: 1 + claw_open_pulse: 250 + claw_close_pulse: 620 + pose_servo_ids: [6, 5, 4, 3] + + # PLACEHOLDERS: replace with LeArm readback values from the real robot. + home_pulses: [500, 500, 500, 500] + left_platform_pulses: [500, 500, 500, 500] + grasp_offsets: [0, 0, 0, 0] + lift_offsets: [0, 0, 0, 0] diff --git a/dev_ws/src/supply_pickup_manager/config/supply_pickup_manager.yaml b/dev_ws/src/supply_pickup_manager/config/supply_pickup_manager.yaml new file mode 100644 index 0000000..7d68d0d --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/config/supply_pickup_manager.yaml @@ -0,0 +1,46 @@ +supply_pickup_manager: + ros__parameters: + auto_start_on_supply_arrival: true + fallback_team: "red" + enable_pick_after_center: false + + # Relative to the servo-6 pulse read from LeArm at startup. + scan_offsets: [0, -60, 60, -100, 100] + max_scan_offset: 120 + servo_min_pulse: 125 + servo_max_pulse: 875 + scan_dwell_sec: 1.50 + search_timeout_sec: 35.0 + mission_timeout_sec: 70.0 + + horizontal_tolerance: 0.055 + pan_pixel_kp: 75.0 + # If image error grows during centring, change this value to -1.0. + pan_direction_sign: 1.0 + max_center_step_pulse: 35 + max_center_attempts: 8 + target_timeout_sec: 0.50 + arm_timeout_sec: 35.0 + + supply_status_topic: "/supply_nav/status" + raw_point_topic: "/raw_material/point" + raw_visible_topic: "/raw_material/visible" + raw_stable_topic: "/raw_material/stable" + arm_status_topic: "/learm_stage2/status" + arm_command_topic: "/learm_stage2/command" + manual_start_topic: "/supply_pickup/start" + stop_topic: "/supply_pickup/stop" + status_topic: "/supply_pickup/status" + cmd_vel_topic: "/cmd_vel" + imu_topic: "/imu" + ultrasonic_topic: "/ultrasonic/front/range" + turn_speed_radps: 0.45 + turn_angle_deg: 90.0 + turn_tolerance_deg: 3.0 + turn_timeout_sec: 12.0 + max_forward_speed_mps: 0.2 + forward_stop_distance_m: 0.10 + forward_timeout_sec: 20.0 + range_timeout_sec: 0.5 + ultrasonic_forward_offset_m: 0.18 + grasp_skip_hold_sec: 0.5 diff --git a/dev_ws/src/supply_pickup_manager/launch/__pycache__/stage2_supply_pickup.launch.cpython-313.pyc b/dev_ws/src/supply_pickup_manager/launch/__pycache__/stage2_supply_pickup.launch.cpython-313.pyc new file mode 100644 index 0000000..8d81b05 Binary files /dev/null and b/dev_ws/src/supply_pickup_manager/launch/__pycache__/stage2_supply_pickup.launch.cpython-313.pyc differ diff --git a/dev_ws/src/supply_pickup_manager/launch/stage2_supply_pickup.launch.py b/dev_ws/src/supply_pickup_manager/launch/stage2_supply_pickup.launch.py new file mode 100644 index 0000000..ee795fa --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/launch/stage2_supply_pickup.launch.py @@ -0,0 +1,167 @@ +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.conditions import IfCondition +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node +from launch_ros.parameter_descriptions import ParameterValue + + +def config(package_name, filename): + return os.path.join(get_package_share_directory(package_name), 'config', filename) + + +def generate_launch_description(): + start_gemini2 = LaunchConfiguration('start_gemini2') + arm_port = LaunchConfiguration('arm_port') + arm_baud_rate = LaunchConfiguration('arm_baud_rate') + arm_simulation = LaunchConfiguration('arm_simulation') + hardware_motion_enabled = LaunchConfiguration('hardware_motion_enabled') + poses_calibrated = LaunchConfiguration('poses_calibrated') + auto_start = LaunchConfiguration('auto_start_on_supply_arrival') + enable_pick_after_center = LaunchConfiguration('enable_pick_after_center') + pan_direction_sign = LaunchConfiguration('pan_direction_sign') + max_scan_offset = LaunchConfiguration('max_scan_offset') + green_h_min = LaunchConfiguration('green_h_min') + green_h_max = LaunchConfiguration('green_h_max') + green_s_min = LaunchConfiguration('green_s_min') + green_v_min = LaunchConfiguration('green_v_min') + min_contour_area = LaunchConfiguration('min_contour_area') + max_detection_depth_m = LaunchConfiguration('max_detection_depth_m') + horizontal_tolerance = LaunchConfiguration('horizontal_tolerance') + pan_pixel_kp = LaunchConfiguration('pan_pixel_kp') + max_center_attempts = LaunchConfiguration('max_center_attempts') + scan_dwell_sec = LaunchConfiguration('scan_dwell_sec') + stable_frames = LaunchConfiguration('stable_frames') + max_forward_speed_mps = LaunchConfiguration('max_forward_speed_mps') + forward_stop_distance_m = LaunchConfiguration('forward_stop_distance_m') + grasp_skip_hold_sec = LaunchConfiguration('grasp_skip_hold_sec') + + gemini2_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('origintank_bringup'), + 'launch', + 'orbbec_gemini2.launch.py', + ) + ), + launch_arguments={ + 'camera_name': 'camera', + 'enable_point_cloud': 'false', + 'enable_colored_point_cloud': 'false', + 'depth_registration': 'true', + }.items(), + condition=IfCondition(start_gemini2), + ) + + return LaunchDescription([ + DeclareLaunchArgument('start_gemini2', default_value='true'), + DeclareLaunchArgument('arm_port', default_value='/dev/ttyUSB1'), + DeclareLaunchArgument('arm_baud_rate', default_value='9600'), + DeclareLaunchArgument('arm_simulation', default_value='true'), + DeclareLaunchArgument('hardware_motion_enabled', default_value='false'), + DeclareLaunchArgument('poses_calibrated', default_value='false'), + DeclareLaunchArgument('auto_start_on_supply_arrival', default_value='true'), + DeclareLaunchArgument('enable_pick_after_center', default_value='false'), + DeclareLaunchArgument('pan_direction_sign', default_value='1.0'), + DeclareLaunchArgument('max_scan_offset', default_value='120'), + DeclareLaunchArgument('green_h_min', default_value='35'), + DeclareLaunchArgument('green_h_max', default_value='90'), + DeclareLaunchArgument('green_s_min', default_value='60'), + DeclareLaunchArgument('green_v_min', default_value='40'), + DeclareLaunchArgument('min_contour_area', default_value='180.0'), + DeclareLaunchArgument('max_detection_depth_m', default_value='0.80'), + DeclareLaunchArgument('horizontal_tolerance', default_value='0.055'), + DeclareLaunchArgument('pan_pixel_kp', default_value='75.0'), + DeclareLaunchArgument('max_center_attempts', default_value='8'), + DeclareLaunchArgument('scan_dwell_sec', default_value='1.50'), + DeclareLaunchArgument('stable_frames', default_value='3'), + DeclareLaunchArgument('max_forward_speed_mps', default_value='0.2'), + DeclareLaunchArgument('forward_stop_distance_m', default_value='0.10'), + DeclareLaunchArgument('grasp_skip_hold_sec', default_value='0.5'), + gemini2_launch, + Node( + package='raw_material_detector', + executable='raw_material_detector', + name='raw_material_detector', + output='screen', + parameters=[ + config('raw_material_detector', 'raw_material_detector.yaml'), + { + 'green_h_min': ParameterValue(green_h_min, value_type=int), + 'green_h_max': ParameterValue(green_h_max, value_type=int), + 'green_s_min': ParameterValue(green_s_min, value_type=int), + 'green_v_min': ParameterValue(green_v_min, value_type=int), + 'min_contour_area': ParameterValue( + min_contour_area, value_type=float + ), + 'max_depth_m': ParameterValue( + max_detection_depth_m, value_type=float + ), + 'stable_frames': ParameterValue(stable_frames, value_type=int), + }, + ], + ), + Node( + package='supply_pickup_manager', + executable='learm_stage2_controller', + name='learm_stage2_controller', + output='screen', + parameters=[ + config('supply_pickup_manager', 'learm_stage2.yaml'), + { + 'port': arm_port, + 'baud_rate': ParameterValue(arm_baud_rate, value_type=int), + 'simulation': ParameterValue(arm_simulation, value_type=bool), + 'hardware_motion_enabled': ParameterValue( + hardware_motion_enabled, value_type=bool + ), + 'poses_calibrated': ParameterValue(poses_calibrated, value_type=bool), + 'model_path': config( + 'supply_pickup_manager', 'learm_plane_model.yaml' + ), + }, + ], + ), + Node( + package='supply_pickup_manager', + executable='supply_pickup_manager', + name='supply_pickup_manager', + output='screen', + parameters=[ + config('supply_pickup_manager', 'supply_pickup_manager.yaml'), + { + 'auto_start_on_supply_arrival': ParameterValue( + auto_start, value_type=bool + ), + 'enable_pick_after_center': ParameterValue( + enable_pick_after_center, value_type=bool + ), + 'pan_direction_sign': ParameterValue( + pan_direction_sign, value_type=float + ), + 'max_scan_offset': ParameterValue(max_scan_offset, value_type=int), + 'horizontal_tolerance': ParameterValue( + horizontal_tolerance, value_type=float + ), + 'pan_pixel_kp': ParameterValue(pan_pixel_kp, value_type=float), + 'max_center_attempts': ParameterValue( + max_center_attempts, value_type=int + ), + 'scan_dwell_sec': ParameterValue(scan_dwell_sec, value_type=float), + 'max_forward_speed_mps': ParameterValue( + max_forward_speed_mps, value_type=float + ), + 'forward_stop_distance_m': ParameterValue( + forward_stop_distance_m, value_type=float + ), + 'grasp_skip_hold_sec': ParameterValue( + grasp_skip_hold_sec, value_type=float + ), + }, + ], + ), + ]) diff --git a/dev_ws/src/supply_pickup_manager/launch/supply_pickup_manager.launch.py b/dev_ws/src/supply_pickup_manager/launch/supply_pickup_manager.launch.py new file mode 100644 index 0000000..3d47ee5 --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/launch/supply_pickup_manager.launch.py @@ -0,0 +1,23 @@ +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch_ros.actions import Node + + +def generate_launch_description(): + config = os.path.join( + get_package_share_directory('supply_pickup_manager'), + 'config', + 'supply_pickup_manager.yaml', + ) + return LaunchDescription([ + Node( + package='supply_pickup_manager', + executable='supply_pickup_manager', + name='supply_pickup_manager', + output='screen', + parameters=[config], + ) + ]) + diff --git a/dev_ws/src/supply_pickup_manager/package.xml b/dev_ws/src/supply_pickup_manager/package.xml new file mode 100644 index 0000000..3792277 --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/package.xml @@ -0,0 +1,23 @@ + + + + supply_pickup_manager + 0.1.0 + Stage-two supply-station pickup manager for the logistics challenge. + SK + Apache-2.0 + + rclpy + geometry_msgs + sensor_msgs + std_msgs + raw_material_detector + origintank_bringup + python3-serial + python3-yaml + ros2launch + + + ament_python + + diff --git a/dev_ws/src/supply_pickup_manager/resource/supply_pickup_manager b/dev_ws/src/supply_pickup_manager/resource/supply_pickup_manager new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/resource/supply_pickup_manager @@ -0,0 +1 @@ + diff --git a/dev_ws/src/supply_pickup_manager/setup.cfg b/dev_ws/src/supply_pickup_manager/setup.cfg new file mode 100644 index 0000000..a4d25aa --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/setup.cfg @@ -0,0 +1,5 @@ +[develop] +script_dir=$base/lib/supply_pickup_manager +[install] +install_scripts=$base/lib/supply_pickup_manager + diff --git a/dev_ws/src/supply_pickup_manager/setup.py b/dev_ws/src/supply_pickup_manager/setup.py new file mode 100644 index 0000000..a536a81 --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/setup.py @@ -0,0 +1,36 @@ +from setuptools import setup + + +package_name = 'supply_pickup_manager' + + +setup( + name=package_name, + version='0.1.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', [ + 'launch/supply_pickup_manager.launch.py', + 'launch/stage2_supply_pickup.launch.py', + ]), + ('share/' + package_name + '/config', [ + 'config/supply_pickup_manager.yaml', + 'config/learm_stage2.yaml', + 'config/learm_plane_model.yaml', + ]), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='SK', + maintainer_email='sk@example.com', + description='LeArm-mounted Gemini 2 scan, pickup and left-platform placement.', + license='Apache-2.0', + entry_points={ + 'console_scripts': [ + 'supply_pickup_manager = supply_pickup_manager.supply_pickup_manager_node:main', + 'learm_stage2_controller = supply_pickup_manager.learm_stage2_controller_node:main', + ], + }, +) diff --git a/dev_ws/src/supply_pickup_manager/supply_pickup_manager/__init__.py b/dev_ws/src/supply_pickup_manager/supply_pickup_manager/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/supply_pickup_manager/__init__.py @@ -0,0 +1 @@ + diff --git a/dev_ws/src/supply_pickup_manager/supply_pickup_manager/__pycache__/supply_pickup_manager_node.cpython-313.pyc b/dev_ws/src/supply_pickup_manager/supply_pickup_manager/__pycache__/supply_pickup_manager_node.cpython-313.pyc new file mode 100644 index 0000000..0a4fba0 Binary files /dev/null and b/dev_ws/src/supply_pickup_manager/supply_pickup_manager/__pycache__/supply_pickup_manager_node.cpython-313.pyc differ diff --git a/dev_ws/src/supply_pickup_manager/supply_pickup_manager/learm_stage2_controller_node.py b/dev_ws/src/supply_pickup_manager/supply_pickup_manager/learm_stage2_controller_node.py new file mode 100644 index 0000000..4851989 --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/supply_pickup_manager/learm_stage2_controller_node.py @@ -0,0 +1,398 @@ +import math +import queue +import re +import threading +import time +from pathlib import Path +from typing import Dict, List, Optional, Tuple + +import rclpy +import yaml +from geometry_msgs.msg import PointStamped +from rclpy.node import Node +from std_msgs.msg import String + +try: + import serial # type: ignore +except Exception: # pragma: no cover + serial = None + + +HEADER = 0x55 +CMD_MULT_SERVO_MOVE = 0x03 +CMD_SERVO_READ = 0x0D + + +class LeArmStage2Controller(Node): + """LeArm CMD=3 controller used only by the stage-two pickup flow.""" + + def __init__(self) -> None: + super().__init__('learm_stage2_controller') + self._declare_parameters() + self._load_parameters() + + self.status_pub = self.create_publisher(String, self.status_topic, 10) + self.create_subscription(String, self.command_topic, self.on_command, 10) + self.create_subscription(PointStamped, self.target_topic, self.on_target, 10) + + self.latest_target: Optional[PointStamped] = None + self.latest_target_time = None + self.ser = None + self.servo_positions: Dict[int, int] = {} + self.command_queue: 'queue.Queue[str]' = queue.Queue() + self.busy = False + + if self.simulation: + self.servo_positions = { + servo_id: pulse for servo_id, pulse in zip(self.pose_servo_ids, self.home_pulses) + } + else: + self._open_serial() + positions = self._read_servo_positions() + if not positions and self.require_readback: + raise RuntimeError( + 'LeArm servo readback failed; refuse motion. Check port, 9600 baud and wiring.' + ) + self.servo_positions.update(positions) + + self.pan_pulse = int(self.servo_positions.get(self.pan_servo_id, self.simulation_pan_pulse)) + self.servo_positions[self.pan_servo_id] = self.pan_pulse + self.worker = threading.Thread(target=self._worker_loop, daemon=True) + self.worker.start() + self.heartbeat = self.create_timer(1.0, self.publish_idle_heartbeat) + self.publish_status( + f'ready:servo6={self.pan_pulse};positions={self._positions_text()}' + ) + + def _declare_parameters(self) -> None: + defaults = { + 'simulation': True, + 'port': '/dev/ttyUSB1', + 'baud_rate': 9600, + 'serial_timeout_sec': 0.10, + 'startup_wait_sec': 3.0, + 'require_readback': True, + 'hardware_motion_enabled': False, + 'poses_calibrated': False, + 'model_path': '', + 'target_timeout_sec': 1.0, + 'command_topic': '/learm_stage2/command', + 'status_topic': '/learm_stage2/status', + 'target_topic': '/raw_material/point3d', + 'pan_servo_id': 6, + 'simulation_pan_pulse': 500, + 'servo_min_pulse': 125, + 'servo_max_pulse': 875, + 'scan_move_time_ms': 650, + 'arm_move_time_ms': 900, + 'motion_settle_sec': 0.35, + 'max_jog_delta_pulse': 40, + 'claw_servo_id': 1, + 'claw_open_pulse': 250, + 'claw_close_pulse': 620, + 'pose_servo_ids': [6, 5, 4, 3], + # These three poses/offsets MUST be calibrated before real pickup. + 'home_pulses': [500, 500, 500, 500], + 'left_platform_pulses': [500, 500, 500, 500], + 'grasp_offsets': [0, 0, 0, 0], + 'lift_offsets': [0, 0, 0, 0], + } + for name, value in defaults.items(): + self.declare_parameter(name, value) + + def _load_parameters(self) -> None: + get = self.get_parameter + self.simulation = bool(get('simulation').value) + self.port = str(get('port').value) + self.baud_rate = int(get('baud_rate').value) + self.serial_timeout_sec = float(get('serial_timeout_sec').value) + self.startup_wait_sec = abs(float(get('startup_wait_sec').value)) + self.require_readback = bool(get('require_readback').value) + self.hardware_motion_enabled = bool(get('hardware_motion_enabled').value) + self.poses_calibrated = bool(get('poses_calibrated').value) + self.model_path = str(get('model_path').value) + self.target_timeout_sec = abs(float(get('target_timeout_sec').value)) + self.command_topic = str(get('command_topic').value) + self.status_topic = str(get('status_topic').value) + self.target_topic = str(get('target_topic').value) + self.pan_servo_id = int(get('pan_servo_id').value) + self.simulation_pan_pulse = int(get('simulation_pan_pulse').value) + self.servo_min_pulse = int(get('servo_min_pulse').value) + self.servo_max_pulse = int(get('servo_max_pulse').value) + self.scan_move_time_ms = int(get('scan_move_time_ms').value) + self.arm_move_time_ms = int(get('arm_move_time_ms').value) + self.motion_settle_sec = abs(float(get('motion_settle_sec').value)) + self.max_jog_delta_pulse = abs(int(get('max_jog_delta_pulse').value)) + self.claw_servo_id = int(get('claw_servo_id').value) + self.claw_open_pulse = int(get('claw_open_pulse').value) + self.claw_close_pulse = int(get('claw_close_pulse').value) + self.pose_servo_ids = [int(v) for v in get('pose_servo_ids').value] + self.home_pulses = [int(v) for v in get('home_pulses').value] + self.left_platform_pulses = [int(v) for v in get('left_platform_pulses').value] + self.grasp_offsets = [int(v) for v in get('grasp_offsets').value] + self.lift_offsets = [int(v) for v in get('lift_offsets').value] + for name, values in { + 'home_pulses': self.home_pulses, + 'left_platform_pulses': self.left_platform_pulses, + 'grasp_offsets': self.grasp_offsets, + 'lift_offsets': self.lift_offsets, + }.items(): + if len(values) != len(self.pose_servo_ids): + raise ValueError(f'{name} length must match pose_servo_ids') + self.model = self._load_model(self.model_path) + + @staticmethod + def _load_model(path_text: str) -> dict: + path = Path(path_text) + if not path_text or not path.is_file(): + raise ValueError(f'LeArm model file does not exist: {path_text!r}') + with path.open('r', encoding='utf-8') as stream: + model = yaml.safe_load(stream) + if int(model.get('cmd_dim', 0)) != 4 or len(model.get('weights', [])) != 6: + raise ValueError('LeArm model must contain six feature rows and cmd_dim=4') + return model + + def _open_serial(self) -> None: + if serial is None: + raise RuntimeError('pyserial is unavailable') + self.ser = serial.Serial() + self.ser.port = self.port + self.ser.baudrate = self.baud_rate + self.ser.bytesize = serial.EIGHTBITS + self.ser.parity = serial.PARITY_NONE + self.ser.stopbits = serial.STOPBITS_ONE + self.ser.timeout = self.serial_timeout_sec + self.ser.xonxoff = False + self.ser.rtscts = False + self.ser.dsrdtr = False + self.ser.dtr = False + self.ser.rts = False + self.ser.open() + time.sleep(self.startup_wait_sec) + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + self.get_logger().info(f'LeArm opened: {self.port} @ {self.baud_rate}') + + @staticmethod + def _packet(command: int, payload: bytes = b'') -> bytes: + # LeArm length is CMD + payload + one protocol byte, matching learm_test.py. + return bytes([HEADER, HEADER, 2 + len(payload), command]) + payload + + def _write_packet(self, packet: bytes) -> None: + if self.simulation: + self.get_logger().info(f'[SIM] TX {packet.hex(" ")}') + return + assert self.ser is not None + self.ser.write(packet) + self.ser.flush() + + def _read_servo_positions(self) -> Dict[int, int]: + if self.simulation: + return dict(self.servo_positions) + assert self.ser is not None + self.ser.reset_input_buffer() + self._write_packet(self._packet(CMD_SERVO_READ)) + deadline = time.time() + 1.0 + buffer = bytearray() + while time.time() < deadline: + waiting = self.ser.in_waiting + if waiting: + buffer.extend(self.ser.read(waiting)) + time.sleep(0.01) + self.get_logger().info(f'LeArm readback RX: {bytes(buffer).hex(" ")}') + return self._parse_servo_readback(bytes(buffer)) + + @staticmethod + def _parse_servo_readback(buffer: bytes) -> Dict[int, int]: + result: Dict[int, int] = {} + index = 0 + while index <= len(buffer) - 4: + if buffer[index:index + 2] != bytes([HEADER, HEADER]): + index += 1 + continue + frame_length = 2 + int(buffer[index + 2]) + frame = buffer[index:index + frame_length] + if len(frame) < frame_length: + break + if len(frame) >= 7 and frame[3] == CMD_SERVO_READ: + payload = frame[4:] + for offset in range(0, len(payload) - 2, 3): + servo_id = int(payload[offset]) + pulse = int(payload[offset + 1]) | (int(payload[offset + 2]) << 8) + result[servo_id] = pulse + index += frame_length + return result + + def _clamp_pulse(self, pulse: int) -> int: + return max(self.servo_min_pulse, min(self.servo_max_pulse, int(pulse))) + + def move_servos(self, pairs: List[Tuple[int, int]], move_time_ms: int) -> None: + if not self.simulation and not self.hardware_motion_enabled: + raise RuntimeError('hardware_motion_enabled is false') + payload = bytearray([len(pairs), move_time_ms & 0xFF, (move_time_ms >> 8) & 0xFF]) + safe_pairs = [] + for servo_id, pulse in pairs: + if servo_id == self.claw_servo_id: + safe_pulse = max(200, min(700, int(pulse))) + else: + safe_pulse = self._clamp_pulse(pulse) + safe_pairs.append((int(servo_id), safe_pulse)) + payload.extend([int(servo_id) & 0xFF, safe_pulse & 0xFF, (safe_pulse >> 8) & 0xFF]) + self._write_packet(self._packet(CMD_MULT_SERVO_MOVE, bytes(payload))) + for servo_id, pulse in safe_pairs: + self.servo_positions[servo_id] = pulse + self.pan_pulse = self.servo_positions.get(self.pan_servo_id, self.pan_pulse) + time.sleep(max(move_time_ms / 1000.0, self.motion_settle_sec)) + + def on_target(self, msg: PointStamped) -> None: + self.latest_target = msg + self.latest_target_time = self.get_clock().now() + + def on_command(self, msg: String) -> None: + command = msg.data.strip().lower() + if command: + self.command_queue.put(command) + + def target_is_fresh(self) -> bool: + if self.latest_target is None or self.latest_target_time is None: + return False + age = (self.get_clock().now() - self.latest_target_time).nanoseconds / 1e9 + return age <= self.target_timeout_sec + + def publish_status(self, text: str) -> None: + msg = String() + msg.data = text + self.status_pub.publish(msg) + self.get_logger().info(text) + + def _positions_text(self) -> str: + if not self.servo_positions: + return 'unavailable' + return ','.join( + f'{servo_id}={pulse}' + for servo_id, pulse in sorted(self.servo_positions.items()) + ) + + def publish_idle_heartbeat(self) -> None: + if not self.busy: + self.publish_status( + f'idle:servo6={self.pan_pulse};positions={self._positions_text()}' + ) + + def _worker_loop(self) -> None: + while rclpy.ok(): + command = self.command_queue.get() + self.busy = True + self.publish_status(f'busy:{command}') + try: + result = self._execute_command(command) + self.publish_status(result) + except Exception as exc: # pragma: no cover - hardware dependent + self.get_logger().error(f'LeArm command failed: {command}: {exc}') + self.publish_status(f'error:{command}:{exc}') + finally: + self.busy = False + + def _execute_command(self, command: str) -> str: + match = re.fullmatch(r'scan_pose:(-?\d+)', command) + if match: + pulse = self._clamp_pulse(int(match.group(1))) + self.move_servos([(self.pan_servo_id, pulse)], self.scan_move_time_ms) + return f'scan_done:servo6={pulse}' + if command == 'read_positions': + positions = self._read_servo_positions() + self.servo_positions.update(positions) + self.pan_pulse = self.servo_positions.get(self.pan_servo_id, self.pan_pulse) + return f'positions:{self._positions_text()}' + if command == 'preview_target': + if not self.target_is_fresh(): + raise RuntimeError('no fresh /raw_material/point3d') + assert self.latest_target is not None + predicted = self._predict_pose(self.latest_target) + encoded = ','.join( + f'{servo_id}={pulse}' + for servo_id, pulse in zip(self.pose_servo_ids, predicted) + ) + point = self.latest_target.point + return ( + f'prediction:{encoded};' + f'target_xyz={point.x:.4f},{point.y:.4f},{point.z:.4f}' + ) + match = re.fullmatch(r'jog:([1-6]):([+-]?\d+)', command) + if match: + servo_id = int(match.group(1)) + requested_delta = int(match.group(2)) + delta = int(max(-self.max_jog_delta_pulse, min(self.max_jog_delta_pulse, requested_delta))) + if servo_id not in self.servo_positions: + raise RuntimeError(f'no readback position for servo {servo_id}') + pulse = self.servo_positions[servo_id] + delta + self.move_servos([(servo_id, pulse)], self.scan_move_time_ms) + return f'jog_done:id={servo_id},pulse={self.servo_positions[servo_id]}' + if command == 'home': + self._move_pose(self.home_pulses) + return 'done:home' + if command == 'pick_and_place_left': + self.pick_and_place_left() + return 'done:pick_and_place_left' + raise ValueError(f'unsupported command {command!r}') + + def _predict_pose(self, point: PointStamped) -> List[int]: + x_value = float(point.point.x) + y_value = float(point.point.y) + features = [1.0, x_value, y_value, x_value * x_value, x_value * y_value, y_value * y_value] + weights = self.model['weights'] + output = [] + for column in range(4): + value = sum(features[row] * float(weights[row][column]) for row in range(6)) + output.append(self._clamp_pulse(int(round(value)))) + # Servo 6 has already centred the camera on the block. Preserve it. + output[0] = self.pan_pulse + return output + + def _move_pose(self, pulses: List[int]) -> None: + self.move_servos(list(zip(self.pose_servo_ids, pulses)), self.arm_move_time_ms) + + def pick_and_place_left(self) -> None: + if not self.target_is_fresh(): + raise RuntimeError('no fresh /raw_material/point3d') + if not self.simulation and not self.poses_calibrated: + raise RuntimeError('poses_calibrated is false; calibrate home/left/grasp/lift first') + assert self.latest_target is not None + predicted = self._predict_pose(self.latest_target) + grasp = [self._clamp_pulse(a + b) for a, b in zip(predicted, self.grasp_offsets)] + lift = [self._clamp_pulse(a + b) for a, b in zip(grasp, self.lift_offsets)] + self.get_logger().info( + f'predicted={predicted}, grasp={grasp}, lift={lift}, left={self.left_platform_pulses}' + ) + self.move_servos([(self.claw_servo_id, self.claw_open_pulse)], self.arm_move_time_ms) + self._move_pose(predicted) + self._move_pose(grasp) + self.move_servos([(self.claw_servo_id, self.claw_close_pulse)], self.arm_move_time_ms) + self._move_pose(lift) + self._move_pose(self.left_platform_pulses) + self.move_servos([(self.claw_servo_id, self.claw_open_pulse)], self.arm_move_time_ms) + self._move_pose(self.home_pulses) + + def destroy_node(self): + if self.ser is not None: + try: + self.ser.close() + except Exception: + pass + return super().destroy_node() + + +def main() -> None: + rclpy.init() + node = LeArmStage2Controller() + try: + rclpy.spin(node) + except KeyboardInterrupt: + pass + finally: + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/dev_ws/src/supply_pickup_manager/supply_pickup_manager/supply_pickup_manager_node.py b/dev_ws/src/supply_pickup_manager/supply_pickup_manager/supply_pickup_manager_node.py new file mode 100644 index 0000000..cb87e05 --- /dev/null +++ b/dev_ws/src/supply_pickup_manager/supply_pickup_manager/supply_pickup_manager_node.py @@ -0,0 +1,538 @@ +import math +import re +from enum import Enum +from typing import Optional + +import rclpy +from geometry_msgs.msg import PointStamped, Twist +from rclpy.node import Node +from sensor_msgs.msg import Imu, Range +from std_msgs.msg import Bool, String + + +class PickupState(str, Enum): + WAIT_SUPPLY_ARRIVAL = 'WAIT_SUPPLY_ARRIVAL' + STAGE2_GRASP_COMPLETE = 'STAGE2_GRASP_COMPLETE' + STAGE3_TURN_RIGHT_90 = 'STAGE3_TURN_RIGHT_90' + STAGE3_MOVE_FORWARD = 'STAGE3_MOVE_FORWARD' + SEARCH_RAW = 'SEARCH_RAW' + CENTER_RAW = 'CENTER_RAW' + WAIT_ARM = 'WAIT_ARM' + COMPLETE = 'COMPLETE' + FAILED = 'FAILED' + + +def clamp(value: float, low: float, high: float) -> float: + return max(low, min(high, value)) + + +class SupplyPickupManager(Node): + """Run the temporary stage-two turn-and-forward motion test.""" + + def __init__(self) -> None: + super().__init__('supply_pickup_manager') + self._declare_parameters() + self._load_parameters() + + self.arm_cmd_pub = self.create_publisher(String, self.arm_command_topic, 10) + self.cmd_vel_pub = self.create_publisher(Twist, self.cmd_vel_topic, 10) + self.status_pub = self.create_publisher(String, self.status_topic, 10) + self.create_subscription(String, self.supply_status_topic, self.on_supply_status, 10) + self.create_subscription(Imu, self.imu_topic, self.on_imu, 20) + self.create_subscription(Range, self.ultrasonic_topic, self.on_range, 20) + self.create_subscription(PointStamped, self.raw_point_topic, self.on_raw_point, 10) + self.create_subscription(Bool, self.raw_visible_topic, self.on_raw_visible, 10) + self.create_subscription(Bool, self.raw_stable_topic, self.on_raw_stable, 10) + self.create_subscription(String, self.arm_status_topic, self.on_arm_status, 20) + self.create_subscription(Bool, self.manual_start_topic, self.on_manual_start, 10) + self.create_subscription(Bool, self.stop_topic, self.on_stop, 10) + self.timer = self.create_timer(0.05, self.on_timer) + + self.state = PickupState.WAIT_SUPPLY_ARRIVAL + self.selected_team = self.fallback_team + self.raw_point: Optional[PointStamped] = None + self.raw_point_time = None + self.raw_visible = False + self.raw_stable = False + self.arm_ready = False + self.arm_command_active = False + self.pan_center_pulse: Optional[int] = None + self.current_pan_pulse: Optional[int] = None + self.scan_index = 0 + self.scan_settle_start = None + self.center_attempts = 0 + self.previous_horizontal_error: Optional[float] = None + self.pending_start_reason: Optional[str] = None + self.mission_start_time = None + self.current_yaw: Optional[float] = None + self.turn_start_yaw: Optional[float] = None + self.current_range_m: Optional[float] = None + self.last_range_time = None + self.range_sensor_offset_m = 0.18 + self.state_enter_time = self.get_clock().now() + self.last_status_time = None + self.last_status_detail = 'initialising' + self.publish_status('waiting for supply navigation ARRIVED') + + def _declare_parameters(self) -> None: + defaults = { + 'auto_start_on_supply_arrival': True, + 'fallback_team': 'red', + 'enable_pick_after_center': False, + 'scan_offsets': [0, -60, 60, -100, 100], + 'max_scan_offset': 120, + 'servo_min_pulse': 125, + 'servo_max_pulse': 875, + 'scan_dwell_sec': 0.75, + 'search_timeout_sec': 35.0, + 'mission_timeout_sec': 70.0, + 'horizontal_tolerance': 0.055, + 'pan_pixel_kp': 75.0, + 'pan_direction_sign': 1.0, + 'max_center_step_pulse': 35, + 'max_center_attempts': 8, + 'target_timeout_sec': 0.50, + 'arm_timeout_sec': 35.0, + 'supply_status_topic': '/supply_nav/status', + 'raw_point_topic': '/raw_material/point', + 'raw_visible_topic': '/raw_material/visible', + 'raw_stable_topic': '/raw_material/stable', + 'arm_status_topic': '/learm_stage2/status', + 'arm_command_topic': '/learm_stage2/command', + 'manual_start_topic': '/supply_pickup/start', + 'stop_topic': '/supply_pickup/stop', + 'status_topic': '/supply_pickup/status', + 'cmd_vel_topic': '/cmd_vel', + 'imu_topic': '/imu', + 'ultrasonic_topic': '/ultrasonic/front/range', + 'turn_speed_radps': 0.45, + 'turn_angle_deg': 90.0, + 'turn_tolerance_deg': 3.0, + 'turn_timeout_sec': 12.0, + 'max_forward_speed_mps': 0.2, + 'forward_stop_distance_m': 0.10, + 'forward_timeout_sec': 20.0, + 'range_timeout_sec': 0.5, + 'ultrasonic_forward_offset_m': 0.18, + 'grasp_skip_hold_sec': 0.5, + } + for name, value in defaults.items(): + self.declare_parameter(name, value) + + def _load_parameters(self) -> None: + get = self.get_parameter + self.auto_start_on_supply_arrival = bool(get('auto_start_on_supply_arrival').value) + self.fallback_team = str(get('fallback_team').value).strip().lower() + self.enable_pick_after_center = bool(get('enable_pick_after_center').value) + if self.fallback_team not in {'red', 'blue'}: + raise ValueError('fallback_team must be red or blue') + self.scan_offsets = [int(value) for value in get('scan_offsets').value] + if not self.scan_offsets: + raise ValueError('scan_offsets cannot be empty') + self.max_scan_offset = abs(int(get('max_scan_offset').value)) + self.servo_min_pulse = int(get('servo_min_pulse').value) + self.servo_max_pulse = int(get('servo_max_pulse').value) + self.scan_dwell_sec = abs(float(get('scan_dwell_sec').value)) + self.search_timeout_sec = abs(float(get('search_timeout_sec').value)) + self.mission_timeout_sec = abs(float(get('mission_timeout_sec').value)) + self.horizontal_tolerance = abs(float(get('horizontal_tolerance').value)) + self.pan_pixel_kp = abs(float(get('pan_pixel_kp').value)) + self.pan_direction_sign = 1.0 if float(get('pan_direction_sign').value) >= 0.0 else -1.0 + self.max_center_step_pulse = abs(int(get('max_center_step_pulse').value)) + self.max_center_attempts = max(1, int(get('max_center_attempts').value)) + self.target_timeout_sec = abs(float(get('target_timeout_sec').value)) + self.arm_timeout_sec = abs(float(get('arm_timeout_sec').value)) + self.supply_status_topic = str(get('supply_status_topic').value) + self.raw_point_topic = str(get('raw_point_topic').value) + self.raw_visible_topic = str(get('raw_visible_topic').value) + self.raw_stable_topic = str(get('raw_stable_topic').value) + self.arm_status_topic = str(get('arm_status_topic').value) + self.arm_command_topic = str(get('arm_command_topic').value) + self.manual_start_topic = str(get('manual_start_topic').value) + self.stop_topic = str(get('stop_topic').value) + self.status_topic = str(get('status_topic').value) + self.cmd_vel_topic = str(get('cmd_vel_topic').value) + self.imu_topic = str(get('imu_topic').value) + self.ultrasonic_topic = str(get('ultrasonic_topic').value) + self.turn_speed_radps = abs(float(get('turn_speed_radps').value)) + self.turn_angle_rad = math.radians(abs(float(get('turn_angle_deg').value))) + self.turn_tolerance_rad = math.radians(abs(float(get('turn_tolerance_deg').value))) + self.turn_timeout_sec = abs(float(get('turn_timeout_sec').value)) + self.max_forward_speed_mps = abs(float(get('max_forward_speed_mps').value)) + self.forward_stop_distance_m = abs(float(get('forward_stop_distance_m').value)) + self.forward_timeout_sec = abs(float(get('forward_timeout_sec').value)) + self.range_timeout_sec = abs(float(get('range_timeout_sec').value)) + self.ultrasonic_forward_offset_m = float(get('ultrasonic_forward_offset_m').value) + self.grasp_skip_hold_sec = abs(float(get('grasp_skip_hold_sec').value)) + + def now_seconds_in_state(self) -> float: + return (self.get_clock().now() - self.state_enter_time).nanoseconds / 1e9 + + def transition(self, state: PickupState, detail: str) -> None: + self.state = state + self.state_enter_time = self.get_clock().now() + self.publish_status(detail) + + def publish_status(self, detail: str) -> None: + self.last_status_detail = detail + msg = String() + msg.data = f'{self.state.value}:{detail}' + self.status_pub.publish(msg) + self.get_logger().info(msg.data) + self.last_status_time = self.get_clock().now() + + def status_due(self) -> bool: + return self.last_status_time is None or ( + self.get_clock().now() - self.last_status_time + ).nanoseconds >= 2_000_000_000 + + def on_supply_status(self, msg: String) -> None: + if not msg.data.startswith('ARRIVED:'): + return + match = re.search(r'team=(red|blue)', msg.data.lower()) + if match: + self.selected_team = match.group(1) + if self.auto_start_on_supply_arrival and self.state == PickupState.WAIT_SUPPLY_ARRIVAL: + self.request_start('supply navigation reported ARRIVED') + + def on_imu(self, msg: Imu) -> None: + q = msg.orientation + siny_cosp = 2.0 * (q.w * q.z + q.x * q.y) + cosy_cosp = 1.0 - 2.0 * (q.y * q.y + q.z * q.z) + self.current_yaw = math.atan2(siny_cosp, cosy_cosp) + + def on_range(self, msg: Range) -> None: + if not math.isfinite(msg.range): + return + self.current_range_m = float(msg.range) + self.last_range_time = self.get_clock().now() + + def on_manual_start(self, msg: Bool) -> None: + if msg.data and self.state in { + PickupState.WAIT_SUPPLY_ARRIVAL, + PickupState.COMPLETE, + PickupState.FAILED, + }: + self.request_start('manual stage-two start') + + def request_start(self, reason: str) -> None: + self.begin_turn(reason) + + def begin_turn(self, reason: str) -> None: + self.pending_start_reason = None + self.mission_start_time = self.get_clock().now() + self.turn_start_yaw = None + self.transition( + PickupState.STAGE2_GRASP_COMPLETE, + f'{reason}; grasp considered complete, physical pickup skipped', + ) + + def begin_pickup(self, reason: str) -> None: + self.pending_start_reason = None + self.raw_point = None + self.raw_point_time = None + self.raw_visible = False + self.raw_stable = False + self.scan_index = 0 + self.center_attempts = 0 + self.previous_horizontal_error = None + self.mission_start_time = self.get_clock().now() + self.transition(PickupState.SEARCH_RAW, reason) + self.send_next_scan_pose() + + def on_stop(self, msg: Bool) -> None: + if not msg.data: + return + self.pending_start_reason = None + self.arm_command_active = False + self.mission_start_time = None + self.stop_robot() + self.transition(PickupState.WAIT_SUPPLY_ARRIVAL, 'software reset requested') + + def stop_robot(self) -> None: + self.cmd_vel_pub.publish(Twist()) + + @staticmethod + def angle_wrap(angle: float) -> float: + while angle > math.pi: + angle -= 2.0 * math.pi + while angle < -math.pi: + angle += 2.0 * math.pi + return angle + + def on_raw_point(self, msg: PointStamped) -> None: + self.raw_point = msg + self.raw_point_time = self.get_clock().now() + + def on_raw_visible(self, msg: Bool) -> None: + self.raw_visible = bool(msg.data) + + def on_raw_stable(self, msg: Bool) -> None: + self.raw_stable = bool(msg.data) + + def _parse_servo6(self, text: str) -> Optional[int]: + match = re.search(r'servo6=(-?\d+)', text) + return int(match.group(1)) if match else None + + def on_arm_status(self, msg: String) -> None: + status = msg.data.strip().lower() + pulse = self._parse_servo6(status) + if status.startswith(('ready:', 'idle:')) and pulse is not None: + self.arm_ready = True + self.current_pan_pulse = pulse + if self.pan_center_pulse is None: + self.pan_center_pulse = pulse + self.get_logger().info(f'LeArm scan centre captured from readback: {pulse}') + if self.pending_start_reason is not None: + reason = self.pending_start_reason + self.begin_pickup(reason) + return + if status.startswith('busy:'): + self.arm_command_active = True + return + if status.startswith('scan_done:') and pulse is not None: + self.current_pan_pulse = pulse + self.arm_command_active = False + self.scan_settle_start = self.get_clock().now() + return + if status == 'done:pick_and_place_left': + self.arm_command_active = False + if self.state == PickupState.WAIT_ARM: + self.transition( + PickupState.COMPLETE, + 'green raw material picked and placed on left platform', + ) + return + if status.startswith('error:'): + self.arm_command_active = False + self.fail(f'LeArm reported {status}') + + def target_is_fresh(self) -> bool: + if self.raw_point is None or self.raw_point_time is None: + return False + age = (self.get_clock().now() - self.raw_point_time).nanoseconds / 1e9 + return age <= self.target_timeout_sec + + def stable_target_available(self) -> bool: + return self.raw_visible and self.raw_stable and self.target_is_fresh() + + def send_arm_command(self, command: str) -> None: + msg = String() + msg.data = command + self.arm_cmd_pub.publish(msg) + self.arm_command_active = True + self.scan_settle_start = None + + def safe_scan_pulse(self, requested: int) -> int: + assert self.pan_center_pulse is not None + low = max(self.servo_min_pulse, self.pan_center_pulse - self.max_scan_offset) + high = min(self.servo_max_pulse, self.pan_center_pulse + self.max_scan_offset) + return int(clamp(requested, low, high)) + + def send_scan_pose(self, pulse: int) -> None: + safe_pulse = self.safe_scan_pulse(pulse) + self.send_arm_command(f'scan_pose:{safe_pulse}') + self.publish_status(f'LeArm servo6 scan command={safe_pulse}') + + def send_next_scan_pose(self) -> None: + assert self.pan_center_pulse is not None + offset = self.scan_offsets[self.scan_index % len(self.scan_offsets)] + self.scan_index += 1 + self.send_scan_pose(self.pan_center_pulse + offset) + + def scan_has_settled(self) -> bool: + if self.scan_settle_start is None: + return False + elapsed = (self.get_clock().now() - self.scan_settle_start).nanoseconds / 1e9 + return elapsed >= self.scan_dwell_sec + + def centre_target(self) -> None: + assert self.raw_point is not None and self.current_pan_pulse is not None + horizontal_error = float(self.raw_point.point.y) + if abs(horizontal_error) <= self.horizontal_tolerance and self.raw_stable: + if not self.enable_pick_after_center: + self.transition( + PickupState.COMPLETE, + 'scan test complete: target centred; pickup is disabled', + ) + return + self.send_arm_command('pick_and_place_left') + self.transition(PickupState.WAIT_ARM, 'target centred; LeArm pickup command sent') + return + + if self.center_attempts >= self.max_center_attempts: + self.fail('servo6 target centring exceeded maximum attempts') + return + if ( + self.previous_horizontal_error is not None + and abs(horizontal_error) > abs(self.previous_horizontal_error) * 1.35 + and self.center_attempts >= 2 + ): + self.fail('servo6 centring diverged; reverse pan_direction_sign') + return + + correction = self.pan_direction_sign * self.pan_pixel_kp * horizontal_error + correction = clamp( + correction, + -float(self.max_center_step_pulse), + float(self.max_center_step_pulse), + ) + if abs(correction) < 2.0: + correction = 2.0 if correction >= 0.0 else -2.0 + requested = self.current_pan_pulse + int(round(correction)) + safe_requested = self.safe_scan_pulse(requested) + if safe_requested == self.current_pan_pulse and requested != self.current_pan_pulse: + self.fail( + f'target remains off-centre at servo6 scan boundary: ' + f'error={horizontal_error:.4f}, current={self.current_pan_pulse}, ' + f'requested={requested}; increase max_scan_offset only if cabling is safe' + ) + return + self.previous_horizontal_error = horizontal_error + self.center_attempts += 1 + self.send_arm_command(f'scan_pose:{safe_requested}') + self.publish_status( + f'centering attempt={self.center_attempts}/{self.max_center_attempts}, ' + f'error={horizontal_error:.4f}, current={self.current_pan_pulse}, ' + f'correction={correction:.1f}, command={safe_requested}' + ) + + def mission_timed_out(self) -> bool: + if self.mission_start_time is None: + return False + elapsed = (self.get_clock().now() - self.mission_start_time).nanoseconds / 1e9 + return elapsed > self.mission_timeout_sec + + def fail(self, reason: str) -> None: + self.transition(PickupState.FAILED, reason) + + def on_timer(self) -> None: + if self.state == PickupState.WAIT_SUPPLY_ARRIVAL: + if self.status_due(): + self.publish_status('waiting for supply ARRIVED/manual start') + return + if self.state == PickupState.STAGE2_GRASP_COMPLETE: + self.stop_robot() + if self.now_seconds_in_state() >= self.grasp_skip_hold_sec: + self.transition( + PickupState.STAGE3_TURN_RIGHT_90, + 'stage 2 complete; starting stage 3 right turn', + ) + return + if self.state == PickupState.STAGE3_TURN_RIGHT_90: + if self.current_yaw is None: + self.stop_robot() + if self.status_due(): + self.publish_status('waiting for IMU before right turn') + return + if self.turn_start_yaw is None: + self.turn_start_yaw = self.current_yaw + + # ROS uses positive angular.z for left/CCW rotation, so right is negative. + turned_right = -self.angle_wrap(self.current_yaw - self.turn_start_yaw) + if turned_right >= self.turn_angle_rad - self.turn_tolerance_rad: + self.stop_robot() + self.transition( + PickupState.STAGE3_MOVE_FORWARD, + f'right turn complete: {math.degrees(turned_right):.1f} deg; moving forward', + ) + return + if self.now_seconds_in_state() > self.turn_timeout_sec: + self.stop_robot() + self.fail('right turn timeout') + return + + cmd = Twist() + cmd.angular.z = -self.turn_speed_radps + self.cmd_vel_pub.publish(cmd) + return + if self.state == PickupState.STAGE3_MOVE_FORWARD: + if self.current_range_m is None or self.last_range_time is None: + self.stop_robot() + if self.status_due(): + self.publish_status('waiting for ultrasonic range before forward motion') + return + range_age = (self.get_clock().now() - self.last_range_time).nanoseconds / 1e9 + if range_age > self.range_timeout_sec: + self.stop_robot() + self.fail('ultrasonic range timeout during forward motion') + return + if self.current_range_m <= self.forward_stop_distance_m: + self.stop_robot() + self.transition( + PickupState.COMPLETE, + f'stage 3 complete: sensor_range={self.current_range_m:.3f}m, ' + f'base_centre_range={self.current_range_m + self.ultrasonic_forward_offset_m:.3f}m', + ) + return + if self.now_seconds_in_state() > self.forward_timeout_sec: + self.stop_robot() + self.fail('forward motion timeout') + return + cmd = Twist() + cmd.linear.x = self.max_forward_speed_mps + self.cmd_vel_pub.publish(cmd) + if self.status_due(): + self.publish_status( + f'sensor_range={self.current_range_m:.3f}m, ' + f'base_centre_range=' + f'{self.current_range_m + self.ultrasonic_forward_offset_m:.3f}m, ' + f'target_sensor_range={self.forward_stop_distance_m:.3f}m' + ) + return + if self.state in {PickupState.COMPLETE, PickupState.FAILED}: + self.stop_robot() + if self.status_due(): + self.publish_status(self.last_status_detail) + return + if self.mission_timed_out(): + self.fail('stage-two total timeout') + return + + if self.state == PickupState.SEARCH_RAW: + if self.now_seconds_in_state() > self.search_timeout_sec: + self.fail('green raw material search timeout') + return + if self.arm_command_active or not self.scan_has_settled(): + return + if self.stable_target_available(): + self.center_attempts = 0 + self.previous_horizontal_error = None + self.transition(PickupState.CENTER_RAW, 'stable green block found') + self.centre_target() + return + self.send_next_scan_pose() + return + + if self.state == PickupState.CENTER_RAW: + if self.arm_command_active or not self.scan_has_settled(): + return + if not self.stable_target_available(): + self.transition(PickupState.SEARCH_RAW, 'target lost; servo6 scan resumed') + self.send_next_scan_pose() + return + self.centre_target() + return + + if self.state == PickupState.WAIT_ARM: + if self.status_due(): + self.publish_status(self.last_status_detail) + if self.now_seconds_in_state() > self.arm_timeout_sec: + self.fail('LeArm pickup/place timeout') + + +def main() -> None: + rclpy.init() + node = SupplyPickupManager() + try: + rclpy.spin(node) + except KeyboardInterrupt: + pass + finally: + node.stop_robot() + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/dev_ws/src/supply_station_nav/README.md b/dev_ws/src/supply_station_nav/README.md new file mode 100644 index 0000000..0f88797 --- /dev/null +++ b/dev_ws/src/supply_station_nav/README.md @@ -0,0 +1,135 @@ +# 绗竴闃舵锛氫粠璧风偣鐩磋鍒颁腑杞ˉ缁欑珯 + +鏈寘鍙礋璐g涓�闃舵绉诲姩銆傝妭鐐瑰惎鍔ㄥ悗涓嶄細绔嬪嵆鎺у埗灏忚溅锛涘綋閲岀▼璁°�両MU 鍜� +鍓嶅悜瓒呭0娉㈤兘姝e父鍚庯紝鎵嬪姩鍙戦�佷竴娆� `red` 鎴� `blue`锛屽皬杞︽墠娌胯溅浣� +X 鏂瑰悜 +鐩磋銆備袱绉嶅懡浠ゅ綋鍓嶅彧鐢ㄤ簬璁板綍鍙傝禌闃佃惀锛岀Щ鍔ㄦ柟鍚戠浉鍚屻�� + +## 鍋滆溅璺濈鐨勮绠� + +鏍规嵁鍦哄湴鍥撅紝涓浆琛ョ粰绔欐部琛岄┒鏂瑰悜鐨勬繁搴︿负 0.80 m銆傚洜姝ゆ満鍣ㄤ汉鍩哄噯涓績 +浣嶄簬琛ョ粰绔欐涓棿鏃讹紝鍒板墠鏂硅竟鐣岀殑璺濈搴斾负锛� + +```text +鏈哄櫒浜轰腑蹇冨埌杈圭晫 = 0.80 / 2 = 0.40 m +``` + +鐜版湁 `origintank_base` 涓紝鍓嶅悜瓒呭0娉㈠潗鏍囩郴浣嶄簬 `base_link` 鍓嶆柟绾� 0.18 m锛� +鎵�浠ヨ秴澹版尝鐨勭洰鏍囪鏁颁负锛� + +```text +瓒呭0娉㈢洰鏍囪鏁� = 0.40 - 0.18 = 0.22 m +``` + +杩欎袱涓昂瀵搁兘鍋氭垚浜嗗惎鍔ㄥ弬鏁帮紝瀹為檯浣跨敤鍓嶅簲娴嬮噺鏈哄櫒浜哄嚑浣曚腑蹇冨埌瓒呭0娉㈡帰澶� +琛ㄩ潰鐨勭湡瀹炶窛绂伙紝骞剁敤瀹炴祴鍊兼浛鎹� `ultrasonic_forward_offset_m`銆� + +閲嶈锛氳秴澹版尝鍙兘娴嬮噺姝e鎺㈠ご鐨勫疄浣撴尅鏉裤�佸洿鏍忔垨澧欓潰锛屼笉鑳借瘑鍒湴闈笂鐨� +娌规紗杈圭嚎銆傝嫢琛ョ粰绔欒竟绾垮彧鏈夊湴闈㈡爣绾匡紝蹇呴』鏀圭敤鐩告満璇嗗埆鏍囩嚎锛屼笉鑳戒緷闈犳湰鑺傜偣 +鐨勮秴澹版尝鍋滆溅閫昏緫銆� + +## 鍓嶆彁 + +- 灏忚溅鏀惧湪绾㈡柟鎴栬摑鏂硅捣鐐规椂锛岃溅澶村繀椤诲凡缁忔湞鍚戣ˉ缁欑珯鐨勫疄浣撹竟鐣屻�� +- `base_link` 閬靛惊 ROS 绾﹀畾锛�+X 涓鸿溅澶存柟鍚戯紝+Y 涓哄乏渚с�� +- 瓒呭0娉㈡瀵圭洰鏍囪竟鐣岋紝琛岄┒閫斾腑鏃犻伄鎸$墿杩涘叆鎺㈠ご娉㈡潫銆� +- Gemini 2 鍜屾満姊拌噦涓嶅弬涓庣涓�闃舵銆� + +## 缂栬瘧 + +褰撳墠鏈哄櫒浜洪暅鍍忕殑 setuptools/colcon 缁勫悎涓嶆敮鎸� editable install锛屽洜姝や笉瑕� +浣跨敤 `--symlink-install`锛� + +```bash +cd /root/dev_ws +source /opt/ros/humble/setup.bash +colcon build --packages-select supply_station_nav +source install/setup.bash +``` + +濡傛灉姝ゅ墠缁堢 source 杩囨棫鐨勫伐浣滅┖闂达紝寤鸿鎵撳紑涓�涓柊缁堢鍐嶇紪璇戙�� + +## 杩愯涓庢祴璇� + +缁堢 1锛屽惎鍔ㄥ簳鐩橈細 + +```bash +cd /root/dev_ws +source /opt/ros/humble/setup.bash +source install/setup.bash +ros2 launch origintank_base origintank_base.launch.py \ + cmd_port:=/dev/ttyUSB0 \ + baud_rate:=B115200 +``` + +鍏堢‘璁よ秴澹版尝鏈夎繛缁�佸悎鐞嗙殑绫冲埗璇绘暟锛� + +```bash +ros2 topic echo /ultrasonic/front/range +ros2 topic hz /ultrasonic/front/range +``` + +缁堢 2锛岄娆℃祴璇曟妸鏈�澶ч�熷害闄愬埗涓� 0.06 m/s锛� + +```bash +cd /root/dev_ws +source /opt/ros/humble/setup.bash +source install/setup.bash +ros2 launch supply_station_nav supply_station_nav.launch.py \ + station_depth_m:=0.80 \ + ultrasonic_forward_offset_m:=0.18 \ + max_forward_speed_mps:=0.06 +``` + +缁堢 3锛岃瀵熺姸鎬侊細 + +```bash +source /root/dev_ws/install/setup.bash +ros2 topic echo /supply_nav/status +``` + +蹇呴』鐪嬪埌 `WAIT_TEAM_COMMAND` 鍚庢墠鑳藉彂杞︺�� + +绾㈡柟鍚姩锛� + +```bash +ros2 topic pub --once /supply_nav/team_command std_msgs/msg/String "{data: red}" +``` + +钃濇柟鍚姩锛� + +```bash +ros2 topic pub --once /supply_nav/team_command std_msgs/msg/String "{data: blue}" +``` + +绱ф�ヨ蒋浠跺仠杞﹀苟澶嶄綅锛� + +```bash +ros2 topic pub --once /supply_nav/stop std_msgs/msg/Bool "{data: true}" +``` + +娴嬭瘯鏃朵粛闇�淇濊瘉瀹炰綋鎬ュ仠鎸夐挳闅忔椂鍙寜銆傚皬杞﹀埌杈惧悗鐘舵�佷负 `ARRIVED`锛屽苟淇濇寔 +鍙戝竷闆堕�熷害锛涚浜岄樁娈电鐞嗚妭鐐逛粛鍙娇鐢ㄨ鐘舵�佷綔涓哄紑濮嬫姄鍙栫殑瑙﹀彂鏉′欢銆� + +## 鐜板満鏍″噯 + +鍒拌揪鐘舵�佷細鍚屾椂鏄剧ず锛� + +- `sensor_range`锛氳秴澹版尝瀹炴祴璺濈锛岄粯璁ょ洰鏍囦负 0.22 m锛� +- `base_centre_range`锛氱敱鈥滆秴澹版尝璇绘暟 + 鎺㈠ご鍓嶇疆璺濈鈥濅及璁″嚭鐨勬満鍣ㄤ汉涓績鍒� + 杈圭晫璺濈锛岄粯璁ょ洰鏍囦负 0.40 m銆� + +璇峰疄娴� `base_link` 瀵瑰簲鐨勬満鍣ㄤ汉涓績浣嶇疆锛岃�屼笉鏄彧鐪嬭溅澹宠竟缂橈細 + +- 涓績姣旂洰鏍囪繙 0.03 m锛氬皢瀵瑰簲闃佃惀淇璁句负 `-0.03`锛� +- 涓績姣旂洰鏍囪繎 0.03 m锛氬皢瀵瑰簲闃佃惀淇璁句负 `+0.03`銆� + +渚嬪鍙慨姝g孩鏂癸細 + +```bash +ros2 launch supply_station_nav supply_station_nav.launch.py \ + red_range_adjust_m:=-0.03 \ + max_forward_speed_mps:=0.06 +``` + +绾㈣摑涓や晶瀹炰綋杈圭晫鎴栨憜鏀捐宸笉鍚屾椂锛屽彲鍒嗗埆璁剧疆 +`red_range_adjust_m` 鍜� `blue_range_adjust_m`銆� diff --git a/dev_ws/src/supply_station_nav/config/supply_station_nav.yaml b/dev_ws/src/supply_station_nav/config/supply_station_nav.yaml new file mode 100644 index 0000000..d216478 --- /dev/null +++ b/dev_ws/src/supply_station_nav/config/supply_station_nav.yaml @@ -0,0 +1,44 @@ +supply_station_nav: + ros__parameters: + # Supply station depth is 800 mm. Its centre is 400 mm from the boundary. + # The ultrasonic sensor is about 180 mm ahead of base_link, therefore the + # nominal sensor reading at the centre is 400 - 180 = 220 mm. + station_depth_m: 0.80 + ultrasonic_forward_offset_m: 0.18 + red_range_adjust_m: 0.0 + blue_range_adjust_m: 0.0 + + range_filter_window: 5 + range_tolerance_m: 0.020 + arrival_hold_sec: 0.60 + distance_kp: 0.65 + lateral_kp: 0.80 + yaw_kp: 1.80 + + max_forward_speed_mps: 0.12 + max_reverse_speed_mps: 0.035 + max_lateral_correction_mps: 0.045 + max_yaw_rate_radps: 0.45 + max_linear_accel_mps2: 0.22 + max_angular_accel_radps2: 0.90 + + lateral_tolerance_m: 0.050 + yaw_tolerance_deg: 4.0 + max_safe_yaw_error_deg: 20.0 + max_safe_lateral_drift_m: 0.20 + max_forward_travel_m: 1.80 + emergency_stop_range_m: 0.080 + + mission_timeout_sec: 20.0 + odom_timeout_sec: 0.50 + imu_timeout_sec: 0.50 + range_timeout_sec: 0.50 + + cmd_vel_topic: "/cmd_vel" + odom_topic: "/odom" + imu_topic: "/imu" + ultrasonic_topic: "/ultrasonic/front/range" + team_command_topic: "/supply_nav/team_command" + stop_topic: "/supply_nav/stop" + legacy_start_topic: "/supply_nav/start" + status_topic: "/supply_nav/status" diff --git a/dev_ws/src/supply_station_nav/launch/supply_station_nav.launch.py b/dev_ws/src/supply_station_nav/launch/supply_station_nav.launch.py new file mode 100644 index 0000000..95b1f94 --- /dev/null +++ b/dev_ws/src/supply_station_nav/launch/supply_station_nav.launch.py @@ -0,0 +1,49 @@ +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node +from launch_ros.parameter_descriptions import ParameterValue + + +def generate_launch_description(): + config = os.path.join( + get_package_share_directory('supply_station_nav'), + 'config', + 'supply_station_nav.yaml', + ) + return LaunchDescription([ + DeclareLaunchArgument('station_depth_m', default_value='0.80'), + DeclareLaunchArgument('ultrasonic_forward_offset_m', default_value='0.18'), + DeclareLaunchArgument('red_range_adjust_m', default_value='0.0'), + DeclareLaunchArgument('blue_range_adjust_m', default_value='0.0'), + DeclareLaunchArgument('max_forward_speed_mps', default_value='0.12'), + Node( + package='supply_station_nav', + executable='supply_station_nav', + name='supply_station_nav', + output='screen', + parameters=[ + config, + { + 'station_depth_m': ParameterValue( + LaunchConfiguration('station_depth_m'), value_type=float + ), + 'ultrasonic_forward_offset_m': ParameterValue( + LaunchConfiguration('ultrasonic_forward_offset_m'), value_type=float + ), + 'red_range_adjust_m': ParameterValue( + LaunchConfiguration('red_range_adjust_m'), value_type=float + ), + 'blue_range_adjust_m': ParameterValue( + LaunchConfiguration('blue_range_adjust_m'), value_type=float + ), + 'max_forward_speed_mps': ParameterValue( + LaunchConfiguration('max_forward_speed_mps'), value_type=float + ), + }, + ], + ), + ]) diff --git a/dev_ws/src/supply_station_nav/package.xml b/dev_ws/src/supply_station_nav/package.xml new file mode 100644 index 0000000..77eaa21 --- /dev/null +++ b/dev_ws/src/supply_station_nav/package.xml @@ -0,0 +1,21 @@ + + + + supply_station_nav + 0.1.0 + Closed-loop start-to-supply-station navigation for the logistics challenge. + SK + Apache-2.0 + + rclpy + geometry_msgs + nav_msgs + sensor_msgs + std_msgs + ros2launch + + + ament_python + + + diff --git a/dev_ws/src/supply_station_nav/resource/supply_station_nav b/dev_ws/src/supply_station_nav/resource/supply_station_nav new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dev_ws/src/supply_station_nav/resource/supply_station_nav @@ -0,0 +1 @@ + diff --git a/dev_ws/src/supply_station_nav/setup.cfg b/dev_ws/src/supply_station_nav/setup.cfg new file mode 100644 index 0000000..b645457 --- /dev/null +++ b/dev_ws/src/supply_station_nav/setup.cfg @@ -0,0 +1,5 @@ +[develop] +script_dir=$base/lib/supply_station_nav +[install] +install_scripts=$base/lib/supply_station_nav + diff --git a/dev_ws/src/supply_station_nav/setup.py b/dev_ws/src/supply_station_nav/setup.py new file mode 100644 index 0000000..8f85082 --- /dev/null +++ b/dev_ws/src/supply_station_nav/setup.py @@ -0,0 +1,28 @@ +from setuptools import setup + + +package_name = 'supply_station_nav' + + +setup( + name=package_name, + version='0.1.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', ['launch/supply_station_nav.launch.py']), + ('share/' + package_name + '/config', ['config/supply_station_nav.yaml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='SK', + maintainer_email='sk@example.com', + description='Straight navigation to the supply station with ultrasonic stopping.', + license='Apache-2.0', + entry_points={ + 'console_scripts': [ + 'supply_station_nav = supply_station_nav.supply_station_nav_node:main', + ], + }, +) diff --git a/dev_ws/src/supply_station_nav/supply_station_nav/__init__.py b/dev_ws/src/supply_station_nav/supply_station_nav/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dev_ws/src/supply_station_nav/supply_station_nav/__init__.py @@ -0,0 +1 @@ + diff --git a/dev_ws/src/supply_station_nav/supply_station_nav/supply_station_nav_node.py b/dev_ws/src/supply_station_nav/supply_station_nav/supply_station_nav_node.py new file mode 100644 index 0000000..b76358d --- /dev/null +++ b/dev_ws/src/supply_station_nav/supply_station_nav/supply_station_nav_node.py @@ -0,0 +1,452 @@ +import math +from collections import deque +from enum import Enum +from statistics import median +from typing import Optional, Tuple + +import rclpy +from geometry_msgs.msg import Twist +from nav_msgs.msg import Odometry +from rclpy.node import Node +from sensor_msgs.msg import Imu, Range +from std_msgs.msg import Bool, String + + +class NavState(str, Enum): + WAIT_SENSORS = 'WAIT_SENSORS' + WAIT_TEAM_COMMAND = 'WAIT_TEAM_COMMAND' + MOVING_TO_SUPPLY = 'MOVING_TO_SUPPLY' + SETTLING = 'SETTLING' + ARRIVED = 'ARRIVED' + ABORTED = 'ABORTED' + + +def clamp(value: float, low: float, high: float) -> float: + return max(low, min(high, value)) + + +def angle_wrap(angle: float) -> float: + while angle > math.pi: + angle -= 2.0 * math.pi + while angle < -math.pi: + angle += 2.0 * math.pi + return angle + + +def yaw_from_imu(msg: Imu) -> float: + q = msg.orientation + siny_cosp = 2.0 * (q.w * q.z + q.x * q.y) + cosy_cosp = 1.0 - 2.0 * (q.y * q.y + q.z * q.z) + return math.atan2(siny_cosp, cosy_cosp) + + +class SupplyStationNavigator(Node): + """Drive straight into the supply station and stop by front ultrasound. + + The 800 mm station centre is 400 mm from its front boundary. The existing + ultrasonic frame is about 180 mm in front of base_link, so the nominal + sensor-to-boundary reading at the station centre is 400 - 180 = 220 mm. + A red or blue command selects the team and starts the same straight-ahead + motion; team-specific range adjustments compensate field asymmetry. + """ + + def __init__(self) -> None: + super().__init__('supply_station_nav') + self._declare_parameters() + self._load_parameters() + + self.cmd_pub = self.create_publisher(Twist, self.cmd_vel_topic, 10) + self.status_pub = self.create_publisher(String, self.status_topic, 10) + self.create_subscription(Odometry, self.odom_topic, self.on_odom, 20) + self.create_subscription(Imu, self.imu_topic, self.on_imu, 20) + self.create_subscription(Range, self.ultrasonic_topic, self.on_range, 20) + self.create_subscription(String, self.team_command_topic, self.on_team_command, 10) + self.create_subscription(Bool, self.stop_topic, self.on_stop, 10) + self.create_subscription(Bool, self.legacy_start_topic, self.on_legacy_start, 10) + self.timer = self.create_timer(0.05, self.on_timer) + + self.state = NavState.WAIT_SENSORS + self.current_position: Optional[Tuple[float, float]] = None + self.current_yaw: Optional[float] = None + self.last_odom_time = None + self.last_imu_time = None + self.last_range_time = None + self.range_samples = deque(maxlen=self.range_filter_window) + + self.selected_team: Optional[str] = None + self.target_sensor_range_m = self.nominal_target_sensor_range_m + self.start_pose: Optional[Tuple[float, float, float]] = None + self.mission_start_time = None + self.settle_start_time = None + self.last_control_time = self.get_clock().now() + self.last_command = Twist() + self.last_status_time = None + self.publish_status('waiting for fresh /odom, /imu and ultrasonic range') + + def _declare_parameters(self) -> None: + defaults = { + 'station_depth_m': 0.80, + 'ultrasonic_forward_offset_m': 0.18, + 'red_range_adjust_m': 0.0, + 'blue_range_adjust_m': 0.0, + 'range_filter_window': 5, + 'range_tolerance_m': 0.020, + 'arrival_hold_sec': 0.60, + 'distance_kp': 0.65, + 'lateral_kp': 0.80, + 'yaw_kp': 1.80, + 'max_forward_speed_mps': 0.12, + 'max_reverse_speed_mps': 0.035, + 'max_lateral_correction_mps': 0.045, + 'max_yaw_rate_radps': 0.45, + 'max_linear_accel_mps2': 0.22, + 'max_angular_accel_radps2': 0.90, + 'lateral_tolerance_m': 0.050, + 'yaw_tolerance_deg': 4.0, + 'max_safe_yaw_error_deg': 20.0, + 'max_safe_lateral_drift_m': 0.20, + 'max_forward_travel_m': 1.80, + 'emergency_stop_range_m': 0.080, + 'mission_timeout_sec': 20.0, + 'odom_timeout_sec': 0.50, + 'imu_timeout_sec': 0.50, + 'range_timeout_sec': 0.50, + 'cmd_vel_topic': '/cmd_vel', + 'odom_topic': '/odom', + 'imu_topic': '/imu', + 'ultrasonic_topic': '/ultrasonic/front/range', + 'team_command_topic': '/supply_nav/team_command', + 'stop_topic': '/supply_nav/stop', + 'legacy_start_topic': '/supply_nav/start', + 'status_topic': '/supply_nav/status', + } + for name, value in defaults.items(): + self.declare_parameter(name, value) + + def _load_parameters(self) -> None: + get = self.get_parameter + self.station_depth_m = float(get('station_depth_m').value) + self.ultrasonic_forward_offset_m = float(get('ultrasonic_forward_offset_m').value) + self.red_range_adjust_m = float(get('red_range_adjust_m').value) + self.blue_range_adjust_m = float(get('blue_range_adjust_m').value) + self.range_filter_window = max(1, int(get('range_filter_window').value)) + self.range_tolerance_m = abs(float(get('range_tolerance_m').value)) + self.arrival_hold_sec = abs(float(get('arrival_hold_sec').value)) + self.distance_kp = abs(float(get('distance_kp').value)) + self.lateral_kp = abs(float(get('lateral_kp').value)) + self.yaw_kp = abs(float(get('yaw_kp').value)) + self.max_forward_speed_mps = abs(float(get('max_forward_speed_mps').value)) + self.max_reverse_speed_mps = abs(float(get('max_reverse_speed_mps').value)) + self.max_lateral_correction_mps = abs(float(get('max_lateral_correction_mps').value)) + self.max_yaw_rate_radps = abs(float(get('max_yaw_rate_radps').value)) + self.max_linear_accel_mps2 = abs(float(get('max_linear_accel_mps2').value)) + self.max_angular_accel_radps2 = abs(float(get('max_angular_accel_radps2').value)) + self.lateral_tolerance_m = abs(float(get('lateral_tolerance_m').value)) + self.yaw_tolerance_rad = math.radians(abs(float(get('yaw_tolerance_deg').value))) + self.max_safe_yaw_error_rad = math.radians(abs(float(get('max_safe_yaw_error_deg').value))) + self.max_safe_lateral_drift_m = abs(float(get('max_safe_lateral_drift_m').value)) + self.max_forward_travel_m = abs(float(get('max_forward_travel_m').value)) + self.emergency_stop_range_m = abs(float(get('emergency_stop_range_m').value)) + self.mission_timeout_sec = abs(float(get('mission_timeout_sec').value)) + self.odom_timeout_sec = abs(float(get('odom_timeout_sec').value)) + self.imu_timeout_sec = abs(float(get('imu_timeout_sec').value)) + self.range_timeout_sec = abs(float(get('range_timeout_sec').value)) + self.cmd_vel_topic = str(get('cmd_vel_topic').value) + self.odom_topic = str(get('odom_topic').value) + self.imu_topic = str(get('imu_topic').value) + self.ultrasonic_topic = str(get('ultrasonic_topic').value) + self.team_command_topic = str(get('team_command_topic').value) + self.stop_topic = str(get('stop_topic').value) + self.legacy_start_topic = str(get('legacy_start_topic').value) + self.status_topic = str(get('status_topic').value) + + self.nominal_target_sensor_range_m = ( + self.station_depth_m * 0.5 - self.ultrasonic_forward_offset_m + ) + if self.nominal_target_sensor_range_m <= self.emergency_stop_range_m: + raise ValueError( + 'station_depth_m/2 - ultrasonic_forward_offset_m must exceed ' + 'emergency_stop_range_m' + ) + + def on_odom(self, msg: Odometry) -> None: + position = msg.pose.pose.position + self.current_position = (float(position.x), float(position.y)) + self.last_odom_time = self.get_clock().now() + self.update_wait_state() + + def on_imu(self, msg: Imu) -> None: + self.current_yaw = yaw_from_imu(msg) + self.last_imu_time = self.get_clock().now() + self.update_wait_state() + + def on_range(self, msg: Range) -> None: + value = float(msg.range) + if math.isfinite(value) and value >= float(msg.min_range) and value <= float(msg.max_range): + self.range_samples.append(value) + self.last_range_time = self.get_clock().now() + self.update_wait_state() + + def filtered_range(self) -> Optional[float]: + if not self.range_samples: + return None + return float(median(self.range_samples)) + + def on_team_command(self, msg: String) -> None: + team = msg.data.strip().lower() + if team not in {'red', 'blue'}: + self.get_logger().warning(f'Invalid team command {msg.data!r}; use red or blue.') + return + if self.state in {NavState.MOVING_TO_SUPPLY, NavState.SETTLING}: + self.get_logger().warning('Team command ignored while the robot is moving.') + return + if self.state in {NavState.ARRIVED, NavState.ABORTED}: + self.get_logger().warning(f'Publish true to {self.stop_topic} before restarting.') + return + if not self.sensors_are_fresh(): + self.state = NavState.WAIT_SENSORS + self.publish_status('cannot start: odom, imu or ultrasonic data is stale') + return + + assert self.current_position is not None and self.current_yaw is not None + adjustment = self.red_range_adjust_m if team == 'red' else self.blue_range_adjust_m + self.target_sensor_range_m = self.nominal_target_sensor_range_m + adjustment + if self.target_sensor_range_m <= self.emergency_stop_range_m: + self.abort(f'invalid target range {self.target_sensor_range_m:.3f}m') + return + self.selected_team = team + self.start_pose = (self.current_position[0], self.current_position[1], self.current_yaw) + self.mission_start_time = self.get_clock().now() + self.settle_start_time = None + self.last_command = Twist() + self.last_control_time = self.get_clock().now() + self.state = NavState.MOVING_TO_SUPPLY + self.publish_status( + f'team={team}, straight motion started, ' + f'target_sensor_range={self.target_sensor_range_m:.3f}m, ' + f'target_base_centre_range=' + f'{self.target_sensor_range_m + self.ultrasonic_forward_offset_m:.3f}m' + ) + + def on_stop(self, msg: Bool) -> None: + if msg.data: + self.reset_to_wait('software stop/reset') + + def on_legacy_start(self, msg: Bool) -> None: + if not msg.data: + self.reset_to_wait('legacy stop command') + else: + self.get_logger().warning( + f'Use red or blue on {self.team_command_topic} to start.' + ) + + def is_fresh(self, last_time, timeout: float) -> bool: + if last_time is None: + return False + return (self.get_clock().now() - last_time).nanoseconds / 1e9 <= timeout + + def sensors_are_fresh(self) -> bool: + return ( + self.current_position is not None + and self.current_yaw is not None + and self.filtered_range() is not None + and self.is_fresh(self.last_odom_time, self.odom_timeout_sec) + and self.is_fresh(self.last_imu_time, self.imu_timeout_sec) + and self.is_fresh(self.last_range_time, self.range_timeout_sec) + ) + + def update_wait_state(self) -> None: + if self.state not in {NavState.WAIT_SENSORS, NavState.WAIT_TEAM_COMMAND}: + return + if self.sensors_are_fresh() and self.state != NavState.WAIT_TEAM_COMMAND: + self.state = NavState.WAIT_TEAM_COMMAND + self.publish_status( + f'sensors ready; ultrasonic={self.filtered_range():.3f}m; enter red or blue' + ) + + def reset_to_wait(self, detail: str) -> None: + self.stop_robot() + self.selected_team = None + self.start_pose = None + self.mission_start_time = None + self.settle_start_time = None + self.target_sensor_range_m = self.nominal_target_sensor_range_m + self.state = NavState.WAIT_TEAM_COMMAND if self.sensors_are_fresh() else NavState.WAIT_SENSORS + self.publish_status(detail) + + def relative_motion(self) -> Tuple[float, float, float]: + assert self.start_pose is not None + assert self.current_position is not None + assert self.current_yaw is not None + start_x, start_y, start_yaw = self.start_pose + dx = self.current_position[0] - start_x + dy = self.current_position[1] - start_y + forward = math.cos(start_yaw) * dx + math.sin(start_yaw) * dy + lateral = -math.sin(start_yaw) * dx + math.cos(start_yaw) * dy + yaw_error = angle_wrap(self.current_yaw - start_yaw) + return forward, lateral, yaw_error + + def stop_robot(self) -> None: + command = Twist() + self.cmd_pub.publish(command) + self.last_command = command + self.last_control_time = self.get_clock().now() + + def publish_motion(self, desired: Twist) -> None: + now = self.get_clock().now() + dt = max(0.001, min((now - self.last_control_time).nanoseconds / 1e9, 0.20)) + linear_step = self.max_linear_accel_mps2 * dt + angular_step = self.max_angular_accel_radps2 * dt + command = Twist() + command.linear.x = self.last_command.linear.x + clamp( + desired.linear.x - self.last_command.linear.x, -linear_step, linear_step + ) + command.linear.y = self.last_command.linear.y + clamp( + desired.linear.y - self.last_command.linear.y, -linear_step, linear_step + ) + command.angular.z = self.last_command.angular.z + clamp( + desired.angular.z - self.last_command.angular.z, -angular_step, angular_step + ) + self.cmd_pub.publish(command) + self.last_command = command + self.last_control_time = now + + def publish_status(self, detail: str) -> None: + msg = String() + msg.data = f'{self.state.value}:{detail}' + self.status_pub.publish(msg) + self.get_logger().info(msg.data) + self.last_status_time = self.get_clock().now() + + def status_due(self) -> bool: + return self.last_status_time is None or ( + self.get_clock().now() - self.last_status_time + ).nanoseconds >= 2_000_000_000 + + def abort(self, detail: str) -> None: + self.stop_robot() + self.state = NavState.ABORTED + self.publish_status(detail) + + def on_timer(self) -> None: + if self.state in {NavState.WAIT_SENSORS, NavState.WAIT_TEAM_COMMAND}: + if self.sensors_are_fresh(): + self.update_wait_state() + elif self.state == NavState.WAIT_TEAM_COMMAND: + self.state = NavState.WAIT_SENSORS + self.publish_status('sensor data became stale') + if self.status_due(): + if self.state == NavState.WAIT_SENSORS: + self.publish_status('waiting for odom, imu and ultrasonic range') + else: + self.publish_status( + f'sensors ready; ultrasonic={self.filtered_range():.3f}m; enter red or blue' + ) + return + + if self.state not in {NavState.MOVING_TO_SUPPLY, NavState.SETTLING}: + return + if not self.sensors_are_fresh(): + self.abort('odom, imu or ultrasonic data timed out') + return + + assert self.mission_start_time is not None + elapsed = (self.get_clock().now() - self.mission_start_time).nanoseconds / 1e9 + if elapsed > self.mission_timeout_sec: + self.abort(f'mission timeout after {elapsed:.1f}s') + return + + sensor_range = self.filtered_range() + assert sensor_range is not None + forward, lateral, yaw_error = self.relative_motion() + if sensor_range <= self.emergency_stop_range_m: + self.abort(f'emergency obstacle range {sensor_range:.3f}m') + return + if abs(yaw_error) > self.max_safe_yaw_error_rad: + self.abort(f'unsafe yaw error {math.degrees(yaw_error):.1f}deg') + return + if abs(lateral) > self.max_safe_lateral_drift_m: + self.abort(f'unsafe lateral drift {lateral:.3f}m') + return + if abs(forward) > self.max_forward_travel_m: + self.abort(f'maximum forward travel exceeded: {forward:.3f}m') + return + + range_error = sensor_range - self.target_sensor_range_m + arrived = ( + abs(range_error) <= self.range_tolerance_m + and abs(lateral) <= self.lateral_tolerance_m + and abs(yaw_error) <= self.yaw_tolerance_rad + ) + if arrived: + self.stop_robot() + if self.state != NavState.SETTLING: + self.state = NavState.SETTLING + self.settle_start_time = self.get_clock().now() + self.publish_status('target range reached; holding still') + return + assert self.settle_start_time is not None + hold = (self.get_clock().now() - self.settle_start_time).nanoseconds / 1e9 + if hold >= self.arrival_hold_sec: + self.state = NavState.ARRIVED + self.publish_status( + f'team={self.selected_team}, supply station reached, ' + f'sensor_range={sensor_range:.3f}m, ' + f'base_centre_range={sensor_range + self.ultrasonic_forward_offset_m:.3f}m, ' + f'forward_travel={forward:.3f}m, lateral_drift={lateral:.3f}m, ' + f'yaw_error={math.degrees(yaw_error):.1f}deg' + ) + return + + if self.state == NavState.SETTLING: + self.state = NavState.MOVING_TO_SUPPLY + self.settle_start_time = None + self.publish_status('range left tolerance; correction resumed') + + desired = Twist() + desired.linear.x = clamp( + self.distance_kp * range_error, + -self.max_reverse_speed_mps, + self.max_forward_speed_mps, + ) + desired.linear.y = clamp( + -self.lateral_kp * lateral, + -self.max_lateral_correction_mps, + self.max_lateral_correction_mps, + ) + desired.angular.z = clamp( + -self.yaw_kp * yaw_error, + -self.max_yaw_rate_radps, + self.max_yaw_rate_radps, + ) + self.publish_motion(desired) + + if self.status_due(): + self.publish_status( + f'team={self.selected_team}, sensor_range={sensor_range:.3f}m, ' + f'target={self.target_sensor_range_m:.3f}m, ' + f'base_centre_range={sensor_range + self.ultrasonic_forward_offset_m:.3f}m, ' + f'forward_travel={forward:.3f}m, lateral_drift={lateral:.3f}m, ' + f'yaw_error={math.degrees(yaw_error):.1f}deg' + ) + + def destroy_node(self): + self.stop_robot() + return super().destroy_node() + + +def main() -> None: + rclpy.init() + node = SupplyStationNavigator() + try: + rclpy.spin(node) + except KeyboardInterrupt: + pass + finally: + node.stop_robot() + node.destroy_node() + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/reference.md b/reference.md new file mode 100644 index 0000000..7a7f8c7 --- /dev/null +++ b/reference.md @@ -0,0 +1,34 @@ +# 鍙傝�冭祫鏂� + +## Linux/Ubuntu + +- [Linux绯荤粺浠嬬粛鍙婂畨瑁匽(https://www.bilibili.com/video/BV1zt411G7Vn?p=2&vd_source=c67aa749a53261eb7bdd22ba5b916d5f) +- [Windows 鍜� Ubuntu 鍙岀郴缁熺殑瀹夎鍜屽嵏杞絔(https://www.bilibili.com/video/BV1554y1n7zv/) +- [Linux绯荤粺鍩虹鎿嶄綔](https://www.bilibili.com/video/BV1zt411G7Vn?p=3&vd_source=c67aa749a53261eb7bdd22ba5b916d5f) + + + +## ROS/ROS2 + +- [ROS2鍏ラ棬21璁瞉(https://class.guyuehome.com/detail/p_628f4288e4b01c509ab5bc7a/6) +- [ROS2鍏ラ棬鍥炬枃鏁欑▼](https://book.guyuehome.com/) +- [ROS2寮�鍙戠幆澧冮厤缃甝(https://www.bilibili.com/video/BV16B4y1Q7jQ?p=5&vd_source=c67aa749a53261eb7bdd22ba5b916d5f) +- [鍙ゆ湀灞呮満鍣ㄤ汉绀惧尯](https://www.guyuehome.com/) + + + +## TogetheROS/RDK X5 + +- [鍦扮摐鏈哄櫒浜虹ぞ鍖篯(https://developer.d-robotics.cc/) +- [RDK X5寮�鍙戣祫鏂橾(https://developer.d-robotics.cc/information) +- [NodeHub](https://developer.d-robotics.cc/nodehub) + +- [RDKStudio](https://developer.d-robotics.cc/rdkstudio) + + +## C++/Python + +- [C++蹇�熷叆闂╙(https://www.bilibili.com/video/BV1Ps411w73m/?spm_id_from=333.337.search-card.all.click&vd_source=c67aa749a53261eb7bdd22ba5b916d5f) + +- [闆跺熀纭�鍏ラ棬瀛︿範Python](https://www.bilibili.com/video/BV1c4411e77t/?spm_id_from=333.337.search-card.all.click) + diff --git a/~$娴嬭瘯杩囩▼.docx b/~$娴嬭瘯杩囩▼.docx new file mode 100644 index 0000000..cb0ea37 Binary files /dev/null and b/~$娴嬭瘯杩囩▼.docx differ diff --git a/~WRL1825.tmp b/~WRL1825.tmp new file mode 100644 index 0000000..8c063bd Binary files /dev/null and b/~WRL1825.tmp differ diff --git a/娴嬭瘯杩囩▼.docx b/娴嬭瘯杩囩▼.docx new file mode 100644 index 0000000..8d72c62 Binary files /dev/null and b/娴嬭瘯杩囩▼.docx differ diff --git a/瑙勫垯/2026鐫挎姉鏈哄櫒浜哄紑鍙戣�呭ぇ璧�-CAIR璧涢亾-鐗╂祦鎸戞垬.pptx b/瑙勫垯/2026鐫挎姉鏈哄櫒浜哄紑鍙戣�呭ぇ璧�-CAIR璧涢亾-鐗╂祦鎸戞垬.pptx new file mode 100644 index 0000000..9e9cd34 Binary files /dev/null and b/瑙勫垯/2026鐫挎姉鏈哄櫒浜哄紑鍙戣�呭ぇ璧�-CAIR璧涢亾-鐗╂祦鎸戞垬.pptx differ diff --git a/瑙勫垯/鐗╂祦鎸戞垬.pdf b/瑙勫垯/鐗╂祦鎸戞垬.pdf new file mode 100644 index 0000000..7ddd171 Binary files /dev/null and b/瑙勫垯/鐗╂祦鎸戞垬.pdf differ