コード例 #1
0
def pneumatrol_1_resume_job():
    timestamp = datetime.now().timestamp()
    # Get the reason for the pause. The app will return the short_description of the activity code
    if "downtime_reason" not in request.json:
        return json.dumps({"success": False})
    notes = request.json.get("notes", "")
    downtime_reason = request.json["downtime_reason"]
    # Get the activity code corresponding to the description
    activity_code = ActivityCode.query.filter_by(short_description=downtime_reason).first()
    user_session = UserSession.query.filter_by(device_ip=request.remote_addr, active=True).first()
    if user_session is None:
        return json.dumps({"success": False, "reason": "User is logged out"})
    current_job = Job.query.filter_by(user_session_id=user_session.id, active=True).first()
    time = datetime.now().strftime("%H:%M")
    if not current_job.notes:
        current_job.notes = ""  # Initialise the string if null
    if notes != "":
        current_job.notes += f"{time} - {downtime_reason} - {notes} \n"
    # Mark the most recent activity in the database as complete
    complete_last_activity(machine_id=user_session.machine_id,
                           activity_code_id=activity_code.id,
                           timestamp_end=timestamp)

    # Start a new activity
    new_activity = Activity(machine_id=user_session.machine_id,
                            machine_state=Config.MACHINE_STATE_RUNNING,
                            activity_code_id=Config.UPTIME_CODE_ID,
                            user_id=user_session.user_id,
                            job_id=current_job.id,
                            timestamp_start=timestamp)
    db.session.add(new_activity)
    db.session.commit()
    return json.dumps({"success": True})
コード例 #2
0
ファイル: helpers.py プロジェクト: DigitME2/oee_server
def end_user_sessions(user_id=None, machine_id=None):
    """ End all sessions for a user or a machine (Either can be given)"""
    timestamp = datetime.now().timestamp()
    sessions = []
    if user_id:
        sessions.extend(
            UserSession.query.filter_by(user_id=user_id, active=True).all())
    elif machine_id:
        sessions.extend(
            UserSession.query.filter_by(machine_id=machine_id,
                                        active=True).all())
    else:
        sessions.extend(UserSession.query.filter_by(active=True).all())
    for us in sessions:
        current_app.logger.info(f"Ending user session {us}")
        us.timestamp_logout = timestamp
        us.active = False
        # End all jobs assigned to the session
        for job in us.jobs:
            job.end_time = timestamp
            job.active = None
        db.session.commit(
        )  # Not committing here would sometimes cause sqlite to have too many operations
        # Set the activity to "no user"
        complete_last_activity(machine_id=us.machine.id,
                               timestamp_end=timestamp)
        new_activity = Activity(machine_id=us.machine.id,
                                timestamp_start=timestamp,
                                activity_code_id=Config.NO_USER_CODE_ID,
                                machine_state=Config.MACHINE_STATE_OFF)
        current_app.logger.debug(
            f"Starting {new_activity} on logout of {us.user}")
        db.session.add(new_activity)
        db.session.commit()
コード例 #3
0
def pneumatrol_1_start_job_or_setting(setting):
    if not request.is_json:
        return 404
    timestamp = datetime.now().timestamp()
    user_session = UserSession.query.filter_by(device_ip=request.remote_addr, active=True).first()
    if user_session is None:
        return json.dumps({"success": False, "reason": "User is logged out"})
    try:
        machine = user_session.machine
    except:
        return json.dumps({"success": False, "reason": "Server did not receive correct data"})

    # Create the job
    if setting:
        try:
            machine = user_session.machine
        except:
            return json.dumps({"success": False, "reason": "Server did not receive correct data"})
        job = Job(start_time=timestamp,
                  user_id=user_session.user_id,
                  user_session_id=user_session.id,
                  wo_number=request.json["wo_number"],
                  planned_set_time=request.json["planned_set_time"],
                  machine_id=machine.id,
                  active=True)
    else:
        job = Job(start_time=timestamp,
                  user_id=user_session.user_id,
                  user_session_id=user_session.id,
                  wo_number=request.json["wo_number"],
                  planned_run_time=request.json["planned_run_time"],
                  planned_quantity=request.json["planned_quantity"],
                  planned_cycle_time=request.json["planned_cycle_time"],
                  machine_id=machine.id,
                  active=True)

    db.session.add(job)
    db.session.commit()

    # End the current activity
    complete_last_activity(machine_id=machine.id, timestamp_end=timestamp)

    # Set the first activity depending on whether the machine is being set
    if setting:
        starting_activity_code = Config.SETTING_CODE_ID
    else:
        starting_activity_code = Config.UPTIME_CODE_ID

    # Start a new activity
    new_activity = Activity(machine_id=machine.id,
                            machine_state=Config.MACHINE_STATE_RUNNING,
                            activity_code_id=starting_activity_code,
                            user_id=user_session.user_id,
                            job_id=job.id,
                            timestamp_start=timestamp)
    db.session.add(new_activity)
    db.session.commit()
    current_app.logger.info(f"{user_session.user} started {job}")
    return json.dumps({"success": True})
