Custom Channel Plan version of MTDOT Box firmware

Dependencies:   DOGS102 GpsParser ISL29011 MMA845x MPL3115A2 MTS-Serial NCP5623B libmDot-Custom mDot_Channel_Plans

Fork of MTDOT-BOX-EVB-Factory-Firmware by MultiTech

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ModeSingle.cpp Source File

ModeSingle.cpp

00001 /* Copyright (c) <2016> <MultiTech Systems>, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction, 
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or 
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 
00019 #include "ModeSingle.h"
00020 #include "MTSLog.h"
00021 
00022 ModeSingle::ModeSingle(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps, SensorHandler* sensors)
00023   : Mode(lcd, buttons, dot, lora, gps, sensors),
00024     _help(lcd),
00025     _file(lcd),
00026     _confirm(lcd),
00027     _progress(lcd),
00028     _success(lcd),
00029     _failure(lcd)
00030 {}
00031 
00032 ModeSingle::~ModeSingle() {}
00033 
00034 bool ModeSingle::start() {
00035     bool data_file = false;
00036     bool send_link_check = false;
00037     bool send_data = false;
00038     bool no_channel_link_check = false;
00039     bool no_channel_data = false;
00040 
00041     // clear any stale signals
00042     osSignalClear(_main_id, buttonSignal | loraSignal);
00043 
00044     _initial_data_rate = _dot->getTxDataRate();
00045     _initial_power = _dot->getTxPower();
00046 
00047     // see if we're supposed to send the data packet after success
00048     // that item is stored in the mDot::StartUpMode config field
00049     _send_data = _dot->getStartUpMode();
00050 
00051     // see if survey data file exists
00052     std::vector<mDot::mdot_file> files = _dot->listUserFiles();
00053     for (std::vector<mDot::mdot_file>::iterator it = files.begin(); it != files.end(); it++) {
00054         if (strcmp(it->name, file_name) == 0) {
00055             logInfo("found survey data file");
00056             data_file = true;
00057             break;
00058         }
00059     }
00060     if (data_file) {
00061         _state = check_file;
00062         _file.display();
00063     } else {
00064         _state = show_help;
00065         _index = 0;
00066         displayHelp();
00067     }
00068 
00069     while (true) {
00070         osEvent e = Thread::signal_wait(0, 250);
00071         if (e.status == osEventSignal) {
00072             if (e.value.signals & buttonSignal) {
00073                 _be = _buttons->getButtonEvent();
00074 
00075                 switch (_be) {
00076                     case ButtonHandler::sw1_press:
00077                         switch (_state) {
00078                             case check_file:
00079                                 _state = show_help;
00080                                 _index = getIndex(single);
00081                                 displayHelp();
00082                                 break;
00083                             case confirm:
00084                                 _state = check_file;
00085                                 _file.display();
00086                                 break;
00087                             case show_help:
00088                                 incrementRatePower();
00089                                 _help.updateMsg(formatRatePower());
00090                                 break;
00091                             case success:
00092                                 incrementRatePower();
00093                                 _success.updateInfo(formatRatePower());
00094                                 break;
00095                             case failure:
00096                                 incrementRatePower();
00097                                 _failure.updateInfo(formatRatePower());
00098                                 break;
00099                         }
00100                         break;
00101 
00102                     case ButtonHandler::sw2_press:
00103                         switch (_state) {
00104                             case check_file:
00105                                 _state = confirm;
00106                                 _confirm.display();
00107                                 break;
00108                             case confirm:
00109                                 _state = show_help;
00110                                 logInfo("deleting survey data file");
00111                                 _dot->deleteUserFile(file_name);
00112                                 _index = 0;
00113                                 displayHelp();
00114                                 break;
00115                             case show_help:
00116                                 _state = in_progress;
00117                                 _progress.display();
00118                                 if (_dot->getNextTxMs() > 0)
00119                                     no_channel_link_check = true;
00120                                 else 
00121                                     send_link_check = true;
00122                                 break;
00123                             case success:
00124                                 _state = in_progress;
00125                                 _progress.display();
00126                                 if (_dot->getNextTxMs() > 0)
00127                                     no_channel_link_check = true;
00128                                 else 
00129                                     send_link_check = true;
00130                                 break;
00131                             case failure:
00132                                 _state = in_progress;
00133                                 _progress.display();
00134                                 if (_dot->getNextTxMs() > 0)
00135                                     no_channel_link_check = true;
00136                                 else 
00137                                     send_link_check = true;
00138                                 break;
00139                         }
00140                         break;
00141                     case ButtonHandler::sw1_hold:
00142                         _dot->setTxDataRate(_initial_data_rate);
00143                         _dot->setTxPower(_initial_power);
00144                         return true;
00145                 }
00146             }
00147             if (e.value.signals & loraSignal) {
00148                 _ls = _lora->getStatus();
00149                 switch (_ls) {
00150                     case LoRaHandler::link_check_success:
00151                         switch (_state) {
00152                             case in_progress:
00153                                 _link_check_result = _lora->getLinkCheckResults();
00154                                 displaySuccess();
00155                                 logInfo("link check successful\tMargin %ld\tRSSI %d dBm\tSNR %2.3f", _link_check_result.up.dBm, _link_check_result.down.rssi, (float)_link_check_result.down.snr / 10.0);
00156                                 updateData(_data, single, true);
00157                                 appendDataFile(_data);
00158                                 if (_send_data) {
00159                                     _state = data;
00160                                     if (_dot->getNextTxMs() > 0)
00161                                         no_channel_data = true;
00162                                     else
00163                                         send_data = true;
00164                                 } else {
00165                                     _state = success;
00166                                     _success.updateSw1("  DR/PWR");
00167                                     _success.updateSw2("Survey");
00168                                 }
00169                                 break;
00170                         }
00171                         break;
00172 
00173                     case LoRaHandler::link_check_failure:
00174                         switch (_state) {
00175                             case in_progress:
00176                                 _state = failure;
00177                                 _failure.display();
00178                                 _failure.updateId(_index);
00179                                 // mDot::DataRateStr returns format DRXX - we only want to display the XX part
00180                                 _failure.updateRate(_dot->DataRateStr(_data_rate).substr(2));
00181                                 updateData(_data, single, false);
00182                                 appendDataFile(_data);
00183                                 _failure.updatePower(_power);
00184                                 if (_gps_available && _gps->getLockStatus()) {
00185                                     GPSPARSER::latitude lat = _gps->getLatitude();
00186                                     GPSPARSER::longitude lon = _gps->getLongitude();
00187                                     struct tm time = _gps->getTimestamp();
00188                                     _failure.updateGpsLatitude(lat);
00189                                     _failure.updateGpsLongitude(lon);
00190                                     _failure.updateGpsTime(time);
00191                                 } else {
00192                                     _failure.updateGpsLatitude("No GPS Lock");
00193                                 }
00194                                 _failure.updateSw1("  DR/PWR");
00195                                 _failure.updateSw2("Survey");
00196                                 logInfo("link check failed");
00197                                 break;
00198                         }
00199                         break;
00200 
00201                     case LoRaHandler::send_success:
00202                         switch (_state) {
00203                             case data:
00204                                 _state = success;
00205                                 _success.updateInfo("                 ");
00206                                 _success.updateSw1("  DR/PWR");
00207                                 _success.updateSw2("Survey");
00208                                 // turn acks and receive windows back on
00209                                 _dot->setAck(1);
00210                                 _dot->setTxWait(true);
00211                                 logInfo("data send success");
00212                                 break;
00213                         }
00214                         break;
00215 
00216                     case LoRaHandler::send_failure:
00217                         switch (_state) {
00218                             case data:
00219                                 _state = success;
00220                                 _success.updateInfo("                 ");
00221                                 _success.updateSw1("  DR/PWR");
00222                                 _success.updateSw2("Survey");
00223                                 // turn acks and receive windows back on
00224                                 _dot->setAck(1);
00225                                 _dot->setTxWait(true);
00226                                 logInfo("data send failed");
00227                                 break;
00228                         }
00229                         break;
00230                 }
00231             }
00232         }
00233 
00234         if (no_channel_link_check) {
00235             uint32_t t = _dot->getNextTxMs();
00236             if (t > 0) {
00237                 logInfo("next tx %lu ms", t);
00238                 _progress.updateCountdown(t / 1000);
00239             } else {
00240                 _progress.display();
00241                 no_channel_link_check = false;
00242                 send_link_check = true;
00243             }
00244         }
00245         if (no_channel_data) {
00246             uint32_t t = _dot->getNextTxMs();
00247             if (t > 0) {
00248                 logInfo("next tx %lu ms", t);
00249                 _success.updateCountdown(t / 1000);
00250             } else {
00251                 displaySuccess();
00252                 no_channel_data = false;
00253                 send_data = true;
00254             }
00255         }
00256         if (send_link_check) {
00257             logInfo("sending link check %s %d", _dot->DataRateStr(_data_rate).c_str(), _power);
00258             send_link_check = false;
00259             _dot->setTxDataRate(_data_rate);
00260             _dot->setTxPower(_power);
00261             _lora->linkCheck();
00262             _index++;
00263         }
00264         if (send_data) {
00265             std::vector<uint8_t> s_data = formatSurveyData(_data);
00266             logInfo("sending data %s %d", _dot->DataRateStr(_data_rate).c_str(), _power);
00267             send_data = false;
00268             _success.updateInfo("Data Sending...");
00269             _dot->setTxDataRate(_data_rate);
00270             _dot->setTxPower(_power);
00271             // we don't care if the server actually gets this packet or not
00272             // we won't retry anyway
00273             _dot->setAck(0);
00274             _dot->setTxWait(false);
00275             _lora->send(s_data);
00276             osDelay(500);
00277         }
00278     }
00279 }
00280 
00281 void ModeSingle::displayHelp() {
00282     _help.display();
00283     _help.updateMode("Survey Single");
00284     _help.updateSw1("  DR/PWR");
00285     _help.updateSw2("Survey");
00286     _help.updateMsg(formatRatePower());
00287 }
00288 
00289 void ModeSingle::displaySuccess() {
00290     uint8_t fix = _gps->getFixStatus();
00291     _success.display();
00292     _success.updateId(_index);
00293     // mDot::DataRateStr returns format SF_XX - we only want to display the XX part
00294     _success.updateRate(_dot->DataRateStr(_data_rate).substr(2));
00295     _success.updatePower(_power);
00296     _success.updateStats(_link_check_result);
00297     if (_gps_available && _gps->getLockStatus()) {
00298         GPSPARSER::latitude lat = _gps->getLatitude();
00299         GPSPARSER::longitude lon = _gps->getLongitude();
00300         struct tm time = _gps->getTimestamp();
00301         _success.updateGpsLatitude(lat);
00302         _success.updateGpsLongitude(lon);
00303         _success.updateGpsTime(time);
00304     } else {
00305         _success.updateGpsLatitude("No GPS Lock");
00306     }
00307 }
00308 
00309 std::string ModeSingle::formatRatePower() {
00310     std::string msg;
00311     char buf[8];
00312     size_t size;
00313 
00314     msg += "DR=";
00315     msg += _dot->DataRateStr(_data_rate).substr(2);
00316     msg += " P=";
00317     size = snprintf(buf, sizeof(buf), "%u", _power);
00318     msg.append(buf, size);
00319 
00320     return msg;
00321 }
00322 
00323 void ModeSingle::incrementRatePower() {
00324     if (_power == 20) {
00325         _power = 2;
00326         _data_rate++;        
00327         if (_data_rate > mDot::DR7) {
00328              _data_rate = mDot::DR0;       
00329         }
00330     } else {
00331         _power += 3;
00332     }
00333 
00334     logInfo("new data rate %s, power %lu", mDot::DataRateStr(_data_rate).c_str(), _power);
00335 }
00336