Exemple #1
0
class Task03_WebServer(TaskBase):
    def __init__(self):
        TaskBase.__init__(self, 'Web Server')
        self.db = WorkshopDb()
        self.subnet = self.db.get_config_item("subnet_ip")
        self.static_ip_start = int(self.db.get_config_item("base_ip"))

    def test(self, group_number, points):
        """
        Send HTTP request to IP - check for status 200
        Meaning - server is up and running.
        """
        url = 'http://' + self.subnet + str(self.static_ip_start +
                                            group_number) + '/'
        try:
            response = requests.get(url)
            if response.status_code == 200:
                self.db.update_group_fields(group_number, 'Web Server is up')
                self.group_completed(
                    group_number,
                    points,
                    dbg_msg=
                    f'HTTP request was responded successfully\n{response.text}\nTask 3 completed'
                )
                return True
        # true - this is bad practice but everything other than 200 here - is a failure.
        except Exception:
            pass
        self.group_failed(group_number,
                          'Could not get valid HTTP response from ' + url)
        return False
Exemple #2
0
def api_reload_yaml():
    print('Reloading yaml')
    db = WorkshopDb()
    db.reload_yaml()
    resp = jsonify({'status': 'success'})
    resp.status_code = 200
    return resp
Exemple #3
0
 def __init__(self):
     TaskBase.__init__(self, 'Light Control')
     self.db = WorkshopDb()
     self.subnet = self.db.get_config_item("subnet_ip")
     self.static_ip_start = int(self.db.get_config_item("base_ip"))
     self.response_keys = [
         'name', 'number', 'temperature', 'time', 'lights'
     ]
class Task04_ApiResponse(TaskBase):
    def __init__(self):
        TaskBase.__init__(self, 'API response')
        self.db = WorkshopDb()
        self.subnet = self.db.get_config_item("subnet_ip")
        self.static_ip_start = int(self.db.get_config_item("base_ip"))
        self.response_keys = ['name', 'number', 'temperature', 'time']

    def try_to_parse_response(self, group_number, response):
        """Try to parse JSON and fail gracefully"""
        response_data = {k: '' for k in self.response_keys}
        try:
            json_data = response.json()
        except Exception:  # json parsing exception
            return 'Could not parse JSON response'
        # make sure all keys are here
        for k in self.response_keys:
            try:
                response_data[k] = json_data[k]
            except Exception:
                return 'Could not find key ' + k
        if int(response_data['number']) == group_number:
            self.db.update_group_fields(group_number,
                                        True,
                                        group_name=response_data['name'],
                                        temp=response_data['temperature'],
                                        group_time=response_data['time'])
            return 'success'
        return 'Wrong group number'

    def test(self, group_number, points):
        """
        Send HTTP request to http://IP/json and attempts to parse expected keys
        :return: True if response is valid and all keys were parsed successfully
        """
        url = 'http://' + self.subnet + str(self.static_ip_start +
                                            group_number) + '/json'
        try:
            response = requests.get(url)
            if response.status_code == 200:
                message = self.try_to_parse_response(group_number, response)
                if message == 'success':
                    self.group_completed(
                        group_number,
                        points,
                        dbg_msg=
                        f'JSON response was received from group {group_number} - '
                        + f'{response.json()["name"]}\nTask 4 completed')
                    return True
                self.group_failed(group_number, message)
                return False
        # true - this is bad practice but everything other than 200 here - is a failure.
        except Exception:
            pass
        self.group_failed(group_number,
                          'Could not get valid json response from ' + url)
        return False
Exemple #5
0
 def test(self, group_number, points):
     self.db = WorkshopDb()
     mac = self.db.get_group_mac(group_number)
     ip = self.db.get_ip_from_mac(mac)
     if ip != '':
         self.db.update_group_fields(group_number, 'Connected')
         self.group_completed(group_number, points,
                              dbg_msg=f'MAC address {mac} found (IP {ip})\nTask 1 completed')
         return True
     self.group_failed(group_number, 'Could not find MAC address in connected devices list')
     return False
