Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
wifi_events.cpp
00001 #include "cisme.h" 00002 #include "wifi_events.h" 00003 #include "wifi.h" 00004 #include "debug.h" 00005 #include "pb_encode.h" 00006 #include "pb_decode.h" 00007 #include "messages.pb.h" 00008 #include "light.h" 00009 #include "pump.h" 00010 #include "presens.h" 00011 #include "calibration.h" 00012 #include "experiments.h" 00013 #include "battery.h" 00014 00015 #ifdef USE_WIFI 00016 00017 #define FILE_BLOCK_SIZE 128 00018 00019 // Struct to encode payload in generic message 00020 typedef struct { 00021 const pb_field_t* fields; 00022 void* msg; 00023 } PbEncodeMessage; 00024 00025 // Struct to get payload from generic message 00026 typedef struct { 00027 uint8_t* msg; 00028 size_t msgLen; 00029 } PbDecodeMessage; 00030 00031 typedef bool (*Encoder)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); 00032 00033 char startErrors = 0; 00034 00035 // Files data 00036 static int32_t fileId; 00037 static int32_t blockId; 00038 static FILE* curFile; 00039 static uint32_t fileLen; 00040 static int32_t numBlocks; 00041 00042 // Experiments data 00043 static int currentExpId; 00044 static bool isExpExecuting; 00045 00046 static LocalFileSystem local("local"); 00047 00048 static void wifiEventsSendFinishExpInd(int32_t id, char* fileName); 00049 00050 static int getNoSetBits(int value) 00051 { 00052 int result = 0; 00053 00054 while (value != 0) { 00055 value &= (value - 1); 00056 result++; 00057 } 00058 00059 return result; 00060 } 00061 00062 static bool pbEncodeMsg(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) 00063 { 00064 if (!pb_encode_tag_for_field(stream, field)) { 00065 return false; 00066 } 00067 00068 if (*arg == NULL) { 00069 pb_encode_varint(stream, 0); 00070 return true; 00071 } 00072 00073 PbEncodeMessage* message = (PbEncodeMessage*)*arg; 00074 00075 if (!pb_encode_submessage(stream, message->fields, message->msg)) { 00076 return false; 00077 } 00078 00079 return true; 00080 } 00081 00082 static bool pbDecodeMsg(pb_istream_t* stream, const pb_field_t* field, void** arg) 00083 { 00084 uint8_t* src = (uint8_t*)stream->state; 00085 00086 PbDecodeMessage* message = (PbDecodeMessage*)*arg; 00087 message->msg = (uint8_t*)stream->state; 00088 message->msgLen = stream->bytes_left; 00089 stream->bytes_left = 0; 00090 stream->state = src + message->msgLen; 00091 00092 return true; 00093 } 00094 00095 static bool pbEncodeString(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) 00096 { 00097 char* str = (char*)*arg; 00098 00099 if (!pb_encode_tag_for_field(stream, field)) { 00100 return false; 00101 } 00102 00103 if (!pb_encode_string(stream, (uint8_t*)str, strlen(str))) { 00104 return false; 00105 } 00106 00107 return true; 00108 } 00109 00110 static bool pbEncodeErrors(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) 00111 { 00112 static const char* errorsText[4] = {"Low battery level. Device will be disabled soon.", 00113 "Zero pump RPM. Please, check RPM wire.", 00114 "Failed to read isfet.sys file.", 00115 "Failed to read dsparams.sys file." 00116 }; 00117 int errorNo = 0; 00118 char errorList = **((char**)arg); 00119 00120 while ((1 << errorNo) <= errorList) { 00121 if ((errorList & (1 << errorNo)) == 0) { 00122 errorNo++; 00123 continue; 00124 } 00125 00126 pbEncodeString(stream, field, (void**)&(errorsText[errorNo])); 00127 errorNo++; 00128 } 00129 00130 return true; 00131 } 00132 00133 static bool pbEncodeFiles(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) 00134 { 00135 DIR* dir = opendir("/msc/data/"); 00136 struct dirent* entry = NULL; 00137 00138 while ((entry = readdir(dir)) != NULL) { 00139 if (strstr(entry->d_name, ".csv") == NULL) { 00140 continue; 00141 } 00142 00143 if (!pb_encode_tag_for_field(stream, field)) { 00144 return false; 00145 } 00146 00147 if (!pb_encode_string(stream, (uint8_t*)entry->d_name, strlen(entry->d_name))) { 00148 return false; 00149 } 00150 } 00151 00152 return true; 00153 } 00154 00155 static bool pbEncodeFileBlock(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) 00156 { 00157 if (!pb_encode_tag_for_field(stream, field)) { 00158 return false; 00159 } 00160 00161 uint64_t size = (blockId < numBlocks) ? FILE_BLOCK_SIZE : (fileLen % FILE_BLOCK_SIZE); 00162 00163 if (!pb_encode_varint(stream, size)) { 00164 return false; 00165 } 00166 00167 if (stream->callback != NULL) { 00168 size_t result = fread(stream->state, 1, size, curFile); 00169 if (result != size) { 00170 return false; 00171 } 00172 00173 uint8_t* src = (uint8_t*)stream->state; 00174 stream->state = src + size; 00175 } 00176 00177 stream->bytes_written += size; 00178 00179 return true; 00180 } 00181 00182 static bool pbDecodeString(pb_istream_t* stream, const pb_field_t* field, void** arg) 00183 { 00184 char* str = (char*)*arg; 00185 size_t len = stream->bytes_left; 00186 00187 if (!pb_read(stream, (uint8_t*)str, len)) { 00188 return false; 00189 } 00190 00191 str[len] = '\0'; 00192 00193 return true; 00194 } 00195 00196 static bool pbDecodeProgramSteps(pb_istream_t* stream, const pb_field_t* field, void** arg) 00197 { 00198 uint8_t* stepIx = (uint8_t*)*arg; 00199 00200 cisme_startExperimentMsg_Step stepMsg = cisme_startExperimentMsg_Step_init_default; 00201 00202 if (!pb_decode(stream, cisme_startExperimentMsg_Step_fields, &stepMsg)) { 00203 return false; 00204 } 00205 00206 if (!stepMsg.has_duration) { 00207 return false; 00208 } 00209 00210 DEBUG1("Program step: lightLevel=%d, duration=%d, phCutoff=%2.3f, o2Cutoff=%3.0f", 00211 stepMsg.lightLevel, stepMsg.duration, stepMsg.phCutoff, stepMsg.o2Cutoff); 00212 00213 pgm[*stepIx][1] = stepMsg.lightLevel; 00214 pgm[*stepIx][2] = stepMsg.duration; 00215 pgm[*stepIx][3] = stepMsg.phCutoff; 00216 pgm[*stepIx][4] = stepMsg.o2Cutoff; 00217 if (stepMsg.has_pumpSpeed) { 00218 pgm[*stepIx][0] = stepMsg.pumpSpeed; 00219 } 00220 00221 (*stepIx)++; 00222 return true; 00223 } 00224 00225 // Encode and send message to app 00226 static void wifiEventsSendMsg(cisme_MessageType type, const pb_field_t* fields, void* msg) 00227 { 00228 static uint8_t msgBuffer[WIFI_MESSAGE_MAX_LENGTH]; 00229 00230 cisme_genericMsg genericMsg = cisme_genericMsg_init_default; 00231 genericMsg.type = type; 00232 genericMsg.payload.funcs.encode = &pbEncodeMsg; 00233 pb_ostream_t stream = pb_ostream_from_buffer(msgBuffer, WIFI_MESSAGE_MAX_LENGTH); 00234 00235 if (fields != NULL && msg != NULL) { 00236 PbEncodeMessage message = {fields, msg}; 00237 genericMsg.payload.arg = &message; 00238 } 00239 00240 if (!pb_encode(&stream, cisme_genericMsg_fields, &genericMsg)) { 00241 ERROR("Failed to encode message"); 00242 return; 00243 } 00244 00245 if (debugGetCurrLvl() >= DEBUG_LEVEL_2) { 00246 DEBUG2("Start of message----------------------------------------------"); 00247 for (int sendByteIt= 0; sendByteIt < stream.bytes_written; sendByteIt++) { 00248 DEBUG2("Byte %d=%d", sendByteIt, msgBuffer[sendByteIt]); 00249 } 00250 DEBUG2("End of message----------------------------------------------"); 00251 } 00252 00253 wifiSendMessage(msgBuffer, stream.bytes_written); 00254 00255 wait(WIFI_COMM_TIME / 1000.0); 00256 } 00257 00258 // Collect data and send heartbeat message 00259 static void wifiEventsSendBeatInd(void) 00260 { 00261 if (isExpExecuting) { 00262 return; 00263 } 00264 00265 cisme_beatDataMsg beatMsg = cisme_beatDataMsg_init_default; 00266 beatMsg.has_battery = true; 00267 beatMsg.has_temperature = true; 00268 beatMsg.has_ph = true; 00269 beatMsg.has_o2 = true; 00270 beatMsg.has_lightLevel = true; 00271 beatMsg.has_pumpRpm = true; 00272 00273 beatMsg.battery = batteryGet(); 00274 00275 float presensData[PRESENS_RES_LENGTH]; 00276 presensGetData(presensData); 00277 beatMsg.temperature = PHTEMP; 00278 beatMsg.ph = pHCorrected; 00279 beatMsg.o2 = presensData[2]; 00280 beatMsg.lightLevel = lightRead(); 00281 beatMsg.pumpRpm = pumpSpeed(); 00282 00283 DEBUG1("Send BEAT_DATA_IND: battery=%3.1f, temperature=%2.1f, ph=%3.2f, o2=%3.0f, lightLevel=%d, pumpRpm=%d", 00284 beatMsg.battery, beatMsg.temperature, beatMsg.ph, beatMsg.o2, beatMsg.lightLevel, beatMsg.pumpRpm); 00285 wifiEventsSendMsg(cisme_MessageType_BEAT_DATA_IND, cisme_beatDataMsg_fields, &beatMsg); 00286 } 00287 00288 // Send instrument identifier to app 00289 static void wifiEventsHandleIdReq(void) 00290 { 00291 DEBUG1("Receive INSTRUMENT_ID_REQ"); 00292 00293 cisme_instrumentIdMsg idRsp = cisme_instrumentIdMsg_init_default; 00294 idRsp.id.funcs.encode = &pbEncodeString; 00295 idRsp.id.arg = instrumentId; 00296 00297 DIR* dir = opendir("/local"); 00298 struct dirent* entry = NULL; 00299 while ((entry = readdir(dir)) != NULL) { 00300 DEBUG1("binary=%s", entry->d_name); 00301 if (strstr(entry->d_name, ".BIN") == NULL) { 00302 continue; 00303 } 00304 00305 idRsp.binary.funcs.encode = &pbEncodeString; 00306 idRsp.binary.arg = entry->d_name; 00307 break; 00308 } 00309 00310 00311 static char buildTime[sizeof(__DATE__) + sizeof(__TIME__) + 1]; 00312 sprintf(buildTime, "%s %s", __DATE__, __TIME__); 00313 idRsp.timestamp.funcs.encode = &pbEncodeString; 00314 idRsp.timestamp.arg = buildTime; 00315 00316 char* name = entry->d_name; 00317 DEBUG1("Send INSTRUMENT_ID_RSP: id=%s, binary=%s, timestamp=%s", instrumentId, name, buildTime); 00318 00319 wifiEventsSendMsg(cisme_MessageType_INSTRUMENT_ID_RSP, cisme_instrumentIdMsg_fields, &idRsp); 00320 closedir(dir); 00321 } 00322 00323 // Handle time synchronization 00324 static void wifiEventsHandleTimeRsp(uint8_t* msg, size_t msgLen) 00325 { 00326 if (msg == NULL || msgLen == 0) { 00327 ERROR("Empty GET_TIME_RSP"); 00328 return; 00329 } 00330 00331 cisme_timeMsg timeMsg = cisme_timeMsg_init_default; 00332 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00333 00334 if (!pb_decode(&stream, cisme_timeMsg_fields, &timeMsg)) { 00335 ERROR("Can't decode received message"); 00336 return; 00337 } 00338 00339 if (!timeMsg.has_time) { 00340 ERROR("Missing time field in GET_TIME_RSP"); 00341 return; 00342 } 00343 00344 DEBUG1("Receive GET_TIME_RSP: time=%d", timeMsg.time); 00345 00346 INFO("Set time to %s", ctime((time_t*)&timeMsg.time)); 00347 set_time(timeMsg.time); 00348 } 00349 00350 // Fill pump speed message and send to app 00351 static void wifiEventsSendPumpRsp(cisme_MessageType type) 00352 { 00353 cisme_pumpSpeedMsg speedMsg = cisme_pumpSpeedMsg_init_default; 00354 speedMsg.has_speed = true; 00355 speedMsg.speed = pumpCurrentIntensity(); 00356 00357 DEBUG1("Send %s: speed=%d", (type == cisme_MessageType_SET_PUMP_RSP) ? "SET_PUMP_RSP" : "GET_PUMP_RSP", speedMsg.speed); 00358 wifiEventsSendMsg(type, cisme_pumpSpeedMsg_fields, &speedMsg); 00359 } 00360 00361 // Handle request to set pump speed 00362 static void wifiEventsHandleSetPumpReq(uint8_t* msg, size_t msgLen) 00363 { 00364 cisme_pumpSpeedMsg pumpMsg = cisme_pumpSpeedMsg_init_default; 00365 00366 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00367 00368 if (!pb_decode(&stream, cisme_pumpSpeedMsg_fields, &pumpMsg)) { 00369 ERROR("Can't decode received message"); 00370 return; 00371 } 00372 00373 DEBUG1("Receive SET_PUMP_REQ: speed=%d", pumpMsg.speed); 00374 00375 pumpSetRpm(pumpMsg.speed); 00376 00377 // Send response 00378 wifiEventsSendPumpRsp(cisme_MessageType_SET_PUMP_RSP); 00379 } 00380 00381 // Handle request to get pump speed 00382 static void wifiEventsHandleGetPumpReq(void) 00383 { 00384 DEBUG1("Receive GET_PUMP_REQ"); 00385 // Send response 00386 wifiEventsSendPumpRsp(cisme_MessageType_GET_PUMP_RSP); 00387 } 00388 00389 // Fill light level message and send to app 00390 static void wifiEventsSendLightRsp(cisme_MessageType type) 00391 { 00392 cisme_lightLevelMsg levelMsg = cisme_lightLevelMsg_init_default; 00393 levelMsg.has_level = true; 00394 levelMsg.level = lightRead(); 00395 00396 DEBUG1("Send %s: level=%d", (type == cisme_MessageType_SET_PUMP_RSP) ? "SET_LIGHT_RSP" : "GET_LIGHT_RSP", levelMsg.level); 00397 wifiEventsSendMsg(type, cisme_lightLevelMsg_fields, &levelMsg); 00398 } 00399 00400 // Handle request to set light level 00401 static void wifiEventsHandleSetLightReq(uint8_t* msg, size_t msgLen) 00402 { 00403 cisme_lightLevelMsg levelMsg = cisme_lightLevelMsg_init_default; 00404 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00405 00406 if (!pb_decode(&stream, cisme_lightLevelMsg_fields, &levelMsg)) { 00407 ERROR("Can't decode received message"); 00408 return; 00409 } 00410 00411 DEBUG1("Receive SET_LIGHT_REQ: level=%d", levelMsg.level); 00412 00413 if ((levelMsg.level < LIGHT_MIN_INTENSITY) || (levelMsg.level > LIGHT_MAX_INTENSITY)) { 00414 ERROR("Incorrect light level: %d", levelMsg.level); 00415 return; 00416 } 00417 00418 lightSet(levelMsg.level); 00419 00420 // Send response 00421 wifiEventsSendLightRsp(cisme_MessageType_SET_LIGHT_RSP); 00422 } 00423 00424 // Handle request to get light level 00425 static void wifiEventsHandleGetLightReq(void) 00426 { 00427 DEBUG1("Receive GET_LIGHT_REQ"); 00428 // Send response 00429 wifiEventsSendLightRsp(cisme_MessageType_GET_LIGHT_RSP); 00430 } 00431 00432 // Send temperature calibration factor 00433 static void wifiEventsSendTempCalibrationRsp(float bValue) 00434 { 00435 cisme_tempCalibrationRspMsg tempRsp = cisme_tempCalibrationRspMsg_init_default; 00436 tempRsp.has_bValue = true; 00437 tempRsp.bValue = bValue; 00438 00439 DEBUG1("Send TEMP_CALIBRATION_RSP: bValue=%2.6f", tempRsp.bValue); 00440 wifiEventsSendMsg(cisme_MessageType_TEMP_CALIBRATION_RSP, cisme_tempCalibrationRspMsg_fields, &tempRsp); 00441 } 00442 00443 // Handle request to calibrate temperature 00444 static void wifiEventsHandleTempCalibrationReq(uint8_t* msg, size_t msgLen) 00445 { 00446 cisme_tempCalibrationMsg tempMsg = cisme_tempCalibrationMsg_init_default; 00447 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00448 00449 if (!pb_decode(&stream, cisme_tempCalibrationMsg_fields, &tempMsg)) { 00450 ERROR("Can't decode received message"); 00451 return; 00452 } 00453 00454 if (!tempMsg.has_temperature) { 00455 ERROR("Missing temperature field in TEMP_CALIBRATION_REQ"); 00456 return; 00457 } 00458 00459 DEBUG1("Receive TEMP_CALIBRATION_REQ: temperature=%2.3f, lightLevel=%d, pumpSpeed=%d", 00460 tempMsg.temperature, tempMsg.lightLevel, tempMsg.pumpSpeed); 00461 00462 // Set light and pump intensity 00463 if (tempMsg.lightLevel) { 00464 float TempLight = lightRead(); 00465 lightSet(TempLight); 00466 } else { 00467 lightSet(LIGHT_OFF_INTENSITY); 00468 } 00469 00470 if (tempMsg.pumpSpeed) { 00471 //pumpSet(50); 00472 float TempSpeed = pumpSpeed(); 00473 pumpSetRpm(TempSpeed); 00474 } else { 00475 pumpSet(PUMP_OFF_INTENSITY); 00476 } 00477 00478 float bValue = calibrationTemperature(tempMsg.temperature); 00479 00480 // Send response 00481 wifiEventsSendTempCalibrationRsp(bValue); 00482 } 00483 00484 // Apply O2 calibration parameters 00485 static void wifiEventsHandleO2CalibrationReq(uint8_t* msg, size_t msgLen) 00486 { 00487 cisme_o2CalibrationMsg o2Msg = cisme_o2CalibrationMsg_init_default; 00488 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00489 00490 if (!pb_decode(&stream, cisme_o2CalibrationMsg_fields, &o2Msg)) { 00491 ERROR("Can't decode received message"); 00492 return; 00493 } 00494 00495 if (!o2Msg.has_pressure) { 00496 ERROR("Missing pressure field in O2_CALIBRATION_REQ"); 00497 return; 00498 } 00499 00500 if (!o2Msg.has_led) { 00501 ERROR("Missing led field in O2_CALIBRATION_REQ"); 00502 return; 00503 } 00504 00505 if (!o2Msg.has_phase1) { 00506 ERROR("Missing phase1 field in O2_CALIBRATION_REQ"); 00507 return; 00508 } 00509 00510 if (!o2Msg.has_temperature1) { 00511 ERROR("Missing temperature1 field in O2_CALIBRATION_REQ"); 00512 return; 00513 } 00514 00515 if (!o2Msg.has_phase2) { 00516 ERROR("Missing phase2 field in O2_CALIBRATION_REQ"); 00517 return; 00518 } 00519 00520 if (!o2Msg.has_temperature2) { 00521 ERROR("Missing temperature2 field in O2_CALIBRATION_REQ"); 00522 return; 00523 } 00524 00525 DEBUG1("Receive O2_CALIBRATION_REQ: pressure=%1.2f, led=%1.2f, phase1=%1.2f, temperature1=%1.2f, phase2=%1.2f, temperature2=%1.2f", 00526 o2Msg.pressure, o2Msg.led, o2Msg.phase1, o2Msg.temperature1, o2Msg.phase2, o2Msg.temperature2); 00527 00528 // Set parameters 00529 PresCal = o2Msg.pressure; 00530 PhaseCal1 = o2Msg.phase1; 00531 TempCal1 = o2Msg.temperature1; 00532 PhaseCal2 = o2Msg.phase2; 00533 TempCal2 = o2Msg.temperature2; 00534 LEDCurrent = o2Msg.led; 00535 00536 // Apply parameters 00537 calibrationO2(); 00538 00539 // Send response 00540 DEBUG1("Send O2_CALIBRATION_RSP: pressure=%1.2f, led=%1.2f, phase1=%1.2f, temperature1=%1.2f, phase2=%1.2f, temperature2=%1.2f", 00541 o2Msg.pressure, o2Msg.led, o2Msg.phase1, o2Msg.temperature1, o2Msg.phase2, o2Msg.temperature2); 00542 wifiEventsSendMsg(cisme_MessageType_O2_CALIBRATION_RSP, cisme_o2CalibrationMsg_fields, &o2Msg); 00543 } 00544 00545 // Handle request to calibrate PH 00546 static void wifiEventsHandlePhCalibrationReq(uint8_t* msg, size_t msgLen) 00547 { 00548 cisme_phCalibrationMsg phMsg = cisme_phCalibrationMsg_init_default; 00549 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00550 00551 if (!pb_decode(&stream, cisme_phCalibrationMsg_fields, &phMsg)) { 00552 ERROR("Can't decode received message"); 00553 return; 00554 } 00555 00556 if (!phMsg.has_ph) { 00557 ERROR("Missing ph field in PH_CALIBRATION_REQ"); 00558 return; 00559 } 00560 00561 DEBUG1("Receive PH_CALIBRATION_REQ: ph=%2.3f, lightLevel=%d, pumpSpeed=%d", 00562 phMsg.ph, phMsg.lightLevel, phMsg.pumpSpeed); 00563 00564 // Set light and pump intensity 00565 if (phMsg.lightLevel) { 00566 float pHLight = lightRead(); 00567 lightSet(pHLight); 00568 } else { 00569 lightSet(LIGHT_OFF_INTENSITY); 00570 } 00571 00572 if (phMsg.pumpSpeed) { 00573 float pHSpeed = pumpSpeed(); 00574 pumpSetRpm(pHSpeed); 00575 00576 } else { 00577 pumpSet(PUMP_OFF_INTENSITY); 00578 } 00579 00580 // Allocate response 00581 cisme_phCalibrationRspMsg phRsp = cisme_phCalibrationRspMsg_init_default; 00582 phRsp.has_phBuffer = true; 00583 phRsp.has_phTemp = true; 00584 phRsp.has_slope = true; 00585 phRsp.has_eo = true; 00586 phRsp.phBuffer = phMsg.ph; 00587 00588 calibrationPh(phRsp.phBuffer, &phRsp.phTemp, &phRsp.slope, &phRsp.eo, NULL); 00589 00590 // Send response 00591 DEBUG1("Send PH_CALIBRATION_RSP: ph=%2.3f, phTemp=%2.3f, slope=%2.6f, eo=%2.6f", 00592 phRsp.phBuffer, phRsp.phTemp, phRsp.slope, phRsp.eo); 00593 wifiEventsSendMsg(cisme_MessageType_PH_CALIBRATION_RSP, cisme_phCalibrationRspMsg_fields, &phRsp); 00594 } 00595 00596 // Send current PH parameters 00597 static void wifiEventsSendCurCalPh(void) 00598 { 00599 cisme_phCalibrationRspMsg phRsp = cisme_phCalibrationRspMsg_init_default; 00600 phRsp.has_phBuffer = true; 00601 phRsp.has_phTemp = true; 00602 phRsp.has_slope = true; 00603 phRsp.has_eo = true; 00604 phRsp.phBuffer = PHBUFFERF; 00605 phRsp.phTemp = PHTEMPF; 00606 phRsp.slope = MSINGLEPT; 00607 phRsp.eo = EOSINGLEPT; 00608 00609 // Send response 00610 DEBUG1("Send PH_CALIBRATION_RSP: ph=%2.3f, phTemp=%2.3f, slope=%2.6f, eo=%2.6f", 00611 phRsp.phBuffer, phRsp.phTemp, phRsp.slope, phRsp.eo); 00612 wifiEventsSendMsg(cisme_MessageType_PH_CALIBRATION_RSP, cisme_phCalibrationRspMsg_fields, &phRsp); 00613 } 00614 00615 // Send current O2 parameters 00616 static void wifiEventsSendCurCalO2(void) 00617 { 00618 cisme_o2CalibrationMsg o2Msg = cisme_o2CalibrationMsg_init_default; 00619 o2Msg.has_pressure = true; 00620 o2Msg.has_phase1 = true; 00621 o2Msg.has_temperature1 = true; 00622 o2Msg.has_phase2 = true; 00623 o2Msg.has_temperature2 = true; 00624 o2Msg.has_led = true; 00625 o2Msg.pressure = PresCal; 00626 o2Msg.phase1 = PhaseCal1; 00627 o2Msg.temperature1 = TempCal1; 00628 o2Msg.phase2 = PhaseCal2; 00629 o2Msg.temperature2 = TempCal2; 00630 o2Msg.led = LEDCurrent; 00631 00632 // Send response 00633 DEBUG1("Send O2_CALIBRATION_RSP: pressure=%1.2f, led=%1.2f, phase1=%1.2f, temperature1=%1.2f, phase2=%1.2f, temperature2=%1.2f", 00634 o2Msg.pressure, o2Msg.led, o2Msg.phase1, o2Msg.temperature1, o2Msg.phase2, o2Msg.temperature2); 00635 wifiEventsSendMsg(cisme_MessageType_O2_CALIBRATION_RSP, cisme_o2CalibrationMsg_fields, &o2Msg); 00636 } 00637 00638 static void sendPumpCalibrationRsp(float aValue, float bValue, float cValue) 00639 { 00640 cisme_pumpCalibrationMsg rspMsg = cisme_pumpCalibrationMsg_init_default; 00641 rspMsg.has_a = true; 00642 rspMsg.has_b = true; 00643 rspMsg.has_c = true; 00644 rspMsg.a = aValue; 00645 rspMsg.b = bValue; 00646 rspMsg.c = cValue; 00647 00648 DEBUG1("Send PUMP_CALIBRATION_RSP: a=%f, b=%f, c=%f", rspMsg.a, rspMsg.b, rspMsg.c); 00649 wifiEventsSendMsg(cisme_MessageType_PUMP_CALIBRATION_RSP, cisme_pumpCalibrationMsg_fields, &rspMsg); 00650 } 00651 00652 // Handle request to get current calibrated parameters 00653 static void wifiEventsHandleCurCalibrationReq(uint8_t* msg, size_t msgLen) 00654 { 00655 cisme_currentCalibrationMsg calMsg = cisme_currentCalibrationMsg_init_default; 00656 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00657 00658 if (!pb_decode(&stream, cisme_currentCalibrationMsg_fields, &calMsg)) { 00659 ERROR("Can't decode received message"); 00660 return; 00661 } 00662 00663 if (!calMsg.has_type) { 00664 calMsg.type = cisme_CalibrationType_PH; 00665 } 00666 00667 DEBUG1("Receive CUR_CALIBRATION_REQ: type=%d", calMsg.type); 00668 00669 switch(calMsg.type) { 00670 case cisme_CalibrationType_PH: 00671 wifiEventsSendCurCalPh(); 00672 break; 00673 case cisme_CalibrationType_TEMPERATURE: 00674 wifiEventsSendTempCalibrationRsp(B); 00675 break; 00676 case cisme_CalibrationType_O2: 00677 wifiEventsSendCurCalO2(); 00678 break; 00679 case cisme_CalibrationType_PUMP: { 00680 float a = 0.0; 00681 float b = 0.0; 00682 float c = 0.0; 00683 pumpGetParams(&a, &b, &c); 00684 sendPumpCalibrationRsp(a, b, c); 00685 break; 00686 } 00687 default: 00688 break; 00689 } 00690 } 00691 00692 // Send calibration accept response 00693 static void wifiEventsSendCalAcceptRsp(cisme_CalibrationType type) 00694 { 00695 cisme_currentCalibrationMsg calMsg = cisme_currentCalibrationMsg_init_default; 00696 calMsg.has_type = true; 00697 calMsg.type = type; 00698 00699 DEBUG1("Send CALIBRATION_ACCEPT_RSP: type=%d", calMsg.type); 00700 wifiEventsSendMsg(cisme_MessageType_CALIBRATION_ACCEPT_RSP, cisme_currentCalibrationMsg_fields, &calMsg); 00701 } 00702 00703 // Handle request to save temperature parameters 00704 static void wifiEventsHandleTempCalAcceptReq(uint8_t* msg, size_t msgLen) 00705 { 00706 cisme_tempCalibrationRspMsg tempMsg = cisme_tempCalibrationRspMsg_init_default; 00707 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00708 00709 if (!pb_decode(&stream, cisme_tempCalibrationRspMsg_fields, &tempMsg)) { 00710 ERROR("Can't decode received message"); 00711 return; 00712 } 00713 00714 if (!tempMsg.has_bValue) { 00715 ERROR("Missing bValue field in TEMP_CALIBRATION_ACCEPT_REQ"); 00716 return; 00717 } 00718 00719 DEBUG1("Receive TEMP_CALIBRATION_ACCEPT_REQ: bValue=%2.6f", tempMsg.bValue); 00720 00721 calibrationTemperatureSave(tempMsg.bValue); 00722 00723 // Send response 00724 wifiEventsSendCalAcceptRsp(cisme_CalibrationType_TEMPERATURE); 00725 } 00726 00727 // Handle request to save PH parameters 00728 static void wifiEventsHandlePhCalAcceptReq(uint8_t* msg, size_t msgLen) 00729 { 00730 cisme_phCalibrationRspMsg phMsg = cisme_phCalibrationRspMsg_init_default; 00731 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00732 00733 if (!pb_decode(&stream, cisme_phCalibrationRspMsg_fields, &phMsg)) { 00734 ERROR("Can't decode received message"); 00735 return; 00736 } 00737 00738 if (!phMsg.has_phBuffer) { 00739 ERROR("Missing phBuffer field in PH_CALIBRATION_ACCEPT_REQ"); 00740 return; 00741 } 00742 00743 if (!phMsg.has_slope) { 00744 ERROR("Missing slope field in PH_CALIBRATION_ACCEPT_REQ"); 00745 return; 00746 } 00747 00748 if (!phMsg.has_phTemp) { 00749 ERROR("Missing phTemp field in PH_CALIBRATION_ACCEPT_REQ"); 00750 return; 00751 } 00752 00753 if (!phMsg.has_eo) { 00754 ERROR("Missing eo field in PH_CALIBRATION_ACCEPT_REQ"); 00755 return; 00756 } 00757 00758 DEBUG1("Receive PH_CALIBRATION_ACCEPT_REQ: ph=%2.3f, phTemp=%2.3f, slope=%2.6f, eo=%2.6f", 00759 phMsg.phBuffer, phMsg.phTemp, phMsg.slope, phMsg.eo); 00760 00761 PHBUFFERF = (float)phMsg.phBuffer; 00762 PHTEMPF = (float)phMsg.phTemp; 00763 PHTEMPKF = (float)(phMsg.phTemp + 273.15); 00764 PHVOLTSF = (float)(phMsg.eo + phMsg.slope * phMsg.phBuffer); 00765 MSINGLEPT = (float)phMsg.slope; 00766 EOSINGLEPT = (float)phMsg.eo; 00767 00768 // Send response 00769 wifiEventsSendCalAcceptRsp(cisme_CalibrationType_PH); 00770 00771 // Save parameters and restart board 00772 calibrationPhSave(); 00773 } 00774 00775 // Start experiment 00776 static void wifiEventsHandleStartExpInd(uint8_t* msg, size_t msgLen) 00777 { 00778 cisme_startExperimentMsg expMsg = cisme_startExperimentMsg_init_default; 00779 static char receivedPrefix[256] = {0}; 00780 00781 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00782 if (!pb_decode(&stream, cisme_startExperimentMsg_fields, &expMsg)) { 00783 ERROR("Can't decode received message"); 00784 return; 00785 } 00786 00787 if (!expMsg.has_id) { 00788 ERROR("Missing id field in START_EXPERIMENT_IND"); 00789 return; 00790 } 00791 00792 if (!expMsg.has_stepsCount) { 00793 ERROR("Missing stepsCount field in START_EXPERIMENT_IND"); 00794 return; 00795 } 00796 00797 if (!expMsg.has_salinity) { 00798 ERROR("Missing salinity field in START_EXPERIMENT_IND"); 00799 return; 00800 } 00801 00802 DEBUG1("Receive START_EXPERIMENT_IND: id=%d, experiment=%d, stepsCount=%d, salinity=%d, pumpSpeed=%d repeats=%d", 00803 expMsg.id, expMsg.experiment, expMsg.stepsCount, expMsg.salinity, expMsg.pumpSpeed, expMsg.repeats); 00804 00805 if (isExpExecuting == true && expMsg.id != currentExpId) { 00806 ERROR("Received START_EXPERIMENT_IND with expMsg.id=%d, but already executing experiment id=%d", 00807 expMsg.id, currentExpId); 00808 return; 00809 } 00810 00811 if (expMsg.stepsCount * (1 + expMsg.repeats) > MAX_STEPS_NO) { 00812 expMsg.repeats = (MAX_STEPS_NO / expMsg.stepsCount) - 1; 00813 ERROR("User wants too many steps. Count of repeats decreased to: %d", expMsg.repeats); 00814 } 00815 00816 for (int ix = 0; ix < expMsg.stepsCount * (1 + expMsg.repeats); ix++) { 00817 pgm[ix][0] = expMsg.pumpSpeed; 00818 } 00819 00820 // Decode steps 00821 uint8_t stepIx = 0; 00822 expMsg.steps.funcs.decode = &pbDecodeProgramSteps; 00823 expMsg.steps.arg = &stepIx; 00824 00825 expMsg.filePrefix.funcs.decode = & pbDecodeString; 00826 expMsg.filePrefix.arg = receivedPrefix; 00827 00828 stream = pb_istream_from_buffer(msg, msgLen); 00829 if (!pb_decode(&stream, cisme_startExperimentMsg_fields, &expMsg)) { 00830 ERROR("Can't decode received message"); 00831 return; 00832 } 00833 00834 if (strcmp(receivedPrefix, "") != 0) { 00835 /* User wants some prefix for the file name.*/ 00836 strncpy(FilePrefix, receivedPrefix, FILE_PREFIX_LENGTH); 00837 DEBUG1("User wants prefix:%s", FilePrefix); 00838 } 00839 00840 Salinity = expMsg.salinity; 00841 numberofprograms = expMsg.stepsCount; 00842 currentExpId = expMsg.id; 00843 isExpExecuting = true; 00844 MeasurementTypeVal = PGM; 00845 00846 if (expMsg.has_repeats && expMsg.experiment >= cisme_startExperimentMsg_ExperimentType_RESPIRATION && 00847 expMsg.experiment < cisme_startExperimentMsg_ExperimentType_MULTI && 00848 expMsg.repeats > 0) { 00849 for (int repeatIx = 0; repeatIx < expMsg.repeats; repeatIx++) { 00850 memcpy(&(pgm[numberofprograms * (repeatIx + 1)]), pgm, sizeof(float) * 20 * numberofprograms); 00851 } 00852 00853 numberofprograms *= expMsg.repeats + 1; 00854 } 00855 00856 experimentPrepareUserProgram(); 00857 } 00858 00859 // Handle experiment action (next step or stop) 00860 static void wifiEventsHandleActionExpInd(cisme_MessageType type, uint8_t* msg, size_t msgLen) 00861 { 00862 cisme_experimentMsg expMsg = cisme_experimentMsg_init_default; 00863 00864 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00865 if (!pb_decode(&stream, cisme_experimentMsg_fields, &expMsg)) { 00866 ERROR("Can't decode received message"); 00867 return; 00868 } 00869 00870 if (!expMsg.has_id) { 00871 ERROR("Missing id field in %s", 00872 (type == cisme_MessageType_NEXT_EXPERIMENT_IND) ? "NEXT_EXPERIMENT_IND" : "STOP_EXPERIMENT_IND"); 00873 return; 00874 } 00875 00876 if (isExpExecuting == false) { 00877 /* Not ERROR because this can happen if the message will be received when experiment already finished. */ 00878 INFO("Unexpected actionExpInd. We are not executing experiment right now."); 00879 return; 00880 } 00881 00882 if (expMsg.id != currentExpId) { 00883 ERROR("Unexpected expId received. Received expId=%d currentExpId=%d", expMsg.id, currentExpId); 00884 return; 00885 } 00886 00887 switch (type) { 00888 case cisme_MessageType_NEXT_EXPERIMENT_IND: 00889 SwitchMode = 1; 00890 INFO("Experiment switched by user."); 00891 fprintf(currentFile,"User Advanced Step\n"); 00892 break; 00893 case cisme_MessageType_STOP_EXPERIMENT_IND: 00894 00895 INFO("User Ended Experiment"); 00896 fprintf(currentFile,"User Ended Experiment\n"); 00897 isExpExecuting = false; 00898 00899 finishExperiment(); 00900 00901 wifiEventsSendFinishExpInd(currentExpId, FileName); 00902 break; 00903 default: 00904 ERROR("Unexpected message type received:%d", type); 00905 return; 00906 } 00907 } 00908 00909 // Send file download response 00910 static void wifiEventsSendFileDownloadRsp(int32_t fileId, int32_t numBlocks) 00911 { 00912 cisme_fileDownloadRspMsg fileRsp = cisme_fileDownloadRspMsg_init_default; 00913 fileRsp.has_fileId = true; 00914 fileRsp.has_numBlocks = true; 00915 fileRsp.fileId = fileId; 00916 fileRsp.numBlocks = numBlocks; 00917 00918 DEBUG1("Send FILE_DOWNLOAD_RSP: fileId=%d, numBlocks=%d", fileRsp.fileId, fileRsp.numBlocks); 00919 wifiEventsSendMsg(cisme_MessageType_FILE_DOWNLOAD_RSP, cisme_fileDownloadRspMsg_fields, &fileRsp); 00920 } 00921 00922 // Send file block 00923 static void wifiEventsSendFileBlockReq(int32_t fileId) 00924 { 00925 blockId++; 00926 00927 if (blockId > numBlocks) { 00928 ERROR("Excess file block requested"); 00929 return; 00930 } 00931 00932 cisme_fileBlockMsg blockReq = cisme_fileBlockMsg_init_default; 00933 blockReq.has_fileId = true; 00934 blockReq.has_blockId = true; 00935 blockReq.has_blockSize = true; 00936 blockReq.fileId = fileId; 00937 blockReq.blockId = blockId; 00938 blockReq.blockSize = (blockId < numBlocks) ? FILE_BLOCK_SIZE : (fileLen % FILE_BLOCK_SIZE); 00939 blockReq.blockData.funcs.encode = &pbEncodeFileBlock; 00940 00941 DEBUG1("Send FILE_BLOCK_REQ: fileId=%d, blockId=%d, blockSize=%d", 00942 blockReq.fileId, blockReq.blockId, blockReq.blockSize); 00943 wifiEventsSendMsg(cisme_MessageType_FILE_BLOCK_REQ, cisme_fileBlockMsg_fields, &blockReq); 00944 } 00945 00946 // Send file action (finish or abort) 00947 static void wifiEventsSendFileActionInd(cisme_MessageType type, int32_t fileId) 00948 { 00949 cisme_fileActionMsg actionMsg = cisme_fileActionMsg_init_default; 00950 actionMsg.has_fileId = true; 00951 actionMsg.fileId = fileId; 00952 00953 DEBUG1("Send %s: fileId=%d", 00954 (type == cisme_MessageType_FILE_FINISH_IND) ? "FILE_FINISH_IND" : "FILE_ABORT_IND", 00955 actionMsg.fileId); 00956 wifiEventsSendMsg(type, cisme_fileActionMsg_fields, &actionMsg); 00957 } 00958 00959 // Handle request to download file 00960 static void wifiEventsHandleFileDownloadReq(uint8_t* msg, size_t msgLen) 00961 { 00962 char fileName[FILE_NAME_LENGTH]; 00963 00964 cisme_fileDownloadMsg fileReq = cisme_fileDownloadMsg_init_default; 00965 fileReq.name.funcs.decode = &pbDecodeString; 00966 fileReq.name.arg = fileName; 00967 00968 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 00969 if (!pb_decode(&stream, cisme_fileDownloadMsg_fields, &fileReq)) { 00970 ERROR("Can't decode received message"); 00971 return; 00972 } 00973 00974 DEBUG1("Receive FILE_DOWNLOAD_REQ: name=%s", fileName); 00975 00976 if (curFile != NULL) { 00977 INFO("New file download request, abort previous one"); 00978 fclose(curFile); 00979 wifiEventsSendFileActionInd(cisme_MessageType_FILE_ABORT_IND, fileId); 00980 } 00981 00982 char dataname[PATH_TO_FILE_LEN]; 00983 sprintf(dataname, "%s%s", "/" FSNAME "/Data/", fileName); 00984 curFile = fopen(dataname, "rb"); 00985 if (curFile == NULL) { 00986 ERROR("File %s not found", fileName); 00987 return; 00988 } 00989 00990 fseek(curFile, 0, SEEK_END); 00991 fileLen = ftell(curFile); 00992 rewind(curFile); 00993 00994 fileId++; 00995 numBlocks = fileLen / FILE_BLOCK_SIZE; 00996 if (fileLen % FILE_BLOCK_SIZE > 0) { 00997 numBlocks++; 00998 } 00999 01000 wifiEventsSendFileDownloadRsp(fileId, numBlocks); 01001 01002 blockId = 0; 01003 wifiEventsSendFileBlockReq(fileId); 01004 } 01005 01006 // Handle response for block transfer 01007 static void wifiEventsHandleFileBlockRsp(uint8_t* msg, size_t msgLen) 01008 { 01009 cisme_fileBlockRspMsg blockRsp = cisme_fileBlockRspMsg_init_default; 01010 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 01011 01012 if (!pb_decode(&stream, cisme_fileBlockRspMsg_fields, &blockRsp)) { 01013 ERROR("Can't decode received message"); 01014 return; 01015 } 01016 01017 if (!blockRsp.has_fileId) { 01018 ERROR("Missing fileId field in FILE_BLOCK_RSP"); 01019 return; 01020 } 01021 01022 if (!blockRsp.has_blockId) { 01023 ERROR("Missing blockId field in FILE_BLOCK_RSP"); 01024 return; 01025 } 01026 01027 DEBUG1("Receive FILE_BLOCK_RSP: fileId=%d, blockId=%d", 01028 blockRsp.fileId, blockRsp.blockId); 01029 01030 if (curFile == NULL) { 01031 ERROR("No file transfer ongoing"); 01032 return; 01033 } 01034 01035 if (fileId != blockRsp.fileId) { 01036 ERROR("Unknown fileId=%d, expected one:%d", blockRsp.fileId, fileId); 01037 01038 // Send abort for both files 01039 wifiEventsSendFileActionInd(cisme_MessageType_FILE_ABORT_IND, fileId); 01040 wifiEventsSendFileActionInd(cisme_MessageType_FILE_ABORT_IND, blockRsp.fileId); 01041 01042 if (curFile != NULL) { 01043 fclose(curFile); 01044 curFile = NULL; 01045 } 01046 return; 01047 } 01048 01049 if (blockId != blockRsp.blockId) { 01050 ERROR("Unknown blockId=%d, expected one:%d", blockRsp.blockId, blockId); 01051 01052 // Send abort for both files 01053 wifiEventsSendFileActionInd(cisme_MessageType_FILE_ABORT_IND, fileId); 01054 01055 if (curFile != NULL) { 01056 fclose(curFile); 01057 curFile = NULL; 01058 } 01059 return; 01060 } 01061 01062 if (blockId == numBlocks) { 01063 fclose(curFile); 01064 curFile = NULL; 01065 wifiEventsSendFileActionInd(cisme_MessageType_FILE_FINISH_IND, fileId); 01066 INFO("File transfer (%d) finished", fileId); 01067 return; 01068 } 01069 01070 wifiEventsSendFileBlockReq(fileId); 01071 } 01072 01073 // Handle file abort 01074 static void wifiEventsHandleFileAbortInd(uint8_t* msg, size_t msgLen) 01075 { 01076 cisme_fileActionMsg actionMsg = cisme_fileActionMsg_init_default; 01077 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 01078 01079 if (!pb_decode(&stream, cisme_fileActionMsg_fields, &actionMsg)) { 01080 ERROR("Can't decode received message"); 01081 return; 01082 } 01083 01084 if (!actionMsg.has_fileId) { 01085 ERROR("Missing fileId field in FILE_ABORT_IND"); 01086 return; 01087 } 01088 01089 DEBUG1("Receive FILE_ABORT_IND: fileId=%d", actionMsg.fileId); 01090 01091 if (fileId != actionMsg.fileId) { 01092 ERROR("Unknown fileId=%d, expected one:%d", actionMsg.fileId, fileId); 01093 return; 01094 } 01095 01096 if (curFile == NULL) { 01097 ERROR("No file transfer ongoing"); 01098 return; 01099 } 01100 01101 fclose(curFile); 01102 curFile = NULL; 01103 } 01104 01105 // Get experiments files 01106 static void wifiEventsHandleGetFilesReq(void) 01107 { 01108 DEBUG1("Receive GET_FILES_REQ"); 01109 01110 // Fill and send response 01111 cisme_filesMsg filesMsg = cisme_filesMsg_init_default; 01112 filesMsg.has_numFiles = true; 01113 filesMsg.numFiles = 0; 01114 filesMsg.names.funcs.encode = pbEncodeFiles; 01115 01116 DIR* dir = opendir("/msc/data/"); 01117 struct dirent* entry = NULL; 01118 01119 while ((entry = readdir(dir)) != NULL) { 01120 if (strstr(entry->d_name, ".csv") != NULL) { 01121 filesMsg.numFiles++; 01122 } 01123 } 01124 01125 DEBUG1("Send GET_FILES_RSP: numFiles=%d", filesMsg.numFiles); 01126 wifiEventsSendMsg(cisme_MessageType_GET_FILES_RSP, cisme_filesMsg_fields, &filesMsg); 01127 } 01128 01129 // Handle request for raw data 01130 static void wifiEventsHandleRawDataReq(void) 01131 { 01132 DEBUG1("Receive RAW_DATA_REQ"); 01133 01134 // Prepare and send response 01135 cisme_rawDataMsg rawMsg = cisme_rawDataMsg_init_default; 01136 rawMsg.has_o2 = true; 01137 rawMsg.has_ph = true; 01138 rawMsg.has_o2Amplitude = true; 01139 rawMsg.has_o2Phase = true; 01140 rawMsg.has_phAdcV = true; 01141 rawMsg.has_temperatureAdcV = true; 01142 rawMsg.has_temperature = true; 01143 01144 float presensData[PRESENS_RES_LENGTH]; 01145 presensGetData(presensData); 01146 01147 rawMsg.o2Amplitude = presensData[0]; 01148 rawMsg.o2Phase = presensData[1]; 01149 rawMsg.o2 = presensData[2]; 01150 rawMsg.ph = pHCorrected; 01151 rawMsg.phAdcV = pH; 01152 rawMsg.temperatureAdcV = pHT; 01153 rawMsg.temperature = PHTEMP; 01154 01155 DEBUG1("Send RAW_DATA_RSP: o2Amplitude=%d, o2Phase=%3.2f, o2=%3.0f, pH=%3.2f, pHAdcV=%3.3f, temperatureAdcV=%3.3f, temperature=%1.1f", 01156 rawMsg.o2Amplitude, rawMsg.o2Phase, rawMsg.o2, rawMsg.ph, rawMsg.phAdcV, rawMsg.temperatureAdcV, rawMsg.temperature); 01157 wifiEventsSendMsg(cisme_MessageType_RAW_DATA_RSP, cisme_rawDataMsg_fields, &rawMsg); 01158 } 01159 01160 // Start pump calibration 01161 static void wifiEventsHandlePumpCalibrationReq(void) 01162 { 01163 DEBUG1("Receive PUMP_CALIBRATION_REQ"); 01164 01165 float a = 0.0; 01166 float b = 0.0; 01167 float c = 0.0; 01168 01169 calibrationPump(&a, &b, &c); 01170 sendPumpCalibrationRsp(a, b, c); 01171 } 01172 01173 // Apply pump calibration parameters 01174 static void wifiEventsHandlePumpCalAcceptReq(uint8_t* msg, size_t msgLen) 01175 { 01176 cisme_pumpCalibrationMsg calMsg = cisme_pumpCalibrationMsg_init_default; 01177 pb_istream_t stream = pb_istream_from_buffer(msg, msgLen); 01178 01179 if (!pb_decode(&stream, cisme_pumpCalibrationMsg_fields, &calMsg)) { 01180 ERROR("Can't decode received message"); 01181 return; 01182 } 01183 01184 DEBUG1("Receive PUMP_CALIBRATION_ACCEPT_REQ: a=%f, b=%f, c=%f", calMsg.a, calMsg.b, calMsg.c); 01185 pumpSetParams(calMsg.a, calMsg.b, calMsg.c); 01186 01187 // Send response 01188 wifiEventsSendCalAcceptRsp(cisme_CalibrationType_PUMP); 01189 } 01190 01191 // Handle message from app 01192 static void wifiEventsHandleMsg(void) 01193 { 01194 uint8_t* buffer; 01195 unsigned int msgLen = wifiGetMessage(&buffer); 01196 01197 if (msgLen == 0) { 01198 return; 01199 } 01200 01201 cisme_genericMsg genericMsg = cisme_genericMsg_init_default; 01202 PbDecodeMessage message = {NULL, 0}; 01203 genericMsg.payload.funcs.decode = pbDecodeMsg; 01204 genericMsg.payload.arg = &message; 01205 01206 for (size_t ix = 0; ix < msgLen; ix++) { 01207 DEBUG1("0x%x", buffer[ix]); 01208 } 01209 01210 pb_istream_t stream = pb_istream_from_buffer(buffer, msgLen); 01211 01212 if (!pb_decode(&stream, cisme_genericMsg_fields, &genericMsg)) { 01213 ERROR("Can't decode received message"); 01214 return; 01215 } 01216 01217 switch (genericMsg.type) { 01218 case cisme_MessageType_INSTRUMENT_ID_REQ: 01219 wifiEventsHandleIdReq(); 01220 break; 01221 case cisme_MessageType_START_EXPERIMENT_IND: 01222 wifiEventsHandleStartExpInd(message.msg, message.msgLen); 01223 break; 01224 case cisme_MessageType_NEXT_EXPERIMENT_IND: 01225 case cisme_MessageType_STOP_EXPERIMENT_IND: 01226 wifiEventsHandleActionExpInd(genericMsg.type, message.msg, message.msgLen); 01227 break; 01228 case cisme_MessageType_TEMP_CALIBRATION_REQ: 01229 wifiEventsHandleTempCalibrationReq(message.msg, message.msgLen); 01230 break; 01231 case cisme_MessageType_O2_CALIBRATION_REQ: 01232 wifiEventsHandleO2CalibrationReq(message.msg, message.msgLen); 01233 break; 01234 case cisme_MessageType_PH_CALIBRATION_REQ: 01235 wifiEventsHandlePhCalibrationReq(message.msg, message.msgLen); 01236 break; 01237 case cisme_MessageType_CUR_CALIBRATION_REQ: 01238 wifiEventsHandleCurCalibrationReq(message.msg, message.msgLen); 01239 break; 01240 case cisme_MessageType_TEMP_CALIBRATION_ACCEPT_REQ: 01241 wifiEventsHandleTempCalAcceptReq(message.msg, message.msgLen); 01242 break; 01243 case cisme_MessageType_PH_CALIBRATION_ACCEPT_REQ: 01244 wifiEventsHandlePhCalAcceptReq(message.msg, message.msgLen); 01245 break; 01246 case cisme_MessageType_SET_PUMP_REQ: 01247 wifiEventsHandleSetPumpReq(message.msg, message.msgLen); 01248 break; 01249 case cisme_MessageType_GET_PUMP_REQ: 01250 wifiEventsHandleGetPumpReq(); 01251 break; 01252 case cisme_MessageType_SET_LIGHT_REQ: 01253 wifiEventsHandleSetLightReq(message.msg, message.msgLen); 01254 break; 01255 case cisme_MessageType_GET_LIGHT_REQ: 01256 wifiEventsHandleGetLightReq(); 01257 break; 01258 case cisme_MessageType_GET_TIME_RSP: 01259 wifiEventsHandleTimeRsp(message.msg, message.msgLen); 01260 break; 01261 case cisme_MessageType_GET_FILES_REQ: 01262 wifiEventsHandleGetFilesReq(); 01263 break; 01264 case cisme_MessageType_FILE_DOWNLOAD_REQ: 01265 wifiEventsHandleFileDownloadReq(message.msg, message.msgLen); 01266 break; 01267 case cisme_MessageType_FILE_BLOCK_RSP: 01268 wifiEventsHandleFileBlockRsp(message.msg, message.msgLen); 01269 break; 01270 case cisme_MessageType_FILE_ABORT_IND: 01271 wifiEventsHandleFileAbortInd(message.msg, message.msgLen); 01272 break; 01273 case cisme_MessageType_RAW_DATA_REQ: 01274 wifiEventsHandleRawDataReq(); 01275 break; 01276 case cisme_MessageType_PUMP_CALIBRATION_REQ: 01277 wifiEventsHandlePumpCalibrationReq(); 01278 break; 01279 case cisme_MessageType_PUMP_CALIBRATION_ACCEPT_REQ: 01280 wifiEventsHandlePumpCalAcceptReq(message.msg, message.msgLen); 01281 break; 01282 default: 01283 ERROR("Unknown message type:%d", genericMsg.type); 01284 break; 01285 } 01286 } 01287 01288 static void wifiEventsSendFinishExpInd(int32_t id, char* fileName) 01289 { 01290 if (!wifiTcpConnectionActive()) { 01291 return; 01292 } 01293 01294 cisme_experimentMsg expMsg = cisme_experimentMsg_init_default; 01295 expMsg.has_id = true; 01296 expMsg.id = id; 01297 expMsg.fileName.funcs.encode = &pbEncodeString; 01298 expMsg.fileName.arg = fileName; 01299 01300 DEBUG1("Send FINISH_EXPERIMENT_IND: id=%d, fileName=%s", expMsg.id, fileName); 01301 wifiEventsSendMsg(cisme_MessageType_FINISH_EXPERIMENT_IND, cisme_experimentMsg_fields, &expMsg); 01302 01303 } 01304 01305 void wifiEventsSendErrorsInd(char errors) 01306 { 01307 if (getNoSetBits(errors) == 0) { 01308 return; 01309 } 01310 01311 cisme_errorMsg errorMsg = cisme_errorMsg_init_default; 01312 errorMsg.has_numErrors = true; 01313 errorMsg.numErrors = getNoSetBits(errors); 01314 errorMsg.errorText.arg = &errors; 01315 errorMsg.errorText.funcs.encode = pbEncodeErrors; 01316 01317 DEBUG1("Send ERRORS_IND: numErrors=%d", errorMsg.numErrors); 01318 wifiEventsSendMsg(cisme_MessageType_ERRORS_IND, cisme_errorMsg_fields, &errorMsg); 01319 } 01320 01321 void wifiEventsSendDataExpInd(int32_t step, int32_t timeRemaining, double ph, double o2, double battery, double temperature) 01322 { 01323 if (!wifiTcpConnectionActive()) { 01324 return; 01325 } 01326 01327 cisme_experimentDataMsg expMsg = cisme_experimentDataMsg_init_default; 01328 expMsg.has_id = true; 01329 expMsg.has_step = true; 01330 expMsg.has_timeRemaining = true; 01331 expMsg.has_ph = true; 01332 expMsg.has_o2 = true; 01333 expMsg.has_battery = true; 01334 expMsg.has_temperature = true; 01335 expMsg.has_lightLevel = true; 01336 expMsg.has_pumpRpm = true; 01337 expMsg.id = currentExpId; 01338 expMsg.step = step; 01339 expMsg.timeRemaining = timeRemaining; 01340 expMsg.ph = ph; 01341 expMsg.o2 = o2; 01342 expMsg.battery = battery; 01343 expMsg.temperature = temperature; 01344 expMsg.lightLevel = lightRead(); 01345 expMsg.pumpRpm = pumpSpeed(); 01346 01347 DEBUG1("Send EXPERIMENT_DATA_IND: id=%d, step=%d, timeRemaining=%d, ph=%3.2f, o2=%3.0f, battery=%3.1f, temperature=%2.1f, lightLevel=%d, pumpRpm=%d", 01348 expMsg.id, expMsg.step, expMsg.timeRemaining, expMsg.ph, expMsg.o2, expMsg.battery, expMsg.temperature, expMsg.lightLevel, expMsg.pumpRpm); 01349 wifiEventsSendMsg(cisme_MessageType_EXPERIMENT_DATA_IND, cisme_experimentDataMsg_fields, &expMsg); 01350 01351 } 01352 01353 void wifiEventsSendTempCalDataInd(float tempBuffer, float tempVolts) 01354 { 01355 cisme_tempCalibrationDataMsg dataMsg = cisme_tempCalibrationDataMsg_init_default; 01356 dataMsg.has_tempBuffer = true; 01357 dataMsg.tempBuffer = tempBuffer; 01358 dataMsg.has_tempVolts = true; 01359 dataMsg.tempVolts = tempVolts; 01360 01361 DEBUG1("Send TEMP_CALIBRATION_DATA_IND: tempBuffer=%2.4f, tempVolts=%2.6f", dataMsg.tempBuffer, dataMsg.tempVolts); 01362 wifiEventsSendMsg(cisme_MessageType_TEMP_CALIBRATION_DATA_IND, cisme_tempCalibrationDataMsg_fields, &dataMsg); 01363 } 01364 01365 void wifiEventsSendPhCalDataInd(float phBuffer, float phVoltsCurrent, float phVoltsAverage) 01366 { 01367 cisme_phCalibrationDataMsg dataMsg = cisme_phCalibrationDataMsg_init_default; 01368 dataMsg.has_phBuffer = true; 01369 dataMsg.phBuffer = phBuffer; 01370 dataMsg.has_phVoltsCurrent = true; 01371 dataMsg.phVoltsCurrent = phVoltsCurrent; 01372 dataMsg.has_phVoltsAverage = true; 01373 dataMsg.phVoltsAverage = phVoltsAverage; 01374 01375 DEBUG1("Send PH_CALIBRATION_DATA_IND: phBuffer=%2.4f, phVoltsCurrent=%2.6f, phVoltsAverage=%2.6f", 01376 dataMsg.phBuffer, dataMsg.phVoltsCurrent, dataMsg.phVoltsAverage); 01377 wifiEventsSendMsg(cisme_MessageType_PH_CALIBRATION_DATA_IND, cisme_phCalibrationDataMsg_fields, &dataMsg); 01378 } 01379 01380 void wifiEventsSendPumpCalDataInd(int intensity, int rpm) 01381 { 01382 cisme_pumpCalibrationDataMsg dataMsg = cisme_pumpCalibrationDataMsg_init_default; 01383 dataMsg.has_intensity = true; 01384 dataMsg.intensity = intensity; 01385 dataMsg.has_rpm = true; 01386 dataMsg.rpm = rpm; 01387 01388 DEBUG1("Send PUMP_CALIBRATION_DATA_IND: intensity=%d, rpm=%d", dataMsg.intensity, dataMsg.rpm); 01389 wifiEventsSendMsg(cisme_MessageType_PUMP_CALIBRATION_DATA_IND, cisme_pumpCalibrationDataMsg_fields, &dataMsg); 01390 } 01391 01392 void wifiEventsStart(void) 01393 { 01394 bool isTimeRequested = false; 01395 01396 while(true) { 01397 01398 if (isExpExecuting && experimentRunUserProgram()) { 01399 INFO("Experiment completed."); 01400 fprintf(currentFile, "Experiment Completed\n"); 01401 isExpExecuting = false; 01402 finishExperiment(); 01403 01404 wifiEventsSendFinishExpInd(currentExpId, FileName); 01405 } 01406 01407 if (!wifiTcpConnectionActive()) { 01408 wait(0.1); 01409 L4=0; 01410 continue; 01411 } 01412 01413 if (batteryGet() < BATTERY_MIN_LEVEL) { 01414 if (isExpExecuting) { 01415 fprintf(currentFile, "Experiment Finished due to Low Battery Level\n"); 01416 finishExperiment(); 01417 wifiEventsSendFinishExpInd(currentExpId, FileName); 01418 } 01419 01420 wifiEventsSendErrorsInd(ERROR_BATTERY_LOW); 01421 lightSet(LIGHT_OFF_INTENSITY); 01422 pumpSet(PUMP_OFF_INTENSITY); 01423 return; 01424 } 01425 01426 if (!isTimeRequested) { 01427 // Request current time 01428 DEBUG1("Send GET_TIME_REQ"); 01429 wifiEventsSendMsg(cisme_MessageType_GET_TIME_REQ, NULL, NULL); 01430 wifiEventsSendErrorsInd(startErrors); 01431 isTimeRequested = true; 01432 } 01433 01434 wifiEventsSendBeatInd(); 01435 01436 wifiEventsHandleMsg(); 01437 } 01438 } 01439 01440 #endif // USE_WIFI
Generated on Fri Sep 23 2022 19:29:17 by
1.7.2