aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestVersionResponse.cs
blob: 3209b9a2fbdf9555f11506dc1a437538ef008029 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.Transport.Web;

namespace Tango.MachineStudio.Common.Web
{
    public class DownloadLatestVersionResponse : WebResponseMessage
    {
        public String Version { get; set; }

        public String BlobAddress { get; set; }
    }
}
/************************************************************************************************************************
 * Printing.c
 * High managment logical unit of slow motors in the system ( 6 dispensers and the screw motor)
 * profile run up begins from screw homing to begin position and only then from fast motors activation.
 * when every slow motor tuches the limit switch (no matter whether its screw or dispenser)
 * an interrupt occures in the system and as long as its pushing the limit switch all the system is prevented from operation.
 * because of that the work flow with interrupts must be :
	 * design a function handle (what to do in the moment the interrupt arrives)
	 * configure the wanted interrupt in the cfg file (according to the defined port and pin and its interrupt number and the handler)
	 * enable interupt for predefined gpio in the application
	 * when the interrupt arrives the handle will be automatically called
	 * in case of the limit switches since the operation is continuess the interrupt must be disabled in order to continue the application running.
	 * then the operation is not continues (like butten pushing) there is no need in disabling the interrupts

 * Printing module is responsible for :
 	 * operating diffrent winding algorithms with predefined parameters from the UI
 	 * operating the dispensers according to predefined dispensing rate from the UI
 **************************************************************************************************************************/

////////////////////////////////State machine operation////////////////////////////////////
//the state machine operation is used to operate in runtime correct profile flow execution
//by recieved esign flow of the user from the UI
///////////////////////////////////////////////////////////////////////////////////////////
#include <Container.h>
#include <DataDef.h>
#include "include.h"
#include <ti/sysbios/knl/mailbox.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/task.h>

#include "Common/report/report.h"

#include "PMR/Printing/JobSegment.pb-c.h"
#include "PMR/Printing/JobRequest.pb-c.h"
#include "PMR/Printing/JobResponse.pb-c.h"
#include "PMR/Printing/CurrentJobRequest.pb-c.h"
#include "PMR/Printing/CurrentJobResponse.pb-c.h"
#include "PMR/Printing/ResumeCurrentJobRequest.pb-c.h"
#include "PMR/Printing/ResumeCurrentJobResponse.pb-c.h"
#include "PMR/Printing/JobStatus.pb-c.h"
#include "PMR/Printing/AbortJobRequest.pb-c.h"
#include "PMR/Printing/AbortJobResponse.pb-c.h"
#include "PMR/Hardware/Hardwaremotor.pb-c.h"
#include "PMR/Hardware/HardwareWinder.pb-c.h"
#include "PMR/common/MessageContainer.pb-c.h"
#include  "PMR/Diagnostics/EventType.pb-c.h"

#include "Modules/General/process.h"
#include "modules/Diagnostics/Diagnostics.h"

#include "PMR/Stubs/StubJobRequest.pb-c.h"
#include "PMR/Stubs/StubJobResponse.pb-c.h"
#include "PMR/Stubs/StubAbortJobRequest.pb-c.h"
#include "PMR/Stubs/StubAbortJobResponse.pb-c.h"

#include "PMR/Diagnostics/ThreadJoggingRequest.pb-c.h"
#include "PMR/Diagnostics/ThreadJoggingResponse.pb-c.h"
#include "PMR/Diagnostics/ThreadAbortJoggingRequest.pb-c.h"
#include "PMR/Diagnostics/ThreadAbortJoggingResponse.pb-c.h"


#include "./printingSTM.h"
#include "modules/thread/thread_ex.h"
#include "modules/AlarmHandling/AlarmHandling.h"
#include "modules/ids/ids_ex.h"
#include "Modules/heaters/heaters_ex.h"
#include "Modules/control/control.h"


#define MAX_TICKET_SIZE  10000

Mailbox_Handle JobmsgQ = NULL;

JobEndReasonEnum JobEndReason = JOB_OK;
ErrorCode JobError_to_ErrorCode[JOB_ERRORS_MAX+1] = {ERROR_CODE__NONE,ERROR_CODE__JOB_UNSPECIFIED_ERROR,ERROR_CODE__JOB_THREAD_BREAK,ERROR_CODE__JOB_WINDER_DANCER_FAIL,
                                                      ERROR_CODE__JOB_POOLER_DANCER_FAIL,ERROR_CODE__JOB_FEEDER_DANCER_FAIL,ERROR_CODE__JOB_OUT_OF_DYE,ERROR_CODE__JOB_OTHER_ALARM,
                                                      ERROR_CODE__JOB_TEMPERATURE_ALARM,ERROR_CODE__JOB_LS_ALARM,ERROR_CODE__JOB_PRESSURE_ALARM,ERROR_CODE__JOB_CURRENT_ALARM,
                                                      ERROR_CODE__JOB_MOTOR_ALARM,ERROR_CODE__JOB_OTHER_ALARM};