class TaskBase:
    def __init__(self, task_name):
        self.db = WorkshopDb()
        self._task_name_in_db = self.db.get_task_name(task_name)
        self._task_number = int(self._task_name_in_db.split('.')[0])
        self.start_time = time.time()

    def group_completed(self, group_number, points, dbg_msg=''):
        if group_number in self.db.get_groups_in_task(self._task_number):
            # advance and don't remove
            self.db.advance_group_task(
                group_number, self._task_number, self._task_name_in_db,
                int(round(time.time() - self.start_time, 0)), points, dbg_msg)
            print(
                f'task {self._task_name_in_db}, completed by group {group_number}'
            )
        else:
            self.db.update_group_debug(group_number, dbg_msg)
            print(
                f'task {self._task_name_in_db}, completed by group {group_number} - db not updated - debug mode?'
            )

    def group_failed(self, group_number, dbg_msg):
        self.db.update_group_debug(group_number, dbg_msg)
        print(
            f'task {self._task_name_in_db}, group {group_number} failed - {dbg_msg}'
        )
Exemple #7
0
def api_bonus(bonus_id):
    data = request.form
    group_id = int(data['group_id'])
    points = int(data['points'])
    if int(bonus_id) <= 2:
        db = WorkshopDb()
        db.group_add_bonus(
            group_id, points,
            f'Bonus task {bonus_id} completed. adding {points} points')
        group = groups_collection.find({'number': group_id}, {'_id': 0})
        msg = group[0]['dbg_msg']
        resp = jsonify({'status': 'passed', 'message': msg})
    else:
        resp = jsonify({'status': 'failed', 'message': 'wrong bonus number'})
    resp.status_code = 200
    return resp
Exemple #8
0
class Task02_StaticIp(TaskBase):
    def __init__(self):
        TaskBase.__init__(self, 'Static IP')
        self.db = WorkshopDb()
        self.static_ip_start = int(self.db.get_config_item('base_ip'))

    def test(self, group_number, points):
        mac = self.db.get_group_mac(group_number)
        ip = self.db.get_ip_from_mac(mac)
        if ip != '':
            ip_arr = ip.split('.')
            if int(ip_arr[3]) == (self.static_ip_start + group_number):
                self.db.update_group_fields(group_number,
                                            'Connected - Static IP')
                self.group_completed(
                    group_number,
                    points,
                    dbg_msg=
                    f'MAC address {mac} found with static IP {ip}\nTask 2 completed'
                )
                return True
        self.group_failed(group_number,
                          'MAC address does not have the correct IP')
        return False
class Task09_AcControl(TaskBase):
    def __init__(self):
        TaskBase.__init__(self, 'AC Control')
        self.db = WorkshopDb()
        self.subnet = self.db.get_config_item("subnet_ip")
        self.static_ip_start = int(self.db.get_config_item("base_ip"))
        self.response_keys = [
            'name', 'number', 'temperature', 'time', 'lights', 'tv_state',
            'ac_state', 'ac_temp'
        ]

    def try_to_parse_response(self, group_number, response, req_state,
                              req_temp):
        response_data = {k: '' for k in self.response_keys}
        try:
            json_data = response.json()
        except Exception:  # json parsing exception
            return 'Could not parse JSON response'
        # make sure all keys are here
        for k in self.response_keys:
            try:
                response_data[k] = json_data[k]
            except Exception:
                return 'Could not find key ' + k
        try:
            resp_lights = [
                int(response_data['lights'][0]),
                int(response_data['lights'][1]),
                int(response_data['lights'][2])
            ]
        except:
            return 'Could not parse lights array'
        if int(response_data['number']) == group_number:
            self.db.update_group_fields(group_number,
                                        True,
                                        group_name=response_data['name'],
                                        temp=response_data['temperature'],
                                        group_time=response_data['time'],
                                        light1=resp_lights[0],
                                        light2=resp_lights[1],
                                        light3=resp_lights[2],
                                        tv=response_data['tv_state'],
                                        ac=response_data['ac_state'],
                                        ac_temp=response_data['ac_temp'])
            # in state off - allow any temp
            if (req_state == response_data['ac_state'] and req_state == 0) or \
               (req_state == response_data['ac_state'] and req_temp == int(response_data['ac_temp'])):
                return 'success'
            return 'Wrong AC parameters in response'
        return 'Wrong group number'

    def test(self, group_number, points):
        """
        Send HTTP multiple requests to http://IP/ac and attempts to parse expected keys
        each request has a different parameter to verify execution
        :return: True if response is valid and all keys were parsed successfully
        """
        # since we only get the group number from the server -
        # we use the variable to overload it with the IR capture device number as well
        ir_dev_number = (group_number & 0xff00) >> 8
        group_number = group_number & 0xff
        req_temp = random.randint(16, 25)
        sequences = [
            '?state=on&temperature=' + str(req_temp),
            '?state=off&temperature=' + str(req_temp),
        ]
        verification_sequences = [
            1,
            0,
        ]
        url_base = 'http://' + self.subnet + str(self.static_ip_start +
                                                 group_number) + '/ac'
        dbg_msg = 'Starting sequence - \n'
        try:
            for i in range(0, 2):
                if not IrWebServices.start_capture(
                        self.subnet + str(ir_dev_number), group_number):
                    self.group_failed(
                        group_number, 'Could not allocate ' + self.subnet +
                        str(ir_dev_number))
                    return False
                url = url_base + sequences[i]
                dbg_msg += url + '\n'
                response = requests.get(url)
                if response.status_code == 200:
                    message = self.try_to_parse_response(
                        group_number, response, verification_sequences[i],
                        req_temp)
                    if message != 'success':
                        self.group_failed(group_number, message)
                        self.during_run = False
                        IrWebServices.release(self.subnet + str(ir_dev_number))
                        return False
                else:
                    self.group_failed(group_number,
                                      'Could not get a response from ' + url)
                    self.during_run = False
                    IrWebServices.release(self.subnet + str(ir_dev_number))
                    return False
                time.sleep(0.5)  # give it a little time...
                dbg_msg += 'got JSON response - checking IR device\n'
                ir_capture = IrWebServices.stop_and_get_capture(
                    self.subnet + str(ir_dev_number))
                inp = IrNecParser()
                if not inp.is_ir_match(ir_capture,
                                       group_number,
                                       device=2,
                                       state=verification_sequences[i],
                                       temperature=req_temp):
                    self.group_failed(group_number, 'IR verification failed')
                    self.during_run = False
                    return False
                dbg_msg += 'success\n'
            dbg_msg += 'AC IR sequence completed'
            self.group_completed(group_number, points, dbg_msg)
            self.during_run = False
            return True
        # true - this is bad practice but everything other than 200 here - is a failure.
        except Exception:
            # in case of exception - release IR device
            IrWebServices.release(self.subnet + str(ir_dev_number))
        self.group_failed(group_number,
                          'Could not get valid json response from ' + url_base)
        self.during_run = False
        return False