コード例 #4
0
def change_activity(machine, job, user):
    current_app.logger.debug(f"changing activity")
    complete_last_activity(machine_id=machine.id)
    chance_the_activity_is_uptime = 0.8
    if random.random() < chance_the_activity_is_uptime:
        new_activity = Activity(machine_id=machine.id,
                                timestamp_start=datetime.now().timestamp(),
                                machine_state=1,
                                activity_code_id=Config.UPTIME_CODE_ID,
                                job_id=job.id,
                                user_id=user.id)
    else:
        # otherwise the activity is downtime
        new_activity = Activity(machine_id=machine.id,
                                timestamp_start=datetime.now().timestamp(),
                                machine_state=0,
                                activity_code_id=randrange(
                                    2, len(ActivityCode.query.all())),
                                job_id=job.id,
                                user_id=user.id)
    db.session.add(new_activity)
    db.session.commit()
コード例 #5
0
def pneumatrol_end_job_or_setting(setting):
    timestamp = datetime.now().timestamp()
    user_session = UserSession.query.filter_by(device_ip=request.remote_addr, active=True).first()
    if user_session is None:
        return json.dumps({"success": False,
                           "reason": "User is logged out"})

    # End the current job
    current_job = Job.query.filter_by(user_session_id=user_session.id, active=True).first()
    current_job.end_time = timestamp
    current_job.active = None

    if setting:
        try:
            scrap_quantity = int(request.json["scrap_quantity"])
        except KeyError:
            return json.dumps({"success": False,
                               "reason": "Did not receive correct data from server"})
        current_job.setup_scrap = scrap_quantity
    else:
        try:
            actual_quantity = int(request.json["actual_quantity"])
            scrap_quantity = int(request.json["scrap_quantity"])
        except KeyError:
            return json.dumps({"success": False,
                               "reason": "Did not receive correct data from server"})
        current_job.production_scrap = scrap_quantity
        current_job.actual_quantity = actual_quantity

    db.session.commit()

    # Mark the most recent activity in the database as complete
    complete_last_activity(machine_id=user_session.machine_id, timestamp_end=timestamp)

    # Start a new activity
    new_activity = Activity(machine_id=user_session.machine_id,
                            machine_state=Config.MACHINE_STATE_OFF,
                            activity_code_id=Config.UNEXPLAINED_DOWNTIME_CODE_ID,
                            user_id=user_session.user_id,
                            timestamp_start=timestamp)
    db.session.add(new_activity)
    db.session.commit()
    current_app.logger.debug(f"User {user_session.user} ended {current_job}")
    return json.dumps({"success": True})