JobTicket *CurrentJob = NULL;
JobRequest *CurrentRequest  = NULL;

double previousJobLength;
uint32_t    StubControlId = 0xFF;
double StubLengthCounter = 0,StubLength = 0,StubSpeed=0;
JobTicket Ticket;
JobSegment *TSegment;
JobSpool *Tspool;
bool CopyConfigured[MAX_SYSTEM_MODULES];
char ErrorMsg[100];


ModuleStateEnum PrepareWaiting[MAX_SYSTEM_MODULES] = {ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle};

/********************************************************************************************
* functions describes motor operation flow and movement state during profile execution
* used to operate in runtime correct profileflow execution
*********************************************************************************************/
//static ReturnCode IdleState(void *JobDetails);
//static ReturnCode ValidateState(void *JobDetails);
static ReturnCode PrepareState(void *JobDetails);
static ReturnCode PrintState(void *JobDetails);
//static ReturnCode CleanState(void *JobDetails);
static ReturnCode ExitState(void *JobDetails);
/**********************************************************************
* the array and enum of JobState_t below must be in sync order
***********************************************************************/
//static ReturnCode (* state[])(void *JobDetails) = { IdleState, ValidateState, PrepareState,  PrintState, CleanState};
void AbortJob(char *Msg);


typedef enum
{
    Idle= 0,
	Validate,
	PrepareJob,
	Print,
	Clean,
	ExitJob
} JobState_t;

typedef struct
{
    JobState_t	m_sourceState;
    ReturnCode   		m_returnCode;
    JobState_t 	m_destinationState;
} Transition_t;


////////////////////////Slow Motor State////////////////////////////////////
char JobToken[36+1]={0};
bool JobAbortedByUser = false;

bool JobActive = false;
bool JobResumed = false;
////////////////////////////////////////////////////////////////////////////
void StartJob(void *JobDetails);


//********************************************************************************************************************
bool JobIsActive(void)
{
    return JobActive;
}
/********************************************************************************************************************
*function describes entry point of motor in profile execution - accelerate from stop position
*function described above used to operate motor operation flow and movement state during profile execution
*********************************************************************************************************************/
/*static ReturnCode IdleState(void *JobDetails)
{
    ReturnCode retcode;
    retcode = JobSuccess;

    return retcode;
}*/
//********************************************************************************************************************
/*static ReturnCode ValidateState(void *JobDetails)
{
    ReturnCode retcode;
    retcode = JobSuccess;

    return retcode;
}*/
//********************************************************************************************************************
bool GetHeatersPrepareWaiting(void)
{
    if (PrepareWaiting[Module_Heaters] == ModuleWaiting)
        return true;
    else
        return false;

}
//********************************************************************************************************************
static ReturnCode PrepareState(void *JobDetails)
{
    ReturnCode retcode;
    retcode = JobSuccess;
    //start (fast??) heating
    DiagnosticsStart();

    if (Configured[Module_IDS])
    {
        PrepareWaiting[Module_IDS] = ModuleWaiting;
    }
    if (Configured[Module_Thread])
    {
        PrepareWaiting[Module_Thread] = ModuleWaiting;
    }
    if (Configured[Module_Winder])
    {
        PrepareWaiting[Module_Winder] = ModuleWaiting;
    }
    if (Configured[Module_Heaters])
    {
        if (HeaterCheckReady() == false) // if heaters are in heating / cooling state we must wait for them
            PrepareWaiting[Module_Heaters] = ModuleWaiting;
    }
    //wait for fast heating to end
    //start other peripheral systems: chiller, waist handling
    //check thread type
    if (Configured[Module_IDS])
    {
        IDSPrepareState(JobDetails);
    }
/*    if (Configured[Module_Heaters])
    {
        //heaters preparation starts on process parameters handling
    }*/
    if (Configured[Module_Thread])
    {
        ThreadPrepareState(CurrentJob);
    }
    if (Configured[Module_Winder])
    {
       if( Winder_Prepare()!= OK)
       {
           SendJobProgress(0.0, 0, false, "Winder prepare failed !!!!");
       }
    }

	return retcode;
}
//********************************************************************************************************************
uint32_t PrepareReady(int ModuleId, ModuleStateEnum result)
{
    int i;
    bool ready = true;
    uint32_t retcode = 0,status = OK;

    JobMessageStruc Message;

    assert (ModuleId<MAX_SYSTEM_MODULES);
    assert (result<=ModuleFail);

    if (JobActive == false)
        return ERROR;
    if (PrepareWaiting[ModuleId] != ModuleWaiting)
    {
        LOG_ERROR (ModuleId, "Message from unrelated module!!");
        return ERROR;
    }

    PrepareWaiting[ModuleId] = result;
    //if (result == ModuleFail) status = ERROR;
    for (i=0;i<MAX_SYSTEM_MODULES ;i++)
    {
        if (PrepareWaiting[i] == ModuleWaiting)
            ready = false;
        if (PrepareWaiting[i] == ModuleFail)
            status = ERROR;
    }
    if ((ready == false)&&(status == OK))
        return OK;
    else
    {
        for (i=0;i<MAX_SYSTEM_MODULES ;i++)
        {
            if (PrepareWaiting[ModuleId] == ModuleWaiting)
                PrepareWaiting[ModuleId] = ModuleDone;
        }
        SendJobProgress(0.0, 0, false, "Prepare Ready");
        if (status == OK)    Message.messageId = PreparationResultsOk;
        else Message.messageId = PreparationResultsFail;
        //memcpy(Message.messageData,JobDetails,MAX_MSG_LEN);
        Message.msglen = 10;
        if (JobmsgQ != NULL)
            retcode = Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT);
    }
    return retcode;
}

