├── .gitignore ├── .gitmodules ├── DataAsset.py ├── HttpUtil.py ├── LICENSE ├── LogReporter.py ├── Makefile ├── README.md ├── RenderManager.py ├── ScBase.py ├── ScInit.py ├── ScManual.py ├── ScManualEx.py ├── ScManualEx2.py ├── ScMenu.py ├── ScPlayback.py ├── ScRemoteApi.py ├── ScReplay.py ├── ScSetting.py ├── SceneManager.py ├── SeekManager.py ├── TouchManager.py ├── V6Util.py ├── Wanem.py ├── WanemManager.py ├── docs ├── FirstStep.md ├── ManualBuild.md ├── NAT66Info.md ├── PartsList.md └── img │ ├── CarryImage.jpg │ ├── CaseImage.png │ ├── HwImage.jpg │ ├── Parts01.png │ ├── Parts02.png │ ├── Parts03.png │ ├── PortMap.jpg │ ├── RpiBari1.jpg │ ├── RpiBari2.jpg │ ├── SampleIPv6Setting.jpg │ ├── ScreenShotDirectMode.png │ ├── Setup01.jpg │ └── Setup02.jpg ├── misc ├── api │ └── ApiInfo.json ├── dstat │ ├── dstat_cpu_temp.py │ ├── dstat_nat_session.py │ └── dstat_tc_param.py ├── iptables │ ├── iptables.ipv4.nat.type2 │ ├── iptables.ipv4.nat.type3 │ ├── iptables.ipv6.nat.type0 │ ├── iptables.ipv6.nat.type2 │ └── iptables.ipv6.nat.type3 ├── patch │ └── fbtft_python3.patch └── textures │ └── Splash.jpg ├── scripts └── php │ ├── IPv6Switcher.php │ ├── SyncDat.php │ ├── UpdateHostapdConf.php │ └── UpdateNetworkManagerConf.php └── tools ├── WanemCtl.jenkinsfile └── WanemCtl.php /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "fbtft"] 2 | path = fbtft 3 | url = https://github.com/notro/fbtft_test.git 4 | -------------------------------------------------------------------------------- /DataAsset.py: -------------------------------------------------------------------------------- 1 | class CTX: 2 | def __init__(self): 3 | # 4 | # Local Context 5 | # 6 | self.tick = 0 7 | self.current = 0 8 | self.debug = False 9 | self.currentReplayData = "" 10 | self.httpsProxy = "" 11 | # 12 | # Local Config 13 | # 14 | self.replayDataPath = "/usr/local/wanem/dat" 15 | self.connectivityCheckUrl = "https://raw.githubusercontent.com/KONAMI/EM-uNetPi/master/misc/api/ApiInfo.json" 16 | self.infoApiUrl = "https://raw.githubusercontent.com/KONAMI/EM-uNetPi/master/misc/api/ApiInfo.json" 17 | self.copyright = "Powered by Sato_Motohiko" 18 | self.revision = "PLA-A-2024110701" 19 | self.lanV6Addr = "fd00:c0a8:1401::1" 20 | self.wlanV6Addr = "fd00:c0a8:1501::1" 21 | 22 | # 23 | # Local Config ( Runtime Writeable ) 24 | # 25 | self.LAN_MODE_WLAN = 1 26 | self.LAN_MODE_HYBRID = 2 27 | self.lanMode = self.LAN_MODE_HYBRID 28 | #self.lanMode = self.LAN_MODE_HYBRID 29 | self.wifiDongleExist = False 30 | self.v6Available = False 31 | self.eth1Exist = False 32 | self.eth2Exist = False 33 | 34 | # 35 | # Remote Config ( from InfoApi ) 36 | # 37 | self.apiStatus = 2 38 | self.activityReportApiUrl = "" 39 | self.activityReportApiKey = "" 40 | self.dhcpClientReportApiUrl = "" 41 | self.dhcpClientReportApiKey = "" 42 | -------------------------------------------------------------------------------- /HttpUtil.py: -------------------------------------------------------------------------------- 1 | import time, sys, subprocess, random 2 | 3 | 4 | class HttpUtil: 5 | @staticmethod 6 | def CheckConnectivity(host, retryLimit, proxy=""): 7 | proxyArg = "" 8 | if proxy != "": 9 | proxyArg = "--proxy " + str(proxy) 10 | cmd = "curl " + proxyArg + " -s -m 5 -o /dev/null " + host + "?" + str( 11 | random.random()) 12 | ret = False 13 | retryCnt = 0 14 | while ret == False: 15 | try: 16 | print("HttpCheck >> " + cmd); 17 | subprocess.check_call(cmd.strip().split(" ")) 18 | ret = True 19 | except subprocess.CalledProcessError: 20 | print("HttpCheck Fail. Retry after 1sec.") 21 | time.sleep(1) 22 | retryCnt += 1 23 | if retryLimit > 0 and retryLimit <= retryCnt: 24 | break 25 | return ret 26 | 27 | @staticmethod 28 | def Get(url, savePath, retryLimit, proxy=""): 29 | proxyArg = "" 30 | if proxy != "": 31 | proxyArg = "--proxy " + str(proxy) 32 | # cmd = "curl " + proxyArg + " -s -m 5 -o " + savePath + " " + url 33 | cmd = "wget " + url + " -O " + savePath + " --timeout=5" 34 | print("Get >> " + cmd); 35 | ret = False 36 | retryCnt = 0 37 | while ret == False: 38 | try: 39 | subprocess.check_call(cmd.strip().split(" ")) 40 | ret = True 41 | except subprocess.CalledProcessError: 42 | print("HttpCheck Fail. Retry after 1sec.") 43 | time.sleep(1) 44 | retryCnt += 1 45 | if retryLimit > 0 and retryLimit <= retryCnt: 46 | break 47 | return ret 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 - 2024 Konami Digital Entertainment Co., Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LogReporter.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, requests, json, socket 2 | from fcntl import ioctl 3 | from DataAsset import CTX 4 | 5 | 6 | class LogReporter: 7 | @staticmethod 8 | def SendLog(pCTX, activityType, activityInfo): 9 | 10 | url = "" 11 | 12 | headers = { 13 | "content-type": "application/x-www-form-urlencoded", 14 | "x-api-key": pCTX.activityReportApiKey, 15 | } 16 | 17 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 18 | ifreq = struct.pack('256s', 'eth0') 19 | SIOCGIFHWADDR = 0x8927 20 | ifaddr = ioctl(sock.fileno(), SIOCGIFHWADDR, ifreq) 21 | hwaddr = ''.join(['%02x' % ord(char) for char in ifaddr[18:24]])[:-1] 22 | 23 | params = { 24 | 'macAddr': hwaddr, 25 | 'activityType': activityType, 26 | 'activityInfo': activityInfo 27 | } 28 | 29 | r = requests.post(pCTX.activityReportApiUrl, 30 | headers=headers, 31 | data=params) 32 | print(r.text) 33 | #data = r.json() 34 | #print json.dumps(data, indent=4) 35 | 36 | @staticmethod 37 | def ReportDhcpClientInfo(pCTX, info, wanemId, isTmp): 38 | 39 | headers = { 40 | "content-type": "application/json", 41 | "x-api-key": pCTX.dhcpClientReportApiKey, 42 | } 43 | 44 | params = { 45 | 'wanemId': wanemId, 46 | 'clientHostname': info[3], 47 | 'clientIp': info[1], 48 | 'clientMacAddr': info[2], 49 | 'registType': isTmp 50 | } 51 | 52 | r = requests.post(pCTX.dhcpClientReportApiUrl, 53 | headers=headers, 54 | data=json.dumps(params)) 55 | print(r.text) 56 | #print json.dumps(params) 57 | 58 | 59 | if __name__ == '__main__': 60 | #main(sys.argv[1:]) 61 | LogReporter.SendLog(1, "Test") 62 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DEPLOY_TARGET = 192.168.31.67 2 | 3 | default: 4 | 5 | prop: 6 | mkdir -p /etc/wanem/tpl 7 | echo "0" > /etc/wanem/apchannel.prop 8 | echo "0" > /etc/wanem/apmode.prop 9 | echo "0" > /etc/wanem/wanemmode.prop 10 | echo "0" > /etc/wanem/tpl/0.prop 11 | echo "1" > /etc/wanem/tpl/1.prop 12 | echo "2" > /etc/wanem/tpl/2.prop 13 | echo "3" > /etc/wanem/tpl/3.prop 14 | sudo cp misc/iptables/iptables.ipv4.nat.type2 /etc/ 15 | sudo cp misc/iptables/iptables.ipv4.nat.type3 /etc/ 16 | sudo cp misc/iptables/iptables.ipv6.nat.type0 /etc/ 17 | sudo cp misc/iptables/iptables.ipv6.nat.type2 /etc/ 18 | sudo cp misc/iptables/iptables.ipv6.nat.type3 /etc/ 19 | sudo cp /etc/iptables.ipv4.nat.type2 /etc/iptables.ipv4.nat 20 | sudo cp /etc/iptables.ipv6.nat.type0 /etc/iptables.ipv6.nat 21 | 22 | ######################################################################################### 23 | 24 | YAPF ?= yapf 25 | PYTHON_SCRIPTS ?= ${shell ls *.py} 26 | 27 | format: 28 | yapf -i ${PYTHON_SCRIPTS} 29 | 30 | deploy: 31 | rsync -avz ./ pi@192.168.31.67:EM-uNetPi/ 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EM-uNetPi - Emulation Network Tool for Raspberry Pi 2 | ================================================================================================== 3 | 4 | This is the 'EM-uNetPi' network debug tool and is released in open source under MIT License. 5 | 6 | - All the needed documentation is in the /docs folder. 7 | - The completed image file can be obtained from the relsease tab. 8 | 9 | To get started, please read the /docs/FirstStep.md 10 | 11 | OVERVIEW 12 | -------------------------------------------------------------------------------------------------- 13 | 14 | By using EM-uNetPi, you can perform the following line simulation. 15 | 16 | - network bandwidth simulation 17 | - network delay simulation 18 | - packet loss simulation 19 | - disconnections simulation 20 | - symmetric-NAT simulation 21 | 22 | Further, these simulations can be performed by the following method. 23 | 24 | - select preset params 25 | - set parameter directly 26 | - set parameter by api 27 | - replay recorded delay-data ( * temporarily unavailable ) 28 | 29 | The figure below is a demonstration screen in direct designation mode. 30 | 31 | ![](docs/img/ScreenShotDirectMode.png) 32 | 33 | LICENSE 34 | -------------------------------------------------------------------------------------------------- 35 | 36 | 'EM-uNetPi' is released under MIT License. Please refer LICENSE file for detail. 37 | -------------------------------------------------------------------------------- /RenderManager.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from fb import Framebuffer 4 | from gfx import Rect 5 | 6 | 7 | class RenderManager: 8 | def ConvRgb(self, color, saturation, brightness): 9 | rgb = colorsys.hsv_to_rgb( 10 | color, saturation, 11 | brightness) # rgb (color, light, light),,,poi? 0 < range < 1 12 | r = int(rgb[0] * ((1 << self.fb.red.length) - 1)) 13 | g = int(rgb[1] * ((1 << self.fb.green.length) - 1)) 14 | b = int(rgb[2] * ((1 << self.fb.blue.length) - 1)) 15 | return self.fb.rgb(r, g, b) 16 | 17 | def __init__(self): 18 | self.device = '/dev/fb0' 19 | self.xres = 480 20 | self.yres = 320 21 | self.fb = Framebuffer(self.device) 22 | print(self.fb) 23 | self.Clear() 24 | print("# %-30s [ %s ]" % ("Renderer Initialize", "OK")) 25 | self.laneState = [-1, -1, -1] 26 | # pink 0.9, purple 0.8, blue 0.7-0.5, green 0.3-0.1, yello 0.16, 27 | self.N = self.ConvRgb(0, 0, 0) 28 | self.W = self.ConvRgb(1, 0, 1) 29 | self.D = self.ConvRgb(1, 0, 0.2) 30 | self.B = self.ConvRgb(0.7, 1, 1) 31 | self.G = self.ConvRgb(0.4, 1, 1) 32 | self.Y = self.ConvRgb(0.16, 1, 1) 33 | self.O = self.ConvRgb(0.08, 1, 1) 34 | self.R = self.ConvRgb(1, 1, 1) 35 | self.H = self.ConvRgb(0.2, 1, 1) 36 | self.X = self.ConvRgb(0.1, 0.1, 0.1) 37 | self.T = self.ConvRgb(0.16, 1, 1) 38 | #self.P = self.ConvRgb(0.82, 1, 1) 39 | self.P = self.ConvRgb(0.82, 1, 1) 40 | self.dotPattern = [ 41 | [ # 0: test 42 | self.R, self.G, self.B, self.H, self.H, self.H, self.H, self.H, 43 | self.T, self.T, self.P, self.P, self.H, self.H, self.D, self.D 44 | ], 45 | [ # 1: chk1 46 | self.P, self.P, self.D, self.D, self.D, self.D, self.D, self.D, 47 | self.P, self.P, self.D, self.D, self.D, self.D, self.D, self.D 48 | ], 49 | [ # 2: chk2 50 | self.D, self.D, self.P, self.P, self.D, self.D, self.D, self.D, 51 | self.D, self.D, self.P, self.P, self.D, self.D, self.D, self.D 52 | ], 53 | [ # 3: chk3 54 | self.D, self.D, self.D, self.D, self.P, self.P, self.D, self.D, 55 | self.D, self.D, self.D, self.D, self.P, self.P, self.D, self.D 56 | ], 57 | [ # 4: chk4 58 | self.D, self.D, self.D, self.D, self.D, self.D, self.P, self.P, 59 | self.D, self.D, self.D, self.D, self.D, self.D, self.P, self.P 60 | ], 61 | [ # 5: AllDark 62 | self.D, self.D, self.D, self.D, self.D, self.D, self.D, self.D, 63 | self.D, self.D, self.D, self.D, self.D, self.D, self.D, self.D 64 | ], 65 | [ # 6: AllRed 66 | self.R, self.R, self.R, self.R, self.R, self.R, self.R, self.R, 67 | self.R, self.R, self.R, self.R, self.R, self.R, self.R, self.R 68 | ], 69 | [ # 7: Gage1 70 | self.B, self.D, self.D, self.D, self.D, self.D, self.D, self.D, 71 | self.B, self.D, self.D, self.D, self.D, self.D, self.D, self.D 72 | ], 73 | [ # 8: Gage2 74 | self.D, self.G, self.D, self.D, self.D, self.D, self.D, self.D, 75 | self.D, self.G, self.D, self.D, self.D, self.D, self.D, self.D 76 | ], 77 | [ # 9: Gage3 78 | self.D, self.D, self.Y, self.D, self.D, self.D, self.D, self.D, 79 | self.D, self.D, self.Y, self.D, self.D, self.D, self.D, self.D 80 | ], 81 | [ # 10: Gage4 82 | self.D, self.D, self.D, self.O, self.D, self.D, self.D, self.D, 83 | self.D, self.D, self.D, self.O, self.D, self.D, self.D, self.D 84 | ], 85 | [ # 11: Gage5 86 | self.D, self.D, self.D, self.D, self.R, self.D, self.D, self.D, 87 | self.D, self.D, self.D, self.D, self.R, self.D, self.D, self.D 88 | ], 89 | [ 90 | self.X, self.X, self.X, self.X, self.X, self.X, self.X, self.X, 91 | self.X, self.X, self.X, self.X, self.X, self.X, self.X, self.X 92 | ] 93 | ] 94 | 95 | def Clear(self): 96 | self.fb.fill(0) 97 | 98 | def Finalize(self): 99 | self.fb.close() 100 | 101 | def UpdateTitle(self, msg): 102 | self.fb.draw.rect(self.N, Rect(20 + 60, 10, 440 - 60, 26), 0) 103 | self.fb.putstr(20 + 60, 20, msg, self.W, 2) 104 | 105 | def UpdateSubTitle(self, msg): 106 | self.fb.draw.rect(self.N, Rect(20 + 60, 46 + 14, 380, 12), 0) 107 | # self.fb.putstr(20 + 60, 46, msg, self.W, 2) 108 | self.fb.putstr(20 + 60, 46 + 14, msg, self.W, 1) 109 | 110 | def RenderDot(self, laneIdx, patIdx): 111 | w = 20 112 | h = 20 113 | 114 | #if self.laneState[laneIdx] == patIdx: 115 | # return 116 | 117 | self.laneState[laneIdx] = patIdx 118 | pat = self.dotPattern[patIdx] 119 | 120 | for yidx in range(0, 2): 121 | yoffset = 80 * (laneIdx + 1) + (20 + 12) * yidx + 14 122 | for xidx in range(0, 8): 123 | xoffset = (20 + 12) * xidx + 14 124 | seek = yidx * 8 + xidx 125 | #print str(xoffset) + " : " + str(yoffset) + " : " + str(r)+","+str(g)+","+str(b) 126 | self.fb.draw.rect(pat[seek], Rect(xoffset, yoffset, w, h), 0) 127 | 128 | def RenderDotMini(self, laneIdx, patIdx): 129 | w = 20 130 | h = 20 131 | 132 | #if self.laneState[laneIdx] == patIdx: 133 | # return 134 | 135 | self.laneState[laneIdx] = patIdx 136 | pat = self.dotPattern[patIdx] 137 | 138 | for yidx in range(0, 2): 139 | yoffset = 80 * (laneIdx + 1) + (20 + 12) * yidx + 14 140 | for xidx in range(0, 4): 141 | xoffset = (20 + 12) * xidx + 14 142 | seek = yidx * 8 + xidx 143 | #print str(xoffset) + " : " + str(yoffset) + " : " + str(r)+","+str(g)+","+str(b) 144 | self.fb.draw.rect(pat[seek], Rect(xoffset, yoffset, w, h), 0) 145 | -------------------------------------------------------------------------------- /ScBase.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from gfx import Rect 6 | from DataAsset import CTX 7 | 8 | 9 | class ScBase(object): 10 | def __init__(self, pCTX, pRender, pWanem): 11 | self.pCTX = pCTX 12 | self.pRender = pRender 13 | self.pWanem = pWanem 14 | 15 | self.STATE_INIT = 0 16 | self.STATE_TERM = 100 17 | self.state = self.STATE_INIT 18 | self.nextScene = "" 19 | self.ptDef = [] 20 | 21 | def TouchDownHandler(self, x, y): 22 | print("TouchDownHandler Pos >> " + str(x) + " : " + str(y)) 23 | self.CallTouchFunc(x, y, True) 24 | return 25 | 26 | def TouchUpHandler(self, x, y): 27 | print("TouchUpHandler Pos >> " + str(x) + " : " + str(y)) 28 | self.CallTouchFunc(x, y, False) 29 | return 30 | 31 | def Start(self): 32 | self.pRender.Clear() 33 | 34 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 35 | self.pRender.fb.draw.rect( 36 | c, Rect(0, 0, self.pRender.fb.xres - 1, self.pRender.fb.yres - 1), 37 | 1) 38 | self.pRender.fb.draw.rect(c, Rect(2, 2, 4, 4), 0) 39 | self.pRender.fb.draw.rect(c, Rect(2, self.pRender.fb.yres - 6, 4, 4), 40 | 0) 41 | self.pRender.fb.draw.rect(c, Rect(self.pRender.fb.xres - 6, 2, 4, 4), 42 | 0) 43 | self.pRender.fb.draw.rect( 44 | c, Rect(self.pRender.fb.xres - 6, self.pRender.fb.yres - 6, 4, 4), 45 | 0) 46 | 47 | self.state = self.STATE_INIT 48 | 49 | return 50 | 51 | def Update(self): 52 | return 53 | 54 | def RenderBackBt(self, enabled): 55 | if enabled: 56 | c = self.pRender.ConvRgb(0.10, 0.2, 0.8) 57 | else: 58 | c = self.pRender.ConvRgb(0.10, 0.2, 0.3) 59 | self.pRender.fb.draw.rect(c, Rect(7, 7, 62, 38), 0) 60 | c = self.pRender.ConvRgb(0.10, 0.2, 0.2) 61 | self.pRender.fb.draw.rect(c, Rect(7, 7 + 38, 62, 4), 0) 62 | self.pRender.fb.putstr(7 + 8, 7 + 12, "Back", c, 2) 63 | 64 | def CallTouchFunc(self, x, y, isOnDown): 65 | for idx in range(0, len(self.ptDef)): 66 | pt = self.ptDef[idx] 67 | if pt[7] != True: 68 | continue 69 | if x >= (pt[1] - pt[3]) and x <= pt[1] and y > pt[2] and y < ( 70 | pt[2] + pt[4]): 71 | if isOnDown == True: 72 | if pt[5] is not None: 73 | pt[5](pt[0]) 74 | else: 75 | if pt[6] is not None: 76 | pt[6](pt[0]) 77 | break 78 | 79 | def SetTouchActive(self, k, isActive): 80 | for idx in range(0, len(self.ptDef)): 81 | pt = self.ptDef[idx] 82 | if pt[0] == k: 83 | pt[7] = isActive 84 | 85 | def CreateTocuhDef(self, 86 | k, 87 | x, 88 | y, 89 | w, 90 | h, 91 | fOnDown=None, 92 | fOnUp=None, 93 | isActive=True): 94 | return [k, x, y, w, h, fOnDown, fOnUp, isActive] 95 | 96 | def GetSelfId(self): 97 | cpuserial = "0000000000000000" 98 | try: 99 | f = open('/proc/cpuinfo', 'r') 100 | for line in f: 101 | #print(line) 102 | if len(line) > 16: 103 | if line[0:6] == 'Serial': 104 | #print("####### HIT"); 105 | cpuserial = line[10:26] 106 | break 107 | f.close() 108 | except Exception as e: 109 | print('=== EXCEPTION ===') 110 | print('type:' + str(type(e))) 111 | print('args:' + str(e.args)) 112 | print('message:' + e.message) 113 | print('e:' + str(e)) 114 | cpuserial = "00000000000ERROR" 115 | 116 | return cpuserial[10:16] 117 | -------------------------------------------------------------------------------- /ScInit.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, datetime, subprocess, json 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from HttpUtil import HttpUtil 6 | from LogReporter import LogReporter 7 | from ScBase import ScBase 8 | from gfx import Rect 9 | from DataAsset import CTX 10 | from pprint import pprint 11 | from V6Util import V6Util 12 | 13 | class ScInit(ScBase): 14 | def __init__(self, pCTX, pRender, pWanem): 15 | super(ScInit, self).__init__(pCTX, pRender, pWanem) 16 | self.tickCnt = 0 17 | self.tickDuration = 3 18 | self.prevTickCnt = -1 19 | self.stepLabel = [".", "..", "...", "OK", "ERR", "N/A"] 20 | self.worker = None 21 | self.workerRet = 0 22 | 23 | self.STATE_CHK_NETWORK = 1 24 | self.STATE_GET_INFO = 2 25 | self.STATE_CHK_EMULATE_DAT = 3 26 | self.STATE_CHK_WIFI_DONGLE = 4 27 | self.STATE_SETUP_AP = 5 28 | self.STATE_CHK_LAN_INTERFACE = 6 29 | self.STATE_CHK_V6_ENV = 7 30 | self.STATE_CRASH = 8 31 | 32 | def CheckHttpConnectivity(self): 33 | print("-------------------------------") 34 | while HttpUtil.CheckConnectivity(self.pCTX.connectivityCheckUrl, 1, 35 | self.pCTX.httpsProxy) == False: 36 | time.sleep(1) 37 | self.workerRet = 3 38 | print("-------------------------------") 39 | return 40 | 41 | def GetApiInfo(self): 42 | apiUrl = self.pCTX.infoApiUrl 43 | savePath = "/tmp/WanemApiInfo.json" 44 | print("-------------------------------") 45 | while HttpUtil.Get(apiUrl, savePath, 1, self.pCTX.httpsProxy) == False: 46 | time.sleep(1) 47 | file = open(savePath) 48 | dat = json.load(file) 49 | file.close() 50 | #pprint(dat) 51 | self.pCTX.apiStatus = dat["status"]["maintStatus"] 52 | self.workerRet = 3 53 | print("-------------------------------") 54 | return 55 | 56 | def CheckWanemDat(self): 57 | print("-------------------------------") 58 | cmd = "php /home/pi/EM-uNetPi/scripts/php/SyncDat.php" 59 | print(cmd) 60 | ret = False 61 | 62 | try: 63 | subprocess.check_call(cmd.strip().split(" ")) 64 | ret = True 65 | self.workerRet = 3 66 | except subprocess.CalledProcessError: 67 | ret = False 68 | self.workerRet = 4 69 | 70 | print(str(ret)) 71 | print("-------------------------------") 72 | return 73 | 74 | def SetupAP(self): 75 | print("-------------------------------") 76 | cmd = "php /home/pi/EM-uNetPi/scripts/php/UpdateNetworkManagerConf.php wanem-" + self.GetSelfId() 77 | print(cmd) 78 | ret = False 79 | 80 | try: 81 | subprocess.check_call(cmd.strip().split(" ")) 82 | ret = True 83 | self.workerRet = 3 84 | except subprocess.CalledProcessError: 85 | ret = False 86 | self.workerRet = 4 87 | 88 | print(str(ret)) 89 | print("-------------------------------") 90 | return 91 | 92 | def CheckLanInterface(self): 93 | print("-------------------------------") 94 | cmd = "ifconfig eth1" 95 | try: 96 | subprocess.check_call(cmd.strip().split(" ")) 97 | self.workerRet = 3 98 | self.pCTX.eth1Exist = True 99 | except subprocess.CalledProcessError: 100 | self.workerRet = 4 101 | return 102 | 103 | cmd = "ifconfig eth2" 104 | try: 105 | subprocess.check_call(cmd.strip().split(" ")) 106 | self.workerRet = 3 107 | self.pCTX.eth2Exist = True 108 | except subprocess.CalledProcessError: 109 | self.workerRet = 4 110 | 111 | print("-------------------------------") 112 | return 113 | 114 | def CheckV6Env(self): 115 | print("-------------------------------") 116 | if V6Util.IsV6Enabled() == True: 117 | addrList = V6Util.GetGua() 118 | if len(addrList) > 0: 119 | print("GUA Nr " + str(len(addrList))) 120 | for addr in addrList: 121 | print("GUA >> " + addr) 122 | self.workerRet = 3 123 | self.pCTX.v6Available = True 124 | else: 125 | self.workerRet = 5 126 | self.pCTX.v6Available = False 127 | else : 128 | self.workerRet = 5 129 | self.pCTX.v6Available = False 130 | 131 | print("-------------------------------") 132 | return 133 | 134 | def CheckWifiDongle(self): 135 | print("-------------------------------") 136 | 137 | # Dummy Boot for Recognize WiFi Dongle 138 | cmd = "php /home/pi/EM-uNetPi/scripts/php/UpdateNetworkManagerConf.php wanem-" + self.GetSelfId() 139 | try: 140 | subprocess.check_call(cmd.strip().split(" ")) 141 | ret = True 142 | except subprocess.CalledProcessError: 143 | ret = False 144 | 145 | retryLimit = 10 146 | retryCnt = 0 147 | 148 | while retryCnt < retryLimit: 149 | 150 | cmd = "lsusb -d 35bc:0108" 151 | ret = False 152 | 153 | try: 154 | subprocess.check_call(cmd.strip().split(" ")) 155 | self.pCTX.wifiDongleExist = True 156 | break 157 | except subprocess.CalledProcessError: 158 | self.pCTX.wifiDongleExist = False 159 | 160 | retryCnt += 1 161 | time.sleep(5) 162 | 163 | print("WifiDongle Exist : " + str(self.pCTX.wifiDongleExist)) 164 | 165 | if self.pCTX.wifiDongleExist == True: 166 | self.workerRet = 3 167 | else: 168 | self.workerRet = 4 169 | 170 | cmd = "cat /etc/wanem/apmode.prop" 171 | try: 172 | currentApMode = int( 173 | subprocess.check_output(cmd.strip().split(" ")).decode().replace( 174 | '\n', '')) 175 | except subprocess.CalledProcessError: 176 | currentApMode = 0 177 | 178 | print("-------------------------------") 179 | return 180 | 181 | def Start(self): 182 | super(ScInit, self).Start() 183 | 184 | ##[ INIT STATE ]################################################################ 185 | 186 | self.state = self.STATE_TERM 187 | self.nextScene = "Menu" 188 | #self.nextScene = "ManualEx" 189 | self.state = self.STATE_CHK_NETWORK 190 | #self.state = self.STATE_CHK_EMULATE_DAT 191 | #self.workerRet = 0 192 | self.worker = threading.Thread(target=self.CheckHttpConnectivity, 193 | args=()) 194 | #self.worker = threading.Thread(target=self.CheckWanemDat, args=()) 195 | self.worker.start() 196 | 197 | ##[ RENDER ]################################################################ 198 | 199 | self.pRender.UpdateTitle("Boot - rev : " + self.pCTX.revision) 200 | 201 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 202 | self.pRender.fb.draw.rect(c, Rect(0, 54, self.pRender.xres, 1), 0) 203 | 204 | label = "%-18s [ ]" % "CHK NETWORK" 205 | self.pRender.fb.putstr(20, 74 + 32 * 0, label, self.pRender.W, 2) 206 | label = "%-18s [ ]" % "GET API INFO" 207 | self.pRender.fb.putstr(20, 74 + 32 * 1, label, self.pRender.W, 2) 208 | label = "%-18s [ ]" % "IPv6 ENV CHECK" 209 | self.pRender.fb.putstr(20, 74 + 32 * 2, label, self.pRender.W, 2) 210 | label = "%-18s [ ]" % "CHK WIFI DONGLE" 211 | self.pRender.fb.putstr(20, 74 + 32 * 3, label, self.pRender.W, 2) 212 | label = "%-18s [ ]" % "SETUP AP" 213 | self.pRender.fb.putstr(20, 74 + 32 * 4, label, self.pRender.W, 2) 214 | label = "%-18s [ ]" % "CHK LAN INTERFACE" 215 | self.pRender.fb.putstr(20, 74 + 32 * 5, label, self.pRender.W, 2) 216 | 217 | self.pRender.fb.putstr(273, 74 + 32 * 0, " - ", self.pRender.W, 2) 218 | self.pRender.fb.putstr(273, 74 + 32 * 1, " - ", self.pRender.W, 2) 219 | self.pRender.fb.putstr(273, 74 + 32 * 2, " - ", self.pRender.W, 2) 220 | self.pRender.fb.putstr(273, 74 + 32 * 3, " - ", self.pRender.W, 2) 221 | self.pRender.fb.putstr(273, 74 + 32 * 4, " - ", self.pRender.W, 2) 222 | self.pRender.fb.putstr(273, 74 + 32 * 5, " - ", self.pRender.W, 2) 223 | #self.pRender.fb.draw.rect(self.pRender.W, Rect(271, 74, 40, 16), 0) 224 | 225 | return 226 | 227 | def ShowFailMessage(self, msg): 228 | self.pRender.fb.putstr( 229 | 48, 294 - 16, 230 | msg, 231 | self.pRender.R, 2) 232 | 233 | def Update(self): 234 | if self.pCTX.tick == 1: 235 | self.tickCnt = (self.tickCnt + 1) % self.tickDuration 236 | 237 | if self.state == self.STATE_CHK_NETWORK: 238 | if self.worker.is_alive() == False: 239 | self.worker.join() 240 | self.UpdateProgress(0, self.workerRet) 241 | self.state = self.STATE_GET_INFO 242 | self.worker = None 243 | self.workerRet = 0 244 | self.worker = threading.Thread(target=self.GetApiInfo, args=()) 245 | self.worker.start() 246 | else: 247 | if self.tickCnt != self.prevTickCnt: 248 | self.UpdateProgress(0, self.tickCnt) 249 | 250 | elif self.state == self.STATE_GET_INFO: 251 | if self.worker.is_alive() == False: 252 | self.worker.join() 253 | self.UpdateProgress(1, self.workerRet) 254 | self.state = self.STATE_CHK_V6_ENV 255 | self.worker = None 256 | self.workerRet = 0 257 | self.worker = threading.Thread(target=self.CheckV6Env, 258 | args=()) 259 | self.worker.start() 260 | else: 261 | if self.tickCnt != self.prevTickCnt: 262 | self.UpdateProgress(1, self.tickCnt) 263 | 264 | elif self.state == self.STATE_CHK_V6_ENV: 265 | if self.worker.is_alive() == False: 266 | self.worker.join() 267 | self.UpdateProgress(2, self.workerRet) 268 | self.state = self.STATE_CHK_WIFI_DONGLE 269 | self.worker = None 270 | self.workerRet = 0 271 | self.worker = threading.Thread(target=self.CheckWifiDongle, 272 | args=()) 273 | self.worker.start() 274 | else: 275 | if self.tickCnt != self.prevTickCnt: 276 | self.UpdateProgress(2, self.tickCnt) 277 | 278 | elif self.state == self.STATE_CHK_WIFI_DONGLE: 279 | if self.worker.is_alive() == False: 280 | self.worker.join() 281 | self.UpdateProgress(3, self.workerRet) 282 | if self.pCTX.wifiDongleExist == True: 283 | self.state = self.STATE_SETUP_AP 284 | self.worker = None 285 | self.workerRet = 0 286 | self.worker = threading.Thread(target=self.SetupAP, args=()) 287 | self.worker.start() 288 | else: 289 | self.ShowFailMessage("Boot Fail >> WiFi Dongle Error.") 290 | else: 291 | if self.tickCnt != self.prevTickCnt: 292 | self.UpdateProgress(3, self.tickCnt) 293 | 294 | elif self.state == self.STATE_SETUP_AP: 295 | if self.worker.is_alive() == False: 296 | self.worker.join() 297 | self.UpdateProgress(4, self.workerRet) 298 | self.state = self.STATE_CHK_LAN_INTERFACE 299 | self.worker = None 300 | self.workerRet = 0 301 | self.worker = threading.Thread(target=self.CheckLanInterface, 302 | args=()) 303 | self.worker.start() 304 | else: 305 | if self.tickCnt != self.prevTickCnt: 306 | self.UpdateProgress(4, self.tickCnt) 307 | 308 | elif self.state == self.STATE_CHK_LAN_INTERFACE: 309 | if self.worker.is_alive() == False: 310 | self.worker.join() 311 | self.UpdateProgress(5, self.workerRet) 312 | 313 | if self.pCTX.eth1Exist == False: 314 | self.ShowFailMessage("Boot Fail >> LAN Adapter 1 Error.") 315 | elif self.pCTX.eth2Exist == False: 316 | self.ShowFailMessage("Boot Fail >> LAN Adapter 2 Error.") 317 | else: 318 | # init v6 319 | if self.pCTX.v6Available == True: 320 | self.LaunchV6Service() 321 | else: 322 | self.ForceOverwriteV4OnlySetting() 323 | 324 | if self.pCTX.apiStatus == 0: 325 | LogReporter.SendLog(self.pCTX, 1, "StartUp") 326 | 327 | self.state = self.STATE_TERM 328 | self.worker = None 329 | else: 330 | if self.tickCnt != self.prevTickCnt: 331 | self.UpdateProgress(5, self.tickCnt) 332 | 333 | self.prevTickCnt = self.tickCnt 334 | 335 | return 336 | 337 | def LaunchV6Service(self): 338 | 339 | cmd = "cat /etc/iptables.ipv6.nat" 340 | try: 341 | ip6tablesConf = subprocess.Popen(cmd.strip().split(" "), 342 | stdout=subprocess.PIPE) 343 | print("Read ip6tables conf Success") 344 | except subprocess.CalledProcessError: 345 | print("Read ip6tables conf Fail") 346 | 347 | try: 348 | subprocess.Popen("ip6tables-restore",shell=True, 349 | stdin=ip6tablesConf.stdout) 350 | print("Apply ip6tables Conf Success") 351 | except subprocess.CalledProcessError: 352 | print("Apply ip6tables Conf Fail") 353 | 354 | cmd = "systemctl start radvd" 355 | try: 356 | subprocess.check_call(cmd.strip().split(" ")) 357 | print("Launch radvd Success") 358 | except subprocess.CalledProcessError: 359 | print("Launch radvd Fail") 360 | 361 | def ForceOverwriteV4OnlySetting(self): 362 | print("Force Overwrite V4Only Setting") 363 | 364 | cmd = "cp /etc/iptables.ipv6.nat.type0 /etc/iptables.ipv6.nat" 365 | cmd2 = "php /home/pi/EM-uNetPi/scripts/php/IPv6Switcher.php 1" 366 | 367 | try: 368 | subprocess.check_call(cmd.strip().split(" ")) 369 | print("Update V6 NAPT Mode Success") 370 | except subprocess.CalledProcessError: 371 | print("Update V6 NAPT Mode Fail") 372 | 373 | try: 374 | subprocess.check_call(cmd2.strip().split(" ")) 375 | print("Update V6 Mode Success") 376 | except subprocess.CalledProcessError: 377 | print("Update V6 Mode Fail") 378 | 379 | def UpdateProgress(self, target, step): 380 | if step == 3: 381 | c = self.pRender.G 382 | elif step == 4 or step == 5: 383 | c = self.pRender.R 384 | else: 385 | c = self.pRender.W 386 | self.pRender.fb.draw.rect(self.pRender.N, 387 | Rect(271, 74 + 32 * target, 40, 16), 0) 388 | self.pRender.fb.putstr(273, 74 + 32 * target, self.stepLabel[step], c, 389 | 2) 390 | -------------------------------------------------------------------------------- /ScManual.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | 9 | 10 | class ScManual(ScBase): 11 | def __init__(self, pCTX, pRender, pWanem): 12 | super(ScManual, self).__init__(pCTX, pRender, pWanem) 13 | self.ptDef.insert( 14 | 0, self.CreateTocuhDef("BtMenu", 468, 29, 62, 42, self.BtHandler)) 15 | self.ptDef.insert( 16 | 1, 17 | self.CreateTocuhDef("BtConnL", 208 - 90 * 0, 100 + 80 * 0, 80, 48, 18 | self.BtHandler)) 19 | self.ptDef.insert( 20 | 2, 21 | self.CreateTocuhDef("BtConnR", 208 - 90 * 1, 100 + 80 * 0, 80, 48, 22 | self.BtHandler)) 23 | self.ptDef.insert( 24 | 3, 25 | self.CreateTocuhDef("BtSpeedL", 208 - 90 * 0, 100 + 80 * 1, 80, 48, 26 | self.BtHandler)) 27 | self.ptDef.insert( 28 | 4, 29 | self.CreateTocuhDef("BtSpeedR", 208 - 90 * 1, 100 + 80 * 1, 80, 48, 30 | self.BtHandler)) 31 | self.ptDef.insert( 32 | 5, 33 | self.CreateTocuhDef("BtDelayL", 208 - 90 * 0, 100 + 80 * 2, 80, 48, 34 | self.BtHandler)) 35 | self.ptDef.insert( 36 | 6, 37 | self.CreateTocuhDef("BtDelayR", 208 - 90 * 1, 100 + 80 * 2, 80, 48, 38 | self.BtHandler)) 39 | 40 | def BtHandler(self, key): 41 | print("BtHandler" + key) 42 | if key == "BtMenu": 43 | self.pWanem.InitSingle() 44 | self.pWanem.Clear() 45 | self.nextScene = "Menu" 46 | self.state = self.STATE_TERM 47 | elif key == "BtConnL": 48 | self.pWanem.EmuDisconnToggle() 49 | elif key == "BtConnR": 50 | self.pWanem.EmuDisconnPush() 51 | elif key == "BtSpeedL": 52 | self.pWanem.EmuSpeedChange(-1) 53 | elif key == "BtSpeedR": 54 | self.pWanem.EmuSpeedChange(1) 55 | elif key == "BtDelayL": 56 | self.pWanem.EmuDelayChange(-1) 57 | elif key == "BtDelayR": 58 | self.pWanem.EmuDelayChange(1) 59 | 60 | def TouchUpHandler(self, x, y): 61 | #print "TouchUpHandler Pos >> " + str(x) + " : " + str(y) 62 | # for Human Err, All Up to DisconnRelease Call 63 | self.pWanem.EmuDisconnRelease() 64 | return 65 | 66 | def Start(self): 67 | super(ScManual, self).Start() 68 | 69 | ##[ RENDER ]################################################################ 70 | 71 | self.pRender.UpdateTitle("WAN Emulation - Manual Preset") 72 | self.pRender.UpdateSubTitle("speed:nolimit, delay:nolimit") 73 | 74 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 75 | self.pRender.fb.draw.rect(c, Rect(0, 54, self.pRender.xres, 1), 0) 76 | self.pRender.fb.draw.rect(c, Rect(0, 74, self.pRender.xres, 1), 0) 77 | self.pRender.fb.draw.rect(c, Rect(0, 54, 10 + 60, 20), 0) 78 | self.pRender.fb.draw.rect(c, Rect(480 - 10, 54, 10, 20), 0) 79 | self.pRender.fb.putstr(26, 54 + 7, ">>>", self.pRender.N, 1) 80 | 81 | c = self.pRender.ConvRgb(0.16, 1, 0.6) 82 | self.pRender.fb.draw.rect(c, Rect(1, 160, self.pRender.xres - 2, 1), 0) 83 | self.pRender.fb.draw.rect(c, Rect(1, 240, self.pRender.xres - 2, 1), 0) 84 | 85 | self.RenderBackBt(True) 86 | 87 | c = self.pRender.ConvRgb(0.56, 0.6, 0.6) 88 | self.pRender.fb.draw.rect(c, Rect(286, 80 * 3 + 8, 80, 44), 0) 89 | self.pRender.fb.draw.rect(c, Rect(380, 80 * 3 + 8, 80, 44), 0) 90 | self.pRender.fb.putstr(286, 80 * 3 + 64, "Delay/Loss Setting", c, 1) 91 | c = self.pRender.ConvRgb(0.56, 0.3, 0.3) 92 | self.pRender.fb.draw.rect(c, Rect(286, 80 * 3 + 8 + 44, 80, 4), 0) 93 | self.pRender.fb.draw.rect(c, Rect(380, 80 * 3 + 8 + 44, 80, 4), 0) 94 | self.pRender.fb.putstr(286 + 20, 80 * 3 + 12, '<', 0, 5) 95 | self.pRender.fb.putstr(386 + 20, 80 * 3 + 12, '>', 0, 5) 96 | 97 | c = self.pRender.ConvRgb(0.36, 0.6, 0.6) 98 | self.pRender.fb.draw.rect(c, Rect(286, 80 * 2 + 8, 80, 44), 0) 99 | self.pRender.fb.draw.rect(c, Rect(380, 80 * 2 + 8, 80, 44), 0) 100 | self.pRender.fb.putstr(286, 80 * 2 + 64, "Speed Setting", c, 1) 101 | c = self.pRender.ConvRgb(0.36, 0.3, 0.3) 102 | self.pRender.fb.draw.rect(c, Rect(286, 80 * 2 + 8 + 44, 80, 4), 0) 103 | self.pRender.fb.draw.rect(c, Rect(380, 80 * 2 + 8 + 44, 80, 4), 0) 104 | self.pRender.fb.putstr(286 + 20, 80 * 2 + 12, '<', 0, 5) 105 | self.pRender.fb.putstr(386 + 20, 80 * 2 + 12, '>', 0, 5) 106 | 107 | c = self.pRender.ConvRgb(0.98, 0.6, 0.6) 108 | self.pRender.fb.draw.rect(c, Rect(286, 80 * 1 + 8, 80, 44), 0) 109 | self.pRender.fb.draw.rect(c, Rect(380, 80 * 1 + 8, 80, 44), 0) 110 | self.pRender.fb.putstr(286, 80 * 1 + 64, "Disconnect Emulation", c, 1) 111 | c = self.pRender.ConvRgb(0.98, 0.3, 0.3) 112 | self.pRender.fb.draw.rect(c, Rect(286, 80 * 1 + 8 + 44, 80, 4), 0) 113 | self.pRender.fb.draw.rect(c, Rect(380, 80 * 1 + 8 + 44, 80, 4), 0) 114 | self.pRender.fb.putstr(286 + 5, 80 * 1 + 22, "Toggle", 0, 2) 115 | self.pRender.fb.putstr(386 + 11, 80 * 1 + 22, 'Push', 0, 2) 116 | 117 | self.pRender.RenderDot(0, 5) 118 | self.pRender.RenderDot(1, 7) 119 | self.pRender.RenderDot(2, 7) 120 | 121 | self.pWanem.InitSingle() 122 | #self.pWanem.InitDual(0) 123 | #self.pWanem.EmuSpeedChange(1) 124 | #self.pWanem.EmuSpeedChange(-1) 125 | 126 | return 127 | -------------------------------------------------------------------------------- /ScManualEx.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | 9 | 10 | class ScManualEx(ScBase): 11 | def __init__(self, pCTX, pRender, pWanem): 12 | super(ScManualEx, self).__init__(pCTX, pRender, pWanem) 13 | self.ptDef.insert( 14 | 0, self.CreateTocuhDef("BtMenu", 468, 29, 62, 42, self.BtHandler)) 15 | self.ptDef.insert( 16 | 1, self.CreateTocuhDef("BtApply", 149, 255, 110, 48, 17 | self.BtHandler)) 18 | self.ptDef.insert( 19 | 2, self.CreateTocuhDef("BtConnL", 346, 255, 80, 48, 20 | self.BtHandler)) 21 | self.ptDef.insert( 22 | 3, self.CreateTocuhDef("BtConnR", 258, 255, 80, 48, 23 | self.BtHandler)) 24 | self.ptDef.insert( 25 | 4, 26 | self.CreateTocuhDef("BtUpBand1L", 477, 158, 40, 26, 27 | self.BtHandler)) 28 | self.ptDef.insert( 29 | 5, 30 | self.CreateTocuhDef("BtUpBand1R", 405, 158, 40, 26, 31 | self.BtHandler)) 32 | self.ptDef.insert( 33 | 6, 34 | self.CreateTocuhDef("BtUpBand10L", 477, 158 + 30 * 1, 40, 26, 35 | self.BtHandler)) 36 | self.ptDef.insert( 37 | 7, 38 | self.CreateTocuhDef("BtUpBand10R", 405, 158 + 30 * 1, 40, 26, 39 | self.BtHandler)) 40 | self.ptDef.insert( 41 | 8, 42 | self.CreateTocuhDef("BtUpBand100L", 477, 158 + 30 * 2, 40, 26, 43 | self.BtHandler)) 44 | self.ptDef.insert( 45 | 9, 46 | self.CreateTocuhDef("BtUpBand100R", 405, 158 + 30 * 2, 40, 26, 47 | self.BtHandler)) 48 | self.ptDef.insert( 49 | 10, 50 | self.CreateTocuhDef("BtDwBand1L", 368, 158, 40, 26, 51 | self.BtHandler)) 52 | self.ptDef.insert( 53 | 11, 54 | self.CreateTocuhDef("BtDwBand1R", 368 - 72, 158, 40, 26, 55 | self.BtHandler)) 56 | self.ptDef.insert( 57 | 12, 58 | self.CreateTocuhDef("BtDwBand10L", 368, 158 + 30 * 1, 40, 26, 59 | self.BtHandler)) 60 | self.ptDef.insert( 61 | 13, 62 | self.CreateTocuhDef("BtDwBand10R", 368 - 72, 158 + 30 * 1, 40, 26, 63 | self.BtHandler)) 64 | self.ptDef.insert( 65 | 14, 66 | self.CreateTocuhDef("BtDwBand100L", 368, 158 + 30 * 2, 40, 26, 67 | self.BtHandler)) 68 | self.ptDef.insert( 69 | 15, 70 | self.CreateTocuhDef("BtDwBand100R", 368 - 72, 158 + 30 * 2, 40, 26, 71 | self.BtHandler)) 72 | self.ptDef.insert( 73 | 16, 74 | self.CreateTocuhDef("BtUpDelay1L", 258, 158, 40, 26, 75 | self.BtHandler)) 76 | self.ptDef.insert( 77 | 17, 78 | self.CreateTocuhDef("BtUpDelay1R", 258 - 72, 158, 40, 26, 79 | self.BtHandler)) 80 | self.ptDef.insert( 81 | 18, 82 | self.CreateTocuhDef("BtUpDelay10L", 258, 158 + 30 * 1, 40, 26, 83 | self.BtHandler)) 84 | self.ptDef.insert( 85 | 19, 86 | self.CreateTocuhDef("BtUpDelay10R", 258 - 72, 158 + 30 * 1, 40, 26, 87 | self.BtHandler)) 88 | self.ptDef.insert( 89 | 20, 90 | self.CreateTocuhDef("BtUpDelay100L", 258, 158 + 30 * 2, 40, 26, 91 | self.BtHandler)) 92 | self.ptDef.insert( 93 | 21, 94 | self.CreateTocuhDef("BtUpDelay100R", 258 - 72, 158 + 30 * 2, 40, 95 | 26, self.BtHandler)) 96 | self.ptDef.insert( 97 | 22, 98 | self.CreateTocuhDef("BtDwDelay1L", 144, 158, 40, 26, 99 | self.BtHandler)) 100 | self.ptDef.insert( 101 | 23, 102 | self.CreateTocuhDef("BtDwDelay1R", 144 - 72, 158, 40, 26, 103 | self.BtHandler)) 104 | self.ptDef.insert( 105 | 24, 106 | self.CreateTocuhDef("BtDwDelay10L", 144, 158 + 30 * 1, 40, 26, 107 | self.BtHandler)) 108 | self.ptDef.insert( 109 | 25, 110 | self.CreateTocuhDef("BtDwDelay10R", 144 - 72, 158 + 30 * 1, 40, 26, 111 | self.BtHandler)) 112 | self.ptDef.insert( 113 | 26, 114 | self.CreateTocuhDef("BtDwDelay100L", 144, 158 + 30 * 2, 40, 26, 115 | self.BtHandler)) 116 | self.ptDef.insert( 117 | 27, 118 | self.CreateTocuhDef("BtDwDelay100R", 144 - 72, 158 + 30 * 2, 40, 119 | 26, self.BtHandler)) 120 | 121 | def BtHandler(self, key): 122 | print("BtHandler" + key) 123 | if key == "BtMenu": 124 | self.pWanem.ClearEx() 125 | self.nextScene = "Menu" 126 | self.state = self.STATE_TERM 127 | elif key == "BtConnL": 128 | if self.isApply != 0: 129 | self.pWanem.EmuDisconnToggleMini(self.upBand, self.dwBand, 130 | self.upDelay, self.dwDelay) 131 | elif key == "BtConnR": 132 | if self.isApply != 0: 133 | self.pWanem.EmuDisconnPushMini(self.upBand, self.dwBand, 134 | self.upDelay, self.dwDelay) 135 | elif key == "BtApply": 136 | self.isApply = (self.isApply + 1) % 2 137 | self.RenderApplyBt() 138 | if self.isApply == 0: 139 | self.ReleaseDirectParam() 140 | self.pRender.UpdateSubTitle( 141 | "Set Param Manually - Status : Non Active") 142 | else: 143 | self.ApplyDirectParam() 144 | self.pRender.UpdateSubTitle( 145 | "Set Param Manually - Status : Active") 146 | elif key == "BtUpBand1L": 147 | self.UpdateUpBandParam(-1) 148 | elif key == "BtUpBand1R": 149 | self.UpdateUpBandParam(1) 150 | elif key == "BtUpBand10L": 151 | self.UpdateUpBandParam(-10) 152 | elif key == "BtUpBand10R": 153 | self.UpdateUpBandParam(10) 154 | elif key == "BtUpBand100L": 155 | self.UpdateUpBandParam(-100) 156 | elif key == "BtUpBand100R": 157 | self.UpdateUpBandParam(100) 158 | elif key == "BtDwBand1L": 159 | self.UpdateDwBandParam(-1) 160 | elif key == "BtDwBand1R": 161 | self.UpdateDwBandParam(1) 162 | elif key == "BtDwBand10L": 163 | self.UpdateDwBandParam(-10) 164 | elif key == "BtDwBand10R": 165 | self.UpdateDwBandParam(10) 166 | elif key == "BtDwBand100L": 167 | self.UpdateDwBandParam(-100) 168 | elif key == "BtDwBand100R": 169 | self.UpdateDwBandParam(100) 170 | elif key == "BtUpDelay1L": 171 | self.UpdateUpDelayParam(-1) 172 | elif key == "BtUpDelay1R": 173 | self.UpdateUpDelayParam(1) 174 | elif key == "BtUpDelay10L": 175 | self.UpdateUpDelayParam(-10) 176 | elif key == "BtUpDelay10R": 177 | self.UpdateUpDelayParam(10) 178 | elif key == "BtUpDelay100L": 179 | self.UpdateUpDelayParam(-100) 180 | elif key == "BtUpDelay100R": 181 | self.UpdateUpDelayParam(100) 182 | elif key == "BtDwDelay1L": 183 | self.UpdateDwDelayParam(-1) 184 | elif key == "BtDwDelay1R": 185 | self.UpdateDwDelayParam(1) 186 | elif key == "BtDwDelay10L": 187 | self.UpdateDwDelayParam(-10) 188 | elif key == "BtDwDelay10R": 189 | self.UpdateDwDelayParam(10) 190 | elif key == "BtDwDelay100L": 191 | self.UpdateDwDelayParam(-100) 192 | elif key == "BtDwDelay100R": 193 | self.UpdateDwDelayParam(100) 194 | 195 | def TouchUpHandler(self, x, y): 196 | #print "TouchUpHandler Pos >> " + str(x) + " : " + str(y) 197 | # for Human Err, All Up to DisconnRelease Call 198 | if self.isApply != 0: 199 | self.pWanem.EmuDisconnReleaseMini(self.upBand, self.dwBand, 200 | self.upDelay, self.dwDelay) 201 | return 202 | 203 | def ApplyDirectParam(self): 204 | self.pRender.fb.draw.rect(self.pRender.N, 205 | Rect(116 * 0 + 20, 112, 60, 18), 0) 206 | self.pRender.fb.draw.rect(self.pRender.N, 207 | Rect(116 * 1 + 20, 112, 60, 18), 0) 208 | self.pRender.fb.draw.rect(self.pRender.N, 209 | Rect(116 * 2 + 20, 112, 60, 18), 0) 210 | self.pRender.fb.draw.rect(self.pRender.N, 211 | Rect(116 * 3 + 20, 112, 60, 18), 0) 212 | self.pRender.fb.putstr(116 * 0 + 16 * 1 + 10, 114, 213 | "%04d" % self.upBand, self.pRender.W, 2) 214 | self.pRender.fb.putstr(116 * 1 + 16 * 1 + 10, 114, 215 | "%04d" % self.dwBand, self.pRender.W, 2) 216 | self.pRender.fb.putstr(116 * 2 + 16 * 1 + 10, 114, 217 | "%04d" % self.upDelay, self.pRender.W, 2) 218 | self.pRender.fb.putstr(116 * 3 + 16 * 1 + 10, 114, 219 | "%04d" % self.dwDelay, self.pRender.W, 2) 220 | self.pWanem.DirectApplyEx(self.upBand, self.dwBand, self.upDelay, 221 | self.dwDelay) 222 | 223 | def ReleaseDirectParam(self): 224 | c = self.pRender.ConvRgb(0.94, 0.8, 0.9) 225 | self.pRender.fb.draw.rect(self.pRender.N, 226 | Rect(116 * 0 + 20, 112, 60, 18), 0) 227 | self.pRender.fb.draw.rect(self.pRender.N, 228 | Rect(116 * 1 + 20, 112, 60, 18), 0) 229 | self.pRender.fb.draw.rect(self.pRender.N, 230 | Rect(116 * 2 + 20, 112, 60, 18), 0) 231 | self.pRender.fb.draw.rect(self.pRender.N, 232 | Rect(116 * 3 + 20, 112, 60, 18), 0) 233 | self.pRender.fb.putstr(116 * 0 + 16 * 1 + 10, 114, 234 | "%04d" % self.upBand, c, 2) 235 | self.pRender.fb.putstr(116 * 1 + 16 * 1 + 10, 114, 236 | "%04d" % self.dwBand, c, 2) 237 | self.pRender.fb.putstr(116 * 2 + 16 * 1 + 10, 114, 238 | "%04d" % self.upDelay, c, 2) 239 | self.pRender.fb.putstr(116 * 3 + 16 * 1 + 10, 114, 240 | "%04d" % self.dwDelay, c, 2) 241 | self.pWanem.ClearEx() 242 | 243 | def UpdateUpBandParam(self, delta): 244 | if self.isApply != 0: 245 | return 246 | self.upBand = self.upBand + delta 247 | if self.upBand > 9999: 248 | self.upBand = 9999 249 | if self.upBand < 16: 250 | self.upBand = 16 251 | self.RenderParamForm(0, "", "%04d" % self.upBand, "", True) 252 | 253 | def UpdateDwBandParam(self, delta): 254 | if self.isApply != 0: 255 | return 256 | self.dwBand = self.dwBand + delta 257 | if self.dwBand > 9999: 258 | self.dwBand = 9999 259 | if self.dwBand < 16: 260 | self.dwBand = 16 261 | self.RenderParamForm(1, "", "%04d" % self.dwBand, "", True) 262 | 263 | def UpdateUpDelayParam(self, delta): 264 | if self.isApply != 0: 265 | return 266 | self.upDelay = self.upDelay + delta 267 | if self.upDelay > 9999: 268 | self.upDelay = 9999 269 | if self.upDelay < 0: 270 | self.upDelay = 0 271 | self.RenderParamForm(2, "", "%04d" % self.upDelay, "", True) 272 | 273 | def UpdateDwDelayParam(self, delta): 274 | if self.isApply != 0: 275 | return 276 | self.dwDelay = self.dwDelay + delta 277 | if self.dwDelay > 9999: 278 | self.dwDelay = 9999 279 | if self.dwDelay < 0: 280 | self.dwDelay = 0 281 | self.RenderParamForm(3, "", "%04d" % self.dwDelay, "", True) 282 | 283 | def RenderParamForm(self, idx, label, value, unit, isParamOnly=False): 284 | 285 | if isParamOnly == True: 286 | self.pRender.fb.draw.rect(self.pRender.N, 287 | Rect(116 * idx + 20, 112, 60, 18), 0) 288 | 289 | c = self.pRender.ConvRgb(0.94, 0.8, 0.9) 290 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 10, 114, value, c, 2) 291 | 292 | if isParamOnly == True: 293 | return 294 | 295 | c = self.pRender.ConvRgb(0.44, 0.3, 0.9) 296 | self.pRender.fb.putstr(116 * idx + 16 * 1, 85, label, c, 2) 297 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 10 + 58, 120, unit, 298 | self.pRender.W, 1) 299 | 300 | c = self.pRender.ConvRgb(0.4, 0.6, 0.4) 301 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 16 * 1, 100, 100, 2), 0) 302 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 16 * 1, 100 + 40, 100, 303 | 2), 0) 304 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 16 * 1, 100, 2, 40), 0) 305 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 16 * 1 + 100, 100, 2, 306 | 42), 0) 307 | 308 | c = self.pRender.W 309 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 33, 152 + 30 * 0, " 1", c, 310 | 2) 311 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 33 + 6, 152 + 30 + 1, "10", 312 | c, 2) 313 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 33, 152 + 30 * 2, "100", c, 314 | 2) 315 | 316 | c = self.pRender.ConvRgb(0.44, 0.9, 0.7) 317 | self.pRender.fb.draw.rect( 318 | c, Rect(116 * idx + 16 * 1, 146 + 30 * 0, 30, 26), 0) 319 | self.pRender.fb.draw.rect( 320 | c, Rect(116 * idx + 16 * 1 + 72, 146 + 30 * 0, 30, 26), 0) 321 | self.pRender.fb.draw.rect( 322 | c, Rect(116 * idx + 16 * 1, 146 + 30 * 1, 30, 26), 0) 323 | self.pRender.fb.draw.rect( 324 | c, Rect(116 * idx + 16 * 1 + 72, 146 + 30 * 1, 30, 26), 0) 325 | self.pRender.fb.draw.rect( 326 | c, Rect(116 * idx + 16 * 1, 146 + 30 * 2, 30, 26), 0) 327 | self.pRender.fb.draw.rect( 328 | c, Rect(116 * idx + 16 * 1 + 72, 146 + 30 * 2, 30, 26), 0) 329 | 330 | c = self.pRender.ConvRgb(0.44, 0.1, 1) 331 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 5, 145 + 30 * 0, "-", c, 4) 332 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 77, 145 + 30 * 0, "+", c, 333 | 4) 334 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 5, 145 + 30 * 1, "-", c, 4) 335 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 77, 145 + 30 * 1, "+", c, 336 | 4) 337 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 5, 145 + 30 * 2, "-", c, 4) 338 | self.pRender.fb.putstr(116 * idx + 16 * 1 + 77, 145 + 30 * 2, "+", c, 339 | 4) 340 | 341 | def Start(self): 342 | super(ScManualEx, self).Start() 343 | 344 | ##[ PARAM ]################################################################ 345 | 346 | self.upBand = 512 347 | self.dwBand = 512 348 | self.upDelay = 0 349 | self.dwDelay = 0 350 | self.isApply = 0 351 | 352 | ##[ RENDER ]################################################################ 353 | 354 | self.pRender.UpdateTitle("WAN Emulation - Manual Direct") 355 | self.pRender.UpdateSubTitle("Set Param Manually - Status : Non Active") 356 | 357 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 358 | self.pRender.fb.draw.rect(c, Rect(0, 54, self.pRender.xres, 1), 0) 359 | self.pRender.fb.draw.rect(c, Rect(0, 74, self.pRender.xres, 1), 0) 360 | self.pRender.fb.draw.rect(c, Rect(0, 54, 10 + 60, 20), 0) 361 | self.pRender.fb.draw.rect(c, Rect(480 - 10, 54, 10, 20), 0) 362 | self.pRender.fb.putstr(26, 54 + 7, ">>>", self.pRender.N, 1) 363 | 364 | c = self.pRender.ConvRgb(0.16, 1, 0.6) 365 | #self.pRender.fb.draw.rect(c, Rect(1, 160, self.pRender.xres-2, 1), 0) 366 | self.pRender.fb.draw.rect(c, 367 | Rect(1, 240, self.pRender.xres - 2 - 150, 1), 368 | 0) 369 | self.pRender.fb.draw.rect( 370 | c, Rect(self.pRender.xres - 150 - 1, 240, 1, 79), 0) 371 | 372 | self.RenderBackBt(True) 373 | 374 | self.RenderParamForm(0, "Up Band", "%04d" % self.upBand, "kbps") 375 | self.RenderParamForm(1, "Dw Band", "%04d" % self.dwBand, "kbps") 376 | self.RenderParamForm(2, "Up Delay", "%04d" % self.upDelay, "msec") 377 | self.RenderParamForm(3, "Dw Delay", "%04d" % self.dwDelay, "msec") 378 | #c = self.pRender.ConvRgb(0.56,0.6,0.6) 379 | #self.pRender.fb.draw.rect(c, Rect(286, 80*3 + 8, 80, 44), 0) 380 | #self.pRender.fb.draw.rect(c, Rect(380, 80*3 + 8, 80, 44), 0) 381 | #self.pRender.fb.putstr(286, 80*3+64, "Delay Setting", c, 1) 382 | #c = self.pRender.ConvRgb(0.56,0.3,0.3) 383 | #self.pRender.fb.draw.rect(c, Rect(286, 80*3 + 8 + 44, 80, 4), 0) 384 | #self.pRender.fb.draw.rect(c, Rect(380, 80*3 + 8 + 44, 80, 4), 0) 385 | #self.pRender.fb.putstr(286 + 20, 80*3 + 12, '<', 0, 5) 386 | #self.pRender.fb.putstr(386 + 20, 80*3 + 12, '>', 0, 5) 387 | 388 | #c = self.pRender.ConvRgb(0.36,0.6,0.6) 389 | #self.pRender.fb.draw.rect(c, Rect(286, 80*2 + 8, 80, 44), 0) 390 | #self.pRender.fb.draw.rect(c, Rect(380, 80*2 + 8, 80, 44), 0) 391 | #self.pRender.fb.putstr(286, 80*2+64, "Speed Setting", c, 1) 392 | #c = self.pRender.ConvRgb(0.36,0.3,0.3) 393 | #self.pRender.fb.draw.rect(c, Rect(286, 80*2 + 8 + 44, 80, 4), 0) 394 | #self.pRender.fb.draw.rect(c, Rect(380, 80*2 + 8 + 44, 80, 4), 0) 395 | #self.pRender.fb.putstr(286 + 20, 80*2 + 12, '<', 0, 5) 396 | #self.pRender.fb.putstr(386 + 20, 80*2 + 12, '>', 0, 5) 397 | 398 | c = self.pRender.ConvRgb(0.98, 0.6, 0.6) 399 | self.pRender.fb.draw.rect(c, Rect(286 - 140, 80 * 3 + 8, 80, 44), 0) 400 | self.pRender.fb.draw.rect(c, Rect(380 - 140, 80 * 3 + 8, 80, 44), 0) 401 | self.pRender.fb.putstr(286 - 140, 80 * 3 + 64, "Disconnect Emulation", 402 | c, 1) 403 | c = self.pRender.ConvRgb(0.98, 0.3, 0.3) 404 | self.pRender.fb.draw.rect(c, Rect(286 - 140, 80 * 3 + 8 + 44, 80, 4), 405 | 0) 406 | self.pRender.fb.draw.rect(c, Rect(380 - 140, 80 * 3 + 8 + 44, 80, 4), 407 | 0) 408 | self.pRender.fb.putstr(286 - 140 + 5, 80 * 3 + 22, "Toggle", 0, 2) 409 | self.pRender.fb.putstr(386 - 140 + 11, 80 * 3 + 22, 'Push', 0, 2) 410 | 411 | self.pRender.RenderDotMini(2, 5) 412 | 413 | self.RenderApplyBt() 414 | self.pWanem.ClearEx() 415 | 416 | return 417 | 418 | def RenderApplyBt(self): 419 | c = self.pRender.ConvRgb(0.18, 0.6, 0.6) 420 | self.pRender.fb.draw.rect(c, Rect(350, 80 * 3 + 8, 110, 44), 0) 421 | self.pRender.fb.putstr(350, 80 * 3 + 64, "Wan Setting", c, 1) 422 | c = self.pRender.ConvRgb(0.18, 0.3, 0.3) 423 | self.pRender.fb.draw.rect(c, Rect(350, 80 * 3 + 8 + 44, 110, 4), 0) 424 | if self.isApply == 0: 425 | self.pRender.fb.putstr(350 + 24, 80 * 3 + 22, "Apply", 0, 2) 426 | else: 427 | self.pRender.fb.putstr(350 + 12, 80 * 3 + 22, "Release", 0, 2) 428 | -------------------------------------------------------------------------------- /ScManualEx2.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | 9 | 10 | class ScManualEx2(ScBase): 11 | def __init__(self, pCTX, pRender, pWanem): 12 | super(ScManualEx2, self).__init__(pCTX, pRender, pWanem) 13 | self.ptDef.insert( 14 | 0, self.CreateTocuhDef("BtMenu", 468, 29, 62, 42, self.BtHandler)) 15 | self.ptDef.insert( 16 | 1, self.CreateTocuhDef("BtApply", 149, 255, 110, 48, 17 | self.BtHandler)) 18 | self.ptDef.insert( 19 | 2, self.CreateTocuhDef("BtConnL", 346, 255, 80, 48, 20 | self.BtHandler)) 21 | self.ptDef.insert( 22 | 3, self.CreateTocuhDef("BtConnR", 258, 255, 80, 48, 23 | self.BtHandler)) 24 | self.ptDef.insert( 25 | 4, 26 | self.CreateTocuhDef("BtUp1L", 477 + 6, 158, 40, 26, 27 | self.BtHandler)) 28 | self.ptDef.insert( 29 | 5, 30 | self.CreateTocuhDef("BtUp1R", 405 + 6, 158, 40, 26, 31 | self.BtHandler)) 32 | self.ptDef.insert( 33 | 6, 34 | self.CreateTocuhDef("BtUp10L", 477 + 6, 158 + 30 * 1, 40, 26, 35 | self.BtHandler)) 36 | self.ptDef.insert( 37 | 7, 38 | self.CreateTocuhDef("BtUp10R", 405 + 6, 158 + 30 * 1, 40, 26, 39 | self.BtHandler)) 40 | self.ptDef.insert( 41 | 8, 42 | self.CreateTocuhDef("BtUp100L", 477 + 6, 158 + 30 * 2, 40, 26, 43 | self.BtHandler)) 44 | self.ptDef.insert( 45 | 9, 46 | self.CreateTocuhDef("BtUp100R", 405 + 6, 158 + 30 * 2, 40, 26, 47 | self.BtHandler)) 48 | self.ptDef.insert( 49 | 10, 50 | self.CreateTocuhDef("BtDw1L", 368 + 6, 158, 40, 26, 51 | self.BtHandler)) 52 | self.ptDef.insert( 53 | 11, 54 | self.CreateTocuhDef("BtDw1R", 368 - 72 + 6, 158, 40, 26, 55 | self.BtHandler)) 56 | self.ptDef.insert( 57 | 12, 58 | self.CreateTocuhDef("BtDw10L", 368 + 6, 158 + 30 * 1, 40, 26, 59 | self.BtHandler)) 60 | self.ptDef.insert( 61 | 13, 62 | self.CreateTocuhDef("BtDw10R", 368 - 72 + 6, 158 + 30 * 1, 40, 26, 63 | self.BtHandler)) 64 | self.ptDef.insert( 65 | 14, 66 | self.CreateTocuhDef("BtDw100L", 368 + 6, 158 + 30 * 2, 40, 26, 67 | self.BtHandler)) 68 | self.ptDef.insert( 69 | 15, 70 | self.CreateTocuhDef("BtDw100R", 368 - 72 + 6, 158 + 30 * 2, 40, 26, 71 | self.BtHandler)) 72 | 73 | self.ptDef.insert( 74 | 16, 75 | self.CreateTocuhDef("BtEditBand", 248, 98, 52, 39, self.BtHandler)) 76 | self.ptDef.insert( 77 | 17, 78 | self.CreateTocuhDef("BtEditDelay", 248, 147, 52, 39, 79 | self.BtHandler)) 80 | self.ptDef.insert( 81 | 18, 82 | self.CreateTocuhDef("BtEditLoss", 248, 196, 52, 39, 83 | self.BtHandler)) 84 | 85 | def BtHandler(self, key): 86 | print("BtHandler" + key) 87 | if key == "BtMenu": 88 | self.pWanem.ClearEx() 89 | self.nextScene = "Menu" 90 | self.state = self.STATE_TERM 91 | elif key == "BtConnL": 92 | if self.isApply != 0: 93 | self.pWanem.EmuDisconnToggleMini(self.upBand, self.dwBand, 94 | self.upDelay, self.dwDelay, 95 | self.upLoss, self.dwLoss) 96 | elif key == "BtConnR": 97 | if self.isApply != 0: 98 | self.pWanem.EmuDisconnPushMini(self.upBand, self.dwBand, 99 | self.upDelay, self.dwDelay, 100 | self.upLoss, self.dwLoss) 101 | elif key == "BtApply": 102 | self.isApply = (self.isApply + 1) % 2 103 | self.RenderApplyBt() 104 | if self.isApply == 0: 105 | self.ReleaseDirectParam() 106 | self.pRender.UpdateSubTitle( 107 | "Set Param Manually - Status : Non Active") 108 | else: 109 | self.ApplyDirectParam() 110 | self.pRender.UpdateSubTitle( 111 | "Set Param Manually - Status : Active") 112 | elif key == "BtUp1L": 113 | self.UpdateUpParam(-1) 114 | elif key == "BtUp1R": 115 | self.UpdateUpParam(1) 116 | elif key == "BtUp10L": 117 | self.UpdateUpParam(-10) 118 | elif key == "BtUp10R": 119 | self.UpdateUpParam(10) 120 | elif key == "BtUp100L": 121 | self.UpdateUpParam(-100) 122 | elif key == "BtUp100R": 123 | self.UpdateUpParam(100) 124 | elif key == "BtDw1L": 125 | self.UpdateDwParam(-1) 126 | elif key == "BtDw1R": 127 | self.UpdateDwParam(1) 128 | elif key == "BtDw10L": 129 | self.UpdateDwParam(-10) 130 | elif key == "BtDw10R": 131 | self.UpdateDwParam(10) 132 | elif key == "BtDw100L": 133 | self.UpdateDwParam(-100) 134 | elif key == "BtDw100R": 135 | self.UpdateDwParam(100) 136 | elif key == "BtEditBand": 137 | self.SwitchLink(0) 138 | elif key == "BtEditDelay": 139 | self.SwitchLink(1) 140 | elif key == "BtEditLoss": 141 | self.SwitchLink(2) 142 | 143 | def TouchUpHandler(self, x, y): 144 | # print "TouchUpHandler Pos >> " + str(x) + " : " + str(y) 145 | # for Human Err, All Up to DisconnRelease Call 146 | if self.isApply != 0: 147 | self.pWanem.EmuDisconnReleaseMini(self.upBand, self.dwBand, 148 | self.upDelay, self.dwDelay, 149 | self.upLoss, self.dwLoss) 150 | return 151 | 152 | def ApplyDirectParam(self): 153 | self.RenderWire(True) 154 | self.pWanem.DirectApplyEx(self.upBand, self.dwBand, self.upDelay, 155 | self.dwDelay, self.upLoss, self.dwLoss) 156 | 157 | def ReleaseDirectParam(self): 158 | self.RenderWire(False) 159 | self.pWanem.ClearEx() 160 | 161 | def UpdateUpParam(self, delta): 162 | if self.isApply != 0: 163 | return 164 | if self.currentEdit == 0: 165 | self.upBand = self.upBand + delta 166 | if self.upBand > 9999: 167 | self.upBand = 9999 168 | if self.upBand < 32: 169 | self.upBand = 32 170 | self.RenderParamForm(0, "Up Band", "%04d" % self.upBand, "kbps", 171 | True) 172 | self.RenderUpdateParamRow(0, "%04d" % self.upBand, True) 173 | elif self.currentEdit == 1: 174 | self.upDelay = self.upDelay + delta 175 | if self.upDelay > 9999: 176 | self.upDelay = 9999 177 | if self.upDelay < 0: 178 | self.upDelay = 0 179 | self.RenderParamForm(0, "Up Delay", "%04d" % self.upDelay, "msec", 180 | True) 181 | self.RenderUpdateParamRow(1, "%04d" % self.upDelay, True) 182 | elif self.currentEdit == 2: 183 | self.upLoss = self.upLoss + delta 184 | if self.upLoss > 100: 185 | self.upLoss = 100 186 | if self.upLoss < 0: 187 | self.upLoss = 0 188 | self.RenderParamForm(0, "Up Loss", "%4d" % self.upLoss, "%", True) 189 | self.RenderUpdateParamRow(2, "%4d" % self.upLoss, True) 190 | 191 | def UpdateDwParam(self, delta): 192 | if self.isApply != 0: 193 | return 194 | if self.currentEdit == 0: 195 | self.dwBand = self.dwBand + delta 196 | if self.dwBand > 9999: 197 | self.dwBand = 9999 198 | if self.dwBand < 32: 199 | self.dwBand = 32 200 | self.RenderParamForm(1, "Dw Band", "%04d" % self.dwBand, "kbps", 201 | True) 202 | self.RenderUpdateParamRow(0, "%04d" % self.dwBand, False) 203 | elif self.currentEdit == 1: 204 | self.dwDelay = self.dwDelay + delta 205 | if self.dwDelay > 9999: 206 | self.dwDelay = 9999 207 | if self.dwDelay < 0: 208 | self.dwDelay = 0 209 | self.RenderParamForm(1, "Dw Delay", "%04d" % self.dwDelay, "msec", 210 | True) 211 | self.RenderUpdateParamRow(1, "%04d" % self.dwDelay, False) 212 | elif self.currentEdit == 2: 213 | self.dwLoss = self.dwLoss + delta 214 | if self.dwLoss > 100: 215 | self.dwLoss = 100 216 | if self.dwLoss < 0: 217 | self.dwLoss = 0 218 | self.RenderParamForm(1, "Dw Loss", "%4d" % self.dwLoss, "%", True) 219 | self.RenderUpdateParamRow(2, "%4d" % self.dwLoss, False) 220 | 221 | def RenderParamRowBt(self, idx, isActive=False): 222 | 223 | if isActive == False: 224 | c = self.pRender.ConvRgb(0.14, 0.8, 0.7) 225 | #self.pRender.fb.draw.rect(c, Rect(238 + 2 , 84 + 50 * idx + 2, 60, 43), 0) 226 | self.pRender.fb.draw.rect(c, Rect(238 + 3, 84 + 50 * idx + 4, 2, 227 | 40), 0) 228 | self.pRender.fb.draw.rect( 229 | c, Rect(238 + 2 + 55, 84 + 50 * idx + 4, 2, 40), 0) 230 | self.pRender.fb.draw.rect( 231 | c, Rect(238 + 3, 84 + 50 * idx + 4 + 38, 56, 2), 0) 232 | 233 | if isActive == True: 234 | c = self.pRender.ConvRgb(0.9, 1.0, 1.0) 235 | self.pRender.fb.draw.rect(c, Rect(241, 88 + 50 * idx, 56, 2), 0) 236 | self.pRender.fb.draw.rect(c, Rect(241, 88 + 50 * idx + 38, 56, 2), 237 | 0) 238 | self.pRender.fb.draw.rect(c, Rect(241, 88 + 50 * idx, 2, 40), 0) 239 | self.pRender.fb.draw.rect(c, Rect(241 + 54, 88 + 50 * idx, 2, 40), 240 | 0) 241 | 242 | c = self.pRender.ConvRgb(0.51, 0.3, 0.2) 243 | self.pRender.fb.draw.rect(c, Rect(243, 90 + 50 * idx + 32, 52, 4), 0) 244 | 245 | c = self.pRender.ConvRgb(0.51, 0.6, 0.79) 246 | if isActive == True: 247 | self.pRender.fb.draw.rect(c, Rect(243, 90 + 50 * idx, 52, 35), 0) 248 | self.pRender.fb.putstr(243 + 3, 90 + 50 * idx + 11, "LINK", 249 | self.pRender.N, 2) 250 | else: 251 | self.pRender.fb.draw.rect(c, Rect(243, 90 + 50 * idx - 2, 52, 35), 252 | 0) 253 | self.pRender.fb.putstr(243 + 3, 90 + 50 * idx + 11 - 2, "EDIT", 254 | self.pRender.N, 2) 255 | 256 | def RenderUpdateParamRow(self, idx, value, isUp=True): 257 | #c = self.pRender.ConvRgb(0.44,0.4,0.7); 258 | if isUp == True: 259 | c = self.pRender.N 260 | self.pRender.fb.draw.rect(c, Rect(306, 110 + 50 * idx, 46, 14), 0) 261 | c = self.pRender.ConvRgb(0.44, 0.3, 0.9) 262 | self.pRender.fb.putstr(306, 110 + 50 * idx, value, c, 2) 263 | else: 264 | c = self.pRender.N 265 | self.pRender.fb.draw.rect(c, Rect(386, 110 + 50 * idx, 46, 14), 0) 266 | c = self.pRender.ConvRgb(0.44, 0.3, 0.9) 267 | self.pRender.fb.putstr(306 + 80, 110 + 50 * idx, value, c, 2) 268 | 269 | def RenderParamRow(self, 270 | idx, 271 | UpLabel, 272 | UpValue, 273 | UpUnit, 274 | DwLabel, 275 | DwValue, 276 | DwUnit, 277 | isActive, 278 | opt=""): 279 | 280 | c = self.pRender.ConvRgb(0.44, 0.3, 0.9) 281 | self.pRender.fb.putstr(306, 110 + 50 * idx, UpValue, c, 2) 282 | self.pRender.fb.putstr(306 + 80, 110 + 50 * idx, DwValue, c, 2) 283 | 284 | c = self.pRender.ConvRgb(0.14, 0.8, 0.7) 285 | self.pRender.fb.draw.rect(c, Rect(238, 84 + 50 * idx, 229, 2), 0) 286 | self.pRender.fb.draw.rect(c, Rect(238, 84 + 50 * idx + 45, 229, 2), 0) 287 | self.pRender.fb.draw.rect(c, Rect(238, 84 + 50 * idx, 2, 47), 0) 288 | self.pRender.fb.draw.rect(c, Rect(238 + 207 + 20, 84 + 50 * idx, 2, 289 | 47), 0) 290 | self.pRender.fb.draw.rect(c, Rect(238 + 2, 84 + 50 * idx + 2, 60, 43), 291 | 0) 292 | 293 | if opt != "": 294 | c = self.pRender.ConvRgb(0.96, 0.9, 0.7) 295 | self.pRender.fb.draw.rect(c, Rect(446, 87 + 50 * idx, 18, 12), 0) 296 | c = self.pRender.ConvRgb(0, 0, 0.5) 297 | self.pRender.fb.putstr(452, 86 + 50 * idx + 4, opt, self.pRender.W, 298 | 1) 299 | 300 | self.pRender.fb.putstr(306 + 50, 116 + 50 * idx, UpUnit, 301 | self.pRender.W, 1) 302 | self.pRender.fb.putstr(306 + 130, 116 + 50 * idx, DwUnit, 303 | self.pRender.W, 1) 304 | 305 | c = self.pRender.ConvRgb(0, 0, 0.5) 306 | self.pRender.fb.draw.rect(c, Rect(304, 102 + 50 * idx, 157, 1), 0) 307 | 308 | self.pRender.fb.putstr(306, 88 + 50 * idx + 4, UpLabel, self.pRender.W, 309 | 1) 310 | self.pRender.fb.putstr(306 + 80, 88 + 50 * idx + 4, DwLabel, 311 | self.pRender.W, 1) 312 | 313 | self.RenderParamRowBt(idx, isActive) 314 | 315 | return 316 | 317 | def RenderParamUI(self, idx): 318 | c = self.pRender.W 319 | self.pRender.fb.putstr(116 * idx + 8 + 33, 152 + 30 * 0, " 1", c, 2) 320 | self.pRender.fb.putstr(116 * idx + 8 + 33 + 6, 152 + 30 + 1, "10", c, 321 | 2) 322 | self.pRender.fb.putstr(116 * idx + 8 + 33, 152 + 30 * 2, "100", c, 2) 323 | 324 | c = self.pRender.ConvRgb(0.44, 0.9, 0.7) 325 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 8, 146 + 30 * 0, 30, 26), 326 | 0) 327 | self.pRender.fb.draw.rect( 328 | c, Rect(116 * idx + 8 + 72, 146 + 30 * 0, 30, 26), 0) 329 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 8, 146 + 30 * 1, 30, 26), 330 | 0) 331 | self.pRender.fb.draw.rect( 332 | c, Rect(116 * idx + 8 + 72, 146 + 30 * 1, 30, 26), 0) 333 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 8, 146 + 30 * 2, 30, 26), 334 | 0) 335 | self.pRender.fb.draw.rect( 336 | c, Rect(116 * idx + 8 + 72, 146 + 30 * 2, 30, 26), 0) 337 | 338 | c = self.pRender.ConvRgb(0.44, 0.1, 1) 339 | self.pRender.fb.putstr(116 * idx + 8 + 5, 145 + 30 * 0, "-", c, 4) 340 | self.pRender.fb.putstr(116 * idx + 8 + 77, 145 + 30 * 0, "+", c, 4) 341 | self.pRender.fb.putstr(116 * idx + 8 + 5, 145 + 30 * 1, "-", c, 4) 342 | self.pRender.fb.putstr(116 * idx + 8 + 77, 145 + 30 * 1, "+", c, 4) 343 | self.pRender.fb.putstr(116 * idx + 8 + 5, 145 + 30 * 2, "-", c, 4) 344 | self.pRender.fb.putstr(116 * idx + 8 + 77, 145 + 30 * 2, "+", c, 4) 345 | 346 | def SwitchLink(self, idx): 347 | # @todo if same idx, skip. 348 | if idx == 0: 349 | self.RenderParamForm(0, "Up Band", "%04d" % self.upBand, "kbps") 350 | self.RenderParamForm(1, "Dw Band", "%04d" % self.dwBand, "kbps") 351 | elif idx == 1: 352 | self.RenderParamForm(0, "Up Delay", "%04d" % self.upDelay, "msec") 353 | self.RenderParamForm(1, "Dw Delay", "%04d" % self.dwDelay, "msec") 354 | elif idx == 2: 355 | self.RenderParamForm(0, "Up Loss", "%4d" % self.upLoss, "%") 356 | self.RenderParamForm(1, "Dw Loss", "%4d" % self.dwLoss, "%") 357 | else: 358 | return 359 | if self.currentEdit != idx: 360 | self.RenderParamRowBt(idx, True) 361 | self.RenderParamRowBt(self.currentEdit, False) 362 | self.currentEdit = idx 363 | 364 | def RenderParamForm(self, idx, label, value, unit, isParamOnly=False): 365 | 366 | if isParamOnly == True: 367 | self.pRender.fb.draw.rect(self.pRender.N, 368 | Rect(116 * idx + 12, 112, 60, 18), 0) 369 | else: 370 | #self.pRender.fb.draw.rect(self.pRender.N, Rect(116*idx+8, 84, 102, 150), 0) 371 | #self.pRender.fb.draw.rect(self.pRender.W, Rect(116*idx+8, 84, 102, 58), 0) 372 | self.pRender.fb.draw.rect(self.pRender.N, 373 | Rect(116 * idx + 8 + 34, 84, 62, 16), 0) 374 | self.pRender.fb.draw.rect(self.pRender.N, 375 | Rect(116 * idx + 18, 114, 82, 16), 0) 376 | 377 | c = self.pRender.ConvRgb(0.94, 0.8, 0.9) 378 | self.pRender.fb.putstr(116 * idx + 8 + 10, 114, value, c, 2) 379 | 380 | if isParamOnly == True: 381 | return 382 | 383 | c = self.pRender.ConvRgb(0.44, 0.3, 0.9) 384 | self.pRender.fb.putstr(116 * idx + 8, 85, label, c, 2) 385 | self.pRender.fb.putstr(116 * idx + 8 + 10 + 58, 120, unit, 386 | self.pRender.W, 1) 387 | 388 | c = self.pRender.ConvRgb(0.4, 0.6, 0.4) 389 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 8, 100, 100, 2), 0) 390 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 8, 100 + 40, 100, 2), 0) 391 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 8, 100, 2, 40), 0) 392 | self.pRender.fb.draw.rect(c, Rect(116 * idx + 8 + 100, 100, 2, 42), 0) 393 | 394 | def RenderWire(self, isActive): 395 | if isActive == True: 396 | #c = self.pRender.ConvRgb(0.18,0.6,0.6) 397 | c = self.pRender.ConvRgb(0.18, 1.0, 1.0) 398 | else: 399 | c = self.pRender.ConvRgb(0.44, 0.0, 0.7) 400 | self.pRender.fb.draw.rect(c, Rect(234, 80, 238, 1), 0) 401 | self.pRender.fb.draw.rect(c, Rect(234, 80 + 154, 238, 1), 0) 402 | self.pRender.fb.draw.rect(c, Rect(234, 80, 1, 154), 0) 403 | self.pRender.fb.draw.rect(c, Rect(234 + 237, 80, 1, 154), 0) 404 | self.pRender.fb.draw.rect(c, Rect(248 + 150, 80 + 154 + 1, 2, 2), 0) 405 | self.pRender.fb.draw.rect(c, Rect(248 + 152, 80 + 154 + 1, 2, 4), 0) 406 | self.pRender.fb.draw.rect(c, Rect(248 + 154, 80 + 154 + 1, 2, 6), 0) 407 | self.pRender.fb.draw.rect(c, Rect(248 + 156, 80 + 154 + 1, 2, 4), 0) 408 | self.pRender.fb.draw.rect(c, Rect(248 + 158, 80 + 154 + 1, 2, 2), 0) 409 | 410 | def Start(self): 411 | super(ScManualEx2, self).Start() 412 | 413 | ##[ PARAM ]################################################################ 414 | 415 | self.upBand = 1024 416 | self.dwBand = 1024 417 | self.upDelay = 0 418 | self.dwDelay = 0 419 | self.upLoss = 0 420 | self.dwLoss = 0 421 | self.isApply = 0 422 | self.currentEdit = 0 423 | 424 | ##[ RENDER ]################################################################ 425 | 426 | self.pRender.UpdateTitle("WAN Emulation - Manual Direct") 427 | self.pRender.UpdateSubTitle("Set Param Manually - Status : Non Active") 428 | 429 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 430 | self.pRender.fb.draw.rect(c, Rect(0, 54, self.pRender.xres, 1), 0) 431 | self.pRender.fb.draw.rect(c, Rect(0, 74, self.pRender.xres, 1), 0) 432 | self.pRender.fb.draw.rect(c, Rect(0, 54, 10 + 60, 20), 0) 433 | self.pRender.fb.draw.rect(c, Rect(480 - 10, 54, 10, 20), 0) 434 | self.pRender.fb.putstr(26, 54 + 7, ">>>", self.pRender.N, 1) 435 | 436 | c = self.pRender.ConvRgb(0.16, 1, 0.6) 437 | #self.pRender.fb.draw.rect(c, Rect(1, 160, self.pRender.xres-2, 1), 0) 438 | self.pRender.fb.draw.rect(c, 439 | Rect(1, 240, self.pRender.xres - 2 - 150, 1), 440 | 0) 441 | self.pRender.fb.draw.rect( 442 | c, Rect(self.pRender.xres - 150 - 1, 240, 1, 79), 0) 443 | 444 | self.RenderBackBt(True) 445 | 446 | self.RenderWire(False) 447 | 448 | if self.pWanem.wanemMode == 0: 449 | wanemModeLabel = "P" 450 | else: 451 | wanemModeLabel = "S" 452 | 453 | self.RenderParamRow(0, "Up Band", "%04d" % self.upBand, "kbps", 454 | "Dw Band", "%04d" % self.dwBand, "kbps", True, 455 | wanemModeLabel) 456 | self.RenderParamRow(1, "Up Delay", "%04d" % self.upDelay, "msec", 457 | "Dw Delay", "%04d" % self.dwDelay, "msec", False) 458 | self.RenderParamRow(2, "Up Loss", "%4d" % self.upLoss, "%", "Dw Loss", 459 | "%4d" % self.dwLoss, "%", False) 460 | 461 | self.RenderParamForm(0, "Up Band", "%04d" % self.upBand, "kbps") 462 | self.RenderParamUI(0) 463 | self.RenderParamForm(1, "Dw Band", "%04d" % self.dwBand, "kbps") 464 | self.RenderParamUI(1) 465 | 466 | c = self.pRender.ConvRgb(0.98, 0.6, 0.6) 467 | self.pRender.fb.draw.rect(c, Rect(286 - 140, 80 * 3 + 8, 80, 44), 0) 468 | self.pRender.fb.draw.rect(c, Rect(380 - 140, 80 * 3 + 8, 80, 44), 0) 469 | self.pRender.fb.putstr(286 - 140, 80 * 3 + 64, "Disconnect Emulation", 470 | c, 1) 471 | c = self.pRender.ConvRgb(0.98, 0.3, 0.3) 472 | self.pRender.fb.draw.rect(c, Rect(286 - 140, 80 * 3 + 8 + 44, 80, 4), 473 | 0) 474 | self.pRender.fb.draw.rect(c, Rect(380 - 140, 80 * 3 + 8 + 44, 80, 4), 475 | 0) 476 | self.pRender.fb.putstr(286 - 140 + 5, 80 * 3 + 22, "Toggle", 0, 2) 477 | self.pRender.fb.putstr(386 - 140 + 11, 80 * 3 + 22, 'Push', 0, 2) 478 | 479 | self.pRender.RenderDotMini(2, 5) 480 | 481 | self.RenderApplyBt() 482 | self.pWanem.ClearEx() 483 | 484 | return 485 | 486 | def RenderApplyBt(self): 487 | if self.isApply == 0: 488 | c = self.pRender.ConvRgb(0.18, 0.6, 0.6) 489 | else: 490 | c = self.pRender.ConvRgb(0.18, 1.0, 1.0) 491 | self.pRender.fb.draw.rect(c, Rect(350, 80 * 3 + 8, 110, 44), 0) 492 | self.pRender.fb.putstr(350, 80 * 3 + 64, "Wan Setting", c, 1) 493 | c = self.pRender.ConvRgb(0.18, 0.3, 0.3) 494 | self.pRender.fb.draw.rect(c, Rect(350, 80 * 3 + 8 + 44, 110, 4), 0) 495 | if self.isApply == 0: 496 | self.pRender.fb.putstr(350 + 24, 80 * 3 + 22, "Apply", 0, 2) 497 | else: 498 | self.pRender.fb.putstr(350 + 12, 80 * 3 + 22, "Release", 0, 2) 499 | -------------------------------------------------------------------------------- /ScMenu.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | 9 | 10 | class ScMenu(ScBase): 11 | def __init__(self, pCTX, pRender, pWanem): 12 | super(ScMenu, self).__init__(pCTX, pRender, pWanem) 13 | #self.ptDef.insert(0, self.CreateTocuhDef("BtManual", 434, 132, 180, 132, self.BtHandler)) 14 | self.ptDef.insert( 15 | 0, self.CreateTocuhDef("BtPreset", 429, 210, 81, 81, 16 | self.BtHandler)) 17 | self.ptDef.insert( 18 | 1, self.CreateTocuhDef("BtDirect", 348, 210, 81, 81, 19 | self.BtHandler)) 20 | #self.ptDef.insert(2, self.CreateTocuhDef("BtReplay", 434-204, 95, 180, 132, self.BtHandler)) 21 | if self.pCTX.apiStatus == 0: 22 | self.ptDef.insert( 23 | 2, 24 | self.CreateTocuhDef("BtReplay", 434 - 204, 95, 180, 50, 25 | self.BtHandler)) 26 | self.ptDef.insert( 27 | 3, self.CreateTocuhDef("BtInit", 468, 29, 62, 42, self.BtHandler)) 28 | self.ptDef.insert( 29 | 4, 30 | self.CreateTocuhDef("BtSetting", 434 - 204, 233, 180, 50, 31 | self.BtHandler)) 32 | self.ptDef.insert( 33 | 5, 34 | self.CreateTocuhDef("BtRemote", 434 - 204, 164, 180, 50, 35 | self.BtHandler)) 36 | 37 | def BtHandler(self, key): 38 | #print "BtHandler" + key 39 | if key == "BtManual": 40 | self.nextScene = "Manual" 41 | self.state = self.STATE_TERM 42 | elif key == "BtPreset": 43 | self.nextScene = "Manual" 44 | self.state = self.STATE_TERM 45 | elif key == "BtDirect": 46 | self.nextScene = "ManualEx2" 47 | self.state = self.STATE_TERM 48 | elif key == "BtReplay": 49 | self.nextScene = "Replay" 50 | self.state = self.STATE_TERM 51 | elif key == "BtSetting": 52 | self.nextScene = "Setting" 53 | self.state = self.STATE_TERM 54 | #elif key == "BtInit": 55 | #self.nextScene = "Init" 56 | #self.state = self.STATE_TERM 57 | elif key == "BtRemote": 58 | self.nextScene = "RemoteApi" 59 | self.state = self.STATE_TERM 60 | 61 | def Start(self): 62 | super(ScMenu, self).Start() 63 | 64 | ##[ RENDER ]################################################################ 65 | 66 | self.pRender.UpdateTitle("Mode Select") 67 | 68 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 69 | self.pRender.fb.draw.rect(c, Rect(0, 54, self.pRender.xres, 1), 0) 70 | 71 | #self.RenderBackBt(True) 72 | 73 | c = self.pRender.ConvRgb(0.62, 0.4, 1.0) 74 | self.pRender.fb.draw.rect(c, Rect(48, 90, 180, 200), 0) 75 | c = self.pRender.ConvRgb(0.62, 0.4, 0.4) 76 | self.pRender.fb.draw.rect(c, Rect(48 + 10, 120 + 70 - 50, 160, 40), 0) 77 | self.pRender.fb.putstr(48 + 22, 120 + 26 - 40, "Manual Mode", c, 2) 78 | self.pRender.fb.putstr(133, 120 + 26 + 36, "v", c, 2) 79 | c = self.pRender.ConvRgb(0.62, 0.2, 1.0) 80 | self.pRender.fb.putstr(48 + 22 + 5, 120 + 80 - 50, 81 | "WAN Emulate by manual", c, 1) 82 | self.pRender.fb.putstr(48 + 22 + 5, 120 + 92 - 50, "operation", c, 1) 83 | 84 | c = self.pRender.ConvRgb(0.62, 0.8, 0.8) 85 | self.pRender.fb.draw.rect(c, Rect(54, 90 + 112, 81, 76), 0) 86 | self.pRender.fb.draw.rect(c, Rect(54 + 87, 90 + 112, 81, 76), 0) 87 | c = self.pRender.ConvRgb(0.62, 0.8, 0.2) 88 | self.pRender.fb.draw.rect(c, Rect(54, 90 + 112 + 76, 81, 6), 0) 89 | self.pRender.fb.draw.rect(c, Rect(54 + 87, 90 + 112 + 76, 81, 6), 0) 90 | c = self.pRender.ConvRgb(0.62, 0.4, 0.4) 91 | self.pRender.fb.putstr(59, 222, "Preset", c, 2) 92 | self.pRender.fb.putstr(59, 242, " Mode ", c, 2) 93 | self.pRender.fb.putstr(59 + 87, 222, "Direct", c, 2) 94 | self.pRender.fb.putstr(59 + 87, 242, " Mode ", c, 2) 95 | 96 | baseX = 48 + 204 97 | baseY = 120 - 30 98 | if self.pCTX.apiStatus == 0: 99 | disabledDiff = 0 100 | menuLabel = "Replay Mode" 101 | menuLabelPosXOffset = 0 102 | else: 103 | disabledDiff = 0.5 104 | menuLabel = "N/A" 105 | menuLabelPosXOffset = 48 106 | 107 | c = self.pRender.ConvRgb(0.92, 0.8, 0.8 - disabledDiff) 108 | self.pRender.fb.draw.rect(c, Rect(baseX, baseY, 180, 50), 0) 109 | c = self.pRender.ConvRgb(0.92, 0.4, 0.4 - disabledDiff / 2) 110 | self.pRender.fb.draw.rect(c, Rect(baseX + 10, baseY + 29, 160, 16), 0) 111 | c = self.pRender.ConvRgb(0.92, 0.8, 0.2) 112 | self.pRender.fb.draw.rect(c, Rect(baseX, baseY + 50, 180, 10), 0) 113 | self.pRender.fb.putstr(baseX + 22 + menuLabelPosXOffset, baseY + 7, 114 | menuLabel, c, 2) 115 | c = self.pRender.ConvRgb(0.92, 0.2, 1.0 - disabledDiff) 116 | self.pRender.fb.putstr(baseX + 22 + 3 - 10, baseY + 34, 117 | "Reproduce by recorded DAT", c, 1) 118 | 119 | baseX = 48 + 204 120 | baseY = 120 - 30 + 70 121 | baseC = 0.12 122 | c = self.pRender.ConvRgb(baseC, 0.8, 0.8) 123 | self.pRender.fb.draw.rect(c, Rect(baseX, baseY, 180, 50), 0) 124 | c = self.pRender.ConvRgb(baseC, 0.4, 0.4) 125 | self.pRender.fb.draw.rect(c, Rect(baseX + 10, baseY + 29, 160, 16), 0) 126 | c = self.pRender.ConvRgb(baseC, 0.8, 0.2) 127 | self.pRender.fb.draw.rect(c, Rect(baseX, baseY + 50, 180, 10), 0) 128 | self.pRender.fb.putstr(baseX + 22 + 20, baseY + 7, "API Mode", c, 2) 129 | c = self.pRender.ConvRgb(baseC, 0.2, 1.0) 130 | self.pRender.fb.putstr(baseX + 22 + 3 - 10 + 5, baseY + 34, 131 | "Contorl from Remote CLI", c, 1) 132 | 133 | c = self.pRender.ConvRgb(0.32, 0.4, 0.8) 134 | self.pRender.fb.draw.rect(c, Rect(48 + 204, 120 + 110, 180, 50), 0) 135 | c = self.pRender.ConvRgb(0.32, 0.4, 0.4) 136 | self.pRender.fb.draw.rect( 137 | c, Rect(48 + 10 + 204, 120 + 20 + 115 + 4, 160, 16), 0) 138 | c = self.pRender.ConvRgb(0.32, 0.4, 0.2) 139 | self.pRender.fb.draw.rect(c, 140 | Rect(48 + 204, 120 + 20 + 115 + 25, 180, 10), 141 | 0) 142 | self.pRender.fb.putstr(48 + 22 + 204, 120 + 26 - 3 + 110 - 16, 143 | " Setting ", c, 2) 144 | c = self.pRender.ConvRgb(0.32, 0.2, 1.0) 145 | self.pRender.fb.putstr(48 + 22 + 3 + 204 + 10, 120 + 80 + 64, 146 | "Check Wanem Config", c, 1) 147 | 148 | return 149 | -------------------------------------------------------------------------------- /ScPlayback.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess, random, os.path, math, json 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | from SeekManager import SeekManager 9 | 10 | 11 | class ScPlayback(ScBase): 12 | def __init__(self, pCTX, pRender, pWanem): 13 | super(ScPlayback, self).__init__(pCTX, pRender, pWanem) 14 | 15 | self.STATE_IDLE = 1 16 | self.STATE_PLAY = 2 17 | self.STATE_PAUSE = 3 18 | 19 | self.ptDef.insert( 20 | 0, self.CreateTocuhDef("BtBack", 468, 29, 62, 42, self.BtHandler)) 21 | self.ptDef.insert( 22 | 1, self.CreateTocuhDef("BtPrev", 470, 95, 43, 90, self.BtHandler)) 23 | self.ptDef.insert( 24 | 2, self.CreateTocuhDef("BtNext", 65, 95, 43, 90, self.BtHandler)) 25 | #self.ptDef.insert(3, self.CreateTocuhDef("BtAuto", 460, 268, 80, 50, self.BtHandler)) 26 | self.ptDef.insert( 27 | 4, self.CreateTocuhDef("BtStop", 370, 268, 80, 50, self.BtHandler)) 28 | self.ptDef.insert( 29 | 5, self.CreateTocuhDef("BtPlay", 280, 268, 80, 50, self.BtHandler)) 30 | self.ptDef.insert( 31 | 6, self.CreateTocuhDef("BtPause", 190, 268, 80, 50, 32 | self.BtHandler)) 33 | self.ptDef.insert( 34 | 7, self.CreateTocuhDef("BtRepeat", 100, 268, 80, 50, 35 | self.BtHandler)) 36 | #self.ptDef.insert(3, self.CreateTocuhDef("BtTargetL", 430, 95, 120, 90, self.BtHandler)) 37 | #self.ptDef.insert(4, self.CreateTocuhDef("BtTargetC", 430, 95, 120, 90, self.BtHandler)) 38 | #self.ptDef.insert(5, self.CreateTocuhDef("BtTargetR", 430, 95, 120, 90, self.BtHandler)) 39 | 40 | def BtHandler(self, key): 41 | print("BtHandler" + key + " @ " + str(self.state)) 42 | 43 | if key == "BtBack": 44 | if self.state == self.STATE_IDLE: 45 | self.pWanem.Clear() 46 | self.nextScene = "Replay" 47 | self.state = self.STATE_TERM 48 | elif key == "BtPrev": 49 | if self.state == self.STATE_IDLE: 50 | self.UpdatePanel(-1) 51 | elif key == "BtNext": 52 | if self.state == self.STATE_IDLE: 53 | self.UpdatePanel(1) 54 | elif key == "BtStop": 55 | if self.state == self.STATE_PLAY or self.state == self.STATE_PAUSE: 56 | self.StopHandler() 57 | elif key == "BtPlay": 58 | if self.state == self.STATE_IDLE: 59 | self.RenderCurrentInfo("PLAYING") 60 | self.PlayHandler() 61 | elif key == "BtPause": 62 | if self.state == self.STATE_PLAY: 63 | self.seekManager.isPause = True 64 | elif self.state == self.STATE_PAUSE: 65 | self.seekManager.isPause = False 66 | elif key == "BtRepeat": 67 | self.seekManager.isRepeat = not self.seekManager.isRepeat 68 | self.RenderToggleFocus(4, self.seekManager.isRepeat) 69 | 70 | def RenderPanel(self, panelIdx, isActive, isFocus=False, datPath=""): 71 | 72 | offsetX = 128 * panelIdx 73 | 74 | if isActive == False: 75 | c = self.pRender.ConvRgb(0.31, 0.2, 0.2) 76 | self.pRender.fb.draw.rect(c, Rect(52 + offsetX, 84, 120, 90), 0) 77 | return 78 | 79 | targetPath = self.pCTX.currentReplayData + "/" + datPath 80 | file = open(targetPath) 81 | dat = json.load(file) 82 | file.close() 83 | 84 | mtime = os.path.getmtime(targetPath) 85 | t = datetime.datetime.fromtimestamp(mtime) 86 | datMtime = t.strftime("%y/%m/%d") 87 | 88 | c = self.pRender.ConvRgb(0.31, 0.2, 0.8) 89 | self.pRender.fb.draw.rect(c, Rect(52 + offsetX, 84, 120, 90), 0) 90 | 91 | c = self.pRender.ConvRgb(0.31, 0.2, 0.1) 92 | self.pRender.fb.putstr(52 + 10 + offsetX, 84 + 10, datPath[0:8], c, 2) 93 | 94 | c = self.pRender.ConvRgb(0.31, 0.2, 0.1) 95 | self.pRender.fb.putstr(52 + 10 + offsetX, 84 + 10 + 12 * 2, "Modify", 96 | c, 1) 97 | self.pRender.fb.putstr(52 + 10 + 70 + offsetX, 84 + 10 + 12 * 2, 98 | "Time", c, 1) 99 | self.pRender.fb.putstr(52 + 10 + offsetX, 84 + 10 + 12 * 3, datMtime, 100 | c, 1) 101 | self.pRender.fb.putstr( 102 | 52 + 10 + 70 + offsetX, 84 + 10 + 12 * 3, 103 | self.seekManager.Conv2FormatedTime(dat["dps"], dat["duration"]), c, 104 | 1) 105 | self.pRender.fb.putstr(52 + 10 + offsetX, 84 + 10 + 12 * 4, "Memo", c, 106 | 1) 107 | self.pRender.fb.putstr(52 + 10 + offsetX, 84 + 10 + 12 * 5, 108 | dat["memo"][0:17], c, 1) 109 | 110 | if isFocus: 111 | self.RenderGraph(dat["graph"]) 112 | self.seekManager.Setup(dat["dps"], dat["duration"]) 113 | self.RenderSeekInfo() 114 | self.dat = dat["dat"] 115 | 116 | def UpdatePanel(self, vec, forceClear=False): 117 | 118 | prevPageIdx = self.datPageIdx 119 | prevFocusIdx = self.datFocusIdx 120 | isPageSwitch = forceClear 121 | 122 | if (self.datPageIdx * 3 + self.datFocusIdx) == 0 and vec == -1: 123 | return 124 | if (self.datPageIdx * 3 + self.datFocusIdx) == (self.datNr - 125 | 1) and vec == 1: 126 | return 127 | if (self.datFocusIdx % 3) == 0 and vec == -1: 128 | self.datPageIdx -= 1 129 | isPageSwitch = True 130 | elif (self.datFocusIdx % 3) == 2 and vec == 1: 131 | self.datPageIdx += 1 132 | isPageSwitch = True 133 | 134 | self.datFocusIdx = (self.datFocusIdx + vec) % 3 135 | 136 | self.ClearFocus(prevFocusIdx) 137 | 138 | if isPageSwitch: 139 | 140 | self.datFocusIdx = 0 141 | 142 | # Render List 143 | # currentIdx = self.datPageIdx * 3 + self.datFocusIdx 144 | 145 | currentIdxTop = self.datPageIdx * 3 146 | focusIdx = 0 147 | for file in self.datList[currentIdxTop:currentIdxTop + 3]: 148 | if focusIdx == self.datFocusIdx: 149 | self.RenderPanel(focusIdx, True, True, file) 150 | else: 151 | self.RenderPanel(focusIdx, True, False, file) 152 | focusIdx += 1 153 | for idx in range(focusIdx, 3): 154 | self.RenderPanel(idx, False) 155 | else: 156 | currentIdxTop = self.datPageIdx * 3 157 | focusIdx = 0 158 | for file in self.datList[currentIdxTop:currentIdxTop + 3]: 159 | if focusIdx == self.datFocusIdx: 160 | targetPath = self.pCTX.currentReplayData + "/" + file 161 | file = open(targetPath) 162 | dat = json.load(file) 163 | file.close() 164 | self.RenderGraph(dat["graph"]) 165 | self.seekManager.Setup(dat["dps"], dat["duration"]) 166 | self.RenderSeekInfo() 167 | self.dat = dat["dat"] 168 | 169 | focusIdx += 1 170 | 171 | self.RenderFocus(self.datFocusIdx) 172 | 173 | def RenderFocus(self, idx): 174 | c = self.pRender.ConvRgb(1.00, 0.9, 0.8) 175 | self.pRender.fb.draw.rect(c, Rect(48 + 128 * idx, 84 - 4, 128, 4), 0) 176 | self.pRender.fb.draw.rect( 177 | c, Rect(48 + 128 * idx, 84 - 4 + 90 + 4, 128, 4), 0) 178 | self.pRender.fb.draw.rect(c, Rect(48 + 128 * idx, 84, 4, 90), 0) 179 | self.pRender.fb.draw.rect(c, Rect(48 + 128 * idx + 124, 84, 4, 90), 0) 180 | 181 | def RenderToggleFocus(self, idx, isActivey): 182 | if idx == 3: 183 | xoffset = 0 184 | elif idx == 4: 185 | xoffset = 90 186 | else: 187 | return 188 | if isActivey: 189 | c = self.pRender.ConvRgb(1.00, 0.9, 0.8) 190 | else: 191 | c = self.pRender.N 192 | self.pRender.fb.draw.rect(c, Rect(288 + xoffset, 264 - 2, 84, 2), 0) 193 | self.pRender.fb.draw.rect(c, 194 | Rect(288 + xoffset, 264 - 2 + 50 + 2, 84, 2), 195 | 0) 196 | self.pRender.fb.draw.rect(c, Rect(288 + xoffset, 264, 2, 50), 0) 197 | self.pRender.fb.draw.rect(c, Rect(288 + xoffset + 82, 264, 2, 50), 0) 198 | 199 | def ClearFocus(self, idx): 200 | c = self.pRender.ConvRgb(0, 0, 0) 201 | self.pRender.fb.draw.rect(c, Rect(48 + 128 * idx, 84 - 4, 128, 4), 0) 202 | self.pRender.fb.draw.rect( 203 | c, Rect(48 + 128 * idx, 84 - 4 + 90 + 4, 128, 4), 0) 204 | self.pRender.fb.draw.rect(c, Rect(48 + 128 * idx, 84, 4, 90), 0) 205 | self.pRender.fb.draw.rect(c, Rect(48 + 128 * idx + 124, 84, 4, 90), 0) 206 | 207 | def RenderFootBt(self, idx, label, h): 208 | if idx == 0: 209 | x = 200 - 180 210 | elif idx == 1: 211 | x = 200 - 90 212 | elif idx == 2: 213 | x = 200 + 0 214 | elif idx == 3: 215 | x = 200 + 90 216 | elif idx == 4: 217 | x = 200 + 180 218 | 219 | c = self.pRender.ConvRgb(h, 0.6, 0.6) 220 | self.pRender.fb.draw.rect(c, Rect(x, 264, 80, 44), 0) 221 | c = self.pRender.ConvRgb(h, 0.6, 0.2) 222 | self.pRender.fb.draw.rect(c, Rect(x, 264 + 44, 80, 6), 0) 223 | if idx == 3: 224 | self.pRender.fb.putstr(x + 4 + 7, 278, label, c, 2) 225 | else: 226 | self.pRender.fb.putstr(x + 4, 278, label, c, 2) 227 | 228 | def RenderSeekInfo(self): 229 | self.pRender.fb.draw.rect(self.pRender.N, Rect(445, 219, 30, 7), 0) 230 | self.pRender.fb.putstr(445, 240 - 21, 231 | self.seekManager.GetTotalFormatTime(), 232 | self.pRender.W, 1) 233 | 234 | ################################################################################ 235 | 236 | def Update(self): 237 | isRender = False 238 | 239 | if self.pCTX.tick == 1: 240 | isRender = True 241 | 242 | if self.state == self.STATE_PLAY: 243 | 244 | ####################################### 245 | if isRender: 246 | if self.seekManager.isPause: 247 | self.RenderToggleFocus(3, self.seekManager.isPause) 248 | self.state = self.STATE_PAUSE 249 | return 250 | self.seekManager.seekSec += 1 251 | 252 | if self.seekManager.seekSec < 0: 253 | return 254 | 255 | if self.seekManager.IsTerm(): 256 | if self.seekManager.isRepeat: 257 | self.RenderDotAll() 258 | self.PlayHandler() 259 | self.UpdateSeekTime() 260 | else: 261 | self.StopHandler() 262 | return 263 | ####################################### 264 | 265 | # check Seek diff and force loop and apply. 266 | # @todo variable fps 267 | if self.pCTX.tick % self.seekManager.updateInterval == 0: 268 | #datSeek = self.seekSec * 30 + int(self.pCTX.tick / 2) 269 | #if self.pCTX.tick >= 60: 270 | # print str(self.pCTX.tick) + ":" + str(self.seekManager.seekFrame) + ":" + str(self.seekManager.updateInterval) 271 | self.pWanem.DirectApply(self.dat[self.seekManager.seekFrame]) 272 | if (self.pCTX.tick % 15) == 0: 273 | self.RenderCurrentInfo( 274 | "", self.dat[self.seekManager.seekFrame]) 275 | self.seekManager.Update(isRender) 276 | 277 | # nnn.... 278 | if isRender: 279 | self.UpdateSeekTime() 280 | 281 | elif self.state == self.STATE_PAUSE: 282 | if not self.seekManager.isPause: 283 | self.RenderToggleFocus(3, self.seekManager.isPause) 284 | self.state = self.STATE_PLAY 285 | return 286 | 287 | ################################################################################ 288 | 289 | def RenderDotAll(self): 290 | for idx in range(0, self.seekManager.progressBarResolution): 291 | self.RenderDot(idx, False) 292 | 293 | def RenderDot(self, idx, isFlush): 294 | w = 10 295 | h = 10 296 | if isFlush: 297 | c = self.pRender.ConvRgb(0.4, 1, 1) 298 | else: 299 | c = self.pRender.ConvRgb(0.4, 0.3, 0.3) 300 | xoffset = 11 * idx + 20 301 | self.pRender.fb.draw.rect(c, Rect(xoffset, 238, w, h), 0) 302 | 303 | def RenderGraph(self, graphDat): 304 | 305 | c = self.pRender.ConvRgb(0, 0, 0) 306 | self.pRender.fb.draw.rect(c, Rect(20, 186, 440, 30), 0) 307 | 308 | for idx in range(0, 440): 309 | xoffset = idx + 20 310 | h = graphDat[idx] 311 | 312 | #c = self.pRender.ConvRgb(1.0/440.0*idx,0.8,0.8) 313 | c = self.pRender.ConvRgb(1.0 / 30.0 * h, 0.8, 0.8) 314 | self.pRender.fb.draw.rect(c, Rect(xoffset, 216 - h, 1, h), 0) 315 | 316 | # Update block and seek string 317 | def UpdateSeekTime(self): 318 | if self.seekManager.seekLap >= self.seekManager.progressBarResolution: 319 | return 320 | 321 | self.pRender.fb.draw.rect(self.pRender.N, Rect(224, 219, 30, 7), 0) 322 | self.pRender.fb.putstr(224, 219, 323 | self.seekManager.GetCurrentFormatTime(), 324 | self.pRender.W, 1) 325 | 326 | while self.seekManager.IsSeekSecOverCurrentLap(): 327 | self.RenderDot(self.seekManager.seekLap, True) 328 | self.seekManager.seekLap += 1 329 | if self.seekManager.seekLap >= self.seekManager.progressBarResolution: 330 | return 331 | 332 | self.isBlockFlash = not self.isBlockFlash 333 | self.RenderDot(self.seekManager.seekLap, self.isBlockFlash) 334 | 335 | def PlayHandler(self): 336 | self.seekManager.Start() 337 | self.state = self.STATE_PLAY 338 | self.RenderDotAll() 339 | 340 | def StopHandler(self): 341 | self.seekManager.Stop() 342 | self.state = self.STATE_IDLE 343 | self.UpdateSeekTime() 344 | self.RenderDotAll() 345 | self.RenderToggleFocus(3, self.seekManager.isPause) 346 | self.RenderCurrentInfo("STOP", 0) 347 | self.pWanem.DirectApply(0) 348 | 349 | def Start(self): 350 | super(ScPlayback, self).Start() 351 | 352 | ##[ INIT STATE ]################################################################ 353 | 354 | self.progressBarResolution = 40 355 | self.seekManager = SeekManager(self.pCTX, self.progressBarResolution) 356 | 357 | self.state = self.STATE_IDLE 358 | self.isBlockFlash = False 359 | self.dat = None 360 | 361 | ##[ Get DataDir Info ]###################################################### 362 | 363 | self.datList = os.listdir(self.pCTX.currentReplayData) 364 | self.datList.sort() 365 | self.datPageIdx = 0 366 | self.datNr = len(self.datList) 367 | self.datFocusIdx = 0 368 | 369 | ##[ RENDER ]################################################################ 370 | 371 | self.pRender.UpdateTitle("WAN Emulation - Replay") 372 | self.pRender.UpdateSubTitle("Dat Path : " + 373 | self.pCTX.currentReplayData) 374 | 375 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 376 | self.pRender.fb.draw.rect(c, Rect(0, 54, self.pRender.xres, 1), 0) 377 | self.pRender.fb.draw.rect(c, Rect(0, 74, self.pRender.xres, 1), 0) 378 | self.pRender.fb.draw.rect(c, Rect(0, 54, 10 + 60, 20), 0) 379 | self.pRender.fb.draw.rect(c, Rect(480 - 10, 54, 10, 20), 0) 380 | self.pRender.fb.putstr(26, 54 + 7, ">>>", self.pRender.N, 1) 381 | 382 | ###################### 383 | 384 | self.UpdatePanel(0, True) 385 | 386 | c = self.pRender.ConvRgb(0.31, 0.2, 0.2) 387 | self.pRender.fb.draw.rect(c, Rect(1, 84, 43, 90), 0) 388 | self.pRender.fb.draw.rect(c, Rect(480 - 44, 84, 43, 90), 0) 389 | self.pRender.fb.putstr(10, 84 + 29, '<', 0, 4) 390 | self.pRender.fb.putstr(480 - 34, 84 + 29, '>', 0, 4) 391 | 392 | ###################### 393 | 394 | c = self.pRender.ConvRgb(0.16, 1, 0.6) 395 | #self.pRender.fb.draw.rect(c, Rect(1, 240 - 54, self.pRender.xres-2, 1), 0) 396 | self.pRender.fb.putstr(5, 240 - 21, "00:00", self.pRender.W, 1) 397 | 398 | self.UpdateSeekTime() 399 | 400 | self.pRender.fb.draw.rect(c, Rect(1, 240 - 12, self.pRender.xres - 2, 401 | 1), 0) 402 | self.pRender.fb.draw.rect(c, Rect(1, 240 + 18, self.pRender.xres - 2, 403 | 1), 0) 404 | 405 | #self.RenderFootBt(0, " Auto", 0.16) 406 | self.RenderFootBt(1, " Stop", 0.36) 407 | self.RenderFootBt(2, " Play", 0.36) 408 | self.RenderFootBt(3, "Pause", 0.16) 409 | self.RenderFootBt(4, "Repeat", 0.16) 410 | 411 | self.RenderDotAll() 412 | 413 | self.RenderBackBt(True) 414 | 415 | self.RenderCurrentInfo("STOP", 0) 416 | self.pRender.fb.putstr(12 + 54, 268 + 24 + 6, "msec", self.pRender.W, 417 | 1) 418 | 419 | self.pWanem.InitSingle() 420 | 421 | def RenderCurrentInfo(self, state="", delay=-1): 422 | if state != "": 423 | self.pRender.fb.draw.rect(self.pRender.N, Rect(12, 268, 84, 16), 0) 424 | self.pRender.fb.putstr(12, 268, state, self.pRender.W, 2) 425 | if delay >= 0: 426 | self.pRender.fb.draw.rect(self.pRender.N, 427 | Rect(12, 268 + 24, 50, 16), 0) 428 | self.pRender.fb.putstr(12, 268 + 24, "%04d" % delay, 429 | self.pRender.W, 2) 430 | -------------------------------------------------------------------------------- /ScRemoteApi.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess, socket, errno, select, json 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | from fcntl import ioctl 9 | 10 | 11 | class ScRemoteApi(ScBase): 12 | def __init__(self, pCTX, pRender, pWanem): 13 | super(ScRemoteApi, self).__init__(pCTX, pRender, pWanem) 14 | self.ptDef.insert( 15 | 0, self.CreateTocuhDef("BtMenu", 468, 29, 62, 42, self.BtHandler)) 16 | self.updateCnt = 60 17 | 18 | def BtHandler(self, key): 19 | print("BtHandler" + key) 20 | if key == "BtMenu": 21 | self.pWanem.Clear() 22 | self.nextScene = "Menu" 23 | self.state = self.STATE_TERM 24 | self.DestroyApiSocket() 25 | 26 | def CreateApiSocket(self): 27 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 28 | self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 29 | self.sock.bind(("", 10393)) 30 | self.sock.setblocking(0) 31 | self.socklist = [] 32 | self.socklist.append(self.sock) 33 | 34 | def DestroyApiSocket(self): 35 | self.sock.close() 36 | 37 | def Update(self): 38 | if self.state == self.STATE_INIT: 39 | read_sockets, write_sockets, error_sockets = select.select( 40 | self.socklist, [], [], 0) 41 | for s in read_sockets: 42 | if s == self.sock: 43 | try: 44 | rBuf, peer = self.sock.recvfrom(self.rBufSize) 45 | self.ApplyApiCall(rBuf.decode().strip()) 46 | #self.pRender.UpdateSubTitle(rBuf.decode().strip()) 47 | resp = '{"status":"E_OK"}'.encode('utf-8') 48 | self.sock.sendto(resp, peer) 49 | except socket.error as v: 50 | errorcode = v[0] 51 | print(("socket recv error. >> " + errorcode)) 52 | self.updateCnt -= 1 53 | if self.updateCnt <= 0: 54 | self.RenderTrafficInfo(True) 55 | self.updateCnt = 60 56 | return 57 | 58 | def ApplyApiCall(self, query): 59 | isUpdateBand = 0 60 | isUpdateDelay = 0 61 | isUpdateLoss = 0 62 | isUpdateDiscon = 0 63 | 64 | #todo aplly diff Update 65 | #print ("ApplyApiCall >> " + query) 66 | req = json.loads(query) 67 | self.upBand = req["bandUp"] 68 | self.dwBand = req["bandDw"] 69 | self.upDelay = req["delayUp"] 70 | self.dwDelay = req["delayDw"] 71 | self.upLoss = req["lossUp"] 72 | self.dwLoss = req["lossDw"] 73 | self.upDiscon = req["disconnUp"] 74 | self.dwDiscon = req["disconnDw"] 75 | 76 | upLoss = self.upLoss 77 | dwLoss = self.dwLoss 78 | 79 | if self.upDiscon != 0: 80 | upLoss = 100 81 | if self.dwDiscon != 0: 82 | dwLoss = 100 83 | 84 | self.pWanem.DirectUpdateEx2(self.upBand, self.dwBand, self.upDelay, 85 | self.dwDelay, upLoss, dwLoss) 86 | self.RenderParamOnly(0, 0, self.upBand, self.dwBand) 87 | self.RenderParamOnly(1, 0, self.upDelay, self.dwDelay) 88 | self.RenderParamOnly(2, 0, self.upLoss, self.dwLoss) 89 | self.RenderParamOnly(3, 1, self.upDiscon, self.dwDiscon) 90 | 91 | def Start(self): 92 | super(ScRemoteApi, self).Start() 93 | 94 | ##[ PARAM ]################################################################ 95 | 96 | self.upBand = 8096 97 | self.dwBand = 8096 98 | self.upDelay = 0 99 | self.dwDelay = 0 100 | self.upLoss = 0 101 | self.dwLoss = 0 102 | self.upDiscon = 0 103 | self.dwDiscon = 0 104 | 105 | self.rBufSize = 4096 106 | self.bindPort = 10393 107 | 108 | ##[ RENDER ]################################################################ 109 | 110 | self.pRender.UpdateTitle("WAN Emulation - API Control") 111 | self.pRender.UpdateSubTitle("") 112 | 113 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 114 | self.pRender.fb.draw.rect(c, Rect(0, 54, self.pRender.xres, 1), 0) 115 | self.pRender.fb.draw.rect(c, Rect(0, 74, self.pRender.xres, 1), 0) 116 | self.pRender.fb.draw.rect(c, Rect(0, 54, 10 + 60, 20), 0) 117 | self.pRender.fb.draw.rect(c, Rect(480 - 10, 54, 10, 20), 0) 118 | self.pRender.fb.draw.rect(c, Rect(342, 74, 1, self.pRender.yres - 74), 119 | 0) 120 | self.pRender.fb.putstr(26, 54 + 7, ">>>", self.pRender.N, 1) 121 | 122 | self.RenderBackBt(True) 123 | 124 | self.CreateApiSocket() 125 | ifreq = struct.pack('16s16x', 'eth2'.encode()) 126 | SIOCGIFADDR = 0x8915 # oh... not defined... orz 127 | 128 | retryLimit = 1 129 | retryCnt = 0 130 | while retryCnt <= retryLimit: 131 | try: 132 | ifaddr = ioctl(self.sock.fileno(), SIOCGIFADDR, ifreq) 133 | _, sa_family, port, in_addr = struct.unpack('16sHH4s8x', ifaddr) 134 | #print socket.inet_ntoa(in_addr) 135 | lanIp = socket.inet_ntoa(in_addr) 136 | break 137 | except: 138 | if retryCnt == 0: 139 | subprocess.check_call(['nmcli', 'connection', 'up', 'Wired connection 3']) 140 | lanIp = "0.0.0.0" 141 | retryCnt += 1 142 | 143 | self.pRender.UpdateSubTitle("API Endpoint >> " + 144 | lanIp + ":" + 145 | str(self.bindPort)) 146 | 147 | self.RenderParamBar(0, 0, "Band", self.upBand, self.dwBand, "kbps") 148 | self.RenderParamBar(1, 0, "Delay", self.upDelay, self.dwDelay, "msec") 149 | self.RenderParamBar(2, 0, "Loss", self.upLoss, self.upLoss, " %") 150 | self.RenderParamBar(3, 1, "Discon") 151 | #self.RenderParamOnly(0, 0, 1024, 1024) 152 | #self.RenderParamOnly(1, 0, 100, 300) 153 | #self.RenderParamOnly(2, 0, 5, 5) 154 | #c = self.pRender.ConvRgb(0.32,0.4,0.2) 155 | #self.pRender.fb.putstr(80, 96, " Coinfig Param List ", c, 2) 156 | 157 | self.pWanem.ClearEx2() 158 | self.pWanem.DirectApplyEx2(self.upBand, self.dwBand, self.upDelay, 159 | self.dwDelay, self.upLoss, self.dwLoss) 160 | 161 | self.RenderTrafficInfo() 162 | 163 | return 164 | 165 | def RenderParamOnly(self, idx, isToggle, up, down): 166 | if isToggle == 0: 167 | c = self.pRender.ConvRgb(0.32, 0.1, 1) 168 | self.pRender.fb.draw.rect( 169 | c, Rect(20 + 102 + 106 + 12, 86 + 22 + idx * 58, 50, 16), 0) 170 | self.pRender.fb.draw.rect( 171 | c, Rect(20 + 102 + 12, 86 + 22 + idx * 58, 50, 16), 0) 172 | c = self.pRender.ConvRgb(0.32, 0.4, 0.4) 173 | self.pRender.fb.putstr(20 + 102 + 12, 86 + 22 + idx * 58, 174 | "%04d" % up, c, 2) 175 | self.pRender.fb.putstr(20 + 102 + 106 + 12, 86 + 22 + idx * 58, 176 | "%04d" % down, c, 2) 177 | else: 178 | if up == 0: 179 | c = self.pRender.ConvRgb(0.32, 0.1, 1) 180 | else: 181 | c = self.pRender.ConvRgb(0.92, 0.8, 1) 182 | self.pRender.fb.draw.rect( 183 | c, Rect(20 + 102 + 12, 86 + 22 + idx * 58, 50, 16), 0) 184 | 185 | if down == 0: 186 | c = self.pRender.ConvRgb(0.32, 0.1, 1) 187 | else: 188 | c = self.pRender.ConvRgb(0.92, 0.8, 1) 189 | self.pRender.fb.draw.rect( 190 | c, Rect(20 + 102 + 106 + 12, 86 + 22 + idx * 58, 50, 16), 0) 191 | 192 | return 193 | 194 | def RenderParamBar(self, idx, isToggle, label, up=0, down=0, unit=""): 195 | c = self.pRender.ConvRgb(0.32, 0.4, 0.8) 196 | self.pRender.fb.draw.rect(c, Rect(12, 86 + idx * 58, 320, 48), 0) 197 | c = self.pRender.ConvRgb(0.32, 0.1, 1) 198 | self.pRender.fb.draw.rect(c, Rect(20 + 102, 86 + 12 + idx * 58, 100, 199 | 32), 0) 200 | self.pRender.fb.draw.rect( 201 | c, Rect(20 + 102 + 106, 86 + 12 + idx * 58, 100, 32), 0) 202 | self.pRender.fb.putstr(20 + 102, 86 + 2 + idx * 58, "UP", c, 1) 203 | self.pRender.fb.putstr(20 + 102 + 106, 86 + 2 + idx * 58, "DOWN", c, 1) 204 | self.pRender.fb.putstr(20 + 2, 86 + 22 + idx * 58, label + "> ", c, 2) 205 | 206 | c = self.pRender.ConvRgb(0.32, 0.3, 1) 207 | self.pRender.fb.draw.rect(c, Rect(20 + 2, 86 + 7 + idx * 58, 84, 6), 0) 208 | 209 | if isToggle == 0: 210 | c = self.pRender.ConvRgb(0.32, 0.4, 0.4) 211 | self.pRender.fb.putstr(20 + 102 + 70, 86 + 30 + idx * 58, unit, c, 212 | 1) 213 | self.pRender.fb.putstr(20 + 102 + 12, 86 + 22 + idx * 58, 214 | "%04d" % up, c, 2) 215 | self.pRender.fb.putstr(20 + 102 + 106 + 70, 86 + 30 + idx * 58, 216 | unit, c, 1) 217 | self.pRender.fb.putstr(20 + 102 + 106 + 12, 86 + 22 + idx * 58, 218 | "%04d" % down, c, 2) 219 | 220 | def RenderTrafficInfo(self, isUpdate=False): 221 | tcpNr = 0 222 | udpNr = 0 223 | c = self.pRender.ConvRgb(0.1, 0.1, 0.9) 224 | if isUpdate == False: 225 | self.pRender.fb.putstr(350, 88, "NAT SESS", c, 2) 226 | self.pRender.fb.putstr(350, 110, "TCP", c, 1) 227 | self.pRender.fb.putstr(414, 110, "UDP", c, 1) 228 | else: 229 | c = self.pRender.ConvRgb(0.0, 0.0, 0.0) 230 | self.pRender.fb.draw.rect(c, Rect(344, 120, 128, 18), 0) 231 | 232 | #cmd = "cat /proc/net/nf_conntrack" 233 | cmd = "conntrack -L" 234 | conntrack = subprocess.check_output( 235 | cmd.strip().split(" ")).splitlines() 236 | 237 | for line in conntrack: 238 | elm = list(map(str, line.decode().split())) 239 | if elm[0] == 'tcp': 240 | tcpNr += 1 241 | if elm[0] == 'udp': 242 | udpNr += 1 243 | 244 | c = self.pRender.ConvRgb(0.1, 0.1, 0.9) 245 | self.pRender.fb.putstr(350, 120, "%5d" % tcpNr, c, 2) 246 | self.pRender.fb.putstr(414, 120, "%5d" % udpNr, c, 2) 247 | 248 | return 249 | -------------------------------------------------------------------------------- /ScReplay.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess, os.path, math 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | 9 | 10 | class ScReplay(ScBase): 11 | def __init__(self, pCTX, pRender, pWanem): 12 | super(ScReplay, self).__init__(pCTX, pRender, pWanem) 13 | self.ptDef.insert( 14 | 0, self.CreateTocuhDef("BtMenu", 468, 29, 62, 42, self.BtHandler)) 15 | 16 | self.ptDef.insert( 17 | 1, 18 | self.CreateTocuhDef("BtGroupPrev", 470, 264, 80, 50, 19 | self.BtHandler)) 20 | self.ptDef.insert( 21 | 2, 22 | self.CreateTocuhDef("BtGroupNext", 388, 264, 80, 50, 23 | self.BtHandler)) 24 | self.ptDef.insert( 25 | 3, 26 | self.CreateTocuhDef("BtCatPrev", 296, 264, 80, 50, self.BtHandler)) 27 | self.ptDef.insert( 28 | 4, 29 | self.CreateTocuhDef("BtCatNext", 214, 264, 80, 50, self.BtHandler)) 30 | self.ptDef.insert( 31 | 5, self.CreateTocuhDef("BtSelect", 110, 264, 80, 50, 32 | self.BtHandler)) 33 | 34 | def BtHandler(self, key): 35 | print("BtHandler" + key) 36 | if key == "BtMenu": 37 | self.nextScene = "Menu" 38 | self.state = self.STATE_TERM 39 | elif key == "BtGroupPrev": 40 | self.UpdateGroup(-1) 41 | elif key == "BtGroupNext": 42 | self.UpdateGroup(1) 43 | elif key == "BtCatPrev": 44 | self.UpdateCategory(-1) 45 | elif key == "BtCatNext": 46 | self.UpdateCategory(1) 47 | elif key == "BtSelect": 48 | if self.datNr > 0: 49 | self.nextScene = "Playback" 50 | self.state = self.STATE_TERM 51 | 52 | def UpdateGroup(self, vec, forceClear=False): 53 | 54 | prevPageIdx = self.groupPageIdx 55 | prevFocusIdx = self.groupFocusIdx 56 | isPageSwitch = forceClear 57 | 58 | if (self.groupPageIdx * 5 + self.groupFocusIdx) == 0 and vec == -1: 59 | return 60 | if (self.groupPageIdx * 5 + self.groupFocusIdx) == (self.groupNr - 61 | 1) and vec == 1: 62 | return 63 | if (self.groupFocusIdx % 5) == 0 and vec == -1: 64 | self.groupPageIdx -= 1 65 | isPageSwitch = True 66 | elif (self.groupFocusIdx % 5) == 4 and vec == 1: 67 | self.groupPageIdx += 1 68 | isPageSwitch = True 69 | 70 | self.groupFocusIdx = (self.groupFocusIdx + vec) % 5 71 | 72 | if isPageSwitch: 73 | # Clear 74 | c = self.pRender.ConvRgb(0, 0, 0) 75 | self.pRender.fb.draw.rect(c, Rect(1, 92, 176, 30 * 5 + 14), 0) 76 | 77 | # Render Focus 78 | c = self.pRender.ConvRgb(1.00, 0.8, 0.4) 79 | self.pRender.fb.draw.rect( 80 | c, Rect(1, 92 + 30 * self.groupFocusIdx, 176, 30), 0) 81 | 82 | # Render List 83 | # currentIdx = self.groupPageIdx * 5 + self.groupFocusIdx 84 | currentIdxTop = self.groupPageIdx * 5 85 | focusIdx = 0 86 | for file in self.groupList[currentIdxTop:currentIdxTop + 5]: 87 | self.pRender.fb.putstr(12, 100 + 30 * focusIdx, 88 | "> %s" % file[0:8], self.pRender.W, 2) 89 | focusIdx += 1 90 | 91 | # Render Pager 92 | self.pRender.fb.putstr( 93 | 12 + 58, 100 + 30 * 5 - 3, " %d / %d" % 94 | (self.groupPageIdx + 1, math.ceil(self.groupNr / 5.0)), 95 | self.pRender.W, 1) 96 | else: 97 | # Clear 98 | c = self.pRender.ConvRgb(0, 0, 0) 99 | self.pRender.fb.draw.rect(c, 100 | Rect(1, 92 + 30 * prevFocusIdx, 176, 30), 101 | 0) 102 | #self.pRender.fb.draw.rect(c, Rect(1, 92 + 30 * self.groupFocusIdx, 176, 30), 0) 103 | 104 | # Render Focus 105 | c = self.pRender.ConvRgb(1.00, 0.8, 0.4) 106 | self.pRender.fb.draw.rect( 107 | c, Rect(1, 92 + 30 * self.groupFocusIdx, 176, 30), 0) 108 | 109 | # Render Prev 110 | idx = prevPageIdx * 5 + prevFocusIdx 111 | file = self.groupList[idx] 112 | self.pRender.fb.putstr(12, 100 + 30 * (prevFocusIdx % 5), 113 | "> %s" % file[0:8], self.pRender.W, 2) 114 | 115 | # Render Current 116 | idx = self.groupPageIdx * 5 + self.groupFocusIdx 117 | file = self.groupList[idx] 118 | self.pRender.fb.putstr(12, 100 + 30 * (self.groupFocusIdx % 5), 119 | "> %s" % file[0:8], self.pRender.W, 2) 120 | 121 | self.LoadCategory() 122 | self.UpdateCategory(0, True) 123 | 124 | def LoadCategory(self): 125 | print("LoadCategory") 126 | gidx = self.groupPageIdx * 5 + self.groupFocusIdx 127 | self.catList = os.listdir(self.pCTX.replayDataPath + "/" + 128 | self.groupList[gidx]) 129 | #self.catList.sort() 130 | self.catPageIdx = 0 131 | self.catNr = len(self.catList) 132 | self.catFocusIdx = 0 133 | 134 | def UpdateCategory(self, vec, forceClear=False): 135 | 136 | prevPageIdx = self.catPageIdx 137 | prevFocusIdx = self.catFocusIdx 138 | isPageSwitch = forceClear 139 | 140 | if (self.catPageIdx * 5 + self.catFocusIdx) == 0 and vec == -1: 141 | return 142 | if (self.catPageIdx * 5 + self.catFocusIdx) == (self.catNr - 143 | 1) and vec == 1: 144 | return 145 | if (self.catFocusIdx % 5) == 0 and vec == -1: 146 | self.catPageIdx -= 1 147 | isPageSwitch = True 148 | elif (self.catFocusIdx % 5) == 4 and vec == 1: 149 | self.catPageIdx += 1 150 | isPageSwitch = True 151 | 152 | self.catFocusIdx = (self.catFocusIdx + vec) % 5 153 | 154 | if isPageSwitch: 155 | # Clear 156 | c = self.pRender.ConvRgb(0, 0, 0) 157 | self.pRender.fb.draw.rect(c, Rect(191, 92, 176, 30 * 5 + 14), 0) 158 | 159 | # Render Focus 160 | c = self.pRender.ConvRgb(1.00, 0.8, 0.4) 161 | self.pRender.fb.draw.rect( 162 | c, Rect(191, 92 + 30 * self.catFocusIdx, 176, 30), 0) 163 | 164 | # Render List 165 | #currentIdx = self.catPageIdx * 5 + self.catFocusIdx 166 | currentIdxTop = self.catPageIdx * 5 167 | focusIdx = 0 168 | currentIdxTopTerm = currentIdxTop + 5 169 | 170 | if currentIdxTopTerm > self.catNr: 171 | currentIdxTopTerm = self.catNr 172 | for file in self.catList[currentIdxTop:currentIdxTopTerm]: 173 | self.pRender.fb.putstr(202, 100 + 30 * focusIdx, 174 | "> %s" % file[0:8], self.pRender.W, 2) 175 | focusIdx += 1 176 | 177 | # Render Pager 178 | self.pRender.fb.putstr( 179 | 260, 100 + 30 * 5 - 3, " %d / %d" % 180 | (self.catPageIdx + 1, math.ceil(self.catNr / 5.0)), 181 | self.pRender.W, 1) 182 | else: 183 | 184 | # Clear 185 | c = self.pRender.ConvRgb(0, 0, 0) 186 | self.pRender.fb.draw.rect( 187 | c, Rect(191, 92 + 30 * prevFocusIdx, 176, 30), 0) 188 | #self.pRender.fb.draw.rect(c, Rect(191, 92 + 30 * self.catFocusIdx, 176, 30), 0) 189 | 190 | # Render Focus 191 | c = self.pRender.ConvRgb(1.00, 0.8, 0.4) 192 | self.pRender.fb.draw.rect( 193 | c, Rect(191, 92 + 30 * self.catFocusIdx, 176, 30), 0) 194 | 195 | # Render Prev 196 | idx = prevPageIdx * 5 + prevFocusIdx 197 | file = self.catList[idx] 198 | self.pRender.fb.putstr(202, 100 + 30 * (prevFocusIdx % 5), 199 | "> %s" % file[0:8], self.pRender.W, 2) 200 | 201 | # Render Current 202 | idx = self.catPageIdx * 5 + self.catFocusIdx 203 | file = self.catList[idx] 204 | self.pRender.fb.putstr(202, 100 + 30 * (self.catFocusIdx % 5), 205 | "> %s" % file[0:8], self.pRender.W, 2) 206 | 207 | self.UpdateInfo(True) 208 | 209 | def UpdateInfo(self, forceClear=False): 210 | 211 | gidx = self.groupPageIdx * 5 + self.groupFocusIdx 212 | self.catList = os.listdir(self.pCTX.replayDataPath + "/" + 213 | self.groupList[gidx]) 214 | cidx = self.catPageIdx * 5 + self.catFocusIdx 215 | 216 | targetPath = self.pCTX.replayDataPath + "/" + self.groupList[ 217 | gidx] + "/" + self.catList[cidx] 218 | 219 | datList = os.listdir(targetPath) 220 | self.datNr = len(datList) 221 | mtime = os.path.getmtime(targetPath) 222 | t = datetime.datetime.fromtimestamp(mtime) 223 | datMtime = t.strftime("%Y/%m/%d") 224 | 225 | if forceClear: 226 | self.pRender.fb.putstr(388, 100 + 30 * 0, "* Data Nr", 227 | self.pRender.W, 1) 228 | self.pRender.fb.putstr(388, 100 + 30 * 2 - 10, "* Last Update", 229 | self.pRender.W, 1) 230 | 231 | # Clear 232 | c = self.pRender.ConvRgb(0, 0, 0) 233 | self.pRender.fb.draw.rect(c, Rect(388, 100 + 30 * 1 - 10, 90, 30), 0) 234 | self.pRender.fb.draw.rect(c, Rect(388, 100 + 30 * 3 - 20, 90, 30), 0) 235 | 236 | self.pRender.fb.putstr(388, 100 + 30 * 1 - 10, "%13d" % self.datNr, 237 | self.pRender.W, 1) 238 | self.pRender.fb.putstr(388, 100 + 30 * 3 - 20, "%13s" % datMtime, 239 | self.pRender.W, 1) 240 | 241 | print(targetPath) 242 | self.pCTX.currentReplayData = targetPath 243 | 244 | def Start(self): 245 | super(ScReplay, self).Start() 246 | 247 | ##[ Get DataDir Info ]###################################################### 248 | 249 | self.datNr = 0 250 | 251 | self.groupList = os.listdir(self.pCTX.replayDataPath) 252 | self.groupList.sort() 253 | self.groupPageIdx = 0 254 | self.groupNr = len(self.groupList) 255 | self.groupFocusIdx = 0 256 | self.LoadCategory() 257 | 258 | #print str(len(files)) 259 | #for file in files[10:15]: 260 | # print file 261 | 262 | ##[ RENDER ]################################################################ 263 | 264 | self.pRender.UpdateTitle("WAN Emulation - Replay") 265 | self.pRender.UpdateSubTitle("Please select group and category") 266 | 267 | c = yellow = self.pRender.fb.rgb(255, 255, 0) 268 | self.pRender.fb.draw.rect(c, Rect(0, 54, self.pRender.xres, 1), 0) 269 | self.pRender.fb.draw.rect(c, Rect(0, 74, self.pRender.xres, 1), 0) 270 | self.pRender.fb.draw.rect(c, Rect(0, 54, 10 + 60, 20), 0) 271 | self.pRender.fb.draw.rect(c, Rect(480 - 10, 54, 10, 20), 0) 272 | self.pRender.fb.putstr(26, 54 + 7, ">>>", self.pRender.N, 1) 273 | 274 | c = self.pRender.ConvRgb(0.16, 0.4, 0.2) 275 | self.pRender.fb.draw.rect(c, Rect(1, 75, 478, 16), 0) 276 | thlabel = "group category info" 277 | self.pRender.fb.putstr(74, 79, thlabel, self.pRender.W, 1) 278 | c = self.pRender.ConvRgb(0.16, 1, 0.6) 279 | self.pRender.fb.draw.rect(c, Rect(178, 75, 12, 320 - 76), 0) 280 | self.pRender.fb.draw.rect(c, Rect(368, 75, 12, 320 - 76), 0) 281 | self.pRender.fb.putstr(178, 160, ">", self.pRender.N, 2) 282 | self.pRender.fb.putstr(368, 160, ">", self.pRender.N, 2) 283 | 284 | c = self.pRender.ConvRgb(0.16, 1, 0.6) 285 | self.pRender.fb.draw.rect(c, Rect(1, 240 + 18, self.pRender.xres - 2, 286 | 1), 0) 287 | 288 | self.RenderFootBt(0, " Up", 0.36) 289 | self.RenderFootBt(1, " Down", 0.36) 290 | self.RenderFootBt(2, " Up", 0.36) 291 | self.RenderFootBt(3, " Down", 0.36) 292 | self.RenderFootBt(4, "Select", 0.56) 293 | 294 | self.UpdateGroup(0, True) 295 | self.RenderBackBt(True) 296 | 297 | def RenderFootBt(self, idx, label, h): 298 | if idx == 0: 299 | x = 10 - 1 300 | elif idx == 1: 301 | x = 10 + 80 + 1 302 | elif idx == 2: 303 | x = 198 304 | elif idx == 3: 305 | x = 198 + 80 + 2 306 | elif idx == 4: 307 | x = 389 308 | 309 | c = self.pRender.ConvRgb(h, 0.6, 0.6) 310 | self.pRender.fb.draw.rect(c, Rect(x, 264, 80, 44), 0) 311 | c = self.pRender.ConvRgb(h, 0.6, 0.2) 312 | self.pRender.fb.draw.rect(c, Rect(x, 264 + 44, 80, 6), 0) 313 | self.pRender.fb.putstr(x + 4, 278, label, c, 2) 314 | -------------------------------------------------------------------------------- /SceneManager.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, select 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScInit import ScInit 6 | from ScMenu import ScMenu 7 | from ScManual import ScManual 8 | from ScManualEx import ScManualEx 9 | from ScManualEx2 import ScManualEx2 10 | from ScReplay import ScReplay 11 | from ScPlayback import ScPlayback 12 | from ScSetting import ScSetting 13 | from ScRemoteApi import ScRemoteApi 14 | from DataAsset import CTX 15 | 16 | 17 | class SceneManager: 18 | def __init__(self, pCTX, pRender, pWanem, **params): 19 | self.pCTX = pCTX 20 | self.pRender = pRender 21 | self.pWanem = pWanem 22 | 23 | self.pCTX.debug = params["debug"] 24 | 25 | self.pScInit = ScInit(self.pCTX, self.pRender, self.pWanem) 26 | self.pScMenu = ScMenu(self.pCTX, self.pRender, self.pWanem) 27 | self.pScManual = ScManual(self.pCTX, self.pRender, self.pWanem) 28 | self.pScManualEx = ScManualEx(self.pCTX, self.pRender, self.pWanem) 29 | self.pScManualEx2 = ScManualEx2(self.pCTX, self.pRender, self.pWanem) 30 | self.pScReplay = ScReplay(self.pCTX, self.pRender, self.pWanem) 31 | self.pScPlayback = ScPlayback(self.pCTX, self.pRender, self.pWanem) 32 | self.pScSetting = ScSetting(self.pCTX, self.pRender, self.pWanem) 33 | self.pScRemoteApi = ScRemoteApi(self.pCTX, self.pRender, self.pWanem) 34 | 35 | if params["initScene"] == None: 36 | self.LoadScene("Init") 37 | else: 38 | self.LoadScene(params["initScene"]) 39 | 40 | def Update(self): 41 | if self.m_currentScene is not None: 42 | self.m_currentScene.Update() 43 | if self.m_currentScene.state == self.m_currentScene.STATE_TERM: 44 | self.LoadScene(self.m_currentScene.nextScene) 45 | 46 | def TouchDownHandler(self, x, y): 47 | if self.m_currentScene is not None: 48 | self.m_currentScene.TouchDownHandler(x, y) 49 | 50 | def TouchUpHandler(self, x, y): 51 | if self.m_currentScene is not None: 52 | self.m_currentScene.TouchUpHandler(x, y) 53 | 54 | def LoadScene(self, nextScene): 55 | if nextScene == "": 56 | self.m_currentScene = None 57 | return 58 | 59 | if nextScene == "Init": 60 | self.m_currentScene = self.pScInit 61 | elif nextScene == "Menu": 62 | self.m_currentScene = self.pScMenu 63 | elif nextScene == "Manual": 64 | self.m_currentScene = self.pScManual 65 | elif nextScene == "ManualEx": 66 | self.m_currentScene = self.pScManualEx 67 | elif nextScene == "ManualEx2": 68 | self.m_currentScene = self.pScManualEx2 69 | elif nextScene == "Replay": 70 | self.m_currentScene = self.pScReplay 71 | elif nextScene == "Playback": 72 | self.m_currentScene = self.pScPlayback 73 | elif nextScene == "Setting": 74 | self.m_currentScene = self.pScSetting 75 | elif nextScene == "RemoteApi": 76 | self.m_currentScene = self.pScRemoteApi 77 | else: 78 | self.m_currentScene = self.pScMenu # default 79 | 80 | self.m_currentScene.Start() 81 | -------------------------------------------------------------------------------- /SeekManager.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess, random, os.path, math 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | 9 | 10 | class SeekManager: 11 | def __init__(self, pCTX, progressBarResolution): 12 | self.pCTX = pCTX 13 | self.progressBarResolution = progressBarResolution 14 | self.isRepeat = False 15 | self.isPause = False 16 | self.laps = list(range(0, self.progressBarResolution)) 17 | self.updateInterval = 1 18 | 19 | self.dps = 0 20 | self.totalFrame = 0 21 | 22 | self.seekFrame = 0 23 | self.seekLap = 0 24 | self.seekSec = 0 25 | 26 | def Setup(self, dps, totalFrame): 27 | self.dps = dps 28 | self.totalFrame = totalFrame 29 | self.updateInterval = int(60.0 / self.dps) 30 | 31 | if self.totalFrame == 0: 32 | return 33 | 34 | #totalSec = float(self.totalFrame) / self.dps 35 | 36 | for idx in range(1, self.progressBarResolution): 37 | #self.laps[idx-1] = int(totalSec / self.progressBarResolution * idx) 38 | self.laps[idx - 1] = int( 39 | float(self.totalFrame) / self.progressBarResolution * idx) 40 | 41 | def Start(self): 42 | #self.startTime = int(self.pCTX.current) 43 | self.seekSec = -1 # Precount 44 | self.seekFrame = 0 45 | self.seekLap = 0 46 | 47 | def Stop(self): 48 | self.isPause = False 49 | self.seekSec = -1 # Precount 50 | self.seekFrame = 0 51 | self.seekLap = 0 52 | return 53 | 54 | # Seek Impl 55 | def Update(self, isBoundary): 56 | self.seekFrame += 1 57 | return 58 | 59 | def IsSeekSecOverCurrentLap(self): 60 | #if self.seekSec >= self.laps[self.seekLap]: 61 | if self.seekFrame >= self.laps[self.seekLap]: 62 | return True 63 | else: 64 | return False 65 | 66 | def Conv2FormatedTime(self, dps, frame): 67 | return "%02d:%02d" % (int(frame / dps / 60), int((frame / dps) % 60.0)) 68 | 69 | def GetTotalFormatTime(self): 70 | return self.Conv2FormatedTime(self.dps, self.totalFrame) 71 | 72 | def GetCurrentFormatTime(self): 73 | return self.Conv2FormatedTime(self.dps, self.seekFrame) 74 | 75 | def IsTerm(self): 76 | if self.seekFrame >= self.totalFrame: 77 | return True 78 | else: 79 | return False 80 | -------------------------------------------------------------------------------- /TouchManager.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, time, struct, termios, fcntl, sys, os, select 2 | from time import sleep 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from SceneManager import SceneManager 6 | 7 | 8 | class TouchManager: 9 | def __init__(self, pScene): 10 | self.pScene = pScene 11 | #self.infile_path = "/dev/input/event" + (sys.argv[1] if len(sys.argv) > 1 else "0") 12 | self.infile_path = "/dev/input/event1" 13 | self.FORMAT = 'llHHI' 14 | self.EVENT_SIZE = struct.calcsize(self.FORMAT) 15 | self.lastPtX = 0 16 | self.lastPtY = 0 17 | self.rateX = float(480) / 3900 18 | self.rateY = float(320) / 3900 19 | self.sep = 0 20 | #print str(rateX) 21 | #print str(rateY) 22 | self.in_file = open(self.infile_path, "rb") 23 | flag = fcntl.fcntl(self.in_file, fcntl.F_GETFL) 24 | fcntl.fcntl(self.in_file, fcntl.F_SETFL, os.O_NONBLOCK) 25 | 26 | def PollEvent(self): 27 | 28 | try: 29 | event = self.in_file.read(self.EVENT_SIZE) 30 | except IOError as e: 31 | if e.errno == 11: 32 | return False 33 | 34 | if(event == None): 35 | return False 36 | 37 | #print("Event : ") 38 | #print(event) 39 | 40 | (tv_sec, tv_usec, type, code, 41 | value) = struct.unpack(self.FORMAT, event) 42 | 43 | if type != 0 or code != 0 or value != 0: 44 | print("Event type %u, code %u, value %u at %d.%d" % (type, code, value, tv_sec, tv_usec)) 45 | # Events with code, type and value == 0 are "separator" events 46 | if code == 0: 47 | self.lastPtX = int(value * self.rateX) 48 | #self.sep = 0 49 | elif code == 1: 50 | self.lastPtY = int(value * self.rateY) 51 | if self.sep == 1: 52 | self.sep = 0 53 | #fDownCallback(pWanem, self.lastPtX, self.lastPtY) 54 | self.pScene.TouchDownHandler(self.lastPtX, self.lastPtY) 55 | elif code == 330: 56 | self.sep = 1 57 | elif code == 24: 58 | if self.sep == 1: 59 | self.sep = 0 60 | #fUpCallback(pWanem, self.lastPtX, self.lastPtY) 61 | self.pScene.TouchUpHandler(self.lastPtX, self.lastPtY) 62 | else: 63 | self.sep = 0 64 | else: 65 | self.sep = 0 66 | 67 | return True 68 | 69 | #def Update(self, pWanem, fDownCallback, fUpCallback, wait): 70 | def Update(self, wait): 71 | 72 | if wait <= 0.0: 73 | return False 74 | 75 | # https://repolinux.wordpress.com/2012/10/09/non-blocking-read-from-stdin-in-python/ 76 | readable = select.select([self.in_file], [], [], wait)[0] 77 | if not readable: 78 | return 79 | 80 | recvable = True 81 | while recvable: 82 | recvable = self.PollEvent() 83 | 84 | def Finalize(self): 85 | self.in_file.close() 86 | -------------------------------------------------------------------------------- /V6Util.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess 2 | 3 | class V6Util: 4 | 5 | @staticmethod 6 | def IsLinklocal(addrStr): 7 | ret = False 8 | addr = addrStr.split(':') 9 | prefix = int(addr[0], 16) 10 | 11 | #print(addr[0]) 12 | #print(hex(prefix)) 13 | #print(hex((prefix >> 8))) 14 | #print(hex(prefix & 0xff)) 15 | 16 | if ((prefix >> 8) == 0xfe) and (prefix & 0xc0 == 0x80): 17 | ret = True 18 | 19 | return ret 20 | 21 | @staticmethod 22 | def IsV6Enabled(): 23 | 24 | cmd = "ip addr show dev eth0" 25 | v6Stat = -1 26 | 27 | try: 28 | cmdOut = subprocess.check_output(cmd.strip().split(" ")) 29 | records = cmdOut.decode().strip().split('\n') 30 | #print(records) 31 | 32 | for record in records: 33 | if("inet6" in record): 34 | elms = record.strip().split() 35 | #print(elms) 36 | addr = elms[1] 37 | isLinkLocal = V6Util.IsLinklocal(addr) 38 | #print(addr + " >> Is Link Local >> " + str(isLinkLocal)) 39 | if isLinkLocal == False: 40 | v6Stat = 1 41 | break 42 | else: 43 | v6Stat = 0 44 | 45 | except subprocess.CalledProcessError: 46 | print(cmd + " >> Error") 47 | v6Stat = -1 48 | 49 | return True if v6Stat == 1 else False 50 | 51 | @staticmethod 52 | def GetGua(): 53 | 54 | cmd = "ip addr show dev eth0" 55 | ret = [] 56 | 57 | try: 58 | cmdOut = subprocess.check_output(cmd.strip().split(" ")) 59 | records = cmdOut.decode().strip().split('\n') 60 | #print(records) 61 | 62 | for record in records: 63 | if("inet6" in record): 64 | elms = record.strip().split() 65 | #print(elms) 66 | addr = elms[1] 67 | isLinkLocal = V6Util.IsLinklocal(addr) 68 | #print(addr + " >> Is Link Local >> " + str(isLinkLocal)) 69 | if isLinkLocal == False: 70 | ret.append(addr) 71 | 72 | except subprocess.CalledProcessError: 73 | print(cmd + " >> Error") 74 | 75 | return ret 76 | 77 | """ sample code 78 | 79 | def main(argv): 80 | print("IsV6Enabled >> " + str(V6Util.IsV6Enabled())) 81 | 82 | addrList = V6Util.GetGua() 83 | print("GUA Nr " + str(len(addrList))) 84 | for addr in addrList: 85 | print("GUA >> " + addr) 86 | 87 | if __name__ == '__main__': 88 | main(sys.argv[1:]) 89 | 90 | """ 91 | -------------------------------------------------------------------------------- /Wanem.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, struct, time, termios, fcntl, sys, os, colorsys, threading, time, datetime, subprocess 2 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/fbtft') 3 | from RenderManager import RenderManager 4 | from WanemManager import WanemManager 5 | from ScBase import ScBase 6 | from gfx import Rect 7 | from DataAsset import CTX 8 | from time import sleep 9 | from TouchManager import TouchManager 10 | from WanemManager import WanemManager 11 | from SceneManager import SceneManager 12 | from argparse import ArgumentParser 13 | 14 | 15 | def keypressed(): 16 | try: 17 | c = sys.stdin.read(1) 18 | return True 19 | except IOError: 20 | return False 21 | 22 | 23 | def pause(secs): 24 | fd = sys.stdin.fileno() 25 | 26 | oldterm = termios.tcgetattr(fd) 27 | newattr = termios.tcgetattr(fd) 28 | newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO 29 | termios.tcsetattr(fd, termios.TCSANOW, newattr) 30 | 31 | oldflags = fcntl.fcntl(fd, fcntl.F_GETFL) 32 | fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) 33 | 34 | try: 35 | ctrlc = False 36 | paused = False 37 | t = secs / 0.1 38 | i = 0 39 | while i < t: 40 | if keypressed(): 41 | paused = True 42 | break 43 | sleep(0.1) 44 | i += 1 45 | 46 | if paused: 47 | while True: 48 | if keypressed(): 49 | break 50 | sleep(0.1) 51 | except KeyboardInterrupt: 52 | ctrlc = True 53 | 54 | termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) 55 | fcntl.fcntl(fd, fcntl.F_SETFL, oldflags) 56 | if ctrlc: 57 | sys.exit(1) 58 | 59 | 60 | def main(argv): 61 | 62 | desc = '{0} [Args] [Options]\nDetailed options -h or --help'.format( 63 | __file__) 64 | parser = ArgumentParser(description=desc) 65 | parser.add_argument('-debug', action='store_true', dest='debug') 66 | parser.add_argument('-scene', 67 | type=str, 68 | dest='initScene', 69 | required=False, 70 | help='initial scene') 71 | parser.add_argument('-proxy', 72 | type=str, 73 | dest='proxy', 74 | required=False, 75 | help='https proxy setting') 76 | args = parser.parse_args() 77 | #print str(args.debug) 78 | #print str(args.initScene) 79 | 80 | pCTX = CTX() 81 | pCTX.httpsProxy = args.proxy 82 | if pCTX.httpsProxy is None: 83 | pCTX.httpsProxy = "" 84 | pRender = RenderManager() 85 | #pRender.RenderBaseFrame() 86 | pWanem = WanemManager(pCTX, pRender) 87 | pSceneManager = SceneManager(pCTX, 88 | pRender, 89 | pWanem, 90 | initScene=args.initScene, 91 | debug=args.debug) 92 | pTouch = TouchManager(pSceneManager) 93 | 94 | now = time.time() 95 | 96 | while True: 97 | pSceneManager.Update() 98 | 99 | pCTX.current = time.time() 100 | waitBy = now + (1 / 60.0 * pCTX.tick) 101 | #pTouch.Update(pWanem, TouchDownHandler, TouchUpHandler, waitBy - pCTX.current) 102 | pTouch.Update(waitBy - pCTX.current) 103 | 104 | pCTX.current = time.time() 105 | 106 | if waitBy > pCTX.current: 107 | time.sleep(waitBy - pCTX.current) 108 | pCTX.current = time.time() 109 | 110 | if pCTX.current - now >= 1.0: 111 | # print "pCTX.tick : %02d / %d" % (pCTX.tick, int(pCTX.current * 1000)) 112 | now += 1.0 113 | pCTX.tick = 0 114 | 115 | pCTX.tick += 1 116 | 117 | pRender.Finalize() 118 | pTouch.Finalize() 119 | 120 | 121 | if __name__ == '__main__': 122 | main(sys.argv[1:]) 123 | -------------------------------------------------------------------------------- /WanemManager.py: -------------------------------------------------------------------------------- 1 | import sys, getopt, time, struct, termios, fcntl, sys, os, subprocess 2 | from time import sleep 3 | from RenderManager import RenderManager 4 | 5 | 6 | class WanemManager: 7 | def __init__(self, pCTX, pRenderManager): 8 | self.pCTX = pCTX 9 | self.pRender = pRenderManager 10 | self.disconnState = 0 11 | self.speedState = 0 12 | self.delayState = 0 13 | self.speedPrevState = 0 14 | self.delayPrevState = 0 15 | self.isDualMode = 0 16 | self.speedLabel = ["nolimit", "8Mbps", "1Mbps", "200Kbps", "128Kbps"] 17 | self.delayLabel = ["nolimit", "LTE", "LTE(Jitter)", "3G", "3G(Jitter)"] 18 | self.speedValue = [ 19 | "", "limit 1Mb buffer 2Mb rate 1Mbps", 20 | "limit 128Kb buffer 256Kb rate 128Kbps", 21 | "limit 25Kb buffer 50Kb rate 25Kbps", 22 | "limit 16Kb buffer 32Kb rate 16Kbps" 23 | ] 24 | self.delayValue = [ 25 | "0msec", "25msec", "50msec 30msec", "100msec", "250msec 100msec" 26 | ] 27 | self.lossValueDef = [0, 1, 2, 1, 2] 28 | self.lossValue = ["0%", "100%", "100%"] 29 | self.InitSingle() 30 | self.upRootDevice = "" 31 | self.dwRootDevice = "" 32 | self.upChildDevice = "" 33 | self.dwChildDevice = "" 34 | 35 | cmd = "cat /etc/wanem/wanemmode.prop" 36 | try: 37 | self.wanemMode = int( 38 | subprocess.check_output(cmd.strip().split(" ")).decode().replace( 39 | '\n', '')) 40 | except subprocess.CalledProcessError: 41 | self.wanemMode = 0 42 | 43 | def InitSingle(self): 44 | self.isDualMode = 0 45 | self.upRootDevice = "eth0 root" 46 | self.dwRootDevice = "wlan0 root" 47 | self.dw2RootDevice = "eth1 root" 48 | 49 | cmd = "tc qdisc del dev " + self.upRootDevice 50 | subprocess.call(cmd.strip().split(" ")) 51 | cmd = "tc qdisc add dev " + self.upRootDevice + " netem delay " + self.delayValue[ 52 | self.delayState] + " loss " + self.lossValue[self.disconnState] 53 | subprocess.call(cmd.strip().split(" ")) 54 | 55 | cmd = "tc qdisc del dev " + self.dwRootDevice 56 | subprocess.call(cmd.strip().split(" ")) 57 | cmd = "tc qdisc add dev " + self.dwRootDevice + " netem delay " + self.delayValue[ 58 | self.delayState] + " loss " + self.lossValue[self.disconnState] 59 | subprocess.call(cmd.strip().split(" ")) 60 | 61 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 62 | cmd = "tc qdisc del dev " + self.dw2RootDevice 63 | subprocess.call(cmd.strip().split(" ")) 64 | cmd = "tc qdisc add dev " + self.dw2RootDevice + " netem delay " + self.delayValue[ 65 | self.delayState] + " loss " + self.lossValue[self.disconnState] 66 | subprocess.call(cmd.strip().split(" ")) 67 | 68 | def InitDual(self, bandValueIdx): 69 | 70 | #print "InitDual >> " + str(bandValueIdx) 71 | #print self.speedValue[bandValueIdx] 72 | 73 | self.isDualMode = 1 74 | self.upRootDevice = "eth0 root" 75 | self.dwRootDevice = "wlan0 root" 76 | self.dw2RootDevice = "eth1 root" 77 | cmd = "tc qdisc del dev " + self.upRootDevice 78 | subprocess.call(cmd.strip().split(" ")) 79 | cmd = "tc qdisc del dev " + self.dwRootDevice 80 | subprocess.call(cmd.strip().split(" ")) 81 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 82 | cmd = "tc qdisc del dev " + self.dw2RootDevice 83 | subprocess.call(cmd.strip().split(" ")) 84 | 85 | self.upRootDevice = "eth0 root handle 1:" 86 | self.dwRootDevice = "wlan0 root handle 2:" 87 | self.dw2RootDevice = "eth1 root handle 3:" 88 | self.upChildDevice = "eth0 parent 1: handle 10:" 89 | self.dwChildDevice = "wlan0 parent 2: handle 20:" 90 | self.dw2ChildDevice = "eth1 parent 3: handle 30:" 91 | cmd = "tc qdisc add dev " + self.upRootDevice + " tbf " + self.speedValue[ 92 | bandValueIdx] 93 | subprocess.call(cmd.strip().split(" ")) 94 | cmd = "tc qdisc add dev " + self.upChildDevice + " netem delay " + self.delayValue[ 95 | self.delayState] + " loss " + self.lossValue[self.disconnState] 96 | subprocess.call(cmd.strip().split(" ")) 97 | 98 | cmd = "tc qdisc add dev " + self.dwRootDevice + " tbf " + self.speedValue[ 99 | bandValueIdx] 100 | subprocess.call(cmd.strip().split(" ")) 101 | cmd = "tc qdisc add dev " + self.dwChildDevice + " netem delay " + self.delayValue[ 102 | self.delayState] + " loss " + self.lossValue[self.disconnState] 103 | subprocess.call(cmd.strip().split(" ")) 104 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 105 | cmd = "tc qdisc add dev " + self.dw2RootDevice + " tbf " + self.speedValue[ 106 | bandValueIdx] 107 | subprocess.call(cmd.strip().split(" ")) 108 | cmd = "tc qdisc add dev " + self.dw2ChildDevice + " netem delay " + self.delayValue[ 109 | self.delayState] + " loss " + self.lossValue[self.disconnState] 110 | subprocess.call(cmd.strip().split(" ")) 111 | 112 | def EmuDisconnPush(self): 113 | print("Push") 114 | self.disconnState = 2 115 | self.pRender.RenderDot(0, 6) 116 | self.Apply(False) 117 | 118 | def EmuDisconnRelease(self): 119 | if self.disconnState != 2: 120 | return 121 | print("Release") 122 | self.pRender.RenderDot(0, 5) 123 | self.disconnState = 0 124 | self.Apply(False) 125 | 126 | def EmuDisconnToggle(self): 127 | if self.disconnState == 1: 128 | self.disconnState = 0 129 | self.pRender.RenderDot(0, 5) 130 | elif self.disconnState == 0: 131 | self.disconnState = 1 132 | self.pRender.RenderDot(0, 6) 133 | self.Apply(False) 134 | 135 | # Call by Only ScManualEx2 136 | def EmuDisconnPushMini(self, upBand, dwBand, upDelay, dwDelay, upLoss, 137 | dwLoss): 138 | print("Push") 139 | self.disconnState = 2 140 | self.pRender.RenderDotMini(2, 6) 141 | self.DirectUpdateEx2(upBand, dwBand, upDelay, dwDelay, upLoss, dwLoss) 142 | 143 | # Call by Only ScManualEx2 144 | def EmuDisconnReleaseMini(self, upBand, dwBand, upDelay, dwDelay, upLoss, 145 | dwLoss): 146 | if self.disconnState != 2: 147 | return 148 | print("Release") 149 | self.pRender.RenderDotMini(2, 5) 150 | self.disconnState = 0 151 | self.DirectUpdateEx2(upBand, dwBand, upDelay, dwDelay, upLoss, dwLoss) 152 | 153 | # Call by Only ScManualEx2 154 | def EmuDisconnToggleMini(self, upBand, dwBand, upDelay, dwDelay, upLoss, 155 | dwLoss): 156 | if self.disconnState == 1: 157 | self.disconnState = 0 158 | self.pRender.RenderDotMini(2, 5) 159 | elif self.disconnState == 0: 160 | self.disconnState = 1 161 | self.pRender.RenderDotMini(2, 6) 162 | self.DirectUpdateEx2(upBand, dwBand, upDelay, dwDelay, upLoss, dwLoss) 163 | 164 | def EmuSpeedChange(self, value): 165 | self.speedPrevState = self.speedState 166 | self.speedState = (self.speedState + value + 5) % 5 167 | self.pRender.RenderDot(1, 7 + self.speedState) 168 | 169 | if self.speedState == 0 and self.speedPrevState != 0: 170 | self.InitSingle() 171 | elif self.speedState != 0 and self.speedPrevState == 0: 172 | self.InitDual(self.speedState) 173 | 174 | self.Apply(True) 175 | 176 | def EmuDelayChange(self, value): 177 | self.delayState = (self.delayState + value + 5) % 5 178 | self.pRender.RenderDot(2, 7 + self.delayState) 179 | self.Apply() 180 | 181 | def Clear(self): 182 | self.speedState = 0 183 | self.delayState = 0 184 | self.disconnState = 0 185 | self.Apply(True) 186 | 187 | def Apply(self, isLabelUpdate=True): 188 | if isLabelUpdate == True: 189 | #self.pRender.UpdateTitle("Wan Emulation Mode") 190 | self.pRender.UpdateSubTitle("speed:" + 191 | self.speedLabel[self.speedState] + 192 | ", delay:" + 193 | self.delayLabel[self.delayState]) 194 | 195 | if self.disconnState == 0: 196 | upLossStmt = " loss %d%%" % self.lossValueDef[self.delayState] 197 | dwLossStmt = " loss %d%%" % self.lossValueDef[self.delayState] 198 | else: 199 | upLossStmt = " loss " + self.lossValue[self.disconnState] 200 | dwLossStmt = " loss " + self.lossValue[self.disconnState] 201 | 202 | if self.isDualMode == 0: 203 | cmd = "tc qdisc change dev " + self.upRootDevice + " netem delay " + self.delayValue[ 204 | self.delayState] + upLossStmt 205 | cmd2 = "tc qdisc change dev " + self.dwRootDevice + " netem delay " + self.delayValue[ 206 | self.delayState] + dwLossStmt 207 | cmd3 = "tc qdisc change dev " + self.dw2RootDevice + " netem delay " + self.delayValue[ 208 | self.delayState] + dwLossStmt 209 | 210 | subprocess.call(cmd.strip().split(" ")) 211 | subprocess.call(cmd2.strip().split(" ")) 212 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 213 | subprocess.call(cmd3.strip().split(" ")) 214 | 215 | else: 216 | #print str(self.speedState) + " >> " + self.speedValue[self.speedState] 217 | cmd = "tc qdisc change dev " + self.upRootDevice + " tbf " + self.speedValue[ 218 | self.speedState] 219 | cmd2 = "tc qdisc change dev " + self.upChildDevice + " netem delay " + self.delayValue[ 220 | self.delayState] + upLossStmt 221 | cmd3 = "tc qdisc change dev " + self.dwRootDevice + " tbf " + self.speedValue[ 222 | self.speedState] 223 | cmd4 = "tc qdisc change dev " + self.dwChildDevice + " netem delay " + self.delayValue[ 224 | self.delayState] + dwLossStmt 225 | cmd5 = "tc qdisc change dev " + self.dw2RootDevice + " tbf " + self.speedValue[ 226 | self.speedState] 227 | cmd6 = "tc qdisc change dev " + self.dw2ChildDevice + " netem delay " + self.delayValue[ 228 | self.delayState] + dwLossStmt 229 | 230 | subprocess.call(cmd.strip().split(" ")) 231 | subprocess.call(cmd2.strip().split(" ")) 232 | subprocess.call(cmd3.strip().split(" ")) 233 | subprocess.call(cmd4.strip().split(" ")) 234 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 235 | subprocess.call(cmd5.strip().split(" ")) 236 | subprocess.call(cmd6.strip().split(" ")) 237 | 238 | def DirectApply(self, delay): 239 | if delay >= 0: 240 | param = str(int(delay / 2)) 241 | cmd = "tc qdisc change dev eth0 root netem delay " + param + "msec loss 0%" 242 | cmd2 = "tc qdisc change dev wlan0 root netem delay " + param + "msec loss 0%" 243 | cmd3 = "tc qdisc change dev eth1 root netem delay " + param + "msec loss 0%" 244 | 245 | subprocess.call(cmd.strip().split(" ")) 246 | subprocess.call(cmd2.strip().split(" ")) 247 | subprocess.call(cmd3.strip().split(" ")) 248 | else: 249 | cmd = "tc qdisc change dev eth0 root netem loss 100%" 250 | cmd2 = "tc qdisc change dev wlan0 root netem loss 100%" 251 | cmd3 = "tc qdisc change dev eth1 root netem loss 100%" 252 | 253 | subprocess.call(cmd.strip().split(" ")) 254 | subprocess.call(cmd2.strip().split(" ")) 255 | subprocess.call(cmd3.strip().split(" ")) 256 | 257 | def ClearEx(self): 258 | self.upRootDevice = "eth0 root" 259 | self.dwRootDevice = "wlan0 root" 260 | self.dw2RootDevice = "eth1 root" 261 | cmd = "tc qdisc del dev " + self.upRootDevice 262 | subprocess.call(cmd.strip().split(" ")) 263 | cmd = "tc qdisc del dev " + self.dwRootDevice 264 | subprocess.call(cmd.strip().split(" ")) 265 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 266 | cmd = "tc qdisc del dev " + self.dw2RootDevice 267 | subprocess.call(cmd.strip().split(" ")) 268 | 269 | self.pRender.RenderDotMini(2, 5) 270 | self.disconnState = 0 271 | return 272 | 273 | def ClearEx2(self): 274 | self.upRootDevice = "eth0 root" 275 | self.dwRootDevice = "wlan0 root" 276 | self.dw2RootDevice = "eth1 root" 277 | cmd = "tc qdisc del dev " + self.upRootDevice 278 | subprocess.call(cmd.strip().split(" ")) 279 | cmd = "tc qdisc del dev " + self.dwRootDevice 280 | subprocess.call(cmd.strip().split(" ")) 281 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 282 | cmd = "tc qdisc del dev " + self.dw2RootDevice 283 | subprocess.call(cmd.strip().split(" ")) 284 | 285 | self.disconnState = 0 286 | return 287 | 288 | def DirectApplyEx(self, 289 | upBand, 290 | dwBand, 291 | upDelay, 292 | dwDelay, 293 | upLoss=0, 294 | dwLoss=0): 295 | 296 | if self.wanemMode == 0: 297 | speedUpValue = "limit %dKb buffer %dKb rate %dKbps" % (4, 8, 298 | upBand / 8) 299 | speedDwValue = "limit %dKb buffer %dKb rate %dKbps" % (4, 8, 300 | dwBand / 8) 301 | else: 302 | speedUpValue = "limit %dKb buffer %dKb rate %dKbps" % ( 303 | upBand / 8, upBand / 4, upBand / 8) 304 | speedDwValue = "limit %dKb buffer %dKb rate %dKbps" % ( 305 | dwBand / 8, dwBand / 4, dwBand / 8) 306 | 307 | delayUpValue = "%dmsec" % upDelay 308 | delayDwValue = "%dmsec" % dwDelay 309 | 310 | self.upRootDevice = "eth0 root handle 1:" 311 | self.dwRootDevice = "wlan0 root handle 2:" 312 | self.dw2RootDevice = "eth1 root handle 3:" 313 | self.upChildDevice = "eth0 parent 1: handle 10:" 314 | self.dwChildDevice = "wlan0 parent 2: handle 20:" 315 | self.dw2ChildDevice = "eth1 parent 3: handle 30:" 316 | 317 | if self.disconnState == 0: 318 | upLossStmt = " loss %d%%" % upLoss 319 | dwLossStmt = " loss %d%%" % dwLoss 320 | else: 321 | upLossStmt = " loss " + self.lossValue[self.disconnState] 322 | dwLossStmt = " loss " + self.lossValue[self.disconnState] 323 | 324 | cmd = "tc qdisc add dev " + self.upRootDevice + " tbf " + speedUpValue 325 | subprocess.call(cmd.strip().split(" ")) 326 | cmd = "tc qdisc add dev " + self.upChildDevice + " netem delay " + delayUpValue + upLossStmt 327 | subprocess.call(cmd.strip().split(" ")) 328 | 329 | cmd = "tc qdisc add dev " + self.dwRootDevice + " tbf " + speedDwValue 330 | subprocess.call(cmd.strip().split(" ")) 331 | cmd = "tc qdisc add dev " + self.dwChildDevice + " netem delay " + delayDwValue + dwLossStmt 332 | subprocess.call(cmd.strip().split(" ")) 333 | 334 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 335 | cmd = "tc qdisc add dev " + self.dw2RootDevice + " tbf " + speedDwValue 336 | subprocess.call(cmd.strip().split(" ")) 337 | cmd = "tc qdisc add dev " + self.dw2ChildDevice + " netem delay " + delayDwValue + dwLossStmt 338 | subprocess.call(cmd.strip().split(" ")) 339 | 340 | def DirectApplyEx2(self, upBand, dwBand, upDelay, dwDelay, upLoss, dwLoss): 341 | 342 | if self.wanemMode == 0: 343 | speedUpValue = "limit %dKb buffer %dKb rate %dKbps" % (4, 8, 344 | upBand / 8) 345 | speedDwValue = "limit %dKb buffer %dKb rate %dKbps" % (4, 8, 346 | dwBand / 8) 347 | else: 348 | speedUpValue = "limit %dKb buffer %dKb rate %dKbps" % ( 349 | upBand / 8, upBand / 4, upBand / 8) 350 | speedDwValue = "limit %dKb buffer %dKb rate %dKbps" % ( 351 | dwBand / 8, dwBand / 4, dwBand / 8) 352 | 353 | delayUpValue = "%dmsec" % upDelay 354 | delayDwValue = "%dmsec" % dwDelay 355 | 356 | self.upRootDevice = "eth0 root handle 1:" 357 | self.dwRootDevice = "wlan0 root handle 2:" 358 | self.dw2RootDevice = "eth1 root handle 3:" 359 | self.upChildDevice = "eth0 parent 1: handle 10:" 360 | self.dwChildDevice = "wlan0 parent 2: handle 20:" 361 | self.dw2ChildDevice = "eth1 parent 3: handle 30:" 362 | cmd = "tc qdisc add dev " + self.upRootDevice + " tbf " + speedUpValue 363 | subprocess.call(cmd.strip().split(" ")) 364 | cmd = "tc qdisc add dev " + self.upChildDevice + " netem delay " + delayUpValue + " loss " + str( 365 | upLoss) + "%" 366 | subprocess.call(cmd.strip().split(" ")) 367 | 368 | cmd = "tc qdisc add dev " + self.dwRootDevice + " tbf " + speedDwValue 369 | subprocess.call(cmd.strip().split(" ")) 370 | cmd = "tc qdisc add dev " + self.dwChildDevice + " netem delay " + delayDwValue + " loss " + str( 371 | dwLoss) + "%" 372 | subprocess.call(cmd.strip().split(" ")) 373 | 374 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 375 | cmd = "tc qdisc add dev " + self.dw2RootDevice + " tbf " + speedDwValue 376 | subprocess.call(cmd.strip().split(" ")) 377 | cmd = "tc qdisc add dev " + self.dw2ChildDevice + " netem delay " + delayDwValue + " loss " + str( 378 | dwLoss) + "%" 379 | subprocess.call(cmd.strip().split(" ")) 380 | 381 | def DirectUpdateEx(self, upBand, dwBand, upDelay, dwDelay): 382 | 383 | if self.wanemMode == 0: 384 | speedUpValue = "limit %dKb buffer %dKb rate %dKbps" % (4, 8, 385 | upBand / 8) 386 | speedDwValue = "limit %dKb buffer %dKb rate %dKbps" % (4, 8, 387 | dwBand / 8) 388 | else: 389 | speedUpValue = "limit %dKb buffer %dKb rate %dKbps" % ( 390 | upBand / 8, upBand / 4, upBand / 8) 391 | speedDwValue = "limit %dKb buffer %dKb rate %dKbps" % ( 392 | dwBand / 8, dwBand / 4, dwBand / 8) 393 | 394 | delayUpValue = "%dmsec" % upDelay 395 | delayDwValue = "%dmsec" % dwDelay 396 | 397 | self.upRootDevice = "eth0 root handle 1:" 398 | self.dwRootDevice = "wlan0 root handle 2:" 399 | self.dw2RootDevice = "eth1 root handle 3:" 400 | self.upChildDevice = "eth0 parent 1: handle 10:" 401 | self.dwChildDevice = "wlan0 parent 2: handle 20:" 402 | self.dw2ChildDevice = "eth1 parent 3: handle 30:" 403 | cmd = "tc qdisc change dev " + self.upRootDevice + " tbf " + speedUpValue 404 | subprocess.call(cmd.strip().split(" ")) 405 | cmd = "tc qdisc change dev " + self.upChildDevice + " netem delay " + delayUpValue + " loss " + self.lossValue[ 406 | self.disconnState] 407 | subprocess.call(cmd.strip().split(" ")) 408 | 409 | cmd = "tc qdisc change dev " + self.dwRootDevice + " tbf " + speedDwValue 410 | subprocess.call(cmd.strip().split(" ")) 411 | cmd = "tc qdisc change dev " + self.dwChildDevice + " netem delay " + delayDwValue + " loss " + self.lossValue[ 412 | self.disconnState] 413 | subprocess.call(cmd.strip().split(" ")) 414 | 415 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 416 | cmd = "tc qdisc change dev " + self.dw2RootDevice + " tbf " + speedDwValue 417 | subprocess.call(cmd.strip().split(" ")) 418 | cmd = "tc qdisc change dev " + self.dw2ChildDevice + " netem delay " + delayDwValue + " loss " + self.lossValue[ 419 | self.disconnState] 420 | subprocess.call(cmd.strip().split(" ")) 421 | 422 | def DirectUpdateEx2(self, 423 | upBand, 424 | dwBand, 425 | upDelay, 426 | dwDelay, 427 | upLoss=0, 428 | dwLoss=0): 429 | 430 | if self.wanemMode == 0: 431 | speedUpValue = "limit %dKb buffer %dKb rate %dKbps" % (4, 8, 432 | upBand / 8) 433 | speedDwValue = "limit %dKb buffer %dKb rate %dKbps" % (4, 8, 434 | dwBand / 8) 435 | else: 436 | speedUpValue = "limit %dKb buffer %dKb rate %dKbps" % ( 437 | upBand / 8, upBand / 4, upBand / 8) 438 | speedDwValue = "limit %dKb buffer %dKb rate %dKbps" % ( 439 | dwBand / 8, dwBand / 4, dwBand / 8) 440 | 441 | delayUpValue = "%dmsec" % upDelay 442 | delayDwValue = "%dmsec" % dwDelay 443 | 444 | self.upRootDevice = "eth0 root handle 1:" 445 | self.dwRootDevice = "wlan0 root handle 2:" 446 | self.dw2RootDevice = "eth1 root handle 3:" 447 | self.upChildDevice = "eth0 parent 1: handle 10:" 448 | self.dwChildDevice = "wlan0 parent 2: handle 20:" 449 | self.dw2ChildDevice = "eth1 parent 3: handle 30:" 450 | 451 | if self.disconnState == 0: 452 | upLossStmt = " loss %d%%" % upLoss 453 | dwLossStmt = " loss %d%%" % dwLoss 454 | else: 455 | upLossStmt = " loss " + self.lossValue[self.disconnState] 456 | dwLossStmt = " loss " + self.lossValue[self.disconnState] 457 | 458 | cmd = "tc qdisc change dev " + self.upRootDevice + " tbf " + speedUpValue 459 | subprocess.call(cmd.strip().split(" ")) 460 | cmd = "tc qdisc change dev " + self.upChildDevice + " netem delay " + delayUpValue + upLossStmt 461 | subprocess.call(cmd.strip().split(" ")) 462 | 463 | cmd = "tc qdisc change dev " + self.dwRootDevice + " tbf " + speedDwValue 464 | subprocess.call(cmd.strip().split(" ")) 465 | cmd = "tc qdisc change dev " + self.dwChildDevice + " netem delay " + delayDwValue + dwLossStmt 466 | subprocess.call(cmd.strip().split(" ")) 467 | 468 | if self.pCTX.lanMode == self.pCTX.LAN_MODE_HYBRID: 469 | cmd = "tc qdisc change dev " + self.dw2RootDevice + " tbf " + speedDwValue 470 | subprocess.call(cmd.strip().split(" ")) 471 | cmd = "tc qdisc change dev " + self.dw2ChildDevice + " netem delay " + delayDwValue + dwLossStmt 472 | subprocess.call(cmd.strip().split(" ")) 473 | -------------------------------------------------------------------------------- /docs/FirstStep.md: -------------------------------------------------------------------------------- 1 | EM-uNetPi 利用ガイド 2 | ================================================================================================== 3 | 4 | 概要 5 | -------------------------------------------------------------------------------------------------- 6 | 7 | 従来、専門的なツールが必要だった回線エミュレーションを、カジュアルに行えるようにするためのツール
8 | \ Network Debug のお楽しみはこれからだ! / 9 | 10 | このツールを使用するには二つの方法があります。 11 | 12 | - 1. 完成イメージをreleaseタブから取得しSDカードに焼き、組み立てた完成ハードに刺す 13 | - 2. [こちらのビルド手順](ManualBuild.md) を参考に素の Raspberry Pi OS から構築する。 14 | 15 | 特にこだわりがない場合、前者を奨励します。また、パーツに関しては [こちら](PartsList.md) を参考に一式揃えてください。 16 | 17 | ハードウェアの組立方法 18 | -------------------------------------------------------------------------------------------------- 19 | 20 | USB機器は差し込み、タッチパネルはGPIOのピンに沿って刺すだけです。 21 | 22 | 23 | 24 | > USB機器の接続ポートは次の項目に従ってください。適当に刺すと、うまく認識しない可能性があります。 25 | 26 | 接続方法 27 | -------------------------------------------------------------------------------------------------- 28 | 29 | ネットワークケーブルの配線方法は下図の通りです。配線後、起動してください。 30 | 31 | クライアントは、有線/無線いずれでも接続が可能です。 32 | 33 | 34 | 35 | > 以前の Raspberry 3 向けの配線とは、LAN / 管理ポートが逆位置になっているので、注意してください。 36 | > 37 | > 組み立ての項目にも書いた通り、刺すポートを間違えるとデバイスをうまく認識しないことがあります。 38 | > 39 | > 認識に失敗している場合、起動画面でエラーとなり、起動に失敗します。 40 | 41 | 起動方法 42 | -------------------------------------------------------------------------------------------------- 43 | 44 | 電源を入れると、1分程度でスプラッシュスクリーン、操作コンソールが表示されます。 45 | 46 | 操作はタッチパネルによるタッチ入力で行います。 47 | 48 | 終了方法 49 | -------------------------------------------------------------------------------------------------- 50 | 51 | Setting > MISC から Shutdown を押し、反応が無くなったら、電源を切ってください。 52 | 53 | > この手順を踏まずに強制的に電源を切断 => 再投入した場合、起動時に数分かかる場合があります。 54 | 55 | 基本的な使用法 56 | -------------------------------------------------------------------------------------------------- 57 | 58 | モードセレクトの左側のManual Modeの 59 | 60 | - Preset Mode 61 | - Direct Mode 62 | 63 | が帯域/遅延/パケットロスト/切断をシミュレーションする基本的なモードです。 64 | 65 | 前者はプリセット値から選択する簡易モードで、後者は直接値を指定するモードです。 66 | 67 | API Mode 68 | -------------------------------------------------------------------------------------------------- 69 | 70 | このモードに入ると、管理ポートに任意のJsonをUDPで送ることにより、帯域/遅延/パケットロスト/切断を制御できるようになります。 71 | 72 | Jsonの形式や送信サンプルについては、tools/WanemCtl.php を参照してください。 73 | 74 | Replay Mode 75 | -------------------------------------------------------------------------------------------------- 76 | 77 | 端末で記録した遅延データを読み込んで、時系列で再現するモードです。 78 | 79 | 諸般の事情で、現在一時的に使用不可能になっています。 80 | 81 | Setting 82 | -------------------------------------------------------------------------------------------------- 83 | 84 | 諸々設定の変更ができます。一部設定は変更後、rebootしないと反映されないため注意 85 | 86 | - APの2.4GHz/5GHz設定切替 87 | - IPv6モードの切替 88 | - NAPTモードのSymmetric切替 89 | - 帯域シミュレーション時のパケット制御方式(Policing/Shaping)切替 90 | 91 | その他 92 | -------------------------------------------------------------------------------------------------- 93 | 94 | ### 管理ポートからのログインについて 95 | 96 | 完成イメージで動作しているものに対して、sshログインしたい場合、
97 | デフォルトで下記のアドレス/ユーザ設定で、管理ポートからログインできます。 98 | 99 | - 管理ポートアドレス: 192.168.31.67 100 | - ユーザ:user 101 | - パスワード:password 102 | -------------------------------------------------------------------------------- /docs/ManualBuild.md: -------------------------------------------------------------------------------- 1 | 一から構築する手順 for Raspberry Pi 5 2 | ================================================================================================== 3 | 4 | 諸注意 5 | -------------------------------------------------------------------------------------------------- 6 | 7 | RaspberryPiとLinuxの知識がある程度あることを前提に記述をします。
8 | 不明な点等がある場合、まずは、一般的な技術文献をあたってください。 9 | 10 | また、最新版では Raspberry Pi 5 を前提にした記述になっています。 11 | 12 | Raspberry Pi の初期設定 13 | -------------------------------------------------------------------------------------------------- 14 | 15 | ### 組み立て 16 | 17 | ハードウェアのパーツを揃えたら、以下の動画にしたがって、組み立てます。 18 | 19 | #### 動画 20 | 21 | // TBD 22 | 23 | #### USBポートへの接続について 24 | 25 | 今回使う Raspberry Pi OS は、USB制御(xhci)まわりに不具合があるのか、いくつかのパーツを挿すポートによっては、うまく動きません。 26 | 27 | - 有線LAN アダプタ => USB2ポート(青くないポート) 28 | 29 | - 無線LAN ドングル => USB3ポート(青いポート) 30 | 31 | に接続してください。間違えると、OS起動中にUSBデバイスのリセットループにハマって起動しません。(起動することもありますが、おそらくUSB機器が正常に認識されていないため、うまく動きません) 32 | 33 | また、電源アダプタによる出力が安定していない場合、USB機器がうまく認識されないことも確認しています(3V5Aアダプタで妥協していると起きがち)。デバイスがうまく認識されていないと疑わしい時は 34 | 35 | ```bash 36 | $ lsusb 37 | ``` 38 | 39 | を実行して、適切に認識されているか、確認してください。 40 | 41 | ### 初期イメージ用意 42 | 43 | - 以下のバージョンの 「Raspberry Pi OS Lite」 のイメージファイルを [RaspberryPi公式ページ](https://www.raspberrypi.com/software/) からダウンロードし、SDカードに焼き、本体に挿入します。 44 | 45 | #### 使用するOSのバージョン 46 | 47 | - Raspberry Pi OS Lite 48 | 49 | - Release date: July 4th 2024 50 | 51 | - System: 64-bit 52 | 53 | - Kernel version: 6.6 54 | 55 | - Debian version: 12 (bookworm) 56 | 57 | - Size: 432MB 58 | 59 | > カーネルのバージョンが異なったりすると、正常に動作しない可能性が高いので、必ず指定のバージョンを使用すること。 60 | 61 | ### OSの設定 62 | 63 | #### 初回起動 64 | 65 | 昔のバージョンと違って、起動時にユーザ作成が要求されるため「pi」というユーザで作成してください(オートログインの設定を後で行うので、パスワードは任意でOK)。 66 | 67 | > 提供するイメージの pi ユーザの passwordは、以前のバージョンと同じ「raspberry」となっています。適宜変更してください。 68 | 69 | 異なるユーザ名で作成した場合、スクリプトを一部書き換える必要が出てくるので、どうしても変えたい方は合わせて追加修正を行うようにしてください。 70 | 71 | #### raspi-configで設定変更 72 | 73 | ユーザ設定後、raspi-configで以下の項目を設定し再起動してください。 74 | 75 | - SSHログインを有効にする 76 | 77 | - SPIを有効にする 78 | - Host名を任意の名前に変更する 79 | - Boot オプションから Auto Login を有効にする 80 | 81 | ```bash 82 | $ sudo raspi-config 83 | ``` 84 | 85 | 以後の作業はsshで行なって大丈夫です。 86 | 87 | #### 作業用ユーザ設定 88 | 89 | 下記のように作業用のユーザを作成、sudo権限付与する。 90 | これ以降は、作成したユーザでsshログインして作業を進める。 91 | 92 | ```bash 93 | $ sudo adduser user 94 | $ sudo gpasswd -a user sudo 95 | ``` 96 | 97 | > 提供するイメージの user ユーザの password は「password」になっています。適宜変更してください。 98 | 99 | #### ミドルウェア諸々追加 100 | 101 | ```bash 102 | $ sudo apt-get update 103 | $ sudo apt-get upgrade 104 | $ sudo apt-get install screen 105 | $ sudo apt-get install rsync 106 | $ sudo apt-get install git 107 | $ sudo apt-get install php 108 | $ sudo apt-get install python-dev-is-python3 109 | $ sudo apt-get install python3-pip 110 | $ sudo apt-get install bc 111 | $ sudo apt-get install libnl-genl-3-dev 112 | $ sudo apt-get install libssl-dev 113 | $ sudo apt-get install conntrack 114 | $ sudo apt-get install iptables 115 | $ sudo apt-get install iptables-persistent 116 | $ sudo apt-get install radvd 117 | $ sudo apt-get install radvdump 118 | ``` 119 | 120 | iptablesのあたりで現在のルールを保存するか訊かれますが、任意で答えて問題ありません。 121 | 122 | radvd は自動起動設定が有効にされてしまうのは厄介なので 123 | 124 | ```bash 125 | $ sudo systemctl disable radvd 126 | ``` 127 | 128 | として、自動起動を無効化しておいてください。 129 | 130 | ### リポジトリからソースの取得・必要なリソース生成 131 | 132 | EM-uNetPiのリポジトリをCloneし 133 | 134 | ```bash 135 | $ cd /home/pi 136 | $ git clone https://github.com/KONAMI/EM-uNetPi.git 137 | $ cd EM-uNetPi 138 | $ git submodule update --init --recursive 139 | $ cd fbtft 140 | $ patch -u < ../misc/patch/fbtft_python3.patch 141 | $ cd ../ 142 | $ sudo make prop 143 | ``` 144 | 145 | ### 各種デバイス・ドライバのセットアップ 146 | 147 | #### タッチパネルドライバのビルド&セットアップ 148 | 149 | ```bash 150 | $ sudo apt-get install fbi 151 | $ git clone https://github.com/swkim01/waveshare-dtoverlays.git 152 | ``` 153 | 154 | リポジトリのモジュールはRaspberry Pi 5 に対応していないので、Raspberry Pi 5 環境でリビルドする必要あり 155 | 156 | ``` 157 | $ cd waveshare-dtoverlays 158 | $ make clean all 159 | $ sudo cp waveshare35a.dtbo /boot/overlays/ 160 | ``` 161 | 162 | 最後に 163 | 164 | /boot/firmware/config.txt の dtparam=spi=on の次の行あたりに 165 | 166 | ``` 167 | dtoverlay=waveshare35a:rotate=90,swapxy=1 168 | ``` 169 | 170 | を追加して、再起動後、タッチパネルにコンソール画面が描画されていれば無事セットアップ完了です。 171 | 172 | > 同じ WaveShare の 3.5inch_RPi_LCD_(A) を組み込んだタッチパネルであっても、モノによって結線が違うことがあるので、rotateの回転角度は環境によって 90 or 270 で適宜書き換えてください。 173 | 174 | 一応確認のために、 175 | 176 | ```bash 177 | $ hexdump /dev/input/event1 178 | ``` 179 | 180 | と打った後に適当に画面をタップして、イベントが拾えているか確認を奨励。 181 | 182 | > もし、タップしてもなにも表示されない場合、event1 を event0 や event2 に変更して検証。それで拾えた場合は、リポジトリのソースをそれに合わせて修正する必要あり。 183 | > 184 | > 大体、キーボードやその他の不要なデバイスを繋ぎっぱなしが原因でズレるので、余計なものを外して再起動すると、想定通りの event1 で拾えるようになるはず。 185 | 186 | #### 無線LANアダプタのビルド&セットアップ 187 | 188 | 相変わらず本体の無線LANチップが貧弱で、そのままAP化するとWANエミュレートに不都合な無線品質になるため、外部の無線LANアダプタを使います。 189 | 190 | まずは、オンボードの無線LANデバイスを無効化します。 191 | 192 | /etc/modprobe.d/raspi-blacklist.conf に下記を追記して再起動すると無効化されます。 193 | 194 | ``` 195 | blacklist brcmfmac 196 | blacklist brcmutil 197 | ``` 198 | 199 | 再起動後に 200 | 201 | ```bash 202 | $ ip addr 203 | ``` 204 | 205 | と打って、wlan0のインターフェースが消えていればOK。 206 | 207 | その後、ドライバをビルドします。 208 | 209 | ``` 210 | git clone https://github.com/morrownr/rtl8852bu.git 211 | cd rtl8852bu 212 | make 213 | sudo make install 214 | ``` 215 | 216 | ##### デバイスの接続 217 | 218 | __ここまで作業を進めたら、有線LANアダプタと無線LANアダプタを本体に接続する。__ 219 | 220 | これより前に繋いでいると、Raspberry Pi OS 自体がそもそも起動しない事がある。 221 | 222 | 再起動後に 223 | 224 | ```bash 225 | $ ip addr 226 | ``` 227 | 228 | と打って、wlan0のインターフェースが現れていればOK。 229 | 230 | > Raspberry Pi OS と ドライバの問題で、起動直後にUSBデバイスの認識がされるまでにそれなりに時間がかかる事がある。 231 | > 232 | > 再起動直後に認識されない場合、数分待ってからあらためて確認することを奨励。 233 | 234 | ### Networkの設定 235 | 236 | 最新のRaspberry Pi OS では dhcpd, interface.d を使った設定からNetworkManagerを使った方式に変わっているので、従来とは大きく設定手順が異なる。 237 | 238 | またこれに合わせて、無線APを構築する方法もhostapdを使わないものに変わっているので要注意。 239 | 240 | #### 下準備 241 | 242 | ここまでの手順をこなしていれば問題ないと思いますが、 243 | 244 | ```bash 245 | $ ip addr 246 | ``` 247 | 248 | を実行して、eth0, eth1, eth2, wlan0 がそれぞれ認識されていることを確認しましょう。 249 | 250 | 出てこない場合、供給電力が足りていないか、接続を間違えているか、パーツが破損しています。 251 | 252 | #### connection 設定(有線) 253 | 254 | メトリクスを明示指定しないと、意味不明な優先順番になる可能性があるので、明示指定 255 | 256 | ```bash 257 | $ sudo nmcli connection modify "Wired connection 1" ipv4.route-metric 100 258 | $ sudo nmcli connection modify "Wired connection 2" ipv4.route-metric 200 259 | $ sudo nmcli connection modify "Wired connection 3" ipv4.route-metric 300 260 | $ sudo nmcli connection modify "Wired connection 1" connection.autoconnect yes 261 | $ sudo nmcli connection modify "Wired connection 2" connection.autoconnect yes 262 | $ sudo nmcli connection modify "Wired connection 3" connection.autoconnect yes 263 | ``` 264 | 265 | LAN側のポートの設定をする 266 | 267 | ```bash 268 | $ sudo nmcli connection modify "Wired connection 2" ipv4.addresses "192.168.20.1/24" 269 | $ sudo nmcli connection modify "Wired connection 2" ipv4.method manual 270 | $ sudo nmcli connection modify "Wired connection 2" ipv6.address fd00:c0a8:1401::1/64 271 | $ sudo nmcli connection modify "Wired connection 2" ipv6.method shared 272 | $ sudo nmcli connection up "Wired connection 2" 273 | ``` 274 | 275 | 管理ポートの設定をする 276 | 277 | ```bash 278 | $ sudo nmcli connection modify "Wired connection 3" ipv4.addresses "192.168.31.67/24" 279 | $ sudo nmcli connection modify "Wired connection 3" ipv4.method manual 280 | $ sudo nmcli connection up "Wired connection 3" 281 | ``` 282 | 283 | 最後に Netowork Manager を再起動 284 | 285 | ```bash 286 | $ sudo systemctl restart NetworkManager 287 | ``` 288 | 289 | #### connection設定(無線) 290 | 291 | まず、初期設定を行います。 292 | 293 | SSID・パスワード含む細かい設定は、EM-uNetPiのメインプロセス設定後、起動時に自動上書きされるので、今は気にしなくてよいです。 294 | 295 | ```bash 296 | $ sudo nmcli connection add type wifi ifname wlan0 con-name rpi_ap autoconnect yes ssid wanem-xxxxxx 802-11-wireless.mode ap 802-11-wireless.band a 802-11-wireless.channel 48 ipv4.method shared ipv4.address 192.168.21.1/24 ipv6.method shared ipv6.address fd00:c0a8:1501::1/64 wifi-sec.key-mgmt wpa-psk wifi-sec.pairwise ccmp wifi-sec.proto rsn wifi-sec.psk "wanem-xxxxxx" 297 | $ sudo nmcli connection up rpi_ap 298 | $ sudo nmcli connection modify rpi_ap autoconnect yes 299 | ``` 300 | 301 | 最後に Netowork Manager を再起動 302 | 303 | ```bash 304 | $ sudo systemctl restart NetworkManager 305 | ``` 306 | 307 | #### IPv6の切り替え(任意) 308 | 309 | IPv6を無効にしたい場合下記を実行し、再起動する。 310 | 311 | ```bash 312 | $ cd /home/pi/EM-uNetPi/scripts/php/ 313 | $ sudo php IPv6Switcher.php 1 314 | ``` 315 | 316 | この切り替えは、EM-uNetPi起動後にタッチパネルからの操作(Setting)からでも行うことが出来ます。 317 | 318 | ### NAT等の設定(IPv4) 319 | 320 | #### DHCPサーバの設定 321 | 322 | ``` 323 | sudo apt-get install isc-dhcp-server 324 | ``` 325 | 326 | インストール後に起動にこけるが、設定ファイルを適切に構成してないせいなので、無視して良い。 327 | 328 | /etc/dhcp/dhcpd.conf の末尾に追加 329 | 330 | ``` 331 | ping-check true; 332 | 333 | subnet 192.168.20.0 netmask 255.255.255.0 { 334 | authoritative; 335 | option routers 192.168.20.1; 336 | option broadcast-address 192.168.20.255; 337 | option subnet-mask 255.255.255.0; 338 | option domain-name "wanem-02"; 339 | option domain-name-servers 8.8.8.8,8.8.4.4; 340 | default-lease-time 600; 341 | max-lease-time 7200; 342 | range 192.168.20.101 192.168.20.254; 343 | } 344 | 345 | subnet 192.168.21.0 netmask 255.255.255.0 { 346 | authoritative; 347 | option routers 192.168.21.1; 348 | option broadcast-address 192.168.21.255; 349 | option subnet-mask 255.255.255.0; 350 | option domain-name "wanem-02"; 351 | option domain-name-servers 8.8.8.8,8.8.4.4; 352 | default-lease-time 600; 353 | max-lease-time 7200; 354 | range 192.168.21.101 192.168.21.254; 355 | } 356 | ``` 357 | 358 | /etc/default/isc-dhcp-server のインターフェース指定を下記のように修正 359 | 360 | ``` 361 | INTERFACESv4="wlan0 eth1" 362 | ``` 363 | 364 | この状態で起動して問題なければOK 365 | 366 | ``` 367 | $ sudo systemctl start isc-dhcp-server.service 368 | ``` 369 | 370 | #### forwardingの設定 371 | 372 | /etc/sysctl.conf の下記コメントアウトを外す 373 | 374 | ``` 375 | # net.ipv4.ip_forward=1 376 | # net.ipv6.conf.all.forwarding=1 377 | ``` 378 | 379 | ### NAT等の設定(IPv6)※ experimental 380 | 381 | NAT66の設定を行います。 382 | 383 | 必要な追加設定を行いますが、起動後に「Settings > IP/NAT」の IPv6 Mode を NAT66 にしない限り有効にはなりません。 384 | 385 | NAT66実装に関しては、こちらの [実装に至った経緯](NAT66Info.md) も併せて参照ください。 386 | 387 | #### アドレス設計について 388 | 389 | /64 環境での利用を想定しているため、ULAの fd00::/8 空間を使用します。 390 | 391 | 一部プラットフォーム/アプリケーションでは、ULAを用いたNAT66環境下で、IPv6通信がうまく行えない可能性があるので、ご留意ください。 392 | 393 | #### radvd の設定 394 | 395 | コンフィグファイルを /etc/radvd.conf として、下記の通り定義します。 396 | 397 | ``` 398 | interface eth1 { 399 | 400 | AdvSendAdvert on; 401 | MinRtrAdvInterval 3; 402 | MaxRtrAdvInterval 10; 403 | AdvDefaultPreference high; 404 | 405 | prefix fd00:c0a8:1401::/64 406 | { 407 | AdvOnLink on; 408 | AdvAutonomous on; 409 | AdvRouterAddr off; 410 | }; 411 | 412 | RDNSS 2001:4860:4860::8888 2001:4860:4860::8844 { 413 | AdvRDNSSLifetime 3600; 414 | }; 415 | }; 416 | 417 | interface wlan0 { 418 | 419 | AdvSendAdvert on; 420 | MinRtrAdvInterval 3; 421 | MaxRtrAdvInterval 10; 422 | AdvDefaultPreference high; 423 | 424 | prefix fd00:c0a8:1501::/64 425 | { 426 | AdvOnLink on; 427 | AdvAutonomous on; 428 | AdvRouterAddr off; 429 | }; 430 | 431 | RDNSS 2001:4860:4860::8888 2001:4860:4860::8844 { 432 | AdvRDNSSLifetime 3600; 433 | }; 434 | }; 435 | ``` 436 | 437 | ### その他の設定 438 | 439 | #### 起動画面設定 440 | 441 | スプラッシュスクリーンの設定で、 /etc/rc.local の exitの手前に追加 442 | 443 | ``` 444 | sudo fbi -d /dev/fb0 -T 1 -noverbose -a /home/pi/EM-uNetPi/misc/textures/Splash.jpg 445 | ``` 446 | 447 | 上の方の 448 | 449 | ``` 450 | _IP=$(hostname -I) || true 451 | if [ "$_IP" ]; then 452 | printf "My IP address is %s\n" "$_IP" 453 | fi 454 | ``` 455 | 456 | はコメントアウト 457 | 458 | #### 画面出力抑制(任意) 459 | 460 | タッチパネル側の描画に出てきてしまう余計な描画を抑制したい場合は /boot/firmware/cmdline.txt の rootwait の後に下記を追加。(末尾は ipv6.disable=1 or 0 のままにすること) 461 | 462 | ``` 463 | vt.global_cursor_default=0 quiet logo.nologo 464 | ``` 465 | 466 | ### 自動ログインユーザの起動時の処理を設定 467 | 468 | ~/.bash_profile を作成し、以下を記載 469 | 470 | ```bash 471 | $ sudo nmcli connection up "Wired connection 2" 472 | $ sudo nmcli connection up "Wired connection 3" 473 | $ sudo route del -net default gw 192.168.31.1 eth2 474 | $ sudo iw wlan0 set power_save off 475 | $ sudo systemctl stop isc-dhcp-server.service 476 | $ sudo systemctl start isc-dhcp-server.service 477 | $ sudo iptables-restore < /etc/iptables.ipv4.nat 478 | $ sudo python EM-uNetPi/Wanem.py 1>/dev/null 2>/dev/null 479 | ``` 480 | 481 | 最後にリブートをして、タッチパネルに操作コンソールが表示されれば構築完了。 482 | 483 | > キーボード等を接続している場合、リブート前に抜いてください。 484 | -------------------------------------------------------------------------------- /docs/NAT66Info.md: -------------------------------------------------------------------------------- 1 | NAT66機能について 2 | ================================================================================================== 3 | 4 | 実装の経緯 5 | -------------------------------------------------------------------------------------------------- 6 | 7 | __まず最初に、この機能はNAT66を推進するものではありません。__ NAT66が顕在化してきた環境に対して必要になったため、実装した機能になります。 8 | 9 | というのも、IPv6におけるNATは存在するべきではないと長らくIETFで議論されてきてましたが、実際のゲームを遊ぶユーザの環境として一定数検知され、それが増加傾向にあると、近年の弊社のオンラインゲームタイトルのログ調査から判明しています。 10 | 11 | 既存の実装や今後のネットワーク実装における、NAT66環境下における動作検証の準備が求められ、この機能は実装されました。 12 | 13 | NAT66に関する詳細は、CEDEC2024で行われた下記セッションにて解説していますので、そちらも併せて参照ください。 14 | 15 | ##### 参考講演 16 | 17 | - [CEDEC2024 / IPv6向けNATの台頭と新たなNAT挙動を理解・対応実装を学び、変化するIPv6環境に備えよう!](https://cedil.cesa.or.jp/cedil_sessions/view/2928) 18 | 19 | ## NAT66を有効にする手順 20 | 21 | 配布イメージではデフォルトで無効になっています。 22 | 23 | IPv6が利用可能な環境(適切にRAが降ってくる環境)に接続してIPv4 only モードで起動し、「Setting > IP/NAT > IPv6 Mode Setting」から 「Disable => NAT」に変更し、本体を再起動します。これで有効になります。 24 | 25 | なお一度有効にしても、IPv6が無効な環境で起動すると強制的にIPv4 only モードにフォールバックするため、ご注意ください。 26 | 27 | 現在IPv6モードかどうかは「Setting > SYSTEM」に表示されるIP情報から確認可能です。IPv6 有効時には各種IP情報が下図のようにIPv4/IPv6で併記されます。(起動時の初期化画面で、IPv6 ENV CHECK の項目がOKになるかどうかでも判定できます。) 28 | 29 | SampleIPv6Setting 30 | 31 | > NAT、NAT/Symmetric の 2モードが存在しますが、いづれもNAT66モードになります。後者はNAPTのMapping挙動がいわゆるシンメトリック挙動になるという違いあります。 32 | 33 | 今後のIPv6まわりの機能改修について 34 | -------------------------------------------------------------------------------------------------- 35 | 36 | - 各種IPv6モード 37 | 38 | - NPTv6 に関しては、今後の市場における動向を見た上で必要があると判断した場合、実装を検討する予定です。 39 | 40 | - Bridge / ND-Proxy に関しては、今後実装予定です。(時期未定) 41 | 42 | - UPnP機能 43 | - 国内でIPv6向けのUPnPを検証する環境が構築しにくい問題を解決するため、IPv6向けUPnP機能を実装予定です。(時期未定) 44 | 45 | -------------------------------------------------------------------------------- /docs/PartsList.md: -------------------------------------------------------------------------------- 1 | EM-uNetPi for Raspberry Pi 5 構成パーツ 2 | ================================================================================================== 3 | 4 | EM-uNetPiのハードウェアは下記のパーツを組み立てることで完成します。 5 | 6 | 7 | 8 | コアパーツ 9 | -------------------------------------------------------------------------------------------------- 10 | 11 | > 型番違いや、チップが変わった場合、動作しない可能性が高いため、確実に下記と一致するものを使用すること。 12 | 13 | #### RaspberryPi 本体 14 | 15 | 16 | 17 | - メーカー:Raspberry Pi 18 | - 型番:Raspberry Pi 5 19 | - 数量:1 20 | - 備考:メモリ容量は2GB/4GB/8GB どのモデルでも問わない。 21 | 22 | > 最近のロットだと、下図の様に基盤の淵が微妙に膨らんでいることがある。 23 | > 24 | > これだと、ケースによってはそこがつっかえてうまく入らないことがある。そのため、そういう基盤を引いてしまった場合は膨らんでいる部分をヤスリなどで削ってください。 25 | 26 | RpiBari2 27 | 28 | #### タッチパネル 29 | 30 | ![](img/Parts02.png) 31 | 32 | - メーカー:Waveshare 33 | - 型番:3.5inch RPi LCD (A), 480x320 34 | - 数量:1 35 | 36 | #### 有線LANアダプタ 37 | 38 | - メーカー:PLANEX 39 | 40 | - 型番:USB-LAN2500R2 41 | 42 | - 数量:2 43 | 44 | > LAN側インターフェース用と管理ポート用で2つ必要 45 | 46 | #### 無線LANアダプタ 47 | 48 | - メーカー:TP-Link 49 | - 型番:Archer TX20U Nano 50 | - 数量:1 51 | 52 | > チップが RTL8852bu 系のものなら、他のものでも代用可能。 53 | 54 | アクセサリ 55 | -------------------------------------------------------------------------------------------------- 56 | 57 | #### 5V5A対応 電源アダプタ 58 | 59 | - メーカー:スイッチサイエンス 60 | 61 | - 型番:ラズパイ5に最適なACアダプター 5.1V/5.0A USB-PD Type-Cコネクタ出力 / SSCI-093453 62 | - 数量:1 63 | 64 | > 5V5Aで適切に出力可能であれば、上記以外でも可。カタログスペックだけだと、実測値で足りてないものもあるため、信頼できるブランドの製品を奨励 65 | 66 | #### MicroSDカード 67 | 68 | - Class10以上、MLC採用製品奨励 69 | - 最低16GBでも大丈夫だが、ReplayMode用のデータ同期やパケットキャプチャを行う場合にディスク容量が必要となるため、大きめの容量のものを使用することを奨励 70 | 71 | > あまり品質のよくないSDカードを使用した場合、動作が不安定になったり、突然再起動が発生したりするため、メジャーブランド品を奨励 72 | 73 | #### 本体ケース 74 | 75 | CaseImage 76 | 77 | - ファン付きで、GPIOにアクセスでき、タッチパネルを取り付けられるような形状のものであれば任意のもので可 78 | - Raspberry Pi 5 の発熱量の都合上、ファンなしでの運用は非奨励 79 | 80 | #### GPIO エクステンダー:連結ピンソケット 2×20(40P) ラズパイ用スタッキングコネクタ 81 | 82 | Parts03 83 | 84 | - ファン付きケースを用いる場合、高さの問題でタッチパネルがそのままでは刺さらないことが多い。そのため、スタッキングコネクタ等をつかって持ち上げてあげる必要がある。一般的な Raspiberry Pi 用のパーツなので、任意で探してください。 85 | 86 | #### タッチパネル用スペーサー 87 | 88 | - メーカー:3M 89 | 90 | - 型番:しっかりつくクッションゴム(CS-05) 91 | - 数量:1 92 | 93 | > ケースから浮いたタッチパネルの四隅を安定させられるものであれば、なんでも代用可能 94 | 95 | #### ヒートシンク 96 | 97 | - 連続稼働時に熱をもつため、RaspberryPi本体に適合する任意のものを購入し、使用することを奨励 98 | 99 | > ケースに付属することもあるので、それを使っても可 100 | 101 | #### 感圧式対応 タッチペン(任意) 102 | 103 | - タッチパネル操作が細かいため、あった方がよい。 104 | 105 | > 最近のスマートフォン向けの静電容量式用のものではなく、感圧式向けのものを使用すること 106 | > 107 | > タッチパネルに付属することもあるので、それを使っても可 108 | 109 | #### キャリングケース(任意) 110 | 111 | CarryImage 112 | 113 | - メーカー:SANWA SUPPLY 114 | 115 | - 型番:IN-HDAD4BK 116 | - 数量:1 117 | 118 | > 持ち運びや収納時にあると便利 119 | -------------------------------------------------------------------------------- /docs/img/CarryImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/CarryImage.jpg -------------------------------------------------------------------------------- /docs/img/CaseImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/CaseImage.png -------------------------------------------------------------------------------- /docs/img/HwImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/HwImage.jpg -------------------------------------------------------------------------------- /docs/img/Parts01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/Parts01.png -------------------------------------------------------------------------------- /docs/img/Parts02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/Parts02.png -------------------------------------------------------------------------------- /docs/img/Parts03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/Parts03.png -------------------------------------------------------------------------------- /docs/img/PortMap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/PortMap.jpg -------------------------------------------------------------------------------- /docs/img/RpiBari1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/RpiBari1.jpg -------------------------------------------------------------------------------- /docs/img/RpiBari2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/RpiBari2.jpg -------------------------------------------------------------------------------- /docs/img/SampleIPv6Setting.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/SampleIPv6Setting.jpg -------------------------------------------------------------------------------- /docs/img/ScreenShotDirectMode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/ScreenShotDirectMode.png -------------------------------------------------------------------------------- /docs/img/Setup01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/Setup01.jpg -------------------------------------------------------------------------------- /docs/img/Setup02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/docs/img/Setup02.jpg -------------------------------------------------------------------------------- /misc/api/ApiInfo.json: -------------------------------------------------------------------------------- 1 | {"lastupdate":1531976305,"status":{"maintStatus":1,"maintMessage":"Some services are down."},"list":[],"key":""} 2 | -------------------------------------------------------------------------------- /misc/dstat/dstat_cpu_temp.py: -------------------------------------------------------------------------------- 1 | class dstat_plugin(dstat): 2 | 3 | def __init__(self): 4 | self.name = 'temp' 5 | self.nick = ('cpu',) 6 | self.vars = ('cpuTempValue',) 7 | self.type = 's' 8 | self.width = 8 9 | self.scale = 0 10 | 11 | def Update(self): 12 | import commands 13 | import re 14 | 15 | current = commands.getoutput("vcgencmd measure_temp") 16 | 17 | pattern = re.compile(r'temp=.*') 18 | matchObj = pattern.search(current) 19 | if matchObj: 20 | param = matchObj.group().split("=")[1].split("'") 21 | self.val['cpuTempValue'] = param[0] 22 | else: 23 | self.val['cpuTempValue'] = '0.0' 24 | 25 | def extract(self): 26 | self.Update() 27 | 28 | -------------------------------------------------------------------------------- /misc/dstat/dstat_nat_session.py: -------------------------------------------------------------------------------- 1 | class dstat_plugin(dstat): 2 | def __init__(self): 3 | self.name = 'NAT Session' 4 | self.nick = ('tcp','udp') 5 | self.vars = ('tcpNr', 'udpNr') 6 | self.type = 's' 7 | self.width = 8 8 | self.scale = 0 9 | 10 | def Update(self): 11 | import commands 12 | self.val['tcpNr'] = commands.getoutput("cat /proc/net/nf_conntrack | grep tcp | wc -l ") 13 | self.val['udpNr'] = commands.getoutput("cat /proc/net/nf_conntrack | grep udp | wc -l ") 14 | 15 | def extract(self): 16 | self.Update() 17 | -------------------------------------------------------------------------------- /misc/dstat/dstat_tc_param.py: -------------------------------------------------------------------------------- 1 | class dstat_plugin(dstat): 2 | """ 3 | Example "Hello world!" output plugin for aspiring Dstat developers. 4 | """ 5 | 6 | def __init__(self): 7 | self.name = 'tc param' 8 | self.nick = ('delayUP','lossUP','delayDW','lossDW') 9 | self.vars = ('delayUPValue','lossUPValue','delayDWValue','lossDWValue') 10 | self.type = 's' 11 | self.width = 8 12 | self.scale = 0 13 | 14 | def Update(self): 15 | import commands 16 | import re 17 | 18 | current = commands.getoutput("tc qdisc show dev eth0") 19 | 20 | pattern = re.compile(r'delay.*?ms') 21 | matchObj = pattern.search(current) 22 | if matchObj: 23 | param = matchObj.group().split() 24 | self.val['delayUPValue'] = param[1] 25 | else: 26 | self.val['delayUPValue'] = '0.0ms' 27 | pattern = re.compile(r'loss.*?\%') 28 | matchObj = pattern.search(current) 29 | if matchObj: 30 | param = matchObj.group().split() 31 | self.val['lossUPValue'] = param[1] 32 | else: 33 | self.val['lossUPValue'] = '0%' 34 | 35 | current = commands.getoutput("tc qdisc show dev wlan0") 36 | 37 | pattern = re.compile(r'delay.*?ms') 38 | matchObj = pattern.search(current) 39 | if matchObj: 40 | param = matchObj.group().split() 41 | self.val['delayDWValue'] = param[1] 42 | else: 43 | self.val['delayDWValue'] = '0.0ms' 44 | pattern = re.compile(r'loss.*?\%') 45 | matchObj = pattern.search(current) 46 | if matchObj: 47 | param = matchObj.group().split() 48 | self.val['lossDWValue'] = param[1] 49 | else: 50 | self.val['lossDWValue'] = '0%' 51 | 52 | def extract(self): 53 | self.Update() 54 | 55 | -------------------------------------------------------------------------------- /misc/iptables/iptables.ipv4.nat.type2: -------------------------------------------------------------------------------- 1 | *filter 2 | :INPUT ACCEPT [50:2728] 3 | :FORWARD ACCEPT [0:0] 4 | :OUTPUT ACCEPT [48:4432] 5 | #-A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED,INVALID,NEW -j ACCEPT 6 | -A FORWARD -i eth0 -o wlan0 -j ACCEPT 7 | -A FORWARD -i wlan0 -o eth0 -j ACCEPT 8 | -A FORWARD -i eth0 -o eth1 -j ACCEPT 9 | -A FORWARD -i eth1 -o eth0 -j ACCEPT 10 | COMMIT 11 | *nat 12 | :PREROUTING ACCEPT [1:234] 13 | :INPUT ACCEPT [1:234] 14 | :OUTPUT ACCEPT [1:108] 15 | :POSTROUTING ACCEPT [0:0] 16 | -A POSTROUTING -o eth0 -j MASQUERADE 17 | COMMIT 18 | -------------------------------------------------------------------------------- /misc/iptables/iptables.ipv4.nat.type3: -------------------------------------------------------------------------------- 1 | *filter 2 | :INPUT ACCEPT [50:2728] 3 | :FORWARD ACCEPT [0:0] 4 | :OUTPUT ACCEPT [48:4432] 5 | -A FORWARD -i eth0 -o wlan0 -j ACCEPT 6 | -A FORWARD -i wlan0 -o eth0 -j ACCEPT 7 | -A FORWARD -i eth0 -o eth1 -j ACCEPT 8 | -A FORWARD -i eth1 -o eth0 -j ACCEPT 9 | COMMIT 10 | *nat 11 | :PREROUTING ACCEPT [1:234] 12 | :INPUT ACCEPT [1:234] 13 | :OUTPUT ACCEPT [1:108] 14 | :POSTROUTING ACCEPT [0:0] 15 | -A POSTROUTING -o eth0 -j MASQUERADE --random 16 | COMMIT 17 | -------------------------------------------------------------------------------- /misc/iptables/iptables.ipv6.nat.type0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/misc/iptables/iptables.ipv6.nat.type0 -------------------------------------------------------------------------------- /misc/iptables/iptables.ipv6.nat.type2: -------------------------------------------------------------------------------- 1 | *filter 2 | :INPUT ACCEPT [0:0] 3 | :FORWARD ACCEPT [0:0] 4 | :OUTPUT ACCEPT [0:0] 5 | -A FORWARD -i eth0 -o wlan0 -j ACCEPT 6 | -A FORWARD -i wlan0 -o eth0 -j ACCEPT 7 | -A FORWARD -i eth0 -o eth1 -j ACCEPT 8 | -A FORWARD -i eth1 -o eth0 -j ACCEPT 9 | COMMIT 10 | *nat 11 | :PREROUTING ACCEPT [0:0] 12 | :INPUT ACCEPT [0:0] 13 | :OUTPUT ACCEPT [0:0] 14 | :POSTROUTING ACCEPT [0:0] 15 | -A POSTROUTING -o eth0 -j MASQUERADE 16 | COMMIT 17 | -------------------------------------------------------------------------------- /misc/iptables/iptables.ipv6.nat.type3: -------------------------------------------------------------------------------- 1 | *filter 2 | :INPUT ACCEPT [0:0] 3 | :FORWARD ACCEPT [0:0] 4 | :OUTPUT ACCEPT [0:0] 5 | -A FORWARD -i eth0 -o wlan0 -j ACCEPT 6 | -A FORWARD -i wlan0 -o eth0 -j ACCEPT 7 | -A FORWARD -i eth0 -o eth1 -j ACCEPT 8 | -A FORWARD -i eth1 -o eth0 -j ACCEPT 9 | COMMIT 10 | *nat 11 | :PREROUTING ACCEPT [0:0] 12 | :INPUT ACCEPT [0:0] 13 | :OUTPUT ACCEPT [0:0] 14 | :POSTROUTING ACCEPT [0:0] 15 | -A POSTROUTING -o eth0 -j MASQUERADE --random 16 | COMMIT 17 | -------------------------------------------------------------------------------- /misc/patch/fbtft_python3.patch: -------------------------------------------------------------------------------- 1 | diff --git a/asn_test.py b/asn_test.py 2 | index 6db5fff..36995d5 100644 3 | --- a/asn_test.py 4 | +++ b/asn_test.py 5 | @@ -70,7 +70,7 @@ for rotate in [0]: 6 | mplayer_test(160, 128) 7 | 8 | 9 | -raw_input("Nokia 3310, move chip select :") 10 | +input("Nokia 3310, move chip select :") 11 | 12 | if get_board_revision() == 1: 13 | P1_13 = 21 14 | diff --git a/fb.py b/fb.py 15 | index 1fa2008..baa456c 100644 16 | --- a/fb.py 17 | +++ b/fb.py 18 | @@ -36,12 +36,12 @@ class Framebuffer(gfx.BaseGFX): 19 | self.dev = dev 20 | self.fbfd = os.open(dev, os.O_RDWR) 21 | vinfo = struct.unpack("8I12I16I4I", fcntl.ioctl(self.fbfd, FBIOGET_VSCREENINFO, " "*((8+12+16+4)*4))) 22 | - finfo = struct.unpack("16cL4I3HI", fcntl.ioctl(self.fbfd, FBIOGET_FSCREENINFO, " "*48)) 23 | + finfo = struct.unpack("16cL4I3HI", fcntl.ioctl(self.fbfd, FBIOGET_FSCREENINFO, " "*52)) 24 | 25 | - bytes_per_pixel = (vinfo[6] + 7) / 8 26 | + bytes_per_pixel = (vinfo[6] + 7) // 8 27 | screensize = vinfo[0] * vinfo[1] * bytes_per_pixel 28 | 29 | - fbp = mmap.mmap(self.fbfd, screensize, flags=mmap.MAP_SHARED, prot=mmap.PROT_READ|mmap.PROT_WRITE) 30 | + fbp = mmap.mmap(self.fbfd, int(screensize), flags=mmap.MAP_SHARED, prot=mmap.PROT_READ|mmap.PROT_WRITE) 31 | 32 | self.fbp = fbp 33 | self.xres = vinfo[0] 34 | @@ -56,7 +56,7 @@ class Framebuffer(gfx.BaseGFX): 35 | self.blue = gfx.Bitfield(vinfo[14], vinfo[15], vinfo[16]) 36 | self.transp = gfx.Bitfield(vinfo[17], vinfo[18], vinfo[19]) 37 | self.nonstd = vinfo[20] 38 | - self.name = ''.join([x for x in finfo[0:15] if x != '\x00']) 39 | + self.name = b''.join([x for x in finfo[0:15] if x != '\x00']) 40 | self.type = finfo[18] 41 | self.visual = finfo[20] 42 | self.line_length = finfo[24] 43 | @@ -98,7 +98,7 @@ class Framebuffer(gfx.BaseGFX): 44 | "\n" + \ 45 | "Frame buffer device information:\n" + \ 46 | " Device : %s\n" % self.dev + \ 47 | - " Name : %s\n" % self.name + \ 48 | + " Name : %s\n" % self.name.decode(encoding='utf-8') + \ 49 | " Size : %s\n" % self.screensize + \ 50 | " Type : %s\n" % type_name + \ 51 | " Visual : %s\n" % visual_name + \ 52 | diff --git a/fbtft.py b/fbtft.py 53 | index e99fb53..04f306e 100644 54 | --- a/fbtft.py 55 | +++ b/fbtft.py 56 | @@ -66,13 +66,13 @@ class FBTFTdevice: 57 | self.autoload = autoload 58 | if not devname: devname = name 59 | self.devname = devname 60 | - cmd = ["modprobe", "--first-time", "fbtft_device", "name=%s" % devname] + ["%s=%s" %(k,v) for k,v in dev.iteritems()] 61 | + cmd = ["modprobe", "--first-time", "fbtft_device", "name=%s" % devname] + ["%s=%s" %(k,v) for k,v in dev.items()] 62 | print("\n") 63 | - print " ".join(cmd) 64 | + print(" ".join(cmd)) 65 | sudocall(cmd) 66 | if not self.autoload: 67 | - cmd = ["modprobe", self.name] + ["%s=%s" %(k,v) for k,v in drv.iteritems()] 68 | - print " ".join(cmd) 69 | + cmd = ["modprobe", self.name] + ["%s=%s" %(k,v) for k,v in drv.items()] 70 | + print(" ".join(cmd)) 71 | sudocall(cmd) 72 | time.sleep(wait) 73 | self.fbdev = Framebuffer("/dev/fb1") 74 | @@ -100,13 +100,13 @@ class FBTFTdevice: 75 | 76 | class ADS7846device: 77 | def __init__(self, dev={}, drv={}): 78 | - cmd = ["modprobe", "--first-time", "ads7846_device"] + ["%s=%s" %(k,v) for k,v in dev.iteritems()] 79 | + cmd = ["modprobe", "--first-time", "ads7846_device"] + ["%s=%s" %(k,v) for k,v in dev.items()] 80 | print("") 81 | - print " ".join(cmd) 82 | + print(" ".join(cmd)) 83 | sudocall(cmd) 84 | - cmd = ["modprobe", "ads7846"] + ["%s=%s" %(k,v) for k,v in drv.iteritems()] 85 | + cmd = ["modprobe", "ads7846"] + ["%s=%s" %(k,v) for k,v in drv.items()] 86 | print("") 87 | - print " ".join(cmd) 88 | + print(" ".join(cmd)) 89 | sudocall(cmd) 90 | 91 | def __enter__(self): 92 | @@ -126,13 +126,13 @@ class ADS7846device: 93 | 94 | class GPIO_MOUSEdevice: 95 | def __init__(self, dev={}, drv={}): 96 | - cmd = ["modprobe", "--first-time", "gpio_mouse_device"] + ["%s=%s" %(k,v) for k,v in dev.iteritems()] 97 | + cmd = ["modprobe", "--first-time", "gpio_mouse_device"] + ["%s=%s" %(k,v) for k,v in dev.items()] 98 | print("") 99 | - print " ".join(cmd) 100 | + print(" ".join(cmd)) 101 | sudocall(cmd) 102 | - cmd = ["modprobe", "gpio_mouse"] + ["%s=%s" %(k,v) for k,v in drv.iteritems()] 103 | + cmd = ["modprobe", "gpio_mouse"] + ["%s=%s" %(k,v) for k,v in drv.items()] 104 | print("") 105 | - print " ".join(cmd) 106 | + print(" ".join(cmd)) 107 | sudocall(cmd) 108 | 109 | def __enter__(self): 110 | @@ -152,7 +152,7 @@ class GPIO_MOUSEdevice: 111 | 112 | def lsmod(): 113 | # if not "fbtft" in subprocess.check_output("lsmod"): 114 | - print subprocess.check_output("lsmod") 115 | + print(subprocess.check_output("lsmod")) 116 | 117 | # by BlackJack 118 | def get_revision(): 119 | @@ -184,7 +184,7 @@ def mplayer_test(x, y, playlength=6): 120 | def startx_test(wait=True): 121 | os.environ['FRAMEBUFFER'] = "/dev/fb1" 122 | print("\nX test") 123 | - print " To end the test, click Off button in lower right corner and press Alt-l (lowercase L) to logout (if screen is too small)" 124 | + print(" To end the test, click Off button in lower right corner and press Alt-l (lowercase L) to logout (if screen is too small)") 125 | if wait: 126 | call(["startx"]) 127 | return 128 | @@ -230,7 +230,7 @@ def bl_pwm_test(dev): 129 | dev.fbdev.fill(0) 130 | c = dev.fbdev.rgb(255,0,0) 131 | msg(dev.fbdev, "Brightness ", c, 2) 132 | - for i in range(0, max_brightness, 10) + [actual_brightness]: 133 | + for i in list(range(0, max_brightness, 10)) + [actual_brightness]: 134 | msg(dev.fbdev, " %s" % (3*chr(255)), 0, 2) 135 | msg(dev.fbdev, " %3d" % i, c, 2) 136 | sudoecho(file, "%d" % i) 137 | diff --git a/gfx.py b/gfx.py 138 | index 53f70ac..c920bd2 100644 139 | --- a/gfx.py 140 | +++ b/gfx.py 141 | @@ -26,7 +26,7 @@ class Draw: 142 | 143 | def rect(self, color, rect, width=0): 144 | if (width==0): 145 | - for y in range(rect.top, rect.top + rect.height): 146 | + for y in range(int(rect.top), int(rect.top + rect.height)): 147 | self.fb.hline(rect.left, y, rect.width, color) 148 | else: 149 | self.line(color, (rect.left, rect.top), (rect.left + rect.width, rect.top)) 150 | @@ -67,7 +67,7 @@ class Draw: 151 | # print "%sx + %s = y" % (m,b) 152 | 153 | for i in range(start_pos[0], end_pos[0]+1): 154 | - print "%s,%s" % (i, int(round(m*i+b))) 155 | + print("%s,%s" % (i, int(round(m*i+b)))) 156 | self.fb.putpixel(i, \ 157 | int(round(m*i+b)), \ 158 | color) 159 | @@ -124,8 +124,8 @@ class BaseGFX: 160 | colstr = struct.pack("H", color) 161 | offset = ((x + self.xoffset) * self.bytes_per_pixel 162 | + (y + self.yoffset) * self.line_length) 163 | - self.fbp.seek(offset) 164 | - for i in range(0, length): 165 | + self.fbp.seek(int(offset)) 166 | + for i in range(0, int(length)): 167 | self.fbp.write(colstr) 168 | else: 169 | for i in range(x, x+length): 170 | @@ -141,9 +141,9 @@ class BaseGFX: 171 | self.fbp.write(buf) 172 | elif (self.bits_per_pixel == 16): 173 | colstr = struct.pack("H", color) 174 | - buf = '' 175 | + buf = b'' 176 | self.fbp.seek(0) 177 | - for i in range(0, self.screensize/2): 178 | + for i in range(0, int(self.screensize/2)): 179 | buf += colstr 180 | self.fbp.write(buf) 181 | else: 182 | diff --git a/test_fb.py b/test_fb.py 183 | index 41b3168..eaa2b5d 100644 184 | --- a/test_fb.py 185 | +++ b/test_fb.py 186 | @@ -72,7 +72,7 @@ def msg(fb, s, c, max_size): 187 | 188 | def show_name(fb, c): 189 | fb.fill(0) 190 | - if not msg(fb, fb.name, c, 3): 191 | + if not msg(fb, fb.name.decode(encoding='utf-8'), c, 3): 192 | msg(fb, 'Test', c, 3) 193 | pause(2) 194 | 195 | @@ -84,7 +84,7 @@ def show_done(fb, c): 196 | 197 | 198 | def test_blank(fb, c): 199 | - print " Blanking" 200 | + print(" Blanking") 201 | fb.fill(0) 202 | msg(fb, 'Blank ', c, 2) 203 | pause(1) 204 | @@ -98,7 +98,7 @@ def test_blank(fb, c): 205 | 206 | 207 | def test_border(fb, c): 208 | - print " Border" 209 | + print(" Border") 210 | fb.fill(0) 211 | fb.draw.rect(c, Rect(0, 0, fb.xres-1, fb.yres-1), 1) 212 | 213 | @@ -111,7 +111,7 @@ def test_border(fb, c): 214 | 215 | 216 | def test_raster(fb, c): 217 | - print " Raster" 218 | + print(" Raster") 219 | fb.fill(0) 220 | for y in range(0, fb.yres, 2): 221 | for x in range(0, fb.xres, 2): 222 | @@ -123,24 +123,24 @@ def test_raster(fb, c): 223 | def test_rgb(fb): 224 | if (fb.bits_per_pixel == 1): 225 | return 226 | - print " RGB" 227 | + print(" RGB") 228 | fb.fill(0) 229 | - width = (fb.xres-1)/3 230 | + width = (fb.xres-1)//3 231 | fb.draw.rect(fb.rgb(255,0,0), Rect(0, 0, width, fb.yres), 0) 232 | - fb.putstr(5, fb.yres/2, 'RED', 0, 1) 233 | + fb.putstr(5, fb.yres//2, 'RED', 0, 1) 234 | 235 | fb.draw.rect(fb.rgb(0,255,0), Rect(width, 0, width, fb.yres), 0) 236 | - fb.putstr(5+width, fb.yres/2, 'GREEN', 0, 1) 237 | + fb.putstr(5+width, fb.yres//2, 'GREEN', 0, 1) 238 | 239 | fb.draw.rect(fb.rgb(0,0,255), Rect(2*width, 0, width, fb.yres), 0) 240 | - fb.putstr(5+2*width, fb.yres/2, 'BLUE', 0, 1) 241 | + fb.putstr(5+2*width, fb.yres//2, 'BLUE', 0, 1) 242 | pause(2) 243 | 244 | 245 | def test_colors(fb): 246 | if (fb.bits_per_pixel != 16): 247 | return 248 | - print " Colors" 249 | + print(" Colors") 250 | 251 | fb.fill(0) 252 | fb.fbp.seek(0) 253 | @@ -157,7 +157,7 @@ def test_colors(fb): 254 | 255 | 256 | def usage(): 257 | - print __doc__ 258 | + print(__doc__) 259 | 260 | def main(argv): 261 | device = '/dev/fb0' 262 | @@ -175,16 +175,14 @@ def main(argv): 263 | device = arg 264 | 265 | fb = Framebuffer(device) 266 | - print fb 267 | - 268 | + print(fb) 269 | + 270 | red = fb.rgb(255,0,0) 271 | yellow = fb.rgb(255,255,0) 272 | green = fb.rgb(0,255,0) 273 | 274 | show_name(fb, red) 275 | 276 | - print "Tests:" 277 | - 278 | test_border(fb, yellow) 279 | 280 | test_rgb(fb) 281 | -------------------------------------------------------------------------------- /misc/textures/Splash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KONAMI/EM-uNetPi/c9c75a20a427c34867f6feb996a7f4fba10378f0/misc/textures/Splash.jpg -------------------------------------------------------------------------------- /scripts/php/IPv6Switcher.php: -------------------------------------------------------------------------------- 1 | 55 | -------------------------------------------------------------------------------- /scripts/php/SyncDat.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/php/UpdateHostapdConf.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/php/UpdateNetworkManagerConf.php: -------------------------------------------------------------------------------- 1 | 109 | -------------------------------------------------------------------------------- /tools/WanemCtl.jenkinsfile: -------------------------------------------------------------------------------- 1 | /*========================================================================================== 2 | * 3 | * JenkinsのPipelineでテストを実行するときに、回線エミュレータを制御する際のJenkinsfileサンプル 4 | * 5 | * - WanemCtl.php は実行できるように配置/設定しておく。 6 | * - 必要なパラメータはPipeline定義の際に渡せるようにしておく 7 | * 8 | * ==========================================================================================*/ 9 | 10 | clientLabelA = "master" 11 | 12 | /*==========================================================================================*/ 13 | 14 | echo "EM-uNetPiのパラメータ設定" 15 | 16 | node(clientLabelA){ 17 | timestamps { 18 | stage('SetupEM-uNetPi@' + clientLabelA){ 19 | deleteDir() 20 | sh "php WanemCtl.php " + SetMode + " " + WanemCtlPoint + " " + bandUp + " " + bandDw + " " + delayUp + " " + delayDw + " " + lossUp + " " + lossDw + " 0 0 > Label.txt" 21 | sh "mkdir SetupInfo" 22 | sh "mv *.txt SetupInfo" 23 | stash name: "SetupInfo" 24 | 25 | // 設定内容は、ビルドの情報をセットする際に出力するとよい。 26 | // unstash "SetupInfo" 27 | // sh 'cat SetupInfo/Label.txt' 28 | // currentBuild.description = readFile 'SetupInfo/Label.txt' 29 | } 30 | } 31 | } 32 | 33 | /*==========================================================================================*/ 34 | -------------------------------------------------------------------------------- /tools/WanemCtl.php: -------------------------------------------------------------------------------- 1 | 4) ? (int)$argv[4] : 0; 18 | $delayDw = ($argc > 5) ? (int)$argv[5] : 0; 19 | $lossUp = ($argc > 6) ? (int)$argv[6] : 0; 20 | $lossDw = ($argc > 7) ? (int)$argv[7] : 0; 21 | $disconnUp = ($argc > 8) ? (int)$argv[8] : 0; 22 | $disconnDw = ($argc > 9) ? (int)$argv[9] : 0; 23 | 24 | $endPointPort = 10393; 25 | 26 | $req = array( 27 | "bandUp" => $bandUp, 28 | "bandDw" => $bandDw, 29 | "delayUp" => $delayUp, 30 | "delayDw" => $delayDw, 31 | "lossUp" => $lossUp, 32 | "lossDw" => $lossDw, 33 | "disconnUp" => $disconnUp, 34 | "disconnDw" => $disconnDw, 35 | ); 36 | 37 | $pkt = json_encode($req); 38 | $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); 39 | $len = strlen($pkt); 40 | 41 | socket_sendto($sock, $pkt, $len, 0, $endPointIp, $endPointPort); 42 | socket_close($sock); 43 | 44 | echo "band : Up " . $bandUp . "kbps / Dw " . $bandDw . "kbps, " 45 | ."delay : Up " . $delayUp . "msec / Dw " . $delayDw . "msec, " 46 | ."loss : Up " . $lossUp . "% / Dw " . $lossDw . "%"; 47 | --------------------------------------------------------------------------------