コード例 #6
0
ファイル: graphs.py プロジェクト: DigitME2/oee_server
def create_multiple_machines_gantt(graph_start, graph_end, machine_ids):
    """ Creates a gantt plot of OEE for all machines in the database between given times
    graph_start = the start time of the graph
    graph_end = the end time of the graph
    machine_ids = a list of ids to include in the graph"""

    activities = []
    machine_ids.sort()
    for machine_id in machine_ids:
        machine_activities = get_machine_activities(machine_id=machine_id, timestamp_start=graph_start,
                                                    timestamp_end=graph_end)
        # If a machine has no activities, add a fake one so it still shows on the graph
        if len(machine_activities) == 0:
            activities.append(Activity(timestamp_start=graph_start, timestamp_end=graph_start))
        else:
            activities.extend(machine_activities)

    df = get_activities_df(activities=activities,
                           group_by="machine_name",
                           graph_start=graph_start,
                           graph_end=graph_end,
                           crop_overflow=True)

    if len(df) == 0:
        return "No machine activity"
    # Create the colours dictionary using codes' colours from the database
    colours = {}
    for act_code in ActivityCode.query.all():
        colours[act_code.short_description] = act_code.graph_colour
    fig = ff.create_gantt(df,
                          group_tasks=True,
                          colors=colours,
                          index_col='Code',
                          bar_width=0.4)

    # Create a layout object using the layout automatically created
    layout = Layout(fig['layout'])
    layout = apply_default_layout(layout)
    layout.showlegend = True
    fig['layout'] = layout
    config = {'responsive': True}
    return plot(fig, output_type="div", include_plotlyjs=True, config=config)
コード例 #7
0
def pneumatrol_1_pause_job():
    timestamp = datetime.now().timestamp()
    user_session = UserSession.query.filter_by(device_ip=request.remote_addr, active=True).first()
    if user_session is None:
        return json.dumps({"success": False,
                           "reason": "User is logged out"})
    current_job = Job.query.filter_by(user_session_id=user_session.id, active=True).first()
    # Mark the most recent activity in the database as complete
    complete_last_activity(machine_id=user_session.machine_id, timestamp_end=timestamp)

    # Start a new activity
    new_activity = Activity(machine_id=user_session.machine_id,
                            machine_state=Config.MACHINE_STATE_OFF,
                            activity_code_id=Config.UNEXPLAINED_DOWNTIME_CODE_ID,
                            user_id=user_session.user_id,
                            job_id=current_job.id,
                            timestamp_start=timestamp)
    db.session.add(new_activity)
    db.session.commit()
    return json.dumps({"success": True})
コード例 #8
0
ファイル: routes.py プロジェクト: DigitME2/oee_server
def android_start_job():
    if not request.is_json:
        return 404
    timestamp = datetime.now().timestamp()
    user_session = UserSession.query.filter_by(device_ip=request.remote_addr,
                                               active=True).first()
    machine = user_session.machine

    if user_session.user.has_job():
        return 400

    # Create the job
    job = Job(start_time=timestamp,
              user_id=user_session.user_id,
              user_session_id=user_session.id,
              wo_number=request.json["wo_number"],
              planned_run_time=request.json["planned_run_time"],
              planned_quantity=request.json["planned_quantity"],
              machine_id=machine.id,
              active=True)

    db.session.add(job)
    db.session.commit()

    # End the current activity
    complete_last_activity(machine_id=machine.id, timestamp_end=timestamp)

    # Set the first activity
    starting_activity_code = Config.UPTIME_CODE_ID

    # Start a new activity
    new_activity = Activity(machine_id=machine.id,
                            machine_state=Config.MACHINE_STATE_RUNNING,
                            activity_code_id=starting_activity_code,
                            user_id=user_session.user_id,
                            job_id=job.id,
                            timestamp_start=timestamp)
    db.session.add(new_activity)
    db.session.commit()
    current_app.logger.info(f"{user_session.user} started {job}")
    return json.dumps({"success": True})
コード例 #9
0
ファイル: routes.py プロジェクト: DigitME2/oee_server
def android_end_job():
    timestamp = datetime.now().timestamp()
    user_session = UserSession.query.filter_by(device_ip=request.remote_addr,
                                               active=True).first()

    try:
        actual_quantity = int(request.json["actual_quantity"])
    except KeyError:
        current_app.logger.error(
            f"Received incorrect data from {user_session} while ending job")
        return json.dumps({
            "success": False,
            "reason": "Server error parsing data"
        })

    # End the current job
    current_job = Job.query.filter_by(user_session_id=user_session.id,
                                      active=True).first()
    current_job.end_time = timestamp
    current_job.active = None

    current_job.actual_quantity = actual_quantity

    db.session.commit()

    # Mark the most recent activity in the database as complete
    complete_last_activity(machine_id=user_session.machine_id,
                           timestamp_end=timestamp)

    # Start a new activity
    new_activity = Activity(
        machine_id=user_session.machine_id,
        machine_state=Config.MACHINE_STATE_OFF,
        activity_code_id=Config.UNEXPLAINED_DOWNTIME_CODE_ID,
        user_id=user_session.user_id,
        timestamp_start=timestamp)
    db.session.add(new_activity)
    db.session.commit()
    current_app.logger.debug(f"User {user_session.user} ended {current_job}")
    return json.dumps({"success": True})