//********************************************************************************************************************
static ReturnCode PrintState(void *JobDetails)
{
    ReturnCode retcode;
    retcode = JobSuccess;
    JobMessageStruc Message;
    PrintMessageStruc *PrtMessage = (PrintMessageStruc *)Message.messageData;

        Message.messageId = PrintMessage;
        PrtMessage->messageId = PrintRequest;
        Message.msglen = 10;
        if (JobmsgQ != NULL)
            Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT);

    return retcode;
}

//********************************************************************************************************************
/*static ReturnCode CleanState(void *JobDetails)
{
    ReturnCode retcode;
    retcode = JobSuccess;

    return retcode;
}*/
//********************************************************************************************************************
static ReturnCode ExitState(void *JobDetails)
{
    ReturnCode retcode;
    retcode = JobStop;

    return retcode;
}

/*static void JobClockHandle(UArg arg0)
{
    //Clock_setTimeout(JobClock, 1000);
    //Clock_start(JobClock);

}*/

//********************************************************************************************************************

/*void JobInit(void)
{
    Clock_Params_init(&jobclkParams);
    jobclkParams.period = 0;
    jobclkParams.startFlag = FALSE;
    JobClock = Clock_create(JobClockHandle, 0, &jobclkParams, NULL);
    return ;
}*/
//********************************************************************************************************************
void JobAbortFunc(MessageContainer* requestContainer)
{
    MessageContainer responseContainer;
    uint8_t* container_buffer;


    AbortJobRequest* request = abort_job_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);

    //AbortJob();
    AbortJobResponse response = ABORT_JOB_RESPONSE__INIT;
    responseContainer = createContainer(MESSAGE_TYPE__AbortJobResponse, requestContainer->token, false, &response, &abort_job_response__pack, &abort_job_response__get_packed_size);
    container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));

    size_t container_size = message_container__pack(&responseContainer, container_buffer);
    my_free(responseContainer.data.data);
    SendChars((char*)container_buffer, container_size);
    abort_job_request__free_unpacked(request,NULL);
    JobAbortedByUser = true;
    AbortJob("Job Aborted by user");
    //We keep the job request until it is done


}
//********************************************************************************************************************
uint32_t ThreadJoggingFunc(int speed)
{
    ProcessParameters ProcessParametersCopy;
    uint32_t status = OK;
    if (JobIsActive() == true)
    {
        status = ERROR;
        LOG_ERROR(JobIsActive(),"Jog JobIsActive");
    }
    else
    {
        memcpy(&CopyConfigured,&Configured,sizeof(CopyConfigured));
        //set the job handler to ignore heaters, ids and waste in the state machine
        Configured[Module_Thread] = true;
        Configured[Module_Winder] = true;
        Configured[Module_IDS] = false;
        Configured[Module_Heaters] = false;
        Configured[Module_Waste] = false;
        //set the requested speed without changing other process parameters
        memcpy (&ProcessParametersCopy,&ProcessParametersKeep,sizeof(ProcessParameters));
        if(speed)
            ProcessParametersCopy.dyeingspeed = speed;
        else
            ProcessParametersCopy.dyeingspeed = 40;
        if (HandleProcessParameters(&ProcessParametersCopy)!= OK)
        {
            status = FAILED;
        }
        else
        {
        //load essential job prameters to enable thread running
            Ticket.n_segments = 1;
            Ticket.segments = my_malloc(sizeof(Ticket.segments));
            TSegment = my_malloc(sizeof(JobSegment));
            Tspool = my_malloc(sizeof(JobSpool));
            TSegment->length = 5000.0;
            TSegment->n_brushstops = 0;
            Ticket.segments[0] = TSegment;
            Tspool->backingrate = 30;
            Tspool->bottombackingrate = 18;
            Tspool->segmentoffsetpulses = 1000;
            Tspool->startoffsetpulses = 240;
            Tspool->rotationsperpassage = 3.1415926*2;
            Ticket.spool = Tspool;
            CurrentJob = &Ticket;
            InternalWindingConfigMessage(Tspool);
            StartJob(&Ticket);
        }
    }
    return status;
}
void ThreadJoggingRequestFunc(MessageContainer* requestContainer)
{
    uint32_t status = OK;

    MessageContainer responseContainer;
    ThreadJoggingRequest* request = thread_jogging_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);

    ThreadJoggingResponse response = THREAD_JOGGING_RESPONSE__INIT;

    status = ThreadJoggingFunc(request->speed);

    responseContainer = createContainer(MESSAGE_TYPE__ThreadJoggingResponse, requestContainer->token, true, &response, &thread_jogging_response__pack, &thread_jogging_response__get_packed_size);
    if (status!= OK)
    {
        responseContainer.error = ERROR_CODE__INVALID_PARAMETER;
        responseContainer.errormessage = "JOb Active or incorrect parameters";
    }
