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
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
Generated on Tue Jul 12 2022 13:07:49 by 1.7.2