Exemple #10
0
class Task07_Lights(TaskBase):
    def __init__(self):
        TaskBase.__init__(self, 'Light Control')
        self.db = WorkshopDb()
        self.subnet = self.db.get_config_item("subnet_ip")
        self.static_ip_start = int(self.db.get_config_item("base_ip"))
        self.response_keys = [
            'name', 'number', 'temperature', 'time', 'lights'
        ]

    def try_to_parse_response(self, group_number, response, req_lights):
        response_data = {k: '' for k in self.response_keys}
        try:
            json_data = response.json()
        except Exception:  # json parsing exception
            return 'Could not parse JSON response'
        # make sure all keys are here
        for k in self.response_keys:
            try:
                response_data[k] = json_data[k]
            except Exception:
                return 'Could not find key ' + k
        try:
            resp_lights = [
                int(response_data['lights'][0]),
                int(response_data['lights'][1]),
                int(response_data['lights'][2])
            ]
        except:
            return 'Could not parse lights array'
        if int(response_data['number']) == group_number:
            self.db.update_group_fields(group_number,
                                        True,
                                        group_name=response_data['name'],
                                        temp=response_data['temperature'],
                                        group_time=response_data['time'],
                                        light1=resp_lights[0],
                                        light2=resp_lights[1],
                                        light3=resp_lights[2])
            if (req_lights[0] == resp_lights[0] or req_lights[0] == 2) and \
               (req_lights[1] == resp_lights[1] or req_lights[1] == 2) and \
               (req_lights[2] == resp_lights[2] or req_lights[2] == 2):
                return 'success'
            return 'Wrong lights in response'
        return 'Wrong group number'

    def test(self, group_number, points):
        """
        Send HTTP multiple requests to http://IP/light and attempts to parse expected keys
        each request has a different parameter to verify execution
        :return: True if response is valid and all keys were parsed successfully
        """
        sequences = [
            '?number=1&state=on', '?number=2&state=on', '?number=3&state=on',
            '?number=3&state=off', '?number=2&state=off', '?number=1&state=off'
        ]
        # 2 is don't care (we don't know what the LED value was before we set it)
        verification_sequences = [[1, 2, 2], [1, 1, 2], [1, 1, 1], [1, 1, 0],
                                  [1, 0, 0], [0, 0, 0]]
        url_base = 'http://' + self.subnet + str(self.static_ip_start +
                                                 group_number) + '/light'
        dbg_msg = 'Starting sequence - \n'
        try:
            for i in range(0, 6):
                url = url_base + sequences[i]
                dbg_msg += url + '\n'
                response = requests.get(url)
                if response.status_code == 200:
                    message = self.try_to_parse_response(
                        group_number, response, verification_sequences[i])
                    if message != 'success':
                        self.group_failed(group_number, message)
                        return False
                    dbg_msg += 'success\n'
                else:
                    self.group_failed(group_number,
                                      'Could not get a response from ' + url)
                    return False
            dbg_msg += 'Lights sequence completed'
            self.group_completed(group_number, points, dbg_msg)
            return True
        # true - this is bad practice but everything other than 200 here - is a failure.
        except Exception:
            pass
        self.group_failed(group_number,
                          'Could not get valid json response from ' + url_base)
        return False