//    responseContainer.continuous = false;
    uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    size_t container_size = message_container__pack(&responseContainer, container_buffer);
    SendChars(container_buffer, container_size);
    my_free(responseContainer.data.data);

    return ;

}
void ThreadAbortJoggingFunc(void)
{
    AbortJob(0);
    //set the job handler to handle heaters, ids and waste in the state machine
    Task_sleep(100); //let the job end procedure role before returning the configuration to normal.
    memcpy(&Configured,&CopyConfigured,sizeof(CopyConfigured));
    my_free(Ticket.segments);
    my_free(TSegment);
    my_free(Tspool);

}
void ThreadAbortJoggingRequestFunc(MessageContainer* requestContainer)
{
    //uint32_t status = OK;

    MessageContainer responseContainer;

    ThreadAbortJoggingRequest* request = thread_abort_jogging_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);

    ThreadAbortJoggingResponse response = THREAD_ABORT_JOGGING_RESPONSE__INIT;

    ThreadAbortJoggingFunc();

    responseContainer = createContainer(MESSAGE_TYPE__ThreadAbortJoggingResponse,  requestContainer->token, false, &response, &thread_abort_jogging_response__pack, &thread_abort_jogging_response__get_packed_size);

    responseContainer.continuous = false;
    uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    if (container_buffer)
    {
        size_t container_size = message_container__pack(&responseContainer, container_buffer);
        SendChars(container_buffer, container_size);
    }
    if (responseContainer.data.data)
        my_free(responseContainer.data.data);

    return ;

}

//********************************************************************************************************************
uint32_t SendStubJobProgress(uint32_t IfIndex, uint32_t readValue)
{
    MessageContainer responseContainer;
    uint8_t* container_buffer;
    bool done = false;
//


    //REPORT_MSG(msdid++,logmsg);
    Report("Stub Job",__FILE__,__LINE__,StubLengthCounter,RpWarning,StubLength,  StubSpeed);

    if (JobToken[0] == 0)
        return OK;


    StubJobResponse response = STUB_JOB_RESPONSE__INIT;
    JobStatus jobStatus = JOB_STATUS__INIT;

    jobStatus.has_progress = true;
    jobStatus.progress = StubLengthCounter/100;
    StubLengthCounter += StubSpeed;
    if (StubLengthCounter>=StubLength)
    {
        done = true;
        RemoveControlCallback(StubControlId, SendStubJobProgress);
    }

    jobStatus.has_currentsegmentindex = true;
    jobStatus.currentsegmentindex = 0;

    response.status = &jobStatus;
    responseContainer = createContainer(MESSAGE_TYPE__StubJobResponse, JobToken, done, &response, &stub_job_response__pack, &stub_job_response__get_packed_size);

    container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    if (container_buffer)
    {
        size_t container_size = message_container__pack(&responseContainer, container_buffer);
        SendChars(container_buffer, container_size);
    }
    if (responseContainer.data.data)
        my_free(responseContainer.data.data);

    return OK;
}

