16 Commits

Author SHA1 Message Date
lai8928 2ab6d04834 update README.md 2023-03-29 17:04:10 +08:00
lai8928 ba91dbdf65 update README.md 2023-03-29 16:32:12 +08:00
lai8928 ab74bafde1 Update README.md 2023-03-29 03:55:31 +00:00
lai8928 709d647e94 Update README.md 2023-03-29 03:28:08 +00:00
lai8928 b55016ee07 add README.md description about command line 2023-03-29 11:08:25 +08:00
lai8928 107c85253a Update README.md 2023-03-28 03:51:46 +00:00
lai8928 3030eaba40 Update README.md 2023-03-28 03:51:18 +00:00
lai8928 f8929fede9 Upload New File 2023-03-28 03:50:24 +00:00
lai8928 5d4da12740 add wait time. 2023-03-28 11:36:39 +08:00
lai8928 8dadb65432 add idle till EDC stop 2023-03-27 18:23:02 +08:00
lai8928 aa45f11ed7 add chart & set chart parameter 2023-03-27 16:59:02 +08:00
lai8928 08b885cbd0 start by imput txt file. 2023-03-25 09:16:58 +08:00
roytingluo 37b718ef63 [update] Show error message. 2023-03-23 18:13:02 +08:00
lai8928 6baeb8c781 [update] Add command line file. 2023-03-23 18:07:49 +08:00
lai8928 f95f5653b4 add file 2023-03-23 17:28:43 +08:00
lai8928 b245e58df9 test 2023-03-23 17:17:48 +08:00
9 changed files with 367 additions and 1 deletions
+113
View File
@@ -0,0 +1,113 @@
# Web Automation
![image](https://gitlab.com/wisetop/frontend/web_automation/-/raw/main/demo.gif)
### 開發環境
* python 3.10.10
* selenium 4.8.2 (python 套件)
## 程式執行檔
### terminal_main
```
$ python terminal_main.py
```
1. 在終端機上執行 terminal_main.py
2. 輸入 START [Page_name] 進入網頁,'END' 離開網頁,指令反饋會即時顯示在終端機上
3. 過程中開啟的視窗可以繼續操作
4. 離開網頁後,輸入 'END_ALL' 結束程式
5. 程式結束後輸出 commend_line/commend_line.txt 紀錄成功執行的指令,可做為 txtfile_main.py 的執行腳本。(以下文為例)
```
START Devices
cleanConnect
scanConnect/EE:3A
END
START TaskContent
selectMode/Cycle/
setEDCParameter/start/-1/
setEDCParameter/stop/-0.5/
addChart/test
setChart/test/Time//EE:/I/0
modeSwitch/start/
IdleTillStop/1/EE
selectMode/Idle/
END
END_ALL
```
### txtfile_main
```
$ python terminal_main.py
$ python terminal_main.py > .\log\[logfile.txt] // 將輸出流程寫入指定 log 檔
```
1. 在終端機上執行 txtfile_main.py
2. 程式會自動執行上一次 terminal_main.py 輸出的腳本
---
## Devices
1. 載入 [url] / admin / devices
### cleanConnect()
```
cleanConnect
```
* 清除所有與 Controller 連線的 Elite
### scanConnect(set_ID)
```
scanConnect/[set_ID]
```
* 掃描並連線到 MAC 中包含 [set_ID] 字串的 Elite
## TaskContent
1. 載入 [url] / admin / task-content
2. 紀錄並輸出以下參數 (重新載入會重置參數)
* Device list: 列出已連線的 Elite 以及對照 MB 的代號
* Chart list: 列出已存在的圖表,並為其命名
(Elite 的預設圖表命名為 XX:XX_defult,其餘命名為chartX,名稱方便用作設定圖表參數時指定圖表)
### selectMode(mode_name, set_ID)
```
selectMode/[mode_name]/[set_ID]
```
1. 指定 MAC 包含 [set_ID] 的 Elite
2. 選擇包含 [mode_name] 的 Mode
* 如果有兩個 Elite/Mode 字串包含 [set_ID]/[mode_name],會跳出警告,並選擇第一個選項,允許空字串
### setEDCParameter(key_name, value, set_ID)
```
setEDCParmeter/[key_name]/[value]/[set_ID]
```
1. 指定 MAC 包含 [set_ID] 的 Elite
2. 參數名稱包含 [key_name] 的項目輸入 [value],或選擇字串包含 [value] 的選項
* 如果有兩個 Elite/參數名稱/選項名稱 字串包含 [set_ID]/[key_name]/[value],會跳出警告,並選擇第一個選項,允許空字串
### ModeSwitch(startOrStop, set_ID)
```
modeSwitch/['START'/'STOP']/[set_ID]
```
1. 指定 MAC 包含 [set_ID] 的 Elite
2. 依照 [startOrStop] 點擊開始或結束,若在 [set_ID] 輸入'ALL',則點擊 START ALL 或 STOP ALL
* 如果有兩個 Elite 字串包含 [set_ID],會跳出警告,並選擇第一個選項,允許空字串
### IdleTillStop(wait_sec, mac_ID)
```
IdleTillStop/[wait_sec]/[mac_ID]
```
1. 等待 [wait_sec] 秒,建議至少一秒
2. 指定 MAC 包含 [set_ID] 的 Elite
3. 暫停動作,直到指定 Elite 重新出現 START 按鍵
### addChart(set_chart_name)
```
addChart/[set_chart_name]
```
1. 新增一個圖表 (點擊 add chart),並命名為 [set_chart_name] (名稱方便設定圖表參數時指定圖表)
### setChart(set_chart_name, x_source, x_channel, y_source, y_channel, subplot)
```
setChart/[set_chart_name]/[x_source]/[x_channel]/[y_source]/[y_channel]/[subplot]
```
1. 以設定的圖表名稱 [set_chart_name] 指定圖表
2. 依序設定 X_source/X_channel/Y_source/Y_channel/subplot
1. 當 source 為 Time 時,忽略 channel
2. source 可填 Elite MAC ID,會自動轉換為 MB 代號
3. 回到顯示圖表狀態
* 所有選項如果有兩個字串包含設定值,會跳出警告,並選擇第一個選項
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

+4
View File
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
+171
View File
@@ -0,0 +1,171 @@
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.keys import Keys
import time
WAITING_TIME = 20
def startDevicesPage(chrome, url, page_select, file, row_list = [] ):
page_class = globals()[page_select]
use_txt = True if len(row_list)>0 else False
page = page_class(chrome, url)
text_row = input(" >>> ").strip() if use_txt==False else row_list.pop(0)
while text_row != 'END':
print(text_row)
text_row_split = text_row.split('/')
try:
func = getattr(page, text_row_split[0])
func() if len(text_row_split)<=1 else func(*text_row_split[1:])
file.write(" "+text_row+"\n")
except Exception as e:
print('*** ERROR:',e)
if len(row_list)<1 and use_txt:
print("*** WARNING: Commend line in txt didn't finish by 'END'.")
break
text_row = input(" >>> ").strip() if len(row_list)<1 else row_list.pop(0)
file.write(" END\n")
return page
# def startDevicesPageTxt(chrome, url, page_select, row_list, file):
# pass
class DevicesPage():
def __init__(self,chrome,url):
chrome.get(url + "#/admin/devices")
WebDriverWait(chrome, WAITING_TIME).until(EC.presence_of_element_located((By.CSS_SELECTOR,'h5.mt-0')))
WebDriverWait(chrome, WAITING_TIME).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'orbit')))
self._chrome = chrome
def cleanConnect(self):
while click_by_item_text(self._chrome, By.CLASS_NAME, 'va-button__content', 'DISCONNECT',error_mes=False):
click_by_item_text(self._chrome, By.CLASS_NAME, 'va-button__content','Confirm')
WebDriverWait(self._chrome, 10).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'orbit')))
def scanConnect(self, set_ID):
test_div = False
while True:
while test_div == False :
click_by_item_text(self._chrome, By.CLASS_NAME,'va-button__content','SCAN')
WebDriverWait(self._chrome, 10).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'orbit')))
test_div = select_div(self._chrome, 'div.va-item-label--caption', set_ID,3,error_mes=False)
click_by_item_text(test_div, By.CLASS_NAME,'va-button__content', 'CONNECT', key_like = False)
WebDriverWait(self._chrome, 10).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'orbit')))
if click_by_item_text(test_div, By.CLASS_NAME,'va-button__content', 'DISCONNECT',click = False):
break
class TaskContentPage():
def __init__(self, chrome, url):
chrome.get(url + "#/admin/task-content")
chrome.implicitly_wait(1)
WebDriverWait(chrome, WAITING_TIME).until(EC.presence_of_element_located((By.CSS_SELECTOR,'h5.mt-0')))
WebDriverWait(chrome, WAITING_TIME).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'orbit')))
self._chrome = chrome
mac_list =[ i.find_element(By.XPATH, './../..').text for i in chrome.find_elements(By.CSS_SELECTOR,'div.va-item-label--caption')]
self._mac_list = {i.split('\n')[1]:i.split('\n')[0][1] for i in mac_list}
chart_list = [i.find_element(By.XPATH, './../..').text.split('\n') for i in chrome.find_elements(By.CSS_SELECTOR,'h5.mt-0')[1:]]
self._chart_list = {i[0]: (i[1].split(" | ") if len(i)>1 else False) for i in chart_list}
# print(self._chart_list)
self._call_chart_list = {self._chart_list[i][1][-5:]+'_default' if self._chart_list[i] else i :i for i in self._chart_list}
print('Device list:', self._mac_list)
print('Chart list:', self._call_chart_list)
# print(self._mac_list)
# print([i.text for i in chrome.find_elements(By.CSS_SELECTOR, 'div.va-tree-category')])
def selectMode(self, mode_name, set_ID):
Devices_mac = select_div(self._chrome,'div.va-item-label--caption', set_ID, 6)
click_by_item_text(Devices_mac, By.CSS_SELECTOR,'label.va-select__label','WORKING MODE')
Drop_list = Devices_mac.find_element(By.CLASS_NAME,'va-dropdown__content')
click_by_item_text(Drop_list, By.CSS_SELECTOR,'span',mode_name)
def setEDCParameter(self, key_name, value, set_ID):
# print(test.text)
Devices_mac = select_div(self._chrome, 'div.va-item-label--caption', set_ID, 6)
mode_par_div = click_by_item_text(Devices_mac, By.CSS_SELECTOR, 'div.va-tree-category', key_name)
input_feild = click_by_item_text(mode_par_div, By.CLASS_NAME,'va-input__container__input','')
if input_feild:
input_feild.send_keys(Keys.CONTROL + "a")
input_feild.send_keys(Keys.DELETE)
input_feild.send_keys(value)
else:
button = click_by_item_text(mode_par_div, By.CSS_SELECTOR,'div.va-button__content__title',value)
# print(input_feild.get_attribute('value'))
click_by_item_text(Devices_mac, By.CSS_SELECTOR,'div.va-tree-category__header-label',key_name)
def modeSwitch(self, startOrStop, set_ID):
if set_ID == 'ALL':
click_by_item_text(self._chrome, By.CLASS_NAME, 'va-button__content__title', startOrStop.upper()+' ALL')
return True
Devices_mac = select_div(self._chrome,'div.va-item-label--caption', set_ID, 6)
if click_by_item_text(Devices_mac, By.CLASS_NAME, 'va-button__content__title', startOrStop.upper()) == False:
print('*** WARNING: Devices',set_ID,'already'+startOrStop.lower()+'.')
def IdleTillStop(self, wait_sec, mac_ID):
time.sleep(int(wait_sec))
Devices_mac = select_div(self._chrome, 'div.va-item-label--caption', mac_ID, 3)
WebDriverWait(Devices_mac,100).until(EC.text_to_be_present_in_element((By.CLASS_NAME, 'va-button__content__title'),'START'))
def addChart(self, set_chart_name):
click_by_item_text(self._chrome, By.CLASS_NAME, 'va-button__content__title', 'ADD CHART')
chart_list = self._chrome.find_elements(By.CSS_SELECTOR,'h5.mt-0')[-1].text
self._call_chart_list[set_chart_name] = chart_list
print('Chart list: ',self._call_chart_list)
def setChart(self, set_chart_name, x_source, x_channel, y_source, y_channel, subplot):
source_value = {'X': x_source,'Y': y_source}
channel_value = {'X': x_channel,'Y': y_channel}
chart_name = self._call_chart_list[[i for i in self._call_chart_list if set_chart_name in i][0]]
chart_card = click_by_item_text(self._chrome, By.CSS_SELECTOR, 'div.va-card', chart_name, click = False)
click_by_item_text(chart_card, By.CSS_SELECTOR, 'div.va-tab__content', 'SOURCE')
for i in ['X','Y']:
source_div = click_by_item_text(chart_card, By.CSS_SELECTOR, 'div.va-dropdown', i + ' SOURCE')
check_mac = check_complete(source_value[i], list(self._mac_list))
click_by_item_text(source_div, By.CSS_SELECTOR, 'li.va-select__option', list(self._mac_list.values())[check_mac] if check_mac!=-1 else source_value[i])
print(source_div.text.split('\n'))
if source_div.text.split('\n')[1].strip() not in 'Time':
channel_div = click_by_item_text(chart_card, By.CSS_SELECTOR, 'div.va-dropdown', i + ' CHANNEL')
click_by_item_text(channel_div, By.CSS_SELECTOR, 'li.va-select__option',channel_value[i] )
subplot_div = click_by_item_text(chart_card, By.CSS_SELECTOR, 'div.va-dropdown', 'SUBPLOT')
click_by_item_text(subplot_div, By.CSS_SELECTOR, 'li.va-select__option',subplot)
click_by_item_text(chart_card, By.CLASS_NAME, 'va-button__content__title','Add')
click_by_item_text(chart_card, By.CSS_SELECTOR, 'div.va-tab__content', 'CHART')
# print(source_div.text)
def click_by_item_text (chrome, item, item_name, text, click=True, key_like = True, error_mes = True):
button = chrome.find_elements(item,item_name)
button_list = [i.text for i in button]
button_search = [i for i in range(len(button_list)) if text == button_list[i]]
button_search = [i for i in range(len(button_list)) if text in button_list[i]] if (len(button_search) <1 and key_like) else button_search
if len(button_search) <1:
if error_mes:
print('*** ERROR: Found no button include keyword',text + '.')
return False
else:
if click:
button[button_search[0]].click()
if len(button_search)>1 and error_mes:
print('*** WARNING: Found more than one button include keyword',text + '.',[button_list[i] for i in button_search])
print('*** Clicked the first option.')
elif len(button_search)>1 and error_mes:
print('*** WARNING: Found more than one button include keyword.',[button_list[i] for i in button_search])
return button[button_search[0]]
def select_div(chrome,css_name, text, path_num, error_mes=False):
Elite_mac = click_by_item_text(chrome,By.CSS_SELECTOR, css_name, text, click=False, error_mes= error_mes)
if Elite_mac==False:
return False
Devices_mac = Elite_mac.find_element(By.XPATH, '.'+'/..'*path_num)
return Devices_mac
def check_complete(value, LIST, key_like = True):
return_list = [i for i in range(len(LIST)) if value == LIST[i]]
return_list = [i for i in range(len(LIST)) if value in LIST[i]] if (len(return_list) <1 and key_like) else return_list
if len(return_list)>1:
print('*** WARNING: Found more than one item include keyword',value+'.',[LIST[i] for i in return_list])
return return_list[0] if len(return_list)>0 else -1
+28
View File
@@ -0,0 +1,28 @@
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import selen_func, time, sys, inspect
set_ID = 'A4:DA:32:D4:EE:3A'
url = 'http://192.168.2.1/'
if __name__ == '__main__':
options = Options()
options.add_argument("--disable-notifications")
options.add_experimental_option('excludeSwitches', ['enable-logging'])
chrome = webdriver.Chrome('./chromedriver', chrome_options=options)
classes = [cls_name for cls_name, cls_obj in inspect.getmembers(sys.modules['selen_func']) if inspect.isclass(cls_obj) and cls_obj.__module__.find('selen_func')>=0]
print(classes)
page_select = input('>>> ').strip()
with open('commend_line/commend_line.txt','w')as f:
while page_select != 'END_ALL':
page_sel_split = page_select.split(' ')
class_index = selen_func.check_complete(page_sel_split[1],classes) if len(page_sel_split)>1 else -1
if page_sel_split[0] == 'START' and class_index != -1:
f.write('START '+classes[class_index]+'\n')
print('START',classes[class_index])
DevicesPage_Test = selen_func.startDevicesPage(chrome, url, classes[class_index] ,f)
else:
print("*** ERROR: Didn't find the corresponding page.")
page_select = input('>>> ').strip()
f.write("END_ALL\n")
-1
View File
@@ -1 +0,0 @@
test
+47
View File
@@ -0,0 +1,47 @@
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import selen_func, time, sys, inspect
set_ID = 'A4:DA:32:D4:EE:3A'
url = 'http://192.168.2.1/'
if __name__ == '__main__':
txt_name = 'commend_line/commend_line'
file = open(txt_name+'.txt','r')
lines_raw = file.readlines()
Line = []
line_temp = []
for i in lines_raw:
if i[0] != ' ':
if len(line_temp)>0:
Line.append(line_temp)
Line.append(i.strip())
else:
line_temp.append(i.strip())
options = Options()
options.add_argument("--disable-notifications")
options.add_experimental_option('excludeSwitches', ['enable-logging'])
chrome = webdriver.Chrome('./chromedriver', chrome_options=options)
chrome.maximize_window()
classes = [cls_name for cls_name, cls_obj in inspect.getmembers(sys.modules['selen_func']) if inspect.isclass(cls_obj) and cls_obj.__module__.find('selen_func')>=0]
page_select = Line.pop(0)
with open('commend_line/commend_line_txt.txt','w')as f:
while page_select != 'END_ALL':
page_sel_split = page_select.split(' ')
class_index = selen_func.check_complete(page_sel_split[1],classes) if len(page_sel_split)>1 else -1
if page_sel_split[0] == 'START' and class_index != -1:
f.write('START '+classes[class_index]+'\n')
print('START',classes[class_index])
DevicesPage_Test = selen_func.startDevicesPage(chrome, url, classes[class_index], f, row_list = Line.pop(0))
if len(Line)>0:
page_select = Line.pop(0)
else:
print("Txt file didn't end with 'END_ALL'.")
break
f.write("END_ALL\n")
a = input(">")