aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Embedded_SW/Embedded/Modules/IDS/IDS_dispenser.c
blob: 6e4eed58043fa82c7319cd7809642bc91413b04e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
generated by cgit v1.3.1 (git 2.54.0) at 2026-08-01 02:37:11 +0000
 


61'>261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
/************************************************************************************************************************
 **************************************************************************************************************************/

#include <DataDef.h>
#include "include.h"

#include "ids.h"
#include "ids_ex.h"

#include "control/control.h"

#include "drivers/Motors/Motor.h"
#include "drivers/valves/valve.h"
#include "PMR/EmbeddedParameters/DispenserRunningData.pb-c.h"
#include "PMR/EmbeddedParameters/DispenserData.pb-c.h"
#include "PMR/EmbeddedParameters/DispenserDataResponse.pb-c.h"
#include "Common/SWUpdate/FileSystem.h"
#include "drivers/Flash_Memory/fatfs/ff.h"

#include "drivers/Flash_ram/FlashProgram.h"

#include "StateMachines/Printing/PrintingSTM.h"

//extern uint32_t DispenserIdToMotorId[MAX_SYSTEM_DISPENSERS];
#define CloseValve MidTank_Dispenser
#define OpenValve Dispenser_Mixer

uint32_t CloseValveTimeout = 10;
uint32_t OpenValveTimeout = 10;
#define DISPENSER_BUILD_PRESSURE_SPEED 940
#define DISPENSER_BUILD_PRESSURE_LIMIT 1.0
#define DISPENSER_BUILD_PRESSURE_TIMEOUT 120000
#define DISPENSER_BUILD_PRESSURE_LAG 50
#define DEFAULT_NANOLITER_PER_PULSE 2.34
uint32_t DispenserPrepareSpeed = DISPENSER_BUILD_PRESSURE_SPEED;
double   DispenserPreparePressure = DISPENSER_BUILD_PRESSURE_LIMIT;
uint32_t DispenserPrepareTimeout = DISPENSER_BUILD_PRESSURE_TIMEOUT;
uint32_t DispenserPrepareTimeLag = DISPENSER_BUILD_PRESSURE_LAG;
uint32_t DispenserPrepareTime[MAX_SYSTEM_DISPENSERS] = {0,0,0,0,0,0,0,0};

int32_t CurrentDispenserSpeed[MAX_SYSTEM_DISPENSERS] = {0, 0, 0, 0, 0, 0, 0, 0,};

callback_fptr DispenserCallback[MAX_SYSTEM_DISPENSERS] = {0, 0, 0, 0, 0, 0, 0, 0,};
uint32_t DispenserControlId[MAX_SYSTEM_DISPENSERS] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

void IDS_Dispenser_SetPrepareValues(    uint32_t DispenserBuildPressureSpeed,   double DispenserBuildPressureLimit, uint32_t DispenserBuildPressureTimeout, uint32_t DispenserBuildPressureLag)
{
     DispenserPrepareSpeed = DispenserBuildPressureSpeed;
     DispenserPreparePressure = DispenserBuildPressureLimit;
     DispenserPrepareTimeout = DispenserBuildPressureTimeout;
     DispenserPrepareTimeLag = DispenserBuildPressureLag;
     Report("IDS_Dispenser_SetPrepareValues ",__FILE__,__LINE__,DispenserPrepareSpeed,RpWarning,(int)(DispenserPreparePressure*100),0);
     Report("IDS_Dispenser_SetPrepareValues ",__FILE__,__LINE__,DispenserPrepareTimeout,RpWarning,(int)DispenserPrepareTimeLag,0);
}
void IDS_Dispenser_SetTimeOutValues(uint32_t CloseTimeout, uint32_t OpenTimeout)
{
#ifndef SPECIAL_DISPENSERS
     CloseValveTimeout = CloseTimeout;
     OpenValveTimeout = OpenTimeout;
#endif
     Report("IDS_Dispenser_SetTimeOutValues ",__FILE__,__LINE__,OpenValveTimeout,RpWarning,(int)CloseValveTimeout,0);
}

//********************************************************************************************************************
int32_t IdsGetMotorSpeed(uint32_t DispenserId)
{
    return  CurrentDispenserSpeed[DispenserId];
}

uint32_t IDS_Dispenser_Build_Pressure_Callback(uint32_t DispenserId, uint32_t ReadValue)
 {
    uint32_t status;
    DispenserPrepareTime[DispenserId]+=DispenserPrepareTimeLag;
    double DispenserPressure = DispenserPreparePressure;

    if (DispenserId == LUBRICANT_DISPENSER)
    {
        DispenserPressure = DispenserPreparePressure/5;
		//lubricant lower pressure buildup
    }

     if ((GetDispenserPressure(DispenserId)>=DispenserPressure)||(DispenserPrepareTime[DispenserId]>=DispenserPrepareTimeout))
     {
         if (DispenserPrepareTime[DispenserId]>=DispenserPrepareTimeout)
             status = ERROR;
         else
             status = OK;
         if (SafeRemoveControlCallback(DispenserControlId[DispenserId], IDS_Dispenser_Build_Pressure_Callback )==OK)
             DispenserControlId[DispenserId] = 0xFF;
         else
             Report("Remove control callback failed",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);
         TimerMotors_t  HW_Motor_Id = DispenserIdToMotorId[DispenserId];
         MotorStop(HW_Motor_Id,Hard_Hiz);
         CurrentDispenserSpeed[DispenserId] = 0;

         if (DispenserCallback[DispenserId])
         {

             DispenserCallback[DispenserId](DispenserId,status);
             DispenserCallback[DispenserId] = 0;
         }
     }
     return status;
}

 uint32_t IDS_Dispenser_Build_Pressure(int DispenserId, callback_fptr callback)
{
    DispenserCallback[DispenserId] = callback;
    Report("IDS_Dispenser_Build_Pressure called  ",__FILE__,__LINE__,(int)DispenserPrepareSpeed,RpWarning,DispenserPrepareTimeLag,0);

    Control3WayValvesWithCallback ((Valves_t)DispenserId, CloseValve, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
    if (DispenserControlId[DispenserId] != 0xFF)
    {
        Report("Cannot Add control callback",__FILE__,(int)DispenserId,GetControlCallbackFuncPtr(DispenserControlId[DispenserId]),RpWarning,(int)DispenserControlId[DispenserId],0);
    }
    DispenserControlId[DispenserId] = AddControlCallback(NULL, IDS_Dispenser_Build_Pressure_Callback, DispenserPrepareTimeLag,TemplateDataReadCBFunction ,DispenserId, DispenserId, 0 );
    if (DispenserControlId[DispenserId] == 0xFF)
        Report("Add control callback failed",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);
    else
    {
        //Report("Add control callback",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);
        DispenserPrepareTime[DispenserId]=0;
        TimerMotors_t  HW_Motor_Id = DispenserIdToMotorId[DispenserId];
        MotorSetDirection(HW_Motor_Id,MotorsCfg[HW_Motor_Id].directionthreadwize);
        MotorSetSpeed(HW_Motor_Id, DispenserPrepareSpeed);
        CurrentDispenserSpeed[DispenserId] = DispenserPrepareSpeed;
    }

    return OK;
}

 uint32_t IDS_Dispenser_StopMotorCallback(uint32_t DispenserId, uint32_t ReadValue)
 {
     Report("IDS_Dispenser_Close_Valve_And_Stop_Motor callback",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)msec_millisecondCounter,0);
     if (SafeRemoveControlCallback(DispenserControlId[DispenserId], IDS_Dispenser_StopMotorCallback )==OK)
         DispenserControlId[DispenserId] = 0xFF;
     else
         Report("Remove control callback failed",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);

     TimerMotors_t  HW_Motor_Id = DispenserIdToMotorId[DispenserId];
     MotorStop(HW_Motor_Id,Hard_Hiz);
     CurrentDispenserSpeed[DispenserId] = 0;

     if (DispenserCallback[DispenserId])
     {
         DispenserCallback[DispenserId](DispenserId,ReadValue);
         DispenserCallback[DispenserId] = 0;
     }
     return OK;
}

 uint32_t IDS_Dispenser_Close_Valve_And_Stop_Motor(int DispenserId, callback_fptr callback)
{
    DispenserCallback[DispenserId] = callback;
    //Report("IDS_Dispenser_Close_Valve_And_Stop_Motor",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)msec_millisecondCounter,0);

    Control3WayValvesWithCallback ((Valves_t)DispenserId, CloseValve, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
    if (DispenserControlId[DispenserId] != 0xFF)
        Report("Cannot Add control callback",__FILE__,(int)DispenserId,GetControlCallbackFuncPtr(DispenserControlId[DispenserId]),RpWarning,(int)DispenserControlId[DispenserId],0);

    DispenserControlId[DispenserId] = AddControlCallback(NULL, IDS_Dispenser_StopMotorCallback, CloseValveTimeout, TemplateDataReadCBFunction,DispenserId, DispenserId, 0 );
    if (DispenserControlId[DispenserId] == 0xFF)
        Report("Add control callback failed",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);
    //else
    //    Report("Add control callback",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);

    return OK;
}

uint32_t IDS_Dispenser_OpenValveCallback(uint32_t DispenserId, uint32_t ReadValue)
{
    //Report("IDS_Dispenser_Start_Motor_and_Open_Valve Callback",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)msec_millisecondCounter,0);

    if (SafeRemoveControlCallback(DispenserControlId[DispenserId], IDS_Dispenser_OpenValveCallback )==OK)
        DispenserControlId[DispenserId] = 0xFF;
    else
        Report("Remove control callback failed",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);

    //Report("Control3WayValvesWithCallback called  ",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)0,0);
    Control3WayValvesWithCallback (DispenserId, OpenValve, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer

    if (DispenserCallback[DispenserId])
    {
        DispenserCallback[DispenserId](DispenserId,ReadValue);
        DispenserCallback[DispenserId] = 0;
    }
    return OK;
}
uint32_t IDS_Dispenser_Start_Motor_and_Open_Valve(int DispenserId, int MotorSpeed, callback_fptr callback)
{
    DispenserCallback[DispenserId] = callback;

    TimerMotors_t  HW_Motor_Id = DispenserIdToMotorId[DispenserId];
    /*if (CurrentDispenserSpeed[DispenserId]) //motor already running
    {
        MotorSetSpeed(HW_Motor_Id, MotorSpeed);
        CurrentDispenserSpeed[DispenserId] = MotorSpeed;
        if (DispenserCallback[DispenserId])
        {
            DispenserCallback[DispenserId](DispenserId,0);
            DispenserCallback[DispenserId] = 0;
        }
    }
    else
    {*/
        MotorSetSpeed(HW_Motor_Id, MotorSpeed);
        CurrentDispenserSpeed[DispenserId] = MotorSpeed;
        if (DispenserControlId[DispenserId] != 0xFF)
            Report("Cannot Add control callback",__FILE__,(int)DispenserId,GetControlCallbackFuncPtr(DispenserControlId[DispenserId]),RpWarning,(int)DispenserControlId[DispenserId],0);
        //Report("IDS_Dispenser_Start_Motor_and_Open_Valve",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)msec_millisecondCounter,0);

        DispenserControlId[DispenserId] = AddControlCallback(NULL, IDS_Dispenser_OpenValveCallback, OpenValveTimeout, TemplateDataReadCBFunction,DispenserId, DispenserId, 0 );
        if (DispenserControlId[DispenserId] == 0xFF)
            Report("Add control callback failed",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);
        //else
        //    Report("Add control callback",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserControlId[DispenserId],0);
    //}

    return OK;
}
DispenserRunningData IDS_Dispenser_Data[MAX_SYSTEM_DISPENSERS];
DispenserData StoreDispenserData;
DispenserRunningData **dispenserdata;
char DispenserStorePath[50] = "0://SysInfo//DispStor.cfg";

void IDS_Dispenser_Content_Init (void)
{
    int i;
    //FRESULT Fresult = FR_OK;
    void* buffer = NULL;
    TimerMotors_t HW_Motor_Id;
    uint32_t Bytes = 0;
    dispenser_data__init(&StoreDispenserData);
    dispenserdata = (DispenserRunningData**)my_malloc(sizeof(DispenserRunningData *)*(MAX_SYSTEM_DISPENSERS));
    for(i=0;i<MAX_SYSTEM_DISPENSERS;i++)
    {
        HW_Motor_Id = DispenserIdToMotorId[i];
        dispenser_running_data__init(&IDS_Dispenser_Data[i]);
        dispenserdata[i] = &IDS_Dispenser_Data[i];
        IDS_Dispenser_Data[i].has_consumedinnanolitter = true;
        IDS_Dispenser_Data[i].has_direction = true;
        IDS_Dispenser_Data[i].has_microsteps = true;
        IDS_Dispenser_Data[i].has_nanolitterperpulse = true;
        IDS_Dispenser_Data[i].has_numberofrefills = true;
        IDS_Dispenser_Data[i].has_totalconsumedinnanolitter = true;
        IDS_Dispenser_Data[i].nanolitterperpulse = DEFAULT_NANOLITER_PER_PULSE;
        IDS_Dispenser_Data[i].microsteps = MotorsCfg[HW_Motor_Id].microstep;
    }
    //==================================

    memcpy(&Bytes,(void *)DISPENSERS_MAP_IN_FLASH,sizeof(Bytes));
    bool havedata = false;
    DispenserData* StoredDispenserData;
    if ((Bytes)&&(Bytes < 500))
    {
        buffer = my_malloc (Bytes);
        if (buffer)
        {
            memcpy(buffer, (void *)(DISPENSERS_MAP_IN_FLASH+4),Bytes);
            StoredDispenserData = dispenser_data__unpack(NULL,Bytes,buffer);
            havedata = true;
            free(buffer);
        }
    }
    /*else
    {
        Fresult = FileRead(DispenserStorePath, &Bytes, &buffer);
        if (Fresult == FR_OK)
        {
            StoredDispenserData = (DispenserRunningData*)buffer;
            havedata = true;
        }
    }*/
    if (havedata == true)
    {
        for(i=0;i<MAX_SYSTEM_DISPENSERS;i++)
        {
            //memcpy (&IDS_Dispenser_Data[i],&StoredDispenserData->dispenserinfo[i],sizeof(DispenserRunningData));
            IDS_Dispenser_Data[i].has_consumedinnanolitter = true;
            IDS_Dispenser_Data[i].has_totalconsumedinnanolitter = true;
            IDS_Dispenser_Data[i].has_direction = true;
            IDS_Dispenser_Data[i].has_microsteps = true;
            IDS_Dispenser_Data[i].has_numberofrefills = true;
            IDS_Dispenser_Data[i].has_nanolitterperpulse = true;
            IDS_Dispenser_Data[i].consumedinnanolitter = StoredDispenserData->dispenserinfo[i]->consumedinnanolitter;
            IDS_Dispenser_Data[i].totalconsumedinnanolitter = StoredDispenserData->dispenserinfo[i]->totalconsumedinnanolitter;
            IDS_Dispenser_Data[i].direction = StoredDispenserData->dispenserinfo[i]->direction;
            IDS_Dispenser_Data[i].microsteps = StoredDispenserData->dispenserinfo[i]->microsteps;
            IDS_Dispenser_Data[i].numberofrefills = StoredDispenserData->dispenserinfo[i]->numberofrefills;
            IDS_Dispenser_Data[i].nanolitterperpulse = StoredDispenserData->dispenserinfo[i]->nanolitterperpulse;
            Report("IDS_Dispenser load data ",__FILE__,i,(int)IDS_Dispenser_Data[i].totalconsumedinnanolitter,RpWarning,(int)IDS_Dispenser_Data[i].consumedinnanolitter,0);
        }
        dispenser_data__free_unpacked(StoredDispenserData,NULL);
    }
    //Report("IDS_Dispenser load data ",__FILE__,__LINE__,(int)Bytes,RpWarning,(int)IDS_Dispenser_Data[0].nanolitterperpulse*100,0);
    return;

    //==================================
}
uint16_t seconds_counter = 0;
bool DispenserDataUpdated = false;
uint32_t IDS_Dispenser_Store_Data (void)
{
    //uint32_t timing =  msec_millisecondCounter;
    FRESULT Status = FR_OK;
    StoreDispenserData.n_dispenserinfo = MAX_SYSTEM_DISPENSERS;
    StoreDispenserData.dispenserinfo = dispenserdata;
    uint8_t dispensers_container_buffer[500];


    size_t response_size;// = sizeof(DispenserRunningData)*8;
    int i;
    for(i=0;i<MAX_SYSTEM_DISPENSERS;i++)
    {
        StoreDispenserData.dispenserinfo[i] = &IDS_Dispenser_Data[i];
        Report("IDS_Dispenser store data ",__FILE__,i,(int)IDS_Dispenser_Data[i].totalconsumedinnanolitter,RpWarning,(int)IDS_Dispenser_Data[i].consumedinnanolitter,0);
    }

//    Report("IDS_Dispenser_Store_Data 0",__FILE__,(int)IDS_Dispenser_Data[0].totalconsumedinnanolitter,(int)IDS_Dispenser_Data[0].consumedinnanolitter,RpWarning,(int)IDS_Dispenser_Data[0].microsteps,0);
//    Report("IDS_Dispenser_Store_Data 4",__FILE__,(int)IDS_Dispenser_Data[4].totalconsumedinnanolitter,(int)IDS_Dispenser_Data[4].consumedinnanolitter,RpWarning,(int)IDS_Dispenser_Data[4].microsteps,0);

    if (JobIsActive()==false)
    {
        response_size = dispenser_data__pack(&StoreDispenserData, dispensers_container_buffer);
        EraseFlashSection(DISPENSERS_MAP_IN_FLASH,response_size+4);
        ReadAppAndProgram(DISPENSERS_MAP_IN_FLASH, 4,&response_size);
        ReadAppAndProgram(DISPENSERS_MAP_IN_FLASH+4, response_size, dispensers_container_buffer);
        //Report("IDS_Dispenser_Store ",__FILE__,__LINE__,(int)response_size,RpWarning,(int)StoreDispenserData.dispenserinfo[4]->nanolitterperpulse *100,0);

        /*Status = FileWrite(IDS_Dispenser_Data,response_size,DispenserStorePath,BIOS_NO_WAIT);
        if (Status == FR_OK)
        {
            DispenserDataUpdated = false;
            REPORT_MSG(msec_millisecondCounter - timing, "Updating dispensers file - time");
        }*/

    }

    return Status;
}
void IDS_Dispenser_Content_Calculation (char DispenserId)
{
    assert (DispenserId<MAX_SYSTEM_DISPENSERS);
    TimerMotors_t HW_Motor_Id = DispenserIdToMotorId[DispenserId];
    if (MotorsCfg[HW_Motor_Id].hardwaremotortype
            != DispenserIdToMotorId[DispenserId])
        return;

    //int dir = (IDS_Dispenser_Data[DispenserId].direction==1)?1:-1;
    //double consumedintimeframe = (double)(CurrentDispenserSpeed[DispenserId])*(double)(IDS_Dispenser_Data[DispenserId].microsteps)*
    //        IDS_Dispenser_Data[DispenserId].nanolitterperpulse ;//* dir;
    //double consumedintimeframe = (double)(CurrentDispenserSpeed[DispenserId]); //pulses only
    //consumedintimeframe = 10+DispenserId;
    IDS_Dispenser_Data[DispenserId].consumedinnanolitter += (CurrentDispenserSpeed[DispenserId]/10);//100 milliseconds ==> speed/10
    if (IDS_Dispenser_Data[DispenserId].consumedinnanolitter<0)
        IDS_Dispenser_Data[DispenserId].consumedinnanolitter = 0;
    if (CurrentDispenserSpeed[DispenserId]>0.1)
    {
        DispenserDataUpdated = true;
        IDS_Dispenser_Data[DispenserId].totalconsumedinnanolitter += (CurrentDispenserSpeed[DispenserId]/10);
        if (seconds_counter%6000 == 0)
        {
            Report("IDS_Dispenser_Data ",__FILE__,DispenserId,(int)IDS_Dispenser_Data[DispenserId].consumedinnanolitter,RpWarning,(int)CurrentDispenserSpeed[DispenserId],0);
        }
    }
    if (DispenserId == 0)
    {
        if ((seconds_counter++>=900)&&(DispenserDataUpdated == true))//9000)// - one hour)
        {
            seconds_counter = 0;
            if (IDS_Dispenser_Data[DispenserId].consumedinnanolitter)
            {
                REPORT_MSG(IDS_Dispenser_Data[DispenserId].consumedinnanolitter,"Saving Dispenser Data" );
            }
            IDS_Dispenser_Store_Data();
        }
    }
}
void DispensersCollectionCall(void)
{
    int i;
    for (i = 0; i<MAX_SYSTEM_DISPENSERS;i++)
    {
        IDS_Dispenser_Content_Calculation(i);
    }
}
void IDS_Dispenser_RefillStarted (char DispenserId,char  MicroSteps)
{
    assert (DispenserId<MAX_SYSTEM_DISPENSERS);
    /*IDS_Dispenser_Data[DispenserId].microsteps = MicroSteps;
    double assumedFlow = IDS_Dispenser_Data[DispenserId].microsteps*IDS_Dispenser_Data[DispenserId].nanolitterperpulse;
    IDS_Dispenser_Data[DispenserId].nanolitterperpulse = assumedFlow;
    IDS_Dispenser_Data[DispenserId].microsteps = 1;
    IDS_Dispenser_Data[DispenserId].direction = 0;*/
    Report("IDS_Dispenser_RefillStarted",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)(CurrentDispenserSpeed[DispenserId]),0);
}
void IDS_Dispenser_RefillEnded (char DispenserId,char  MicroSteps)
{
    assert (DispenserId<MAX_SYSTEM_DISPENSERS);
    //IDS_Dispenser_Data[DispenserId].microsteps = MicroSteps;
    IDS_Dispenser_Data[DispenserId].numberofrefills++;
    //IDS_Dispenser_Data[DispenserId].direction = 1;
    IDS_Dispenser_Data[DispenserId].consumedinnanolitter = 0;
    Report("IDS_Dispenser_RefillEnded",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)IDS_Dispenser_Data[DispenserId].numberofrefills,0);
}
void DispenserDataRequestFunc(MessageContainer* requestContainer)
{
    MessageContainer responseContainer;
    int i;
    //DisconnectRequest* request = disconnect_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);
    DispenserDataResponse response =   DISPENSER_DATA_RESPONSE__INIT;


    response.n_dispenserinfo = MAX_SYSTEM_DISPENSERS;
    response.dispenserinfo = (DispenserRunningData**)my_malloc(sizeof(DispenserRunningData *)*(MAX_SYSTEM_DISPENSERS));
    for(i=0;i<MAX_SYSTEM_DISPENSERS;i++)
    {
        response.dispenserinfo[i] = &IDS_Dispenser_Data[i];
        Report("DispenserDataRequestFunc",__FILE__,__LINE__,(int)response.dispenserinfo[i]->totalconsumedinnanolitter,RpWarning,(int)IDS_Dispenser_Data[i].totalconsumedinnanolitter,0);
    }
    responseContainer = createContainer(MESSAGE_TYPE__DispenserDataResponse, requestContainer->token, true, &response, &dispenser_data_response__pack, &dispenser_data_response__get_packed_size);

    //-------------------------------------------------------------------------------------------
    uint8_t* 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);

}