00001 #include "pw_recorder.h"
00002
00003 #ifdef HAVE_POWERWORLD
00004 #ifndef PWX64
00005
00006 #include <iostream>
00007
00008 EXPORT_CREATE(pw_recorder);
00009 EXPORT_INIT(pw_recorder);
00010 EXPORT_SYNC(pw_recorder);
00011 EXPORT_ISA(pw_recorder);
00012 EXPORT_COMMIT(pw_recorder);
00013 EXPORT_PRECOMMIT(pw_recorder);
00014
00015 CLASS *pw_recorder::oclass = NULL;
00016 pw_recorder *pw_recorder::defaults = NULL;
00017
00018 int pw_recorder::get_pw_values(){
00019 return 1;
00020 }
00021
00022 pw_recorder::pw_recorder(MODULE *module)
00023 {
00024 if (oclass==NULL)
00025 {
00026
00027 oclass = gld_class::create(module,"pw_recorder",sizeof(pw_recorder),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_AUTOLOCK);
00028 if (oclass==NULL)
00029 throw "unable to register class pw_recorder";
00030 else
00031 oclass->trl = TRL_PROVEN;
00032
00033 defaults = this;
00034 if (gl_publish_variable(oclass,
00035 PT_object, "model", get_model_offset(), PT_DESCRIPTION, "pw_model object for the PowerWorld model this recorder is monitoring",
00036 PT_char1024, "outfile", get_outfile_name_offset(), PT_DESCRIPTION, "Output file name",
00037 PT_char256, "obj_class", get_obj_classname_offset(), PT_DESCRIPTION, "PowerWorld object class of object to record",
00038 PT_char1024, "key_strings", get_key_strings_offset(), PT_DESCRIPTION, "Key string values for PowerWorld object to record",
00039 PT_char1024, "key_values", get_key_values_offset(), PT_DESCRIPTION, "Key values for PowerWorld object to record",
00040 PT_char1024, "properties", get_properties_offset(), PT_DESCRIPTION, "Properties desired to record from PowerWorld object",
00041 PT_int64, "interval", get_interval_offset(), PT_DESCRIPTION, "Interval of output for pw_recorder object",
00042 PT_int64, "limit", get_limit_offset(),PT_DESCRIPTION, "Number of data points to write before stopping",
00043 NULL)<1){
00044 char msg[256];
00045 sprintf(msg, "unable to publish properties in %s",__FILE__);
00046 throw msg;
00047 }
00048 memset(this,0,sizeof(pw_recorder));
00049 }
00050 }
00051
00052 int pw_recorder::create(){
00053 return 1;
00054 }
00055
00056 int pw_recorder::init(OBJECT *parent){
00057 char objname[64];
00058
00059
00060 if(0 == model){
00061 if(0 == parent){
00062 gl_error("pw_recorder::init(): object \'%s\' does not specify a model object", gl_name(model, objname, 63));
00063
00064
00065
00066
00067 return 0;
00068 } else {
00069
00070 if(!gl_object_isa(parent, "pw_model")){
00071 gl_error("pw_recorder::init(): parent of '%s' is not a pw_model", gl_name(model, objname, 63) );
00072
00073
00074
00075
00076 return 0;
00077 }
00078 model = parent;
00079 }
00080 } else {
00081
00082 if(!gl_object_isa(model, "pw_model")){
00083 gl_error("pw_recorder::init(): model of '%s' is not a pw_model", gl_name(model, objname, 63) );
00084
00085
00086
00087 return 0;
00088 }
00089 }
00090
00091
00092
00093 if((model->flags & OF_INIT) != OF_INIT){
00094 gl_verbose("pw_recorder::init(): deferring initialization on '%s'", gl_name(model, objname, 63));
00095 return 2;
00096 }
00097
00098
00099
00100 if(0 == key_strings[0]){
00101 gl_error("pw_recorder::init(): key_strings not defined for '%s'", gl_name(model, objname, 63));
00102
00103
00104
00105 return 0;
00106 }
00107
00108
00109 if(0 == key_values[0]){
00110 gl_error("pw_recorder::init(): key_values not defined for '%s'", gl_name(model, objname, 63));
00111
00112
00113
00114 return 0;
00115 }
00116
00117
00118 if(0 == properties[0]){
00119 gl_error("pw_recorder::init(): properties not defined for '%s'", gl_name(model, objname, 63));
00120
00121
00122
00123 return 0;
00124 }
00125
00126
00127
00128 if(0 == build_keys()){
00129 gl_error("pw_recorder::init(): error when building keys for '%s'", gl_name(model, objname, 63));
00130
00131
00132
00133
00134 return 0;
00135 }
00136
00137
00138 cModel = OBJECTDATA(model, pw_model);
00139
00140
00141
00142
00143 if(0 == GPSE()){
00144 gl_error("pw_recorder::init(): error when calling GetParameterSingleElement wrapper function for %s", gl_name(model, objname, 63));
00145
00146
00147
00148
00149 return 0;
00150 }
00151
00152
00153 if(interval < -1){
00154 gl_error("pw_recorder::init(): invalid interval in '%s'", gl_name(model, objname, 63));
00155
00156
00157
00158 return 0;
00159 }
00160
00161
00162 if(interval > 0){
00163 last_write = gl_globalclock - interval;
00164 }
00165
00166
00167 if(limit < 1){
00168 gl_verbose("pw_recorder::init(): '%s' will perform unlimited writes", gl_name(my(), objname, 63));
00169 limit = -1;
00170 }
00171
00172
00173
00174
00175 if(0 == outfile_name[0]){
00176 sprintf(outfile_name, "%s-%u.csv", gl_name(my(), objname, 63), my()->id);
00177 gl_verbose("pw_recorder::init(): '%s' does not define a filename, auto-generating '%s'");
00178 }
00179
00180
00181
00182 outfile = fopen(outfile_name, "w");
00183 if(0 == outfile){
00184 gl_error("pw_recorder::init(): unable to open outfile '%s' for writing", outfile_name);
00185
00186
00187
00188
00189 return 0;
00190 } else {
00191 if(!write_header()){
00192 gl_error("pw_recorder::init(): unable to write header for '%s'", gl_name(my(), objname, 63));
00193
00194
00195
00196
00197 return 0;
00198 }
00199 is_ready = true;
00200 }
00201
00202 return 1;
00203 }
00204
00205 int pw_recorder::precommit(TIMESTAMP t1){
00206
00207 return 1;
00208 }
00209
00210 TIMESTAMP pw_recorder::presync(TIMESTAMP t1){
00211 if(!cModel->get_valid_flag()){
00212 gl_verbose("not fetching voltage due to invalid model state");
00213 } else {
00214 if(0 == GPSE()){
00215 gl_error("pw_load::presync(): GPSE failed");
00216
00217
00218
00219
00220
00221 return TS_INVALID;
00222 }
00223 }
00224
00225
00226 return TS_NEVER;
00227 }
00228
00229 TIMESTAMP pw_recorder::sync(TIMESTAMP t1){
00230 TIMESTAMP rt;
00231 if ((interval > 0) && is_ready && outfile){
00232 if(t1 >= (last_write + interval) ){
00233 interval_write = true;
00234 rt = last_write + interval + interval;
00235 } else {
00236 interval_write = false;
00237 rt = last_write + interval;
00238 }
00239 } else {
00240 rt = TS_NEVER;
00241 }
00242 return rt;
00243 }
00244
00245 TIMESTAMP pw_recorder::postsync(TIMESTAMP t1){
00246 if(0 == interval){
00247 write_line(t1);
00248 }
00249 return TS_NEVER;
00250 }
00251
00252 TIMESTAMP pw_recorder::commit(TIMESTAMP t1, TIMESTAMP t2){
00253 if(outfile && is_ready){
00254 if(interval > 0 && interval_write){
00255 write_line(t1);
00256 interval_write = false;
00257 }
00258 if(interval == -1){
00259 if(strcmp(line_output, last_line_output) != 0){
00260 write_line(t1);
00261 }
00262 }
00263 if(limit > 0 && write_ct >= limit){
00264 is_ready = false;
00265 }
00266
00267 }
00268 return TS_NEVER;
00269 }
00270
00271 int pw_recorder::isa(char *classname){
00272 return 1;
00273 }
00274
00281 int pw_recorder::build_keys(){
00282 char objname[256];
00283 int key_str_ct = 1, key_val_ct = 1, prop_str_ct = 1, i = 0;
00284 int index = 0, len = 0;
00285 char **string_ptrs = 0, **value_ptrs = 0, **prop_ptrs = 0, *context = 0;
00286 _variant_t HUGEP *field_data, HUGEP *value_data;
00287 HRESULT hr;
00288
00289
00290 len = (int)strlen(key_strings);
00291 for(index = 0; index < len; ++index){
00292 if(',' == key_strings[index]){
00293 ++key_str_ct;
00294 }
00295 }
00296
00297
00298 len = (int)strlen(key_values);
00299 for(index = 0; index < len; ++index){
00300 if(',' == key_values[index]){
00301 ++key_val_ct;
00302 }
00303 }
00304
00305
00306 if(0 == key_str_ct){
00307 gl_error("pw_recorder::build_keys(): '%s' did not parse any key strings", gl_name(my(), objname, 255));
00308
00309
00310
00311 return 0;
00312 }
00313 if(0 == key_val_ct){
00314 gl_error("pw_recorder::build_keys(): '%s' did not parse any key values", gl_name(my(), objname, 255));
00315
00316
00317
00318 return 0;
00319 }
00320 if(key_str_ct != key_val_ct){
00321 gl_error("pw_recorder::build_keys(): '%s' has %i key properties and %i key values listed", gl_name(my(), objname, 255), key_str_ct, key_val_ct);
00322
00323
00324
00325 return 0;
00326 }
00327
00328
00329 strncpy(key_strings_copy, key_strings, 1024);
00330 strncpy(key_values_copy, key_values, 1024);
00331
00332 string_ptrs = (char **)malloc(sizeof(char *) * key_str_ct);
00333 value_ptrs = (char **)malloc(sizeof(char *) * key_val_ct);
00334
00335
00336
00337 string_ptrs[0] = strtok_s(key_strings_copy, ",\n\r\t", &context);
00338 for(i = 1; i < key_str_ct; ++i){
00339 string_ptrs[i] = strtok_s(NULL, ",\n\r\t", &context);
00340 }
00341
00342
00343 value_ptrs[0] = strtok_s(key_values_copy, ",\n\r\t", &context);
00344 for(i = 1; i < key_val_ct; ++i){
00345 value_ptrs[i] = strtok_s(NULL, ",\n\r\t", &context);
00346 }
00347
00348 key_count = key_str_ct;
00349
00350
00351 len = (int)strlen(properties);
00352 for(index = 0; index < len; ++index){
00353 if(',' == properties[index]){
00354 ++prop_str_ct;
00355 }
00356 }
00357
00358 prop_count = prop_str_ct;
00359
00360 strncpy(props_copy, properties, 1024);
00361
00362 prop_ptrs = (char **)malloc(sizeof(char *) * prop_count);
00363 out_values = (char **)malloc(prop_count * 64);
00364
00365
00366 prop_ptrs[0] = strtok_s(props_copy, ",\n\r\t", &context);
00367 for(i = 1; i < prop_str_ct; ++i){
00368 prop_ptrs[i] = strtok_s(NULL, ",\n\r\t", &context);
00369 }
00370
00371
00372
00373 bounds[0].lLbound = 0;
00374 bounds[0].cElements = key_count + prop_count;
00375
00376 type_bstr = _com_util::ConvertStringToBSTR(obj_classname);
00377
00378 try {
00379
00380 fields.vt = VT_ARRAY | VT_VARIANT;
00381 fields.parray = SafeArrayCreate(VT_VARIANT, 1, bounds);
00382 if(!fields.parray){
00383 throw _com_error(E_OUTOFMEMORY);
00384 }
00385
00386
00387 hr = SafeArrayAccessData(fields.parray, (void HUGEP **)&field_data);
00388 if(FAILED(hr)){
00389 throw _com_error(E_OUTOFMEMORY);
00390 }
00391
00392 for(index = 0; index < key_count; ++index){
00393 field_data[index] = string_ptrs[index];
00394 }
00395
00396 for(; index < key_count + prop_count; ++index){
00397 field_data[index] = prop_ptrs[index-key_count];
00398 }
00399 SafeArrayUnaccessData(fields.parray);
00400 }
00401 catch(_com_error err){
00402
00403 std::cout << "!!! " << err.ErrorMessage() << "\n";
00404 return 0;
00405 }
00406 catch(...){
00407 gl_error("Unknown exception in pw_recorder::build_keys()!");
00408
00409
00410
00411
00412 return 0;
00413 }
00414
00415 try {
00416
00417 values.vt = VT_ARRAY | VT_VARIANT;
00418 values.parray = SafeArrayCreate(VT_VARIANT, 1, bounds);
00419 if(!values.parray){
00420 throw _com_error(E_OUTOFMEMORY);
00421 }
00422
00423
00424 hr = SafeArrayAccessData(values.parray, (void HUGEP **)&value_data);
00425 if(FAILED(hr)){
00426 throw _com_error(E_OUTOFMEMORY);
00427 }
00428
00429 for(index = 0; index < key_count; ++index){
00430 value_data[index] = value_ptrs[index];
00431 }
00432
00433 for(; index < key_count + prop_count; ++index){
00434 value_data[index] = _variant_t();
00435 }
00436 SafeArrayUnaccessData(values.parray);
00437
00438 }
00439 catch(_com_error err){
00440
00441 std::cout << "!!! " << err.ErrorMessage() << "\n";
00442 return 0;
00443 }
00444 catch(...){
00445 gl_error("Unknown exception in pw_recorder::build_keys()!");
00446
00447
00448
00449
00450 return 0;
00451 }
00452
00453
00454
00455 return 1;
00456 }
00457
00464 int pw_recorder::GPSE(){
00465 _variant_t HUGEP *pResults, HUGEP *pData;
00466 _variant_t results, data;
00467 char output[2048];
00468 char *tempstr;
00469 HRESULT hr;
00470 int i;
00471 bool first = true;
00472
00473 memset(output, 0, sizeof(output));
00474 try{
00475 ISimulatorAutoPtr SimAuto(cModel->A);
00476 results = SimAuto->GetParametersSingleElement(type_bstr, fields, values);
00477
00478 hr = SafeArrayAccessData(results.parray, (void HUGEP **)&pResults);
00479
00480 if (((_bstr_t)(_variant_t)pResults[0]).length()){
00481 tempstr = _com_util::ConvertBSTRToString((_bstr_t)(_variant_t)pResults[0]);
00482 gl_error("Error from GetParametersSingleElement(): %s", tempstr);
00483
00484
00485
00486
00487 delete [] tempstr;
00488 tempstr = 0;
00489 SafeArrayDestroy(fields.parray);
00490 SafeArrayDestroy(values.parray);
00491 return 0;
00492 }
00493
00494 hr = SafeArrayAccessData(pResults[1].parray, (void HUGEP **)&pData);
00495 first = true;
00496 for(i = key_count; i < prop_count + key_count; ++i){
00497 tempstr = _com_util::ConvertBSTRToString(pData[i].bstrVal);
00498 if(!first){
00499 strcat(output, ",");
00500 } else {
00501 first = false;
00502 }
00503 strcat(output, tempstr);
00504 delete [] tempstr;
00505 }
00506 SafeArrayUnaccessData(pResults[1].parray);
00507 SafeArrayUnaccessData(results.parray);
00508 }
00509 catch(...){
00510 ;
00511 }
00512 strncpy(line_output, output, sizeof(line_output));
00513 return 1;
00514 }
00520 int pw_recorder::write_header(){
00521 char namebuf[64];
00522 time_t now = time(NULL);
00523
00524 fprintf(outfile, "# file...... %s\n", (const char*)outfile_name);
00525 fprintf(outfile, "# date...... %s", asctime(localtime(&now)));
00526 #ifdef WIN32
00527 fprintf(outfile, "# user...... %s\n", getenv("USERNAME"));
00528 fprintf(outfile, "# host...... %s\n", getenv("MACHINENAME"));
00529 #else
00530 fprintf(outfile, "# user...... %s\n", getenv("USER"));
00531 fprintf(outfile, "# host...... %s\n", getenv("HOST"));
00532 #endif
00533 fprintf(outfile, "# model..... %s\n", gl_name(model, namebuf, 63));
00534 fprintf(outfile, "# interval.. %d\n", interval);
00535 fprintf(outfile, "# limit..... %d\n", limit);
00536 fprintf(outfile, "# key_str... %s\n", (const char*)key_strings);
00537 fprintf(outfile, "# key_val... %s\n", (const char*)key_values);
00538 fprintf(outfile, "# timestamp,%s\n", (const char*)properties);
00539 return 1;
00540 }
00541
00542 int pw_recorder::write_line(TIMESTAMP t1){
00543 DATETIME dt;
00544 char256 time_output;
00545
00546 gl_localtime(t1, &dt);
00547 gl_strtime(&dt, time_output, sizeof(time_output));
00548 fprintf(outfile, "%s,%s\n",(const char *)time_output, (const char*)line_output);
00549 fflush(outfile);
00550 last_line_output.copy_from(line_output);
00551
00552 ++write_ct;
00553 last_write = t1;
00554 return 1;
00555 }
00556
00557 #endif //PWX64
00558 #endif //HAVE_POWERWORLD
00559