DESERT 3.6.1
Loading...
Searching...
No Matches
uwevologicss2cmodem.cpp
Go to the documentation of this file.
1//
2// Copyright (c) 2019 Regents of the SIGNET lab, University of Padova.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions
7// are met:
8// 1. Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution.
13// 3. Neither the name of the University of Padova (SIGNET lab) nor the
14// names of its contributors may be used to endorse or promote products
15// derived from this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "phymac-clmsg.h"
30#include <clmessage.h>
31#include <hdr-uwal.h>
32#include <ms2c_ClMessage.h>
33#include <uwal.h>
34#include <uwevologicss2cmodem.h>
35#include <uwphy-clmsg.h>
36#include <uwsocket.h>
37#include <uwserial.h>
38
39#include <cstring>
40#include <iostream>
41#include <iterator>
42#include <string>
43#include <ostream>
44
45const std::chrono::milliseconds UwEvoLogicsS2CModem::MODEM_TIMEOUT =
46 std::chrono::milliseconds(210);
47
48const std::chrono::seconds UwEvoLogicsS2CModem::WAIT_DELIVERY_BURST =
49 std::chrono::seconds(5);
50
51const std::chrono::milliseconds UwEvoLogicsS2CModem::WAIT_DELIVERY_IM =
52 std::chrono::milliseconds(200);
53
55
60static class UwEvoLogicsS2C_TclClass : public TclClass
61{
62
63public:
65 : TclClass("Module/UW/UwModem/EvoLogicsS2C")
66 {
67 }
68
69 TclObject *
70 create(int args, const char *const *argv)
71 {
72 return (new UwEvoLogicsS2CModem());
73 }
74
76
78 : UwModem()
79 , p_connector(new UwSocket())
80 , p_interpreter(new UwInterpreterS2C())
81 , status(ModemState::AVAILABLE)
82 , tx_status(TransmissionState::TX_IDLE)
83 , status_m()
84 , tx_status_m()
85 , tx_queue_m()
86 , status_cv()
87 , tx_status_cv()
88 , tx_queue_cv()
89 , receiving(false)
90 , transmitting(false)
91 , im_status_updated(false)
92 , rx_thread()
93 , tx_thread()
94 , tx_mode(TransmissionMode::IM)
95 , ack_mode(false)
96 , curr_source_level(3)
97 , n_rx_failed(0)
98 , pend_source_level(3)
99 , source_level_change(false)
100 , size2dur_()
101 , txdur_file_name_("")
102 , txdur_token_separator_(';')
103 , initLUT_(false)
104
105{
106 bind("buffer_size", (int *) &DATA_BUFFER_LEN);
107 bind("max_read_size", (int *) &MAX_READ_BYTES);
108 bind("max_n_status_queries",
110}
111
116
117void
119{
120 // push new incoming pck into tx_queue
121 hdr_cmn *ch = HDR_CMN(p);
122 hdr_MPhy *ph = HDR_MPHY(p);
123 if (ch->direction() == hdr_cmn::UP) {
124 if (isOn == true) {
125 startRx(p);
126 endRx(p);
127 } else {
128 Packet::free(p);
129 }
130 } else { // DOWN
131 if (!isOn) {
132 return;
133 }
134 ph->Pr = 0;
135 ph->Pn = 0;
136 ph->Pi = 0;
137 ph->txtime = NOW;
138 ph->rxtime = ph->txtime;
139
140 ph->worth_tracing = false;
141
142 ph->srcSpectralMask = getTxSpectralMask(p);
143 ph->srcAntenna = getTxAntenna(p);
144 ph->srcPosition = getPosition();
145 ph->dstSpectralMask = 0;
146 ph->dstPosition = 0;
147 ph->dstAntenna = 0;
148 ph->modulationType = getModulationType(p);
149 ph->duration = getTxDuration(p);
150
151 std::unique_lock<std::mutex> tx_lock(tx_queue_m);
152 tx_queue.push(p);
153 tx_lock.unlock();
155 "EVOLOGICSS2CMODEM",
156 "recv::PUSHING_IN_TX_QUEUE");
157 tx_queue_cv.notify_one();
158 }
159}
160
161int
162UwEvoLogicsS2CModem::command(int argc, const char *const *argv)
163{
164 // Tcl &tcl = Tcl::instance();
165
166 if (argc == 2) {
167 if (!strcmp(argv[1], "start")) {
168 start();
169 return TCL_OK;
170 }
171 if (!strcmp(argv[1], "stop")) {
172 stop();
173 return TCL_OK;
174 }
175 if (!strcmp(argv[1], "setBurstMode")) {
177 return TCL_OK;
178 }
179 if (!strcmp(argv[1], "setIMMode")) {
181 return TCL_OK;
182 }
183 if (!strcmp(argv[1], "enableIMAck")) {
184 ack_mode = true;
185 return TCL_OK;
186 }
187 if (!strcmp(argv[1], "disableIMAck")) {
188 ack_mode = false;
189 return TCL_OK;
190 }
191 if (!strcmp(argv[1], "enableExtProtoMode")) {
192 p_interpreter->setExtProtoMode(true);
193 return TCL_OK;
194 }
195 if (!strcmp(argv[1], "disableExtProtoMode")) {
196 p_interpreter->setExtProtoMode(false);
197 return TCL_OK;
198 }
199 if (!strcmp(argv[1], "initLUT")) {
201 return TCL_OK;
202 }
203 } else if (argc == 3) {
204 if (!strcmp(argv[1], "setConnector")) {
205 if(!strcmp(argv[2], "SOCKET")) {
206 p_connector.reset(new UwSocket());
207 p_interpreter->setTerminator("\n");
208 return TCL_OK;
209 }
210 if(!strcmp(argv[2], "SERIAL")) {
211 p_connector.reset(new UwSerial());
212 p_interpreter->setTerminator("\r");
213 return TCL_OK;
214 }
215 fprintf(stderr, "Invalid connector type, choose between SOCKET and SERIAL");
216 return TCL_ERROR;
217 }
218 if (!strcmp(argv[1], "setSourceLevel")) {
219 std::stringstream sl_ss(argv[2]);
220 int sl_;
221 if (sl_ss >> sl_)
222 return TCL_OK;
223 else
224 return TCL_ERROR;
225 }
226 if (!strcmp(argv[1], "setTXDurationFileName")) {
227 std::string tmp_ = ((char *) argv[2]);
228 if (tmp_.size() == 0) {
229 fprintf(stderr, "Empty string for the file name");
230 return TCL_ERROR;
231 }
232 txdur_file_name_ = tmp_;
233 return TCL_OK;
234 }
235 if (!strcmp(argv[1], "setLUTSeparator")) {
236 string tmp_ = ((char *) argv[2]);
237 if (tmp_.size() == 0) {
238 fprintf(stderr, "Empty char for the file separator");
239 return TCL_ERROR;
240 }
241 txdur_token_separator_ = tmp_.at(0);
242 return TCL_OK;
243 }
244 }
245
246 return UwModem::command(argc, argv);
247}
248
249void
251{
252 ifstream input_file_;
253 string line_;
254
255 input_file_.open(txdur_file_name_.c_str());
256
257 if (input_file_.is_open()) {
258 while (std::getline(input_file_, line_)) {
259 if (line_[0] == '#')
260 continue;
261
262 std::istringstream line_stream(line_);
263 std::string token;
264
265 std::getline(line_stream, token, txdur_token_separator_);
266 int size = std::atoi(token.c_str());
267 if (size < 1) {
269 "EVOLOGICSS2CMODEM",
270 "initializeLUT::INVALID_PKT_SIZE " + token);
271 continue;
272 }
273
274 std::getline(line_stream, token, txdur_token_separator_);
275 double duration = 0;
276 char *end {};
277 if (token.length() > 0) {
278 duration = std::strtod(token.c_str(), &end);
279
280 if (!(duration > 0))
282 "EVOLOGICSS2CMODEM",
283 "initializeLUT::INVALID_DURATION_FOR_PKT_SIZE "
284 + std::to_string(size));
285 }
286
287 std::getline(line_stream, token, txdur_token_separator_);
288 double proc_delay = 0;
289 if (token.length() > 0) {
290 proc_delay = std::strtod(token.c_str(), &end);
291 duration += proc_delay;
292
293 if (!(proc_delay > 0))
295 "EVOLOGICSS2CMODEM",
296 "initializeLUT::INVALID_PROC_DELAY_FOR_PKT_SIZE "
297 + std::to_string(size));
298 }
299
300 size2dur_[size] = duration;
301 }
302
303 initLUT_ = true;
304 } else {
306 "EVOLOGICSS2CMODEM",
307 "initializeLUT::FAIL_TO_READ_FROM_FILE " + txdur_file_name_);
308 }
309}
310
311int
313{
314 if (m->type() == CLMSG_S2C_POWER_LEVEL) {
315 ClMsgS2CPowerLevel *msg = static_cast<ClMsgS2CPowerLevel *>(m);
316 if (msg->getReqType() == ClMsgUwPhy::SET_REQ) {
318 "UWEVOLOGICSS2CMODEM",
319 "RECEIVED_CLMSG_FOR_POWER_CHANGE");
321 source_level_change = true;
323 return 0;
324 } else if (msg->getReqType() == ClMsgUwPhy::GET_REQ) {
327 return 0;
328 }
329 } else if (m->type() == CLMSG_S2C_TX_MODE) {
330 ClMsgS2CTxMode *msg = static_cast<ClMsgS2CTxMode *>(m);
331 if (msg->getReqType() == ClMsgUwPhy::SET_REQ) {
334 } else {
336 }
338 return 0;
339 } else if (msg->getReqType() == ClMsgUwPhy::GET_REQ) {
342 } else {
344 }
346 return 0;
347 }
348 } else if (m->type() == CLMSG_S2C_RX_FAILED) {
349 ClMsgS2CRxFailed *msg = static_cast<ClMsgS2CRxFailed *>(m);
350 if (msg->getReqType() == ClMsgUwPhy::GET_REQ) {
353 return 0;
354 } else {
355 return 1;
356 }
357 } else if (m->type() == CLMSG_MAC2PHY_GETTXDURATION) {
358 Packet *p = ((ClMsgMac2PhyGetTxDuration *) m)->pkt;
359 hdr_cmn *ch = HDR_CMN(p);
360
361 if (ch->direction() == hdr_cmn::DOWN) {
362 double duration = getTxDuration(p);
363
364 if (duration > 0)
366 "EVOLOGICSS2CMODEM",
367 "recvSyncClMsg::SET_TXDURATION " +
368 std::to_string(duration));
369
370 ((ClMsgMac2PhyGetTxDuration *) m)->setDuration(duration);
371
372 return 0;
373 }
374
375 // Don't set TX duration on RX.
376 ((ClMsgMac2PhyGetTxDuration *) m)->setDuration(-1);
377
378 return 1;
379 }
380
381 return MPhy::recvSyncClMsg(m);
382}
383
384double
386{
387 hdr_uwal *uwalh = HDR_UWAL(p);
388 double tx_duration = -1;
389
390 if (initLUT_)
391 tx_duration = size2dur_[uwalh->binPktLength()];
392 else
394 "EVOLOGICSS2CMODEM",
395 "getTxDuration::FAIL_TO_GET_TXDURATION");
396
397 return tx_duration;
398}
399
400bool
402{
403 std::string config_cmd{""};
404
405 switch (cmd) {
406 case Config::ATL_GET: {
407 std::string command = p_interpreter->buildGetATL();
408 break;
409 }
410 case Config::ATL_SET: {
411 std::string command = p_interpreter->buildSetATL(pend_source_level);
412 break;
413 }
414 case Config::ATAL_GET: {
415 std::string command = p_interpreter->buildGetATAL();
416 break;
417 }
418 case Config::ATAL_SET: {
419 std::string command = p_interpreter->buildSetATAL(modemID);
420 break;
421 }
423 std::string command = p_interpreter->buildATS();
424 break;
425 }
427 std::string command = p_interpreter->buildATV();
428 break;
429 }
430 default:
431 return false;
432 }
433
434 std::unique_lock<std::mutex> state_lock(status_m);
435
436 if (status_cv.wait_for(state_lock, MODEM_TIMEOUT, [&] {
437 return status == ModemState::AVAILABLE;
438 })) {
439
441
442 std::lock_guard<std::mutex> tx_state_lock(tx_status_m);
443
444 if (!p_connector->writeToDevice(config_cmd)) {
446 "EVOLOGICSS2CMODEM",
447 "configure::FAIL_TO_WRITE_TO_DEVICE=" + config_cmd);
448 return false;
449 }
450
451 state_lock.unlock();
453
454 } else {
455
456 return false;
457 }
458
459 return true;
460}
461
462void
464{
465 // this method does nothing in ns, so it can be called from an
466 // external thread
467 // save MAC and AL headers and write payload
468 hdr_mac *mach = HDR_MAC(p);
469 hdr_uwal *uwalh = HDR_UWAL(p);
470 std::string payload;
471 payload.assign(uwalh->binPkt(), uwalh->binPktLength());
472
473 // build command to perform a SEND or SENDIM
474 std::string cmd_s;
476 cmd_s = p_interpreter->buildSendIM(payload, mach->macDA(), ack_mode);
477 } else {
478 cmd_s = p_interpreter->buildSend(payload, mach->macDA());
479 }
480
482 "EVOLOGICSS2CMODEM",
483 "startTx::COMMAND_TX::" + cmd_s);
484
485 // write the obtained command to the device, through the connector
486 std::unique_lock<std::mutex> state_lock(status_m);
487 if (status_cv.wait_for(state_lock, MODEM_TIMEOUT, [&] {
488 return status == ModemState::AVAILABLE;
489 })) {
490
492
493 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
494
495 if ((p_connector->writeToDevice(cmd_s)) < 0) {
497 "EVOLOGICSS2CMODEM",
498 "startTx::FAIL_TO_WRITE_TO_DEVICE=" + cmd_s);
499 return;
500 }
501
503 status_cv.wait_for(state_lock, MODEM_TIMEOUT, [&] {
505 });
506 state_lock.unlock();
507
509
510 size_t status_polling_counter = 0;
511 im_status_updated.store(false);
512 while (status_polling_counter < MAX_N_STATUS_QUERIES &&
514
515 cmd_s = p_interpreter->buildATDI();
516
518 "EVOLOGICSS2CMODEM",
519 "startTx::SENDING=" + cmd_s);
520
521 if ((p_connector->writeToDevice(cmd_s)) < 0) {
523 "EVOLOGICSS2CMODEM",
524 "startTx::FAIL_TO_WRITE_TO_DEVICE=" + cmd_s);
525 }
526
527 tx_status_cv.wait_for(tx_state_lock, WAIT_DELIVERY_IM, [&] {
529 });
530
533 "EVOLOGICSS2CMODEM",
534 "startTx::TX_IDLE");
535 break;
536 } else {
537 im_status_updated.store(false);
539 "EVOLOGICSS2CMODEM",
540 "startTx::TX_PENDING");
541 }
542
543 status_polling_counter++;
544 }
545
546 // In case the attempts reached MAX_N_STATUS_QUERIES, force
547 // tx_status
548 if (status_polling_counter == MAX_N_STATUS_QUERIES &&
551 "EVOLOGICSS2CMODEM",
552 "startTx::MAX_N_STATUS_QUERIES_REACHED");
553 }
554
555 } else { // tx_mode == TransmissionMode::BURST
556 tx_status_cv.wait_for(tx_state_lock, WAIT_DELIVERY_BURST, [&] {
558 });
559 }
560
561 std::function<void(UwModem &, Packet * p)> callback =
563 ModemEvent e = {callback, p};
564 event_q.push(e);
565
566 } else {
568 "EVOLOGICSS2CMODEM",
569 "startTx::TIMEOUT_EXPIRED::FORCING_MODEM_AVAILABILITY");
571 }
572}
573
574void
576{
578 "EVOLOGICSS2CMODEM",
579 "startRx::CALL_PHY2MACSTARTRX");
580 Phy2MacStartRx(p);
581}
582
583void
585{
586 printOnLog(LogLevel::INFO, "EVOLOGICSS3CMODEM", "endRx::CALL_SENDUP");
587 sendUp(p, 0.01);
588}
589
590void
592{
593 if (modem_address == "") {
594 std::cout << "ERROR: Modem address not set!" << std::endl;
596 LogLevel::ERROR, "EVOLOGICSS2CMODEM", "start::ADDRESS_NOT_SET");
597 return;
598 }
599
600 if (!p_connector->openConnection(modem_address)) {
601 std::cout << "ERROR: connection to modem failed to open: "
602 << modem_address << std::endl;
604 "EVOLOGICSS2CMODEM",
605 "start::CONNECTION_OPEN_FAILED");
606 return;
607 }
608
609 // set flags to true so loops can start
610 receiving.store(true);
611 transmitting.store(true);
612
613 // branch off threads
614 rx_thread = std::thread(&UwEvoLogicsS2CModem::receivingData, this);
615
617
618 checkTimer = new CheckTimer(this);
619 checkTimer->resched(period);
620}
621
622void
624{
625
626 std::cout << "UwEvoLogicsS2CModem::stop() close conn " << std::endl;
627 printOnLog(LogLevel::INFO, "EVOLOGICSS2CMODEM", "stop::CLOSING_CONNECTION");
628
629 receiving.store(false);
630 transmitting.store(false);
631 tx_queue_cv.notify_one();
632 if (tx_thread.joinable())
633 tx_thread.join();
634 if (p_connector->isConnected() && !p_connector->closeConnection()) {
636 "EVOLOGICSS2CMODEM",
637 "stop::CONNECTION_CLOSE_FAIL");
638 }
639 if (rx_thread.joinable()) {
640 rx_thread.join();
641 }
642
643 checkTimer->force_cancel();
644}
645
646void
648{
649 while (transmitting.load()) {
650
651 std::unique_lock<std::mutex> tx_lock(tx_queue_m);
652 tx_queue_cv.wait(
653 tx_lock, [&] { return !tx_queue.empty() || !transmitting; });
654 if (!transmitting) {
655 break;
656 }
657
658 Packet *pck = tx_queue.front();
659 tx_queue.pop();
660 tx_lock.unlock();
661 if (pck) {
662 startTx(pck);
663 }
664
666 "EVOLOGICSS2CMODEM",
667 "transmittingData::BLOCKING_ON_NEXT_PACKET");
668 }
669}
670
671void
673{
675 std::fill(data_buffer.begin(), data_buffer.end(), '\0');
676 // iterators that keep track of read/write operations
677 std::vector<char>::iterator beg_it = data_buffer.begin();
678 std::vector<char>::iterator end_it = data_buffer.begin();
679 // iterators that keep track of commands research
680 std::vector<char>::iterator cmd_b = data_buffer.begin();
681 std::vector<char>::iterator cmd_e = data_buffer.begin();
683 int r_bytes = 0;
684 int offset = 0;
685
686 while (receiving.load()) {
687
688 r_bytes = p_connector->readFromDevice(
689 &(*beg_it) + offset, MAX_READ_BYTES - r_bytes);
690
691 end_it = beg_it + r_bytes + offset;
692
693 while (receiving.load() && r_bytes > 0 &&
694 (cmd = p_interpreter->findResponse(beg_it, end_it, cmd_b)) !=
696
697 while (receiving.load() &&
698 !p_interpreter->parseResponse(
699 cmd, end_it, cmd_b, cmd_e, rx_payload)) {
700
701 int new_r_bytes = p_connector->readFromDevice(
702 &(*end_it), MAX_READ_BYTES - r_bytes);
703
704 r_bytes += new_r_bytes;
705 end_it = beg_it + r_bytes;
706 }
707
709 "EVOLOGICSS2CMODEM",
710 "receivingData::RX_MSG=" + std::string(cmd_b, cmd_e));
711
712 updateStatus(cmd);
713 std::fill(cmd_b, cmd_e, '\0');
714 cmd_b = cmd_e + 1;
715 }
716
717 // check if bytes are left after parsing and move them to beginning
718 if ((int) (cmd_e - beg_it) < r_bytes) {
719 offset = r_bytes - (int) (cmd_e - beg_it);
720 std::copy(cmd_e, cmd_e + offset, data_buffer.begin());
721 } else {
722 offset = 0;
723 }
724 }
725}
726
727void
729{
730 std::unique_lock<std::mutex> state_lock(status_m);
731 switch (cmd) {
732
734
736 status_cv.notify_all();
737 state_lock.unlock();
738
739 Packet *p = Packet::alloc();
741 std::function<void(UwModem &, Packet * p)> callback =
743 ModemEvent e = {callback, p};
744 event_q.push(e);
745 break;
746 }
749 status_cv.notify_all();
750 state_lock.unlock();
751
752 Packet *p = Packet::alloc();
754 std::function<void(UwModem &, Packet * p)> callback =
756 ModemEvent e = {callback, p};
757 event_q.push(e);
758 break;
759 }
762 state_lock.unlock();
763 status_cv.notify_all();
764 break;
765 }
768 state_lock.unlock();
769 status_cv.notify_all();
770 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
772 im_status_updated.store(true);
773 tx_status_cv.notify_all();
774 break;
775 }
778 state_lock.unlock();
779 status_cv.notify_all();
780 break;
781 }
783 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
785 im_status_updated.store(true);
786 tx_status_cv.notify_all();
787 status_cv.notify_all();
788 break;
789 }
792 state_lock.unlock();
793 status_cv.notify_all();
794 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
796 im_status_updated.store(true);
797 tx_status_cv.notify_all();
798 break;
799 }
802 state_lock.unlock();
803 status_cv.notify_all();
804 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
806 tx_status_cv.notify_all();
807 break;
808 }
811 state_lock.unlock();
812 status_cv.notify_all();
813 break;
814 }
817 status_cv.notify_all();
818 break;
819 }
822 state_lock.unlock();
823 status_cv.notify_all();
824 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
826 im_status_updated.store(true);
827 tx_status_cv.notify_all();
828 break;
829 }
832 state_lock.unlock();
833 status_cv.notify_all();
834 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
836 im_status_updated.store(true);
837 tx_status_cv.notify_all();
838 break;
839 }
842 status_cv.notify_all();
843 break;
844 }
847 status_cv.notify_all();
848 break;
849 }
852 status_cv.notify_all();
853 break;
854 }
857 status_cv.notify_all();
858 break;
859 }
862 status_cv.notify_all();
863 break;
864 }
867 state_lock.unlock();
868 status_cv.notify_all();
869 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
871 im_status_updated.store(true);
872 tx_status_cv.notify_all();
873 break;
874 }
877 status_cv.notify_all();
878 break;
879 }
882 status_cv.notify_all();
883 break;
884 }
887 status_cv.notify_all();
888 break;
889 }
892 status_cv.notify_all();
893 break;
894 }
897 status_cv.notify_all();
898 break;
899 }
901 n_rx_failed++;
903 "EVOLOGICSS2CMODEM",
904 "updateStatus::FAILED_RX");
906 status_cv.notify_all();
907 break;
908 }
911 status_cv.notify_all();
912 break;
913 }
916 state_lock.unlock();
917 status_cv.notify_all();
918 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
920 im_status_updated.store(true);
921 tx_status_cv.notify_all();
922 break;
923 }
926 status_cv.notify_all();
927 break;
928 }
931 status_cv.notify_all();
932 break;
933 }
936 std::shared_ptr<USBLInfo> pos = p_interpreter->getUSBLInfo();
937
938 std::string log_msg = "updateStatus::USBLLONG::curr_time=" +
939 std::to_string(pos->curr_time) +
940 ",meas_time=" + std::to_string(pos->meas_time) +
941 ",remote_address=" + std::to_string(pos->r_address) +
942 ",X=" + std::to_string(pos->X) +
943 ",Y=" + std::to_string(pos->Y) +
944 ",Z=" + std::to_string(pos->Z) +
945 ",E=" + std::to_string(pos->E) +
946 ",N=" + std::to_string(pos->N) +
947 ",U=" + std::to_string(pos->U) +
948 ",accuracy=" + std::to_string(pos->accuracy);
949 printOnLog(LogLevel::INFO, "EVOLOGICSS2CMODEM", log_msg);
950
951 status_cv.notify_all();
952 break;
953 }
956 status_cv.notify_all();
957 break;
958 }
959 default: {
961 status_cv.notify_all();
962 }
963 }
964
965 printOnLog(LogLevel::DEBUG, "EVOLOGICSS2CMODEM", "updateStatus::END");
966}
967
968void
970{
971 hdr_cmn *ch = HDR_CMN(p);
972 ch->error_ = 1;
973}
974
975void
977{
978 hdr_uwal *uwalh = HDR_UWAL(p);
979 uwalh->binPktLength() = rx_payload.size();
980 std::memset(uwalh->binPkt(), 0, uwalh->binPktLength());
981 std::copy(rx_payload.begin(), rx_payload.end(), uwalh->binPkt());
982 HDR_CMN(p)->direction() = hdr_cmn::UP;
983}
Class representing the message for changing or retrieving the power level (source level)
void set_power_level(int level)
Set the poer level in the selected Cl message.
int get_power_level() const
Retrieve the power level specified in the Cl message.
Class representing the Cl message type used for retrieving the failed receptions counter of S2C devic...
void set_n_rx_failed(int n_failed)
Method used to set the number of reception failures in the message.
Cl Message type for setting the Tx Mode: Instant Message, Burst or Piggyback.
tx_mode_t get_tx_mode() const
Method used to retrieve the TX mode value in the message.
void set_tx_mode(tx_mode_t mode)
Method that sets the TX mode in the message to the specified value.
void setReqType(ReqType type)
method to set the request type
ReqType getReqType()
method to return the request type
std::mutex status_m
Mutex associated with the state machine of the modem.
int n_rx_failed
Number of failed receptions up to now.
static uint MAX_N_STATUS_QUERIES
Maximum number of time to query the modem transmission status before to discard the transmitted packe...
bool initLUT_
Flag that tells whether the TX duration LUT is loaded or not.
TransmissionMode tx_mode
Either burst or im.
TransmissionState tx_status
Variable holding the current transmission status of the modem.
void setFailedTx(Packet *p)
Method that allows to set the error flag on the packet to notify upper layers about un-tranmsitted pa...
virtual void recv(Packet *p)
Method that handles the reception of packets arriving from upper layers of the network simulator.
std::atomic< bool > transmitting
Atomic boolean variable that controls the transmitting looping thread.
std::condition_variable status_cv
Condition variable to wait for ModemState::AVAILABLE.
std::atomic< bool > im_status_updated
Atomic boolean variable controlling if the modem had responded to ATDI.
int pend_source_level
Pending source level, requested but not set.
std::condition_variable tx_status_cv
Condition variable to wait for TransmissionState::TX_IDLE.
void updateStatus(UwInterpreterS2C::Response cmd)
Method that updates the status of the modem State Machine: state change is triggered by reception of ...
void createRxPacket(Packet *p)
Method that fills up a packet with the needed header and payload and makes it ready to be sent to the...
std::thread rx_thread
Object with the rx thread.
UwEvoLogicsS2CModem()
Constructor of the UwEvoLogicsS2CModem class.
std::mutex tx_queue_m
Mutex associated with the transmission queue.
virtual void transmittingData()
Method that detach a thread devoted to sending packets found in tx_queue.
virtual void initializeLUT()
Method that loads the TX LUT into a map.
static const std::chrono::seconds WAIT_DELIVERY_BURST
Time interval tu wait for a burst message tobe confirmed through a DELIVERED response.
bool source_level_change
Flag that tells a new SL value to be applied.
virtual void stop()
Method that stops the driver operations.
static const std::chrono::milliseconds MODEM_TIMEOUT
Maximum time to wait for modem to become ModemState::AVAILABLE.
bool ack_mode
Set to true to enable IM ack.
std::string rx_payload
String that is updated witn each new received messsage.
std::atomic< bool > receiving
Atomic boolean variable that controls the receiving looping thread.
Config
Enum listing the availbale configuration settings.
TransmissionMode
Transmission mode: either IM or BURST See the EvoLogics S2C manuals or reach for www....
TransmissionState
Transmission state: controls the flow of execution for sending commands to the S2C device.
virtual void startRx(Packet *p)
Method that starts a packet reception.
std::condition_variable tx_queue_cv
Condition variable that is linked with the transmitting queue.
virtual void receivingData()
Mehod that detach a thread devoted to receiving data from the connector.
virtual void endRx(Packet *p)
Method that ends a packet reception.
char txdur_token_separator_
TX duration LUT separator.
virtual void start()
Method that starts the driver operations.
ModemState status
Variable holding the current status of the modem.
virtual ~UwEvoLogicsS2CModem()
Destructor of the UwEvoLogicsS2CModem class.
TransmissionDurationLUT size2dur_
Map from size [byte] to TX duration [s].
int curr_source_level
Current source level already set in device.
std::string txdur_file_name_
TX duration LUT file name.
virtual bool configure(Config cmd)
Method that sends a written configuration the the EvoLgoics modem.
static const std::chrono::milliseconds WAIT_DELIVERY_IM
Time interval to wait for the modem notifying that there no more IM in its queue and a new IM can be ...
virtual double getTxDuration(Packet *p)
Method that return the duration of a given transmitted packet.
virtual int command(int argc, const char *const *argv)
Tcl command interpreter: Method that maps Tcl commands into C++ methods.
std::unique_ptr< UwInterpreterS2C > p_interpreter
Pointer to Interpreter object to parse device syntax.
std::mutex tx_status_m
Mutex associated with the transmission state machine of the modem.
std::thread tx_thread
Object with the tx thread.
virtual int recvSyncClMsg(ClMessage *m)
Cross-Layer messages synchronous interpreter.
std::unique_ptr< UwConnector > p_connector
Pointer to Connector object that interfaces with the device.
virtual void startTx(Packet *p)
Method that triggers the transmission of a packet through a specified modem.
Class to create the Otcl shadow object for an object of the class UwEvoLogicsS2CModem.
TclObject * create(int args, const char *const *argv)
Response
Enum listing the types of commands that could be received or sent by a S2C device; See the EvoLogics ...
Class that implements the interface to DESERT, as used through Tcl scripts.
Definition uwmodem.h:62
void realTxEnded(Packet *p)
Method to call endTx from end of real packet transmission.
Definition uwmodem.h:219
friend class CheckTimer
Definition uwmodem.h:63
std::string modem_address
String containing the address needed to connect to the device In case of socket, it may be expressed ...
Definition uwmodem.h:252
virtual void recv(Packet *p)=0
Method that handles the reception of packets arriving from the upper layers of the network simulator.
std::queue< ModemEvent > event_q
Queue of events that are scheduled for NS2 to execute (callbacks)
Definition uwmodem.h:269
int MAX_READ_BYTES
Maximum number of bytes to be read by a single dump of data.
Definition uwmodem.h:245
CheckTimer * checkTimer
Pointer to an object to schedule the "check-modem" events.
Definition uwmodem.h:265
std::queue< Packet * > tx_queue
Modem's transmission queue: holds packets that are to be transmitted.
Definition uwmodem.h:234
void printOnLog(LogLevel log_level, string module, string message)
Function that, given the appropriate level of log, prints to the set log file the provided log messag...
Definition uwmodem.cpp:102
unsigned int DATA_BUFFER_LEN
Size of the buffer that holds data.
Definition uwmodem.h:242
virtual int getModulationType(Packet *P)
Method that should return the modulation type used for the packet being transmitted.
Definition uwmodem.h:152
virtual int command(int argc, const char *const *argv)
Tcl command interpreter: Method that maps Tcl commands into C++ methods.
Definition uwmodem.cpp:127
std::vector< char > data_buffer
Char buffer (vector) that holds data read from the modem (unparsed data) Main container for data rece...
Definition uwmodem.h:231
int modemID
Number used for identification purposes: not specified.
Definition uwmodem.h:225
double period
Checking period of the modem's buffer.
Definition uwmodem.h:267
Class that implements serial port connection.
Definition uwserial.h:53
Class that implements a TCP or UDP socket.
Definition uwsocket.h:59
Header of the class providing the Uwal header's description.
#define HDR_UWAL(p)
Definition hdr-uwal.h:43
hdr_uwal describes the packet header used by Uwal objects.
Definition hdr-uwal.h:52
char * binPkt()
Return to the binPkt_ array pointer.
Definition hdr-uwal.h:141
uint32_t & binPktLength()
Reference to the binPktLength_ variable.
Definition hdr-uwal.h:150
Header of the main class that implements the adaptation layer between ns2/NS-Miracle and binary data ...
UwEvoLogicsS2C_TclClass class_evologicss2c
Header of the main class that implements the drivers to manage the EvoLogics S2C line of devices....
ModemState
Enum containing the possible statuses of the driver.
Definition of ClMsgUwMmac class.
This implements a generic serial connector .
Class that implements a connector and, specifically, the socket connector. BSD sockets are used,...