├── .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 | 
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 |
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 | 
27 |
28 | #### タッチパネル
29 |
30 | 
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 |
76 |
77 | - ファン付きで、GPIOにアクセスでき、タッチパネルを取り付けられるような形状のものであれば任意のもので可
78 | - Raspberry Pi 5 の発熱量の都合上、ファンなしでの運用は非奨励
79 |
80 | #### GPIO エクステンダー:連結ピンソケット 2×20(40P) ラズパイ用スタッキングコネクタ
81 |
82 |
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 |
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 |
--------------------------------------------------------------------------------