void Stub_JobRequest(MessageContainer* requestContainer)
{
    uint32_t status = OK;

    MessageContainer responseContainer;

    StubJobRequest* request = stub_job_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);
    JobTicket *Ticket = request->jobticket;

    StubJobResponse response = STUB_JOB_RESPONSE__INIT;
    JobStatus jobStatus = JOB_STATUS__INIT;
    StubSpeed = Ticket->processparameters->dyeingspeed;
    StubLength  = Ticket->length*100;
    StubLengthCounter = 0;
    ustrncpy (JobToken, requestContainer->token,36);
    StubControlId =  AddControlCallback( SendStubJobProgress, eOneSecond,TemplateDataReadCBFunction,0,0,0);

    jobStatus.has_progress = true;
    jobStatus.progress = 0.0;
    jobStatus.has_currentsegmentindex = false;
    response.status = &jobStatus;
    responseContainer = createContainer(MESSAGE_TYPE__StubJobResponse, JobToken, false, &response, &stub_job_response__pack, &stub_job_response__get_packed_size);
    if (status!= OK)
    {
        responseContainer.error = ERROR_CODE__INVALID_PROCESS_ID;
        responseContainer.errormessage = "JOb Active or incorrect parameters";
    }
//    responseContainer.continuous = false;
    uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    if (container_buffer)
    {
        size_t container_size = message_container__pack(&responseContainer, container_buffer);
        SendChars(container_buffer, container_size);
    }
    if (responseContainer.data.data)
        my_free(responseContainer.data.data);

    return ;

}
void Stub_AbortJobRequest(MessageContainer* requestContainer)
{
    //uint32_t status = OK;

    MessageContainer responseContainer;

    StubAbortJobRequest* request = stub_abort_job_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);

    StubAbortJobResponse response = STUB_ABORT_JOB_RESPONSE__INIT;


    //RemoveControlCallback(StubControlId, SendStubJobProgress);
    StubLength  = 0;
    StubLengthCounter = 10;  //trigger job end message;

    responseContainer = createContainer(MESSAGE_TYPE__StubAbortJobResponse,  requestContainer->token, false, &response, &stub_abort_job_response__pack, &stub_abort_job_response__get_packed_size);

    responseContainer.continuous = false;
    uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    if (container_buffer)
    {
        size_t container_size = message_container__pack(&responseContainer, container_buffer);
        SendChars(container_buffer, container_size);
    }
    if (responseContainer.data.data)
        my_free(responseContainer.data.data);

    return ;

}