コード例 #10
0
ファイル: helpers.py プロジェクト: DigitME2/oee_server
def start_user_session(user_id, device_ip):
    """ Start a new session. Usually called when a user logs in. Fails if no machine is assigned to the device ip"""
    timestamp = datetime.now().timestamp()
    user_session = UserSession.query.filter_by(user_id=user_id,
                                               device_ip=device_ip,
                                               active=True).first()
    # Close any user sessions that the current user has
    if user_session is not None:
        current_app.logger.warning(
            f"Tried to start a user session for user {user_id} while one is already open. Closing..."
        )
        end_user_sessions(user_id)
    machine = Machine.query.filter_by(device_ip=device_ip).first()
    if machine is None:
        current_app.logger.info(f"No machine assigned to {device_ip}")
        return False
    # Close any sessions that exist on the current machine
    end_user_sessions(machine_id=machine.id)

    # Create the new user session
    new_us = UserSession(user_id=user_id,
                         machine_id=machine.id,
                         device_ip=device_ip,
                         timestamp_login=timestamp,
                         active=True)
    db.session.add(new_us)
    # Change the machine activity now that the user is logged in
    complete_last_activity(machine_id=machine.id, timestamp_end=timestamp)
    new_activity = Activity(
        machine_id=machine.id,
        timestamp_start=timestamp,
        activity_code_id=Config.UNEXPLAINED_DOWNTIME_CODE_ID,
        machine_state=Config.MACHINE_STATE_OFF)
    db.session.add(new_activity)

    db.session.commit()
    current_app.logger.info(f"Started user session {new_us}")
    return True
コード例 #11
0
ファイル: routes.py プロジェクト: DigitME2/oee_server
def android_update_activity():
    timestamp = datetime.now().timestamp()
    user_session = UserSession.query.filter_by(device_ip=request.remote_addr,
                                               active=True).first()
    try:
        selected_activity_description = request.json["selected_activity_code"]
    except KeyError:
        return json.dumps({"success": False})

    # Mark the most recent activity in the database as complete
    complete_last_activity(machine_id=user_session.machine_id,
                           timestamp_end=timestamp)

    # Start a new activity
    # The current job is the only active job belonging to the user session
    current_job = Job.query.filter_by(user_session_id=user_session.id,
                                      active=True).first()
    # The activity code is obtained from the request
    activity_code = ActivityCode.query.filter_by(
        short_description=selected_activity_description).first()
    # The machine state is calculated from the activity code
    if activity_code.id == Config.UPTIME_CODE_ID:
        machine_state = Config.MACHINE_STATE_RUNNING
    else:
        machine_state = Config.MACHINE_STATE_OFF
    # Create the new activity
    new_activity = Activity(machine_id=user_session.machine_id,
                            machine_state=machine_state,
                            activity_code_id=activity_code.id,
                            user_id=user_session.user_id,
                            job_id=current_job.id,
                            timestamp_start=timestamp)
    db.session.add(new_activity)
    db.session.commit()
    current_app.logger.debug(f"Started {new_activity} for {current_job}")
    return json.dumps({"success": True, "colour": activity_code.graph_colour})
