Exemple #1
0
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()