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
def api_reload_yaml(): print('Reloading yaml') db = WorkshopDb() db.reload_yaml() resp = jsonify({'status': 'success'}) resp.status_code = 200 return resp
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
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}' )
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
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
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
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()
def __init__(self): TaskBase.__init__(self, 'Static IP') self.db = WorkshopDb() self.static_ip_start = int(self.db.get_config_item('base_ip'))
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 __init__(self): TaskBase.__init__(self, 'Connect') self.db = WorkshopDb()
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