diff --git a/tools/tiny-test-fw/Utility/Attenuator.py b/tools/tiny-test-fw/Utility/Attenuator.py new file mode 100644 index 000000000..451c48811 --- /dev/null +++ b/tools/tiny-test-fw/Utility/Attenuator.py @@ -0,0 +1,70 @@ +# Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Internal use only. + +This file provide method to control programmable attenuator. +""" + +import time +import serial + + +def set_att(port, att, att_fix=False): + """ + set attenuation value on the attenuator + + :param port: serial port for attenuator + :param att: attenuation value we want to set + :param att_fix: fix the deviation with experience value + :return: True or False + """ + + assert 0 <= att <= 62 + # fix att + if att_fix: + if att >= 33 and (att - 30 + 1) % 4 == 0: + att_t = att - 1 + elif att >= 33 and (att - 30) % 4 == 0: + att_t = att + 1 + else: + att_t = att + else: + att_t = att + + serial_port = serial.Serial(port, baudrate=9600, rtscts=False, timeout=0.1) + if serial_port.isOpen() is False: + raise IOError("attenuator control, failed to open att port") + + cmd_hex = "7e7e10{:02x}{:x}".format(att_t, 0x10 + att_t) + exp_res_hex = "7e7e20{:02x}00{:x}".format(att_t, 0x20 + att_t) + + cmd = cmd_hex.decode("hex") + exp_res = exp_res_hex.decode("hex") + + serial_port.write(cmd) + res = "" + + for i in range(5): + res += serial_port.read(20) + if res == exp_res: + result = True + break + time.sleep(0.1) + else: + result = False + + serial_port.close() + return result diff --git a/tools/tiny-test-fw/Utility/LineChart.py b/tools/tiny-test-fw/Utility/LineChart.py new file mode 100644 index 000000000..fd5d4b5e6 --- /dev/null +++ b/tools/tiny-test-fw/Utility/LineChart.py @@ -0,0 +1,50 @@ +# Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import matplotlib +# fix can't draw figure with docker +matplotlib.use('Agg') +import matplotlib.pyplot as plt + + +# candidate colors +LINE_STYLE_CANDIDATE = ['b-o', 'r-o', 'k-o', 'm-o', 'c-o', 'g-o', 'y-o', + 'b-s', 'r-s', 'k-s', 'm-s', 'c-s', 'g-s', 'y-s'] + + +def draw_line_chart(file_name, title, x_label, y_label, data_list): + """ + draw line chart and save to file. + + :param file_name: abs/relative file name to save chart figure + :param title: chart title + :param x_label: x-axis label + :param y_label: y-axis label + :param data_list: a list of line data. + each line is a dict of ("x-axis": list, "y-axis": list, "label": string) + """ + + plt.figure(figsize=(12, 6)) + plt.grid(True) + + for i, data in enumerate(data_list): + plt.plot(data["x-axis"], data["y-axis"], LINE_STYLE_CANDIDATE[i], label=data["label"]) + + plt.xlabel(x_label) + plt.ylabel(y_label) + plt.legend(fontsize=12) + plt.title(title) + plt.tight_layout(pad=3, w_pad=3, h_pad=3) + plt.savefig(file_name) + plt.close() diff --git a/tools/tiny-test-fw/Utility/PowerControl.py b/tools/tiny-test-fw/Utility/PowerControl.py new file mode 100644 index 000000000..5b7df4c4f --- /dev/null +++ b/tools/tiny-test-fw/Utility/PowerControl.py @@ -0,0 +1,95 @@ +# Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Internal use only. + +This file implements controlling APC PDU via telnet. +""" + +import telnetlib + + +class Control(object): + """ control APC via telnet """ + + @classmethod + def apc_telnet_make_choice(cls, telnet, choice): + """ select a choice """ + telnet.read_until("Event Log") + telnet.read_until(">") + telnet.write(choice + "\r\n") + + @classmethod + def apc_telnet_common_action(cls, telnet, check_str, action): + """ wait until a pattern and then write a line """ + telnet.read_until(check_str) + telnet.write(action + "\r\n") + + @classmethod + def control(cls, apc_ip, control_dict): + """ + control APC + + :param apc_ip: IP of APC + :param control_dict: dict with outlet ID and "ON" or "OFF" + """ + + for _outlet in control_dict: + assert 0 < _outlet < 9 + assert control_dict[_outlet] in ["ON", "OFF"] + + # telnet + # set timeout as 2s so that it won't waste time even can't access APC + tn = telnetlib.Telnet(host=apc_ip, timeout=5) + # log on + cls.apc_telnet_common_action(tn, "User Name :", "apc") + cls.apc_telnet_common_action(tn, "Password :", "apc") + # go to Device Manager + cls.apc_telnet_make_choice(tn, "1") + # go to Outlet Management + cls.apc_telnet_make_choice(tn, "2") + # go to Outlet Control/Configuration + cls.apc_telnet_make_choice(tn, "1") + + # do select Outlet and control + for _outlet in control_dict: + # choose Outlet + cls.apc_telnet_make_choice(tn, str(_outlet)) + # choose Control Outlet + cls.apc_telnet_make_choice(tn, "1") + # choose action + _action = control_dict[_outlet] + if "ON" in _action: + cls.apc_telnet_make_choice(tn, "1") + else: + cls.apc_telnet_make_choice(tn, "2") + # do confirm + cls.apc_telnet_common_action(tn, "cancel :", "YES") + cls.apc_telnet_common_action(tn, "continue...", "") + # return to Outlet Control/Configuration + cls.apc_telnet_make_choice(tn, "\033") + cls.apc_telnet_make_choice(tn, "\033") + + # exit to main menu and logout + tn.write("\033\r\n") + tn.write("\033\r\n") + tn.write("\033\r\n") + tn.write("4\r\n") + + @classmethod + def control_rest(cls, apc_ip, outlet, action): + outlet_list = range(1, 9) + outlet_list.remove(outlet) + cls.control(apc_ip, dict.fromkeys(outlet_list, action)) diff --git a/tools/tiny-test-fw/docs/index.rst b/tools/tiny-test-fw/docs/index.rst index 22cfd73a8..bc3a3f5f8 100644 --- a/tools/tiny-test-fw/docs/index.rst +++ b/tools/tiny-test-fw/docs/index.rst @@ -129,6 +129,7 @@ The following 3rd party lib is required: * pyyaml * xunitgen * netifaces + * matplotlib (if use Utility.LineChart) To build document, we need to install ``Sphinx`` and ``sphinx-rtd-theme`` (you may replace this with your own theme).