Generating Timestamp Data
generateEspressoRecords.c
This program takes these command line arguments:
- Store Id of the coffee store the machine belongs to
- The model number of the coffee machine
- The percentage that an coffee machine shot fails
- The number of shots (on average) the coffee machine makes per hour
- The deviation between the shot rate
- The clean rate of the machine (in fractions of an hour)
The clean rate determines the amount of time it takes for a coffee machine to start
a clean cycle in fractions of an hour. So 0.2 means 0.2 * 60 = 12
. This means there will be roughly 12 minutes between the clean cycles on a coffee machine.
To begin, a Timeseries is created and inserted into GridDB
GSTimeseries* coffeeMachine = makeEspressoMachine(gridstore, argv[2]);
// Setup Timestamp Column Schema columnInfo.name = "timestamp"; // Timestamp column columnInfo.type = GS_TYPE_TIMESTAMP; …. columnInfo.name = "event_type"; // An espresso shot is classified 3 ways: as a SUCCESS, as a FAILURE, or CLEAN cycle columnInfo.type = GS_TYPE_INTEGER; …. columnInfo.name = "temperature"; // Water temperature of the espresso shot columnInfo.type = GS_TYPE_FLOAT; …. columnInfo.name = "pressure"; // Water pressure of the current espresso shot columnInfo.type = GS_TYPE_FLOAT; …. containerInfo.type = GS_CONTAINER_TIME_SERIES;
The schema creation and insertion into GridDB is similar to the other containers in
Container
creation.
The coffee store container that belongs to will also need to be fetched as well. This
will be used for updating the cycle counts.
gsGetCollectionGeneral(gridstore,argv[1],&coffeeStore);
From there the machine setting arguments are retrieved and parsed and an infinite cycle espresso
cycle begins.
espressoCycle(coffeeMachine,coffeeStore,argv[2],shotsPerHour,standard_deviation, \ DEFAULT_TEMPERATURE,DEFAULT_PRESSURE,failure_rate,clean_rate);
srand((unsigned) time(&timer)); direction = rand(); pressure_direction = rand(); offset = rand() % (MAX_OFFSET + 1); pressure_offset = (float) (rand() % (PRESSURE_OFFSET + 1)) / 100.0; if (direction % 2 == 1) offset = offset * -1; if (pressure_direction % 2 == 1) pressure_offset = pressure_offset * -1.0; pressure = average_pressure + pressure_offset; temperature = average_temperature + offset; if(currentCycle % secondsToCleanCycle == 0 && currentCycle > 0) makeEspressoRecord(basetime,espressoMachine,coffeeStore, \ serial_num,temperature,pressure,failure_rate,seed,true); else makeEspressoRecord(basetime,espressoMachine,coffeeStore, \ serial_num,temperature,pressure,failure_rate,seed,false); basetime = gsAddTime(basetime,secondsPerShot, GS_TIME_UNIT_SECOND); seed += secondsPerShot; currentCycle++; // Move to next cycle newShotRate = (int) adjustedShotsperHour(shotRate,standard_deviation, seed); secondsPerShot = calculateSecondsPerShot(newShotRate,standard_deviation, \ seed); sleep(secondsPerShot); // Wait the waiting time between shots
The shot rate determine the relative wait time in seconds between an espresso shot,
as seen with the sleep function use. The clean rate determines the amount of seconds
between clean cycles. The makeEspressoRecord
function which makes timestamp record
marked with the current time. This functions generates random data to insert as timestamp
records GridDB. The temperature and pressure use random number generators to determine a
random number to determine how much to offset a temperature (positive or negative) by a
set constant mean. The method for determining the amount of seconds between shots is the
same as in preload.c
float recorded_temperature = (float) gaussian_number(average_temperature,SIGMA,seed); float recorded_pressure = (float) \ gaussian_number(average_pressure,PRESSURE_SIGMA,seed); int eventState; // Determine which cycle the current cycle if(isCleanCycle) eventState = CLEAN; else eventState = determineEspressoSuccess(failure_rate,seed); …. gsSetRowFieldByTimestamp(espressoShotRecord,0,timestamp); // Set the timestamp gsSetRowFieldByInteger(espressoShotRecord,1,eventState); // Set the eventType gsSetRowFieldByFloat(espressoShotRecord,2,recorded_temperature); gsSetRowFieldByFloat(espressoShotRecord,3,recorded_pressure); gsPutRow(espressoMachine,NULL,espressoShotRecord,NULL); // Insert row into TimeSeries gsCloseRow(&espressoShotRecord); updateMachineCycles(coffeeStore,serialNumber,isCleanCycle);
The record generation begins by generating a random temperature and a random pressure using the gsl library and if it is not time for a clean cycle, using a another random call to determine if the espresso shot was a successful shot or a failure. From there all the row fields can be set and the row is inserted into GridDB. Also since a shot has been made the coffee machine record in the coffee store must be updated as well.
gsGetRowFieldAsInteger(machineRecord,3,&new_cycles); gsGetRowFieldAsInteger(machineRecord,4,&clean_cycles); gsSetRowFieldByInteger(machineRecord,3,++new_cycles); if(resetCleanCycle) // If the last cycle was a clean cycle gsSetRowFieldByInteger(machineRecord,4,0); // Reset clean cycle count to zero else gsSetRowFieldByInteger(machineRecord,4,++clean_cycles); // Update clean cycles gsPutRow(coffeeStore,NULL,machineRecord,NULL); // Update row
This method uses the serial number of the coffee machine as the row key.
From there row’s can be fetched by there row key’s a string-type in gsGetRowByString
.
The new and clean cycles can be fetched and set by incrementing them.
Once those row fields are set the new and updated row can be put back into GridDB with gsPutRow
.
preloadRecords.c
This programs takes the same command line arguments as generateEspressoRecords.c
with
addition to one more argument: days to preload.
Days to preload determines how many days before the current time the program will generate records for.
If you specify five days, with the machine settings that were provided, the program will generate 5
days worth of records for a coffee machine and insert them all into GridDB.
The records are generated the same way with the makeEspressoRecord
function with the exception
of the timestamp recording being a time in the past rather than a current time.
GSTimestamp timeToInsert = gsAddTime(gsCurrentTime(),-1 * days, GS_TIME_UNIT_DAY); GSTimestamp timeToStopAt = gsCurrentTime(); while(timeToInsert < timeToStopAt){ if(currentSeconds % secondsToCleanCycle == 0 && currentSeconds > 0) makeEspressoRecord(timeToInsert,espressoMachine,coffeeStore,serial_num, \ average_temperature,average_pressure,failure_rate,currentSeconds,true); else makeEspressoRecord(timeToInsert,espressoMachine,coffeeStore,serial_num,\ average_temperature,average_pressure,failure_rate,currentSeconds,false); ….. timeToInsert = gsAddTime(timeToInsert,secondsPerShot, GS_TIME_UNIT_SECOND);
The starting time uses the gsAddTime
to offset the current time by a day.
The stopping time will be the current time. The shot rate determines the amount of records to be generated
and the time difference between them. After a record is created and inserted into GridDB, the timestamp
for the next record adds a certain amount of seconds of the past record. This process will repeat until
the next timestamp to insert reaches or is greater than the current time.
reset.sh / reset.c
The reset program is for removing all the data from a coffee chain. This extends to all the coffee stores, the coffee machine containers and all the timestamp records they contain. The process begins by finding the coffee chain container. From there it locates all the coffee store id’s of all the coffee stores in the coffee chain. From there all the coffee machines in each coffee store are dropped from GridDB. After that the coffee stores then the coffee chain can be dropped as well.
gsGetCollectionGeneral(gridstore,argv[1],&coffee_chain); // Get chain …. while(gsHasNextRow(rowSet)){ // Get all coffee stores in chain …. gsGetNextRow(rowSet,row); // Get coffee store gsGetRowFieldAsString(row,0,&container_name); // Obtain store id gsGetCollectionGeneral(gridstore,container_name,&coffee_store); // Get store … while(gsHasNextRow(innerRs)){ // Get all coffee machines in store gsGetRowFieldAsString(storeEntry,0,&serial_num); // Obtain serial number gsDropTimeSeries(gridstore,serial_num); // Drop the corresponding TimeSeries …. gsDropCollection(gridstore,container_name);// Drop coffee store …. gsDropCollection(gridstore,argv[1]); // Drop coffee chain
Source Code
You can download the application and its source code for the data generating client and data visualisation component from the link below:
Download: datavisualisation_application.tar.gz