Exemple #11
0
def run():
    db = WorkshopDb()
    while True:
        update_known_devices(db)
        time.sleep(10)
 def __init__(self, task_name):
     self.db = WorkshopDb()
     self._task_name_in_db = self.db.get_task_name(task_name)
     self._task_number = int(self._task_name_in_db.split('.')[0])
     self.start_time = time.time()
Exemple #13
0
 def __init__(self):
     TaskBase.__init__(self, 'Static IP')
     self.db = WorkshopDb()
     self.static_ip_start = int(self.db.get_config_item('base_ip'))
Exemple #14
0
 def __init__(self):
     TaskBase.__init__(self, 'Web Server')
     self.db = WorkshopDb()
     self.subnet = self.db.get_config_item("subnet_ip")
     self.static_ip_start = int(self.db.get_config_item("base_ip"))
Exemple #15
0
 def __init__(self):
     TaskBase.__init__(self, 'Connect')
     self.db = WorkshopDb()
Exemple #16
0
class Task05_ApiResponse(TaskBase):
    def __init__(self):
        TaskBase.__init__(self, 'Temperature')
        self.db = WorkshopDb()
        self.subnet = self.db.get_config_item("subnet_ip")
        self.static_ip_start = int(self.db.get_config_item("base_ip"))
        self.response_keys = ['name',
                              'number',
                              'temperature',
                              'time']

    def try_to_parse_response(self, group_number, response):
        response_data = {k: '' for k in self.response_keys}
        try:
            json_data = response.json()
        except Exception:  # json parsing exception
            return 'Could not parse JSON response'
        # make sure all keys are here
        for k in self.response_keys:
            try:
                response_data[k] = json_data[k]
            except Exception:
                return 'Could not find key ' + k
        if int(response_data['number']) == group_number:
            self.db.update_group_fields(group_number,
                                        True,
                                        group_name=response_data['name'],
                                        temp=response_data['temperature'],
                                        group_time=response_data['time'])
            return 'success'
        return 'Wrong group number'

    def test(self, group_number, points):
        """
        Send HTTP request to http://IP/json and attempts to parse expected keys
        :return: True if response is valid and all keys were parsed successfully
        """
        url = 'http://' + self.subnet + str(self.static_ip_start + group_number) + '/json'
        temperature = 0
        try:
            for i in range(1, 4):
                response = requests.get(url)
                if response.status_code == 200:
                    message = self.try_to_parse_response(group_number, response)
                    if message == 'success':
                        temperature += self.db.get_group_temp(group_number)
                    else:
                        self.group_failed(group_number, message)
                        return False
                    time.sleep(0.5)
                else:
                    self.group_failed(group_number, 'Could not get a response from ' + url)
                    return False
            avg_temp = temperature / 3
            temperature = int(temperature / 3)
            if avg_temp != temperature:
                if 15 <= temperature <= 35:
                    self.group_completed(group_number, points,
                                         dbg_msg=f'Valid temperature was received from group {group_number} - ' +
                                                 f'{response.json()["temperature"]}.\nTask 5 completed')
                    return True
                else:
                    self.group_failed(group_number, 'Temperature ' + str(temperature) + ' is not in range 15-35')
                    return False
            else:
                self.group_failed(group_number, 'All temperatures are the same ' + str(temperature) +
                                  '. Try touching sensor while running the test')
                return False
        # true - this is bad practice but everything other than 200 here - is a failure.
        except Exception:
            pass
        self.group_failed(group_number, 'Could not get valid json response from ' + url)
        return False