QPython3 可视化:网络监测-WebText.py、MobileText.py
乘着船
编辑于 2023年03月13日 22:19
收录于文集
共64篇

#需要BaseWindow.py  网页链接​ 

WebText.py

代码块
Python
自动换行
复制代码
#需要QPython 3C 3.7.3或以上,旧版QPython均无法正常运行
from .BaseWindow import *
XML="""<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:background="#0E4200"
	android:orientation="vertical"
	xmlns:android="http://schemas.android.com/apk/res/android">
	<LinearLayout
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:orientation="vertical"
		android:layout_weight="20">
	<ScrollView   
        android:layout_width="fill_parent"   
        android:layout_height="fill_parent" > 
	<LinearLayout
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:orientation="vertical"
		android:layout_weight="20">	
    <TextView
        android:background="#7f007f"
		android:id="@+id/Title"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:textSize="6dp"
		android:text=""
		android:textColor="#00ff00"
		android:layout_weight="1"
		android:gravity="center"
	/>
	<EditText
        android:background="#ffffff"
		android:id="@+id/Text"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:textSize="6dp"
		android:text="正在获取网络信息"
		android:textColor="#0000ff"
		android:layout_weight="1"
	/>
	</LinearLayout>
	</ScrollView>
    </LinearLayout>
	<LinearLayout
		android:layout_width="fill_parent"
		android:layout_height="100dp"
		android:orientation="horizontal"
		android:layout_weight="8">
	<RadioButton
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:text="暂停"
		android:id="@+id/but_pause"
		android:textAllCaps="false"
		android:background="#007f7f"
		android:textColor="#ffffffff"
		android:layout_weight="1"
		android:gravity="center"/>
	<RadioButton
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:text="复制"
		android:id="@+id/but_copy"
		android:textAllCaps="false"
		android:background="#7f7f00"
		android:textColor="#ffffffff"
		android:layout_weight="1"
		android:gravity="center"/>
	<RadioButton
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:text="退出"
		android:id="@+id/but_exit"
		android:textAllCaps="false"
		android:background="#7f007f"
		android:textColor="#ffffffff"
		android:layout_weight="1"
		android:gravity="center"/>
	</LinearLayout>
</LinearLayout>"""
from time import time
def getWebConti():
    t0=0
    v.Text.enabled='false'
    while v.but_copy.checked=='false' and v.but_pause.checked=='false' and v.but_exit.checked=='false':
        t=time()
        if t-t0>=timeInterval:
            getWebOnce()
            if timeInterval<0:
                #单次测试
                p=v.but_pause
                p.checked='true'
                p.text='继续'
            else:
                t0=t
    v.Text.enabled='true'
def getWebOnce():
    try:
        rst=netInfo()
        T.html=rst
    except:
        from traceback import format_exc
        T.text=format_exc()
        v.Title.text="错误信息"
        p=v.but_pause
        p.checked='true'
        p.text='继续'
def dictToStr(s):
    r=[];a=r.append
    def b(s,n):
        a(n*'  '+s)
    _dictToStr('',s,b,-1)
    return '<br>'.join(r[1:-1])
def _dictToStr(k,s,r,n):
    r('<font color=red>%s</font><font color=#007f00> = {</font>'%k,n)
    m=n+1
    for i in s:
        t=s[i]
        j=type(t)
        if j==list:
            _listToStr(i,t,r,m)
        elif j==dict:
            _dictToStr(i,t,r,m)
        else:
            r('<font color=red>%s</font><font color=#007f00> = </font>%s'%(i,Str2Xml(str(t))),m)
    r('<font color=#007f00>}</font>',n)
def _listToStr(k,s,r,n):
    r('<font color=red>%s</font><font color=#007f00> = [</font>'%k,n)
    m=n+1
    for i in s:
        r(i,m)
    r('<font color=#007f00>]</font>',n)
from .MobileText import Int,getInfo,Now
def getSignalStrength():
    info=getInfo()
    return {
    #Type:网络类型:5G/4G/3G/2G/Unknown
    'Type':rsla('getNetworkType'),
    #Level:信号等级:0到4(有的机型是5)
    'Level':info['level'],
    #Strength:综合信号强度
    'Strength':info['dbm'],
    'CellLocation':getCellLocation(),
    #移动信号其他具体信息
    'Detail':info['detail']
    }