コード例 #12
0
ファイル: routes.py プロジェクト: DigitME2/oee_server
def edit_machine():
    """The page to edit a machine (also used for creating a new machine)
    This page will allow an ID to be specified for new machines being created, but will not allow the ID
    to be changed for existing machines."""
    form = MachineForm()
    ids = []

    # Get a list of schedules to create form dropdown
    schedules = []
    for s in Schedule.query.all():
        schedules.append((str(s.id), str(s.name)))  # The ID has to be a string to match the data returned from client
    # Add the list of schedules to the form
    form.schedule.choices = schedules

    # Create machine group dropdown
    groups = []
    groups.append(("0", str("No group")))
    for g in MachineGroup.query.all():
        groups.append((str(g.id), str(g.name)))
    form.group.choices = groups

    # Get a list of workflow types to create dropdown
    workflow_types = []
    for t in WorkflowType.query.all():
        workflow_types.append((str(t.id), str(t.name)))
    # Add the list of workflow types to the form
    form.workflow_type.choices = workflow_types

    # If new=true then the request is for a new machine to be created
    if 'new' in request.args and request.args['new'] == "True":
        creating_new_machine = True
    else:
        creating_new_machine = False

    if creating_new_machine:
        # Create a new machine
        machine = Machine(name="", active=True)
        # Add and flush now to retrieve an id for the new entry
        db.session.add(machine)
        db.session.flush()
        message = "Create new machine"

        # Create a list of existing machine IDs to pass to data validation
        for m in Machine.query.all():
            ids.append(m.id)
        # Allow it to accept the id that has just been assigned for the new entry
        if machine.id in ids:
            ids.remove(machine.id)

    # Otherwise get the machine to be edited
    elif 'machine_id' in request.args:
        # Prevent the ID from being edited for existing machines
        form.id.render_kw = {'readonly': True}
        try:
            machine_id = int(request.args['machine_id'])
            machine = Machine.query.get_or_404(machine_id)
        except ValueError:
            current_app.logger.warn(f"Error parsing machine_id in URL. "
                                    f"machine_id provided : {request.args['machine_id']}")
            error_message = f"Error parsing machine_id : {request.args['machine_id']}"
            return abort(400, error_message)
        # Show a warning to the user
        message = f"This machine ID ({machine_id}) can only be set when a new machine is being created. " \
                  "If the machine is no longer needed, deselect \"Active\" for this machine to hide it from the users."

    else:
        error_message = "No machine_id specified"
        current_app.logger.warn("No machine_id specified in URL")
        return abort(400, error_message)

    # Create validators for the form
    # Create a list of existing names and IPs to prevent duplicates being entered
    names = []
    ips = []
    for m in Machine.query.all():
        names.append(str(m.name))
        ips.append(str(m.device_ip))
    # Don't prevent saving with its own current name/IP
    if machine.name in names:
        names.remove(machine.name)
    if machine.device_ip in ips:
        ips.remove(machine.device_ip)
    # Don't allow duplicate machine names
    form.name.validators = [NoneOf(names, message="Name already exists"), DataRequired()]
    # Don't allow duplicate device IPs
    form.device_ip.validators = [NoneOf(ips, message="This device is already assigned to a machine"), DataRequired()]
    # Don't allow duplicate IDs
    form.id.validators = [NoneOf(ids, message="A machine with that ID already exists"), DataRequired()]

    if form.validate_on_submit():
        current_app.logger.info(f"{machine} edited by {current_user}")
        # Save the new values on submit
        machine.name = form.name.data
        machine.active = form.active.data
        machine.workflow_type_id = form.workflow_type.data
        machine.schedule_id = form.schedule.data
        # If no machine group is selected, null the column instead of 0
        if form.group.data == '0':
            machine.group_id = None
        else:
            machine.group_id = form.group.data
        # Save empty ip values as null to avoid unique constraint errors in the database
        if form.device_ip.data == "":
            machine.device_ip = None
        else:
            machine.device_ip = form.device_ip.data

        # If creating a new machine, save the ID and start an activity on the machine
        if creating_new_machine:
            machine.id = form.id.data
            current_app.logger.info(f"{machine} created by {current_user}")
            first_act = Activity(machine_id=machine.id,
                                 timestamp_start=datetime.now().timestamp(),
                                 machine_state=Config.MACHINE_STATE_OFF,
                                 activity_code_id=Config.NO_USER_CODE_ID)
            db.session.add(first_act)
            current_app.logger.debug(f"{first_act} started on machine creation")

        try:
            db.session.add(machine)
            db.session.commit()

        except IntegrityError as e:
            return str(e)

        return redirect(url_for('admin.admin_home'))

    # Fill out the form with existing values to display on the page
    form.id.data = machine.id
    form.active.data = machine.active
    form.schedule.data = str(machine.schedule_id)
    form.group.data = str(machine.group_id)
    form.workflow_type.data = str(machine.workflow_type_id)

    if not creating_new_machine:
        form.name.data = machine.name
        form.device_ip.data = machine.device_ip

    return render_template("admin/edit_machine.html",
                           form=form,
                           message=message)