//********************************************************************************************************************
void JobRequestFunc(MessageContainer* requestContainer)
{
    uint32_t status = NOT_SUPPORTED;
    MessageContainer responseContainer;
    uint8_t* container_buffer;
    ErrorCode error = ERROR_CODE__NONE;
    JobEndReasonEnum JobAlarmReason = JOB_OK;

    if (JobActive == false)
    {
		LOG_ERROR(JobActive, "Job started while active");
	}
    JobRequest* request = job_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);
    if (request != NULL)
    {
        ustrncpy (JobToken, requestContainer->token,36);
        previousJobLength = 0.0;
        JobTicket *Ticket = request->jobticket;
        int TicketSize = job_ticket__get_packed_size(Ticket);
        if (TicketSize >= MAX_TICKET_SIZE)
        {
            LOG_ERROR (TicketSize, "job ticket message too long");
            status = FAILED;
            error = ERROR_CODE__BAD_CRC;
            usnprintf(ErrorMsg, 100, "job ticket message too long");
        }
        else
        {
            //memcpy(CurrentJob, Ticket,TicketSize);
            CurrentJob = Ticket;
            if (CurrentRequest!= NULL)
                job_request__free_unpacked(CurrentRequest,NULL);
            CurrentRequest = request;

            status  = PASSED;
            JobEndReason = JOB_OK;
            JobAlarmReason = AlarmHandlingPrepareJob(CurrentJob);
            if (JobAlarmReason ==OK)
            {
#warning Process parameters in job request are not handled. push separately for now
                if (Ticket->processparameters)
                {
                    if (HandleProcessParameters(Ticket->processparameters)!= OK)
                    {
                        status = FAILED;
                        error = ERROR_CODE__INVALID_PARAMETER;
                        usnprintf(ErrorMsg, 100, "Hardware Parameters Not Set");
                    }
                }
                REPORT_MSG(0,"Process parameters in job request are not handled. push separately for now");
                if (Ticket->spool)
                {
                    if (InternalWindingConfigMessage(Ticket->spool)!= OK)
                    {
                        status = FAILED;
                        error = ERROR_CODE__INVALID_PARAMETER;
                        usnprintf(ErrorMsg, 100, "spool parameters error");
                    }
                }

            }
            else
            {
                status = FAILED;
                error = JobError_to_ErrorCode[JobAlarmReason];
                usnprintf(ErrorMsg, 100, "Existing alarms prevent running");
            }
        }
        if (status == PASSED)
        {
            Report("Job Request ",__FILE__,__LINE__,Ticket->processparameters->dyeingspeed,RpWarning,Ticket->n_segments, Ticket->intersegmentlength);
            StartJob(CurrentJob);
        }
    }
    else
        status = FAILED;

    JobResponse response = JOB_RESPONSE__INIT;
    JobStatus jobStatus = JOB_STATUS__INIT;
    if (status == PASSED)
    {
        JobResumed = false;
        usnprintf(ErrorMsg, 100, "Job Accepted");

        jobStatus.message =ErrorMsg;
        jobStatus.has_progress = true;
        jobStatus.progress = 0.0;
        jobStatus.has_currentsegmentindex = false;
        response.status = &jobStatus;
        response.has_canceled = false;
        responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, false, &response, &job_response__pack, &job_response__get_packed_size);
        container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    }
    else
    {
        jobStatus.message = ErrorMsg;
        jobStatus.has_progress = true;
        jobStatus.progress = 0.0;
        jobStatus.has_currentsegmentindex = false;
        response.status = &jobStatus;
        response.has_canceled = true;
        response.canceled = true;
        responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, true, &response, &job_response__pack, &job_response__get_packed_size);
        responseContainer.has_error = true;
        responseContainer.error = error;
        container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    }
    if (container_buffer)
    {
        size_t container_size = message_container__pack(&responseContainer, container_buffer);
        my_free(responseContainer.data.data);
        SendChars((char*)container_buffer, container_size);
        //We keep the job request until it is done
        //    job_request__free_unpacked(request,NULL);
    }
}
//********************************************************************************************************************
char logmsg[254];
char infomsg[254];
uint8_t JobStatusBuffer[400];

void SendJobProgress(double ProcessedLength, int SegmentId, bool done, char *Message)
{
    MessageContainer responseContainer;
    uint8_t* container_buffer;

    //int len;
    //static msdid = 0;
    //int length = (int)(ProcessedLength*100);
    //len = usnprintf(logmsg, 254, "MSG: Job Progress Length %d, Seg %d Done %d ",length,  SegmentId,  done);

    //REPORT_MSG(msdid++,logmsg);
    //Report(logmsg,__FILE__,__LINE__,SegmentId,RpWarning,SegmentId,  done);
    /*if (Message)
    {
        strcpy (infomsg,Message);
        Report(infomsg,__FILE__,__LINE__,55,RpWarning,33,  44);
    }*/

    if (JobToken[0] != 0)
    {
        ResumeCurrentJobResponse resumeresponse = RESUME_CURRENT_JOB_RESPONSE__INIT;
        JobResponse response = JOB_RESPONSE__INIT;
        JobStatus jobStatus = JOB_STATUS__INIT;

        if (Message)
        {
            jobStatus.message = Message;
        }
        //previousJobLength =  ProcessedLength;
        jobStatus.has_progress = true;
        jobStatus.progress = TotalProcessedLength;
        jobStatus.has_currentsegmentindex = true;
        jobStatus.currentsegmentindex = SegmentId;

        if (JobResumed == true)
        {
            resumeresponse.status = &jobStatus;
            //responseContainer = createContainer(MESSAGE_TYPE__ResumeCurrentJobResponse,  JobToken, done, &resumeresponse, &resume_current_job_response__pack, &resume_current_job_response__get_packed_size);
            responseContainer = createAllocatedContainer(MESSAGE_TYPE__ResumeCurrentJobResponse,  JobToken, done, &resumeresponse, &resume_current_job_response__pack, &resume_current_job_response__get_packed_size,&JobStatusBuffer);
        }
        else
        {
            response.status = &jobStatus;
            //responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, done, &response, &job_response__pack, &job_response__get_packed_size);
            responseContainer = createAllocatedContainer(MESSAGE_TYPE__JobResponse, JobToken, done, &response, &job_response__pack, &job_response__get_packed_size,&JobStatusBuffer);
        }

        container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
        if (done == true)
        {
            if(JobEndReason != JOB_OK)
            {
                responseContainer.has_error = true;
                responseContainer.error = JobError_to_ErrorCode[JobEndReason];
                switch (JobEndReason)
                {
                    case JOB_THREAD_BREAK:
                        AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_BREAK,true);
                        break;
                    case JOB_POOLER_DANCER_FAIL:
                        AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_PULLER_DANCER,true);
                        break;
                    case JOB_FEEDER_DANCER_FAIL:
                        AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_FEEDER_DANCER,true);
                        break;
                    case JOB_WINDER_DANCER_FAIL:
                        AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_WINDER_DANCER,true);
                        break;
                    default:
                        break;
                }
            }
            if (JobAbortedByUser == true)
            {
                JobAbortedByUser = false;
                responseContainer.has_error = true;
                responseContainer.error = ERROR_CODE__CONTINUOUS_RESPONSE_ABORTED;
            }
        }
        if (container_buffer)
        {
            size_t container_size = message_container__pack(&responseContainer, container_buffer);
            //        if (SendChars(container_buffer, container_size) == false) //comm tx mailbox full
            if (SendCharsWithType(container_buffer, container_size,MESSAGE_TYPE__JobResponse) == false) //comm tx mailbox full
            {
                //AlarmHandlingToken[0] = 0;
                my_free(container_buffer);
            }
        }
    }

    if (done == true)
    {
        if (CurrentRequest!= NULL)
            job_request__free_unpacked(CurrentRequest,NULL);
        JobStopReporting();
        JobMessageStruc JobMessage;

        JobMessage.messageId = PrintingResultsOk;
        JobMessage.msglen = MAX_MSG_LEN;
        if (JobmsgQ != NULL)
            Mailbox_post(JobmsgQ , &JobMessage, BIOS_NO_WAIT);
    }
//    if (responseContainer.data.data)
//        my_free(responseContainer.data.data);
}
void JobStopReporting(void)
{
    JobToken[0] = 0;
}

void AbortJob(char *Msg)
{
    //ReturnCode retcode;
    //retcode = JobSuccess;
    JobMessageStruc Message;
    PrintMessageStruc *PrtMessage = (PrintMessageStruc *)Message.messageData;

        Message.messageId = Abort;
        PrtMessage->messageId = PrintSystemFailure;
        strcpy(PrtMessage->messageData,Msg);
        Message.msglen = 10;
        if (JobmsgQ != NULL)
            Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT);
}
uint32_t    CurrentJobRequestFunc(MessageContainer* requestContainer)
{
    uint32_t status = OK;

    MessageContainer responseContainer;

    CurrentJobRequest* request = current_job_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);

    CurrentJobResponse response = CURRENT_JOB_RESPONSE__INIT;


    if (JobActive == true)
    {
        response.has_isjobinprogress = true;
        response.isjobinprogress = true;
        response.jobticket = CurrentJob;
    }
    else
    {
        response.has_isjobinprogress = true;
        response.isjobinprogress = false;
        response.jobticket = NULL;
    }
    responseContainer = createContainer(MESSAGE_TYPE__CurrentJobResponse,  requestContainer->token, false, &response, &current_job_response__pack, &current_job_response__get_packed_size);
    if (status!= OK)
    {
        responseContainer.error = ERROR_CODE__INVALID_PROCESS_ID;
        responseContainer.errormessage = "JOb Active or incorrect parameters";
    }
    responseContainer.continuous = false;
    uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    if (container_buffer)
    {
        size_t container_size = message_container__pack(&responseContainer, container_buffer);
        SendChars(container_buffer, container_size);
    }
    if (responseContainer.data.data)
        my_free(responseContainer.data.data);

    return OK;
}
uint32_t    ResumeCurrentJobRequestFunc(MessageContainer* requestContainer)
{
    uint32_t status = OK;

    MessageContainer responseContainer;

    ResumeCurrentJobRequest* request = resume_current_job_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);

    ResumeCurrentJobResponse response = RESUME_CURRENT_JOB_RESPONSE__INIT;
    JobStatus jobStatus = JOB_STATUS__INIT;

    ustrncpy (JobToken, requestContainer->token,36);
    JobResumed = true;
    usnprintf(ErrorMsg, 100, "Job Resumeded");

    jobStatus.message =ErrorMsg;
    jobStatus.has_progress = true;
    jobStatus.progress = 0.0;
    jobStatus.has_currentsegmentindex = false;
    response.status = &jobStatus;
    response.has_canceled = false;

    responseContainer = createContainer(MESSAGE_TYPE__ResumeCurrentJobResponse,  JobToken, false, &response, &resume_current_job_response__pack, &resume_current_job_response__get_packed_size);
    if (status!= OK)
    {
        responseContainer.error = ERROR_CODE__INVALID_PROCESS_ID;
        responseContainer.errormessage = "JOb Active or incorrect parameters";
    }
    responseContainer.continuous = false;
    uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer));
    if (container_buffer)
    {
        size_t container_size = message_container__pack(&responseContainer, container_buffer);
        SendChars(container_buffer, container_size);
    }
    if (responseContainer.data.data)
        my_free(responseContainer.data.data);

    return OK;
}


void StartJob(void *JobDetails)
{
    JobMessageStruc Message;

    Message.messageId = JobRequestMsg;
    Message.msglen = MAX_MSG_LEN;
    if (JobmsgQ != NULL)
       Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT);
}

/******************************************************************************
 *  ======== messageTsk ========
 *  Task for this function is created statically. See the project's .cfg file.
 *  this message task is created statically in system initialization,
 ******************************************************************************/
Void jobTask(UArg arg0, UArg arg1)
{
    JobMessageStruc Message;
    //char str[60];
    //uint16_t length;
    //Clock_setTimeout(HostKAClock, 1000);
    //Clock_start(HostKAClock);
    JobmsgQ = Mailbox_create(MAX_MSG_LEN, 20, NULL,NULL);


    while(1)
    {
        Mailbox_pend(JobmsgQ , &Message, BIOS_WAIT_FOREVER);
        switch (Message.messageId)
        {
            case JobRequestMsg:
                JobEndReason = JOB_OK;
                JobActive = true;
                /*ValidateState (CurrentJob);
                break;
            case ValidationResultsOk:*/
                PrepareState (CurrentJob);
                break;
            case ValidationResultsFail:
                //send message data as a validation error message to host
                ExitState(Message.messageData);
                break;
            case PreparationResultsOk:
                PrintState(CurrentJob);
                break;
            case PreparationResultsFail:
                //send message data as a validation error message to host
                EndState(CurrentJob, "Prepare Failed");
                //ExitState(Message.messageData);
                break;
            case PrintMessage:
                //send message data as a validation error message to host
                PrintSTMMsgHandler(&Message);
                break;
            case PrintingResultsOk:
                JobActive = false;
                CurrentJob = NULL;
                  //if (CurrentRequest!= NULL)
                  //    job_request__free_unpacked(CurrentRequest,NULL);
                  CurrentRequest = NULL;
                  SuspendLargeMessages = false;
                  LOG_ERROR(4,"ResumeLargeMessages PrintingResultsOk");
                  //DiagnosticsStart();
                //CleanState(CurrentJob);
                break;
            case PrintingResultsFail:
                JobActive = false;
                CurrentJob = NULL;
                  //if (CurrentRequest!= NULL)
                  //    job_request__free_unpacked(CurrentRequest,NULL);
                  CurrentRequest = NULL;
                  SuspendLargeMessages = false;
                  LOG_ERROR(3,"ResumeLargeMessages PrintingResultsFail");
                  //DiagnosticsStart();

                //send message data as a validation error message to host
                ExitState(Message.messageData);
                break;
            case CleaningResultsOk:
                //send message data as a validation error message to host
                ExitState(Message.messageData);
                break;
            case CleaningResultsFail:
                //send message data as a validation error message to host
                ExitState(Message.messageData);
                break;
            case SystemFailure:
                //send message data as a validation error message to host
                ExitState(Message.messageData);
                break;
            case Abort:
                PrintSTMMsgHandler(&Message);
                break;
            default:
                break;
        }
    }
}