def getCellLocation():
    #获取周围基站个数
    #获取当前基站:LAC/CID/SID/NID/BID等
    #获取当前基站信号Dbm,与综合信号Dbm可不相等
    s=rsla('getCellLocation')
    try:
        for i in tuple(s):
            if s[i] in (-1,0,2147483647):
                s.pop(i)
    except:pass
    return s
def netInfo():
    S = {

    'System Time':Now(),
    'Mobile Network Signal':getSignalStrength(),

    'WiFi Information':{
    'Dhcp Information':rsla('getDhcpInfo'),
    'Connection Information':rsla('wifiGetConnectionInfo'),
    'WiFi HotSpot State':rsla('wifiGetApState')
    },

    'Internet Interface Address Information':rsla('getInternetInterfaceAddress'),
    
    'Web Speed ( since Startup )':getWebSpeed(),
    'Startup Time':startupTime()
    }
    return dictToStr(S)
def getWebSpeed():
    data={}
    stat=esla('getTrafficStats')
    try:
        time=getWebSpeed.Time
    except:
        pass
    Time=getWebSpeed.Time=stat['StartupTime']
    for j in 'Total:include SL4A','Mobile:only  Mobile','QPython:include SL4A':
        d={}
        j,n=j.split(':')
        for i in 'Tt↑','Rr↓':
            i,k,f=i
            exec(f'''
{j}{i}x=stat["{j}{i}xBytes"]
try:
    {j}{k}x=getWebSpeed.{j}{i}x
    {j}{k}x=({j}{i}x-{j}{k}x)*1000/(Time-time)
except:
    {j}{k}x=-1
getWebSpeed.{j}{i}x={j}{i}x
d["{f}"]=GetSpaceText({j}{i}x)+" "+GetSpaceText({j}{k}x)+"/s"
''')
        exec(f'data["{j} ( {n} )"]=d')
    return data
def GetSpaceText(Bytes):
    if Bytes<KB:
        return Str(Bytes)+'B'
    elif Bytes<MB:
        return Str(Bytes/KB)+'KB'
    elif Bytes<GB:
        return Str(Bytes/MB)+'MB'
    elif Bytes<TB:
        return Str(Bytes/GB)+'GB'
    else:
        return Str(Bytes/TB)+'TB'
def Str(Val):
    Val=str(Val)[:5]
    if Val[-1:]=='.':
        Val=Val[:-1]
    return Val
def startupTime():
    ns=rsla('elapsedRealtimeNanos')
    s,ns=divmod(ns,1000000000)
    d,s=divmod(s,86400)
    h,s=divmod(s,3600)
    m,s=divmod(s,60)
    return f'{d}d:{h}h:{m}m:{s}s:{ns}ns'
KB=1024
MB=KB*1024
GB=MB*1024
TB=GB*1024
def showInterval():
    if timeInterval<0:
        v.Title.text='单次(手动)测试'
    else:
        v.Title.text='连续(间隔%s秒)测试'%timeInterval
class MainScreen(Layout):
    def on_show(self):
        global v,T
        v=self.views
        T=v.Text
        v.but_pause.add_event(click_EventHandler(v.but_pause,self.pause))
        v.but_copy.add_event(click_EventHandler(v.but_copy,self.copy))
        v.but_exit.add_event(click_EventHandler(v.but_exit,self.exit))
        showInterval()
        getWebConti()
    def on_close(self):
        pass
    def pause(self,view,dummy):
        p=v.but_pause
        p.checked='false'
        if p.text=='暂停':
            p.text='继续'
        else:
            p.text='暂停'
            showInterval()
            getWebConti()
    def copy(self,view,dummy):
        jsla('setClipboard',T.text)
        v.but_copy.checked='false'
        jsla('makeToast','网络信息已复制')
        if v.but_pause.text=='暂停':
            getWebConti()
    def exit(self,view,dummy):
        FullScreenWrapper2App.close_layout()
def WebText(TimeInterval=1):#主函数
#Web信息(时间间隔=1秒,导出文件=无,备注=无)
#如果:时间间隔==-1,为单次(手动)测试
#如果:时间间隔>=0,为连续(自动)测试
#备注格式:{'bssid1':'备注1',......}
#请授予QPython电话、位置和WiFi权限
    global timeInterval
    timeInterval=TimeInterval
    FullScreenWrapper2App.show_layout(MainScreen(XML))
    FullScreenWrapper2App.eventloop()
__all__=('WebText','droid')
#by 乘着船 at https://www.bilibili.com/read/cv16061380
复制成功

4G + WiFi 测试

3G 测试1

3G 测试2

2G 测试

无信号 测试

双5G 测试

MobileText.py

代码块
Python
自动换行
复制代码
#需要QPython 3C 3.6.0或以上,旧版QPython均无法正常运行
from .BaseWindow import *
XML="""<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:background="#0E4200"
	android:orientation="vertical"
	xmlns:android="http://schemas.android.com/apk/res/android">
	<LinearLayout
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:orientation="vertical"
		android:layout_weight="20">
	<ScrollView   
        android:layout_width="fill_parent"   
        android:layout_height="fill_parent" > 
	<LinearLayout
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:orientation="vertical"
		android:layout_weight="20">	
    <TextView
        android:background="#ffffaf"
		android:id="@+id/Title"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:textSize="6dp"
		android:text=""
		android:textColor="#ff0000"
		android:layout_weight="1"
		android:gravity="center"
	/>
	<EditText
        android:background="#ffffff"
		android:id="@+id/Text"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:textSize="6dp"
		android:text="正在获取网络信息"
		android:textColor="#0000ff"
		android:layout_weight="1"
	/>
	</LinearLayout>
	</ScrollView>
    </LinearLayout>
	<LinearLayout
		android:layout_width="fill_parent"
		android:layout_height="100dp"
		android:orientation="horizontal"
		android:layout_weight="8">
	<RadioButton
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:text="暂停"
		android:id="@+id/but_pause"
		android:textAllCaps="false"
		android:background="#007f7f"
		android:textColor="#ffffffff"
		android:layout_weight="1"
		android:gravity="center"/>
	<RadioButton
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:text="复制"
		android:id="@+id/but_copy"
		android:textAllCaps="false"
		android:background="#7f7f00"
		android:textColor="#ffffffff"
		android:layout_weight="1"
		android:gravity="center"/>
	<RadioButton
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:text="退出"
		android:id="@+id/but_exit"
		android:textAllCaps="false"
		android:background="#7f007f"
		android:textColor="#ffffffff"
		android:layout_weight="1"
		android:gravity="center"/>
	</LinearLayout>
</LinearLayout>"""
from time import time,localtime,strftime
def getMobileConti():
    t0=0
    v.Text.enabled='false'
    while v.but_copy.checked=='false' and v.but_pause.checked=='false' and v.but_exit.checked=='false':
        t=time()
        if t-t0>=timeInterval:
            getMobileOnce()
            if timeInterval<0:
                #单次测试
                p=v.but_pause
                p.checked='true'
                p.text='继续'
            else:
                t0=t
    v.Text.enabled='true'
def getMobileOnce():
    try:
        rst=rsla('getAllCellsLocation')
        if rst==None or len(rst)==0:
            rst=[{'No Cell Location':'No Signal, No Location Permission or No Phone Permission .'}]
        info=getInfo()
        rst.insert(0,{
'Time':Now(),
#Type:网络类型:5G/4G/3G/2G/Unknown
'Type':rsla('getNetworkType'),
#Level:信号等级:0到4(有的机型是5)
'Level':info['level'],
#Strength:综合信号强度
'Strength':info['dbm']
        })
        txt=[]
        r=txt.append;r('')
        for i in rst:
            for j in i:
                r('%s = %s'%(j,i[j]))
            r('')
        T.text='\n'.join(txt)
    except:
        from traceback import format_exc
        T.text=format_exc()
        v.Title.text="错误信息"
        p=v.but_pause
        p.checked='true'
        p.text='继续'
def Int(x):
    try:
        return int(x)
    except:
        return -255
def Now():
    t=time()
    return strftime('%Y-%m-%d %H:%M:%S',localtime(t))+str(round(t-int(t),3))[1:]
sdk=int(rsla('getSysInfo').get('sdk',0))
#detail:信号详细信息,如RSRP/RSRQ/SNR
#level:信号等级
#dbm:信号电平dbm
#getDbm解析综合信号强度
if sdk<=28:
    rsla('startTrackingSignalStrengths')
    def getInfo():
        detail=rsla('readSignalStrengths')
        try:
            level=detail.pop('level')
        except:
            level='Unknown'
        dbm=getDbm(detail)
        return {'detail':detail,'level':level,'dbm':dbm}
    def getDbm(detail):
        try:
            dbm=detail.pop('dbm')
        except:
            dbm=0
        if detail.get('lte_rsrp',0)==dbm and -40>=dbm>=-140:
            return 'LTE %sdbm %sasu'%(dbm,140+dbm)
        if detail.get('wcdma_rscp',0)==dbm and -20>=dbm>=-120:
            return 'WCDMA %sdbm %sasu'%(dbm,120+dbm)
        return '%sdbm'%dbm
else:
    def getInfo():
        detail=rsla('getTelephoneSignalStrengthDetail')
        level=rsla('getTelephoneSignalStrengthLevel')
        dbm=getDbm(detail)
        return {'detail':detail,'level':level,'dbm':dbm}
    def getDbm(detail):
        form={'ssRsrp':'NR','csiRsrp':'NR','rsrp':'LTE','rscp':'WCDMA'}
        sum={'NR':140,'LTE':140,'WCDMA':120}
        if not detail:
            return 'No Signal'
        detail=detail.replace(' = ','=')
        for m in form:
            i=detail.find(m+'=')
            if i==-1:
                continue
            i+=len(m)+1
            j=detail.find(' ',i)
            dbm=Int(detail[i:j])
            if -20>=dbm>=-140:
                j=form[m]
                i=sum[j]
                return '%s %sdbm %sasu'%(j,dbm,dbm+i)
        form=('rsrp','dbm','rssi')
        detail=detail.lower()
        for m in form:
            i=0
            while True:
                i=detail.find(m+'=',i)
                if i==-1:
                    break
                i+=len(m)+1
                j=detail.find(' ',i)
                dbm=Int(detail[i:j])
                if -20>=dbm>=-140:
                    return '%sdbm'%dbm
                else:
                    i=j
def showInterval():
    if timeInterval<0:
        v.Title.text='单次(手动)测试'
    else:
        v.Title.text='连续(间隔%s秒)测试'%timeInterval
class MainScreen(Layout):
    def on_show(self):
        global v,T
        v=self.views
        T=v.Text
        v.but_pause.add_event(click_EventHandler(v.but_pause,self.pause))
        v.but_copy.add_event(click_EventHandler(v.but_copy,self.copy))
        v.but_exit.add_event(click_EventHandler(v.but_exit,self.exit))
        showInterval()
        getMobileConti()
    def on_close(self):
        pass
    def pause(self,view,dummy):
        p=v.but_pause
        p.checked='false'
        if p.text=='暂停':
            p.text='继续'
        else:
            p.text='暂停'
            showInterval()
            getMobileConti()
    def copy(self,view,dummy):
        jsla('setClipboard',T.text)
        v.but_copy.checked='false'
        jsla('makeToast','移动网络信息已复制')
        if v.but_pause.text=='暂停':
            getMobileConti()
    def exit(self,view,dummy):
        FullScreenWrapper2App.close_layout()
def MobileText(TimeInterval=1):#主函数
#移动网络信息(时间间隔=1秒)
#如果:时间间隔==-1,为单次(手动)测试
#如果:时间间隔>=0,为连续(自动)测试
#请授予QPython位置和电话权限
    global timeInterval,remark
    timeInterval=TimeInterval
    FullScreenWrapper2App.show_layout(MainScreen(XML))
    FullScreenWrapper2App.eventloop()
__all__=('MobileText','droid')
#by 乘着船 at https://www.bilibili.com/read/cv16061380
复制成功

4G 测试

3G 测试1

3G 测试2

2G 测试

无信号 测试

双5G 测试

视频演示:网页链接​

周边WiFi网络测试:网页链接​

作者:乘着船 @ Bilibili

更多文章+下载链接:网页链接​