コード例 #13
0
def machine_activity():
    """ Receives JSON data detailing a machine's activity and saves it to the database
    Assigns a simple activity code depending on machine state
    Example format:
    {
        "machine_id": 1,
        "machine_state": 1,
        "timestamp_start": 1500000000,
        "timestamp_end": 1500000000
    }
    """
    # Return an error if the request is not in json format
    if not request.is_json:
        response = jsonify({"error": "Request is not in json format"})
        response.status_code = 400
        return response

    data = request.get_json()
    # I was getting an issue with get_json() sometimes returning a string and sometimes dict so I did this
    if isinstance(data, str):
        data = json.loads(data)

    # Get all of the arguments, respond with an error if not provided
    if 'machine_id' not in data:
        response = jsonify({"error": "No machine_id provided"})
        response.status_code = 400
        return response
    machine = Machine.query.get(data['machine_id'])
    if machine is None:
        response = jsonify({
            "error":
            "Could not find machine with ID " + str(data['machine_id'])
        })
        response.status_code = 400
        return response

    if 'machine_state' not in data:
        response = jsonify({"error": "No machine_state provided"})
        response.status_code = 400
        return response
    try:
        machine_state = int(data['machine_state'])
    except ValueError:
        response = jsonify({"error": "Could not understand machine_state"})
        response.status_code = 400
        return response

    if 'timestamp_start' not in data:
        response = jsonify({"error": "No timestamp_start provided"})
        response.status_code = 400
        return response
    timestamp_start = data['timestamp_start']

    if 'timestamp_end' not in data:
        response = jsonify({"error": "No timestamp_end provided"})
        response.status_code = 400
        return response
    timestamp_end = data['timestamp_end']

    if not validate_timestamp(timestamp_start) or not validate_timestamp(
            timestamp_end):
        response = jsonify({"error": "Bad timestamp"})
        response.status_code = 400
        return response

    if int(machine_state) == Config.MACHINE_STATE_RUNNING:
        activity_id = Config.UPTIME_CODE_ID
    else:
        activity_id = Config.UNEXPLAINED_DOWNTIME_CODE_ID

    # Create and save the activity
    new_activity = Activity(machine_id=machine.id,
                            machine_state=machine_state,
                            activity_code_id=activity_id,
                            timestamp_start=timestamp_start,
                            timestamp_end=timestamp_end)
    db.session.add(new_activity)
    db.session.commit()

    # Recreate the data and send it back to the client for confirmation
    response = jsonify({
        "machine_id": machine.id,
        "machine_state": new_activity.machine_state,
        "timestamp_start": new_activity.timestamp_start,
        "timestamp_end": new_activity.timestamp_end
    })
    response.status_code = 201
    return response
