def test_create_grow_from_json_string_format(): start = datetime.utcnow() + timedelta(0, 3) # 3 seconds from now start -= timedelta(microseconds=start.microsecond) end = start + timedelta(0, 2) # 5 seconds from now grow = Grow.from_json( { "room_id": 1, "rack_id": 2, "shelf_id": 3, "recipe_id": 4, "recipe_phase_num": 5, "start_datetime": start.strftime("%Y-%m-%d %H:%M:%S"), "end_datetime": end.strftime("%Y-%m-%d %H:%M:%S"), } ) assert grow.room_id == 1 assert grow.rack_id == 2 assert grow.shelf_id == 3 assert grow.recipe_id == 4 assert grow.recipe_phase_num == 5 # needs to round because calendar.timegm is converting to seconds losing microsecond precision assert grow.start_datetime == start assert grow.end_datetime == end
def return_all_entities_listener(message) -> None: print("Received message in entities_listener:", message) assert "rooms" in message assert "racks" in message assert "shelves" in message assert "grows" in message assert "recipes" in message assert "recipe_phases" in message found_rooms = [Room.from_json(r) for r in message["rooms"]] found_racks = [Rack.from_json(r) for r in message["racks"]] found_shelves = [Shelf.from_json(s) for s in message["shelves"]] found_grows = [Grow.from_json(g) for g in message["grows"]] found_recipes = [Recipe.from_json(r) for r in message["recipes"]] found_recipe_phases = [ RecipePhase.from_json(rp) for rp in message["recipe_phases"] ] assert collections.Counter(found_rooms) == collections.Counter(rooms) assert collections.Counter(found_racks) == collections.Counter(racks) assert collections.Counter(found_shelves) == collections.Counter( shelves) assert collections.Counter(found_grows) == collections.Counter(grows) assert collections.Counter(found_recipes) == collections.Counter( recipes) assert collections.Counter(found_recipe_phases) == collections.Counter( recipe_phases) flag.append(True)
def return_all_entities_listener(message) -> None: message_dict = json.loads(message) print("Received message in entities_listener:", message_dict) assert "rooms" in message_dict assert "racks" in message_dict assert "shelves" in message_dict assert "grows" in message_dict assert "grow_phases" in message_dict assert "recipes" in message_dict assert "recipe_phases" in message_dict found_rooms = [Room.from_json(r) for r in message_dict["rooms"]] found_racks = [Rack.from_json(r) for r in message_dict["racks"]] found_shelves = [Shelf.from_json(s) for s in message_dict["shelves"]] found_grows = [Grow.from_json(g) for g in message_dict["grows"]] found_grow_phases = [ GrowPhase.from_json(g) for g in message_dict["grow_phases"] ] found_recipes = [Recipe.from_json(r) for r in message_dict["recipes"]] found_recipe_phases = [ RecipePhase.from_json(rp) for rp in message_dict["recipe_phases"] ] assert collections.Counter(found_rooms) == collections.Counter(rooms) assert collections.Counter(found_racks) == collections.Counter(racks) assert collections.Counter(found_shelves) == collections.Counter( shelves ) assert len(found_grows) > 0 x = len(found_grows) assert ( found_grows[x - 1].start_datetime.strftime("%Y-%m-%d %H:%M:%S") == start ) assert ( found_grows[x - 1].estimated_end_datetime.strftime( "%Y-%m-%d %H:%M:%S" ) == end ) i = len(found_grow_phases) assert ( found_grow_phases[i - 1].phase_start_datetime.strftime( "%Y-%m-%d %H:%M:%S" ) == start ) assert ( found_grow_phases[i - 1].phase_end_datetime.strftime( "%Y-%m-%d %H:%M:%S" ) == end ) j = len(found_recipes) assert found_recipe_phases[j - 1].power_level == p_level assert found_recipe_phases[j - 1].red_level == r_level assert found_recipe_phases[j - 1].blue_level == b_level flag.append(True) grow.append(found_grows[0].grow_id)
def _test_send_shelf_grow(sio, room_id, rack_id, shelf_id, recipe_phases): assert len(recipe_phases) == 1 # only support 1 phase for now print("Sending shelf grow") start = datetime.utcnow() + timedelta(0, 3) # 3 seconds from now end = start + timedelta(0, 2) # 5 seconds from now start_time = start.strftime("%Y-%m-%d %H:%M:%S") end_time = end.strftime("%Y-%m-%d %H:%M:%S") shelf_grows = [] for rp in recipe_phases: shelf_grow = Grow.from_json({ "room_id": room_id, "rack_id": rack_id, "shelf_id": shelf_id, "recipe_id": rp.recipe_id, "recipe_phase_num": rp.recipe_phase_num, "start_datetime": start_time, "end_datetime": end_time, }) shelf_grows.append(shelf_grow) flag = [] @sio.on("start_grows_for_shelves_succeeded") def start_grows_for_shelves_succeeded(message) -> None: assert "succeeded" in message assert message["succeeded"] flag.append(True) @sio.on("set_lights_for_grow") def set_lights_for_grow(message) -> None: assert "grow" in message assert "power_level" in message assert "red_level" in message assert "blue_level" in message flag.append(True) sio.emit("start_grows_for_shelves", {"grows": [s.to_json() for s in shelf_grows]}) wait_for_event(sio, flag, 1, 5, "test_start_grows_for_shelves") for i in range(len(shelf_grows)): wait_for_event(sio, flag, i + 2, 5, "test_set_lights_for_grow_job") print("test send shelf grow passed") return shelf_grow
def start_grows_for_shelves(message) -> None: print("message:", message) logging.debug("message sent to post_room_schedule:", message) if "grows" not in message: send_message_to_namespace_if_specified( socketio, message, "start_grow_for_shelf_succeeded", { "succeeded": False, "reason": "Grow not included" }, ) grows: List[Grow] = [Grow.from_json(g) for g in message["grows"]] for grow in grows: ( power_level, red_level, blue_level, ) = app_config.db.read_lights_from_recipe_phase( grow.recipe_id, grow.recipe_phase_num) app_config.scheduler.add_job( schedule_grow_for_shelf, "interval", start_date=grow.start_datetime, end_date=grow.end_datetime, args=[grow, power_level, red_level, blue_level], id=grow.to_job_id(), minutes=5, ) # TODO (lww515): What to do after harvest is finished? # write grows to db app_config.db.write_grows(grows) logging.debug("start_grow_for_shelf succeeded!") send_message_to_namespace_if_specified( socketio, message, "start_grows_for_shelves_succeeded", {"succeeded": True}) print("Grow started successfully, event emitted")
def harvest_grow(message) -> None: db_conn = None try: if "grow" not in message: send_message_to_namespace_if_specified( socketio, message, "harvest_grow_response", { "succeeded": False, "reason": "Grow not included" }, ) return grow_json = message["grow"] grow_id: int = int(grow_json["grow_id"]) grow: Optional[Grow] = app_config.db.read_grow(grow_id) if not grow: send_message_to_namespace_if_specified( socketio, message, "harvest_grow_response", { "succeeded": False, "reason": "Grow not found" }, ) return found_grow_json = grow.to_json() # read all data sent in by user, and mark it on grow for key in grow_json: found_grow_json[key] = grow_json[key] updated_grow: Grow = Grow.from_json(found_grow_json) # harvest the grow by marking it as complete harvest_datetime: datetime = datetime.utcnow() updated_grow.estimated_end_datetime = harvest_datetime updated_grow.is_finished = True # end grow db_conn = app_config.db._new_transaction() app_config.db.update_grow_harvest_data(db_conn, updated_grow) # read current grow phase current_phase: int = updated_grow.current_phase current_grow_phase: Optional[ GrowPhase] = app_config.db.read_grow_phase( db_conn, updated_grow.grow_id, current_phase) if not current_grow_phase: send_message_to_namespace_if_specified( socketio, message, "harvest_grow_response", { "succeeded": False, "reason": "Current grow phase {} not found".format( current_phase), }, ) return # remove ongoing job so that it stops running client_remove_job(current_grow_phase) # update current recipe phase to have proper end date print("Updating grow_phase:", current_grow_phase) app_config.db.end_grow_phase(db_conn, current_grow_phase, harvest_datetime) # commit the transaction db_conn.commit() send_message_to_namespace_if_specified(socketio, message, "harvest_grow_response", {"succeeded": True}) except Exception as e: exception_str: str = str(e) print( "Error with harvesting grow:", message, exception_str, traceback.format_exc(), ) # rollback connection if it exists and report error back to client if db_conn: db_conn.rollback() send_message_to_namespace_if_specified( socketio, message, "harvest_grow_response", { "succeeded": False, "reason": "Unexpected error. Please document the conditions that lead to this error. {}" .format(exception_str), }, ) finally: if db_conn: # close the db connection if it's defined db_conn.close()
def update_incomplete_grow(message) -> None: db_conn = None try: if "grow" not in message: send_message_to_namespace_if_specified( socketio, message, "update_incomplete_grow_response", { "succeeded": False, "reason": "Grow not included" }, ) return grow_json = message["grow"] grow_id: int = int(grow_json["grow_id"]) grow: Optional[Grow] = app_config.db.read_grow(grow_id) if not grow: send_message_to_namespace_if_specified( socketio, message, "update_incomplete_grow_response", { "succeeded": False, "reason": "Grow not found" }, ) return found_grow_json = grow.to_json() # read all data sent in by user, and mark it on grow for key in grow_json: found_grow_json[key] = grow_json[key] updated_grow: Grow = Grow.from_json(found_grow_json) # harvest the grow by marking it as complete harvest_datetime: datetime = datetime.utcnow() updated_grow.estimated_end_datetime = harvest_datetime updated_grow.is_finished = True print( "grow_json to harvest in update_incomplete_grow:", grow_json, updated_grow, flush=True, ) # end grow db_conn = app_config.db._new_transaction() app_config.db.update_grow_harvest_data(db_conn, updated_grow) # commit changes db_conn.commit() send_message_to_namespace_if_specified( socketio, message, "update_incomplete_grow_response", {"succeeded": True}, ) except Exception as e: exception_str: str = str(e) print( "Error with updating incomplete grow:", message, exception_str, traceback.format_exc(), ) # rollback connection if it exists and report error back to client if db_conn: db_conn.rollback() send_message_to_namespace_if_specified( socketio, message, "update_incomplete_grow_response", { "succeeded": False, "reason": "Unexpected error. Please document the conditions that lead to this error. {}" .format(exception_str), }, ) finally: if db_conn: # close the db connection if it's defined db_conn.close()