コード例 #14
0
def setup_database():

    """ Enter default values into the database on its first run"""
    db.create_all()

    create_default_users()

    if len(ActivityCode.query.all()) == 0:

        no_user_code = ActivityCode(id=Config.NO_USER_CODE_ID,
                                    code="NU",
                                    short_description="No User",
                                    long_description="No user is logged onto the machine",
                                    graph_colour="#ffffff")
        db.session.add(no_user_code)

        unexplained_code = ActivityCode(id=Config.UNEXPLAINED_DOWNTIME_CODE_ID,
                                        code="DO",
                                        short_description='Down',
                                        long_description="Downtime that doesn't have an explanation from the user",
                                        graph_colour='#b22222')
        db.session.add(unexplained_code)
        uptime_code = ActivityCode(id=Config.UPTIME_CODE_ID,
                                   code="UP",
                                   short_description='Up',
                                   long_description='The machine is in use',
                                   graph_colour='#00ff80')
        db.session.add(uptime_code)
        setting_code = ActivityCode(id=Config.SETTING_CODE_ID,
                                    code="ST",
                                    short_description="Setting",
                                    long_description="The machine is being set up",
                                    graph_colour="#ff8000")
        db.session.add(setting_code)
        db.session.commit()
        current_app.logger.info("Created default activity codes on first startup")

    if len(Schedule.query.all()) == 0:
        schedule1 = Schedule(name="Default",
                             mon_start=time(hour=6).strftime(SHIFT_STRFTIME_FORMAT),
                             mon_end=time(hour=22).strftime(SHIFT_STRFTIME_FORMAT),
                             tue_start=time(hour=6).strftime(SHIFT_STRFTIME_FORMAT),
                             tue_end=time(hour=22).strftime(SHIFT_STRFTIME_FORMAT),
                             wed_start=time(hour=6).strftime(SHIFT_STRFTIME_FORMAT),
                             wed_end=time(hour=22).strftime(SHIFT_STRFTIME_FORMAT),
                             thu_start=time(hour=6).strftime(SHIFT_STRFTIME_FORMAT),
                             thu_end=time(hour=22).strftime(SHIFT_STRFTIME_FORMAT),
                             fri_start=time(hour=6).strftime(SHIFT_STRFTIME_FORMAT),
                             fri_end=time(hour=22).strftime(SHIFT_STRFTIME_FORMAT),
                             sat_start=time(hour=6).strftime(SHIFT_STRFTIME_FORMAT),
                             sat_end=time(hour=22).strftime(SHIFT_STRFTIME_FORMAT),
                             sun_start=time(hour=6).strftime(SHIFT_STRFTIME_FORMAT),
                             sun_end=time(hour=22).strftime(SHIFT_STRFTIME_FORMAT))
        db.session.add(schedule1)
        db.session.commit()
        current_app.logger.info("Created default schedule on first startup")


    if len(WorkflowType.query.all()) == 0:
        default = WorkflowType(name="Default",
                               description="start job > "
                                           "screen to select machine status with live updates > "
                                           "enter parts >"
                                           "end job")
        db.session.add(default)
        db.session.commit()
        current_app.logger.info("Created default workflow type on first startup")

        pneumatrol1 = WorkflowType(name="Pneumatrol_setting",
                                   description="start job or setting decided by server > "
                                               "active screen with option to pause > "
                                               "pause screen gives option to select reason for pause > "
                                               "resume back to active screen >"
                                               "enter parts >"
                                               "end job")
        db.session.add(pneumatrol1)
        db.session.commit()
        current_app.logger.info("Created pneumatrol_setting workflow type on first startup")

        pneumatrol2 = WorkflowType(name="Pneumatrol_no_setting",
                                   description="start job screen> "
                                               "active screen with option to pause > "
                                               "pause screen gives option to select reason for pause > "
                                               "resume back to active screen >"
                                               "enter parts >"
                                               "end job")
        db.session.add(pneumatrol2)
        db.session.commit()
        current_app.logger.info("Created pneumatrol_no_setting workflow type on first startup")

    if len(MachineGroup.query.all()) == 0:
        group1 = MachineGroup(name="Group 1")
        current_app.logger.info("Created default machine group on first startup")
        db.session.add(group1)
        db.session.commit()

    if len(Machine.query.all()) == 0:
        machine1 = Machine(name="Machine 1",
                           device_ip="127.0.0.1",
                           group_id=1,
                           schedule_id=1)
        db.session.add(machine1)
        db.session.commit()
        current_app.logger.info("Created default machine on first startup")

        act = Activity(machine_id=machine1.id,
                       timestamp_start=datetime.now().timestamp(),
                       machine_state=Config.MACHINE_STATE_OFF,
                       activity_code_id=Config.NO_USER_CODE_ID)
        db.session.add(act)
        db.session.commit()
        current_app.logger.info("Created activity on first startup")
        db.session.commit()

    if len(Settings.query.all()) == 0:
        settings = Settings(threshold=500, dashboard_update_interval_s=10)
        db.session.add(settings)
        db.session.commit()
        current_app.logger.info("Created default settings on first startup")