peer to peer rx terminal
Dependencies: ISL29011 libxDot-dev-mbed5-deprecated
Fork of peer-to-peer_rxtx by
main.cpp@61:ebe1838a9301, 2018-03-10 (annotated)
- Committer:
- NataliaRequejo
- Date:
- Sat Mar 10 14:05:32 2018 +0000
- Revision:
- 61:ebe1838a9301
- Parent:
- 29:0b58d21e87d6
- Child:
- 62:5a4266922385
Ejemplo Peer-To-Peer y OTA
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Jonathan Austin |
0:2757d7abb7d9 | 1 | #include "mbed.h" |
NataliaRequejo | 61:ebe1838a9301 | 2 | #include "mDot.h" |
NataliaRequejo | 61:ebe1838a9301 | 3 | #include "MTSLog.h" |
NataliaRequejo | 61:ebe1838a9301 | 4 | #include "MTSText.h" |
NataliaRequejo | 61:ebe1838a9301 | 5 | #include "RadioEvent.h" |
NataliaRequejo | 61:ebe1838a9301 | 6 | #include "ChannelPlans.h" |
NataliaRequejo | 61:ebe1838a9301 | 7 | #include <string> |
NataliaRequejo | 61:ebe1838a9301 | 8 | #include <vector> |
NataliaRequejo | 61:ebe1838a9301 | 9 | |
NataliaRequejo | 61:ebe1838a9301 | 10 | //#define PEER_TO_PEER_SAMPLE 1 |
NataliaRequejo | 61:ebe1838a9301 | 11 | #define OTA |
NataliaRequejo | 61:ebe1838a9301 | 12 | using namespace mts; |
NataliaRequejo | 61:ebe1838a9301 | 13 | #if defined(PEER_TO_PEER_SAMPLE) |
NataliaRequejo | 61:ebe1838a9301 | 14 | static uint8_t network_address[] = { 0x01, 0x02, 0x03, 0x04 }; |
NataliaRequejo | 61:ebe1838a9301 | 15 | static uint8_t network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 }; |
NataliaRequejo | 61:ebe1838a9301 | 16 | static uint8_t data_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 }; |
NataliaRequejo | 61:ebe1838a9301 | 17 | #else |
Jonathan Austin |
0:2757d7abb7d9 | 18 | |
NataliaRequejo | 61:ebe1838a9301 | 19 | static std::string config_network_name = "conduitUNSAM"; |
NataliaRequejo | 61:ebe1838a9301 | 20 | static std::string config_network_pass = "conduitUNSAM"; |
NataliaRequejo | 61:ebe1838a9301 | 21 | static uint8_t config_frequency_sub_band = 4; |
NataliaRequejo | 61:ebe1838a9301 | 22 | #endif |
NataliaRequejo | 61:ebe1838a9301 | 23 | |
NataliaRequejo | 61:ebe1838a9301 | 24 | mDot* dot; |
NataliaRequejo | 61:ebe1838a9301 | 25 | lora::ChannelPlan* plan = NULL; |
NataliaRequejo | 61:ebe1838a9301 | 26 | |
NataliaRequejo | 61:ebe1838a9301 | 27 | void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power) { |
NataliaRequejo | 61:ebe1838a9301 | 28 | std::vector<uint8_t> current_network_address = dot->getNetworkAddress(); |
NataliaRequejo | 61:ebe1838a9301 | 29 | std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey(); |
NataliaRequejo | 61:ebe1838a9301 | 30 | std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey(); |
NataliaRequejo | 61:ebe1838a9301 | 31 | uint32_t current_tx_frequency = dot->getTxFrequency(); |
NataliaRequejo | 61:ebe1838a9301 | 32 | uint8_t current_tx_datarate = dot->getTxDataRate(); |
NataliaRequejo | 61:ebe1838a9301 | 33 | uint8_t current_tx_power = dot->getTxPower(); |
NataliaRequejo | 61:ebe1838a9301 | 34 | |
NataliaRequejo | 61:ebe1838a9301 | 35 | std::vector<uint8_t> network_address_vector(network_address, network_address + 4); |
NataliaRequejo | 61:ebe1838a9301 | 36 | std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16); |
NataliaRequejo | 61:ebe1838a9301 | 37 | std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16); |
Jonathan Austin |
0:2757d7abb7d9 | 38 | |
NataliaRequejo | 61:ebe1838a9301 | 39 | if (current_network_address != network_address_vector) { |
NataliaRequejo | 61:ebe1838a9301 | 40 | logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 41 | if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 42 | logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 43 | } |
NataliaRequejo | 61:ebe1838a9301 | 44 | } |
NataliaRequejo | 61:ebe1838a9301 | 45 | |
NataliaRequejo | 61:ebe1838a9301 | 46 | if (current_network_session_key != network_session_key_vector) { |
NataliaRequejo | 61:ebe1838a9301 | 47 | logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 48 | if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 49 | logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 50 | } |
NataliaRequejo | 61:ebe1838a9301 | 51 | } |
NataliaRequejo | 61:ebe1838a9301 | 52 | |
NataliaRequejo | 61:ebe1838a9301 | 53 | if (current_data_session_key != data_session_key_vector) { |
NataliaRequejo | 61:ebe1838a9301 | 54 | logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 55 | if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 56 | logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 57 | } |
NataliaRequejo | 61:ebe1838a9301 | 58 | } |
NataliaRequejo | 61:ebe1838a9301 | 59 | |
NataliaRequejo | 61:ebe1838a9301 | 60 | if (current_tx_frequency != tx_frequency) { |
NataliaRequejo | 61:ebe1838a9301 | 61 | logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency); |
NataliaRequejo | 61:ebe1838a9301 | 62 | if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 63 | logError("failed to set TX frequency to %lu", tx_frequency); |
NataliaRequejo | 61:ebe1838a9301 | 64 | } |
NataliaRequejo | 61:ebe1838a9301 | 65 | } |
NataliaRequejo | 61:ebe1838a9301 | 66 | |
NataliaRequejo | 61:ebe1838a9301 | 67 | if (current_tx_datarate != tx_datarate) { |
NataliaRequejo | 61:ebe1838a9301 | 68 | logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate); |
NataliaRequejo | 61:ebe1838a9301 | 69 | if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 70 | logError("failed to set TX datarate to %u", tx_datarate); |
NataliaRequejo | 61:ebe1838a9301 | 71 | } |
NataliaRequejo | 61:ebe1838a9301 | 72 | } |
NataliaRequejo | 61:ebe1838a9301 | 73 | |
NataliaRequejo | 61:ebe1838a9301 | 74 | if (current_tx_power != tx_power) { |
NataliaRequejo | 61:ebe1838a9301 | 75 | logInfo("changing TX power from %u to %u", current_tx_power, tx_power); |
NataliaRequejo | 61:ebe1838a9301 | 76 | if (dot->setTxPower(tx_power) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 77 | logError("failed to set TX power to %u", tx_power); |
NataliaRequejo | 61:ebe1838a9301 | 78 | } |
Jonathan Austin |
0:2757d7abb7d9 | 79 | } |
Jonathan Austin |
0:2757d7abb7d9 | 80 | } |
Jonathan Austin |
1:846c97078558 | 81 | |
NataliaRequejo | 61:ebe1838a9301 | 82 | int main() { |
NataliaRequejo | 61:ebe1838a9301 | 83 | Serial debug(USBTX, USBRX); |
NataliaRequejo | 61:ebe1838a9301 | 84 | debug.baud(115200); |
NataliaRequejo | 61:ebe1838a9301 | 85 | |
NataliaRequejo | 61:ebe1838a9301 | 86 | RadioEvent events; |
NataliaRequejo | 61:ebe1838a9301 | 87 | |
NataliaRequejo | 61:ebe1838a9301 | 88 | int32_t ret; |
NataliaRequejo | 61:ebe1838a9301 | 89 | int32_t next_tx; |
NataliaRequejo | 61:ebe1838a9301 | 90 | int32_t wait_time = 2; |
NataliaRequejo | 61:ebe1838a9301 | 91 | |
NataliaRequejo | 61:ebe1838a9301 | 92 | std::vector<uint8_t> send_data; |
NataliaRequejo | 61:ebe1838a9301 | 93 | std::vector<uint8_t> recv_data; |
NataliaRequejo | 61:ebe1838a9301 | 94 | uint8_t recv = 0; |
NataliaRequejo | 61:ebe1838a9301 | 95 | uint8_t recv_mismatch = 0; |
NataliaRequejo | 61:ebe1838a9301 | 96 | uint8_t send_failure = 0; |
NataliaRequejo | 61:ebe1838a9301 | 97 | uint8_t iterations = 5; |
NataliaRequejo | 61:ebe1838a9301 | 98 | |
NataliaRequejo | 61:ebe1838a9301 | 99 | send_data.push_back(0x00); |
NataliaRequejo | 61:ebe1838a9301 | 100 | send_data.push_back('N'); |
NataliaRequejo | 61:ebe1838a9301 | 101 | send_data.push_back('A'); |
NataliaRequejo | 61:ebe1838a9301 | 102 | send_data.push_back('T'); |
NataliaRequejo | 61:ebe1838a9301 | 103 | send_data.push_back('I'); |
NataliaRequejo | 61:ebe1838a9301 | 104 | send_data.push_back(' '); |
NataliaRequejo | 61:ebe1838a9301 | 105 | send_data.push_back(' '); |
NataliaRequejo | 61:ebe1838a9301 | 106 | send_data.push_back(' '); |
NataliaRequejo | 61:ebe1838a9301 | 107 | |
NataliaRequejo | 61:ebe1838a9301 | 108 | plan = new lora::ChannelPlan_US915(); |
NataliaRequejo | 61:ebe1838a9301 | 109 | |
NataliaRequejo | 61:ebe1838a9301 | 110 | dot = mDot::getInstance(plan); |
NataliaRequejo | 61:ebe1838a9301 | 111 | logInfo("defaulting Dot configuration"); |
NataliaRequejo | 61:ebe1838a9301 | 112 | dot->resetConfig(); |
NataliaRequejo | 61:ebe1838a9301 | 113 | //si se hace un deep sleep la aplicacion inicia desde el principio. |
NataliaRequejo | 61:ebe1838a9301 | 114 | //Y no desde el punto donde se ejecuto el deep_sleep |
NataliaRequejo | 61:ebe1838a9301 | 115 | //Por esto es necesario salvar la sesion y luego recuperarla para continuar trabajando |
NataliaRequejo | 61:ebe1838a9301 | 116 | //dot->resetNetworkSession(); |
NataliaRequejo | 61:ebe1838a9301 | 117 | //dot->restoreNetworkSession(); |
NataliaRequejo | 61:ebe1838a9301 | 118 | //dot->saveNetworkSession(); |
NataliaRequejo | 61:ebe1838a9301 | 119 | dot->setLogLevel(MTSLog::TRACE_LEVEL); |
NataliaRequejo | 61:ebe1838a9301 | 120 | |
NataliaRequejo | 61:ebe1838a9301 | 121 | #if defined(PEER_TO_PEER_SAMPLE) |
NataliaRequejo | 61:ebe1838a9301 | 122 | // attach the custom events handler |
NataliaRequejo | 61:ebe1838a9301 | 123 | dot->setEvents(&events); |
NataliaRequejo | 61:ebe1838a9301 | 124 | |
NataliaRequejo | 61:ebe1838a9301 | 125 | //Peer-to-peer |
NataliaRequejo | 61:ebe1838a9301 | 126 | // Actualizamos la configuracion de Join unicamente si es diferente |
NataliaRequejo | 61:ebe1838a9301 | 127 | //( 0= Manual, 1 = OTA, 2= AUTO_OTA, 3=Peer to Peer) |
NataliaRequejo | 61:ebe1838a9301 | 128 | if (dot->getJoinMode() != mDot::PEER_TO_PEER) { |
NataliaRequejo | 61:ebe1838a9301 | 129 | logInfo("changing network join mode to PEER_TO_PEER"); |
NataliaRequejo | 61:ebe1838a9301 | 130 | if (dot->setJoinMode(mDot::PEER_TO_PEER) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 131 | logError("failed to set network join mode to PEER_TO_PEER"); |
NataliaRequejo | 61:ebe1838a9301 | 132 | } |
NataliaRequejo | 61:ebe1838a9301 | 133 | } |
NataliaRequejo | 61:ebe1838a9301 | 134 | uint32_t tx_frequency= 915500000; |
NataliaRequejo | 61:ebe1838a9301 | 135 | uint8_t tx_datarate = lora::DR_13; |
NataliaRequejo | 61:ebe1838a9301 | 136 | uint8_t tx_power = 20; |
NataliaRequejo | 61:ebe1838a9301 | 137 | |
NataliaRequejo | 61:ebe1838a9301 | 138 | update_peer_to_peer_config(network_address, network_session_key, data_session_key, tx_frequency, tx_datarate, tx_power); |
NataliaRequejo | 61:ebe1838a9301 | 139 | |
NataliaRequejo | 61:ebe1838a9301 | 140 | #else |
NataliaRequejo | 61:ebe1838a9301 | 141 | // Actualizamos la configuracion de Join unicamente si es diferente |
NataliaRequejo | 61:ebe1838a9301 | 142 | //( 0= Manual, 1 = OTA, 2= AUTO_OTA, 3=Peer to Peer) |
NataliaRequejo | 61:ebe1838a9301 | 143 | if (dot->getJoinMode() != mDot::AUTO_OTA) { |
NataliaRequejo | 61:ebe1838a9301 | 144 | logInfo("changing network join mode to AUTO_OTA"); |
NataliaRequejo | 61:ebe1838a9301 | 145 | if (dot->setJoinMode(mDot::AUTO_OTA) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 146 | logError("failed to set network join mode to AUTO_OTA"); |
NataliaRequejo | 61:ebe1838a9301 | 147 | } |
NataliaRequejo | 61:ebe1838a9301 | 148 | } |
NataliaRequejo | 61:ebe1838a9301 | 149 | while ((ret = dot->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 150 | logError("failed to set frequency sub band: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 151 | } |
NataliaRequejo | 61:ebe1838a9301 | 152 | while ((ret = dot->setNetworkName(config_network_name)) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 153 | logError("failed to set network name: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 154 | } |
NataliaRequejo | 61:ebe1838a9301 | 155 | while ((ret = dot->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 156 | logError("failed to set network password: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 157 | } |
NataliaRequejo | 61:ebe1838a9301 | 158 | while ((ret = dot->setPublicNetwork(1)) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 159 | logError("failed to set public network : [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 160 | } |
NataliaRequejo | 61:ebe1838a9301 | 161 | |
NataliaRequejo | 61:ebe1838a9301 | 162 | #endif |
NataliaRequejo | 61:ebe1838a9301 | 163 | |
NataliaRequejo | 61:ebe1838a9301 | 164 | // save changes to configuration |
NataliaRequejo | 61:ebe1838a9301 | 165 | logInfo("saving configuration"); |
NataliaRequejo | 61:ebe1838a9301 | 166 | if (!dot->saveConfig()) { |
NataliaRequejo | 61:ebe1838a9301 | 167 | logError("failed to save configuration"); |
NataliaRequejo | 61:ebe1838a9301 | 168 | } |
NataliaRequejo | 61:ebe1838a9301 | 169 | |
NataliaRequejo | 61:ebe1838a9301 | 170 | //logInfo("enabling activity LED"); |
NataliaRequejo | 61:ebe1838a9301 | 171 | dot->setActivityLedEnable(true); |
NataliaRequejo | 61:ebe1838a9301 | 172 | |
NataliaRequejo | 61:ebe1838a9301 | 173 | logInfo("joining network"); |
NataliaRequejo | 61:ebe1838a9301 | 174 | while ((ret = dot->joinNetwork()) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 175 | logError("failed to join network: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 176 | wait_ms(dot->getNextTxMs() + 1); |
NataliaRequejo | 61:ebe1838a9301 | 177 | } |
NataliaRequejo | 61:ebe1838a9301 | 178 | logInfo("joined"); |
NataliaRequejo | 61:ebe1838a9301 | 179 | |
NataliaRequejo | 61:ebe1838a9301 | 180 | for (uint8_t i = 0; i < iterations; i++) { |
NataliaRequejo | 61:ebe1838a9301 | 181 | send_data[0] = i;//Envio en que iteracion estoy |
NataliaRequejo | 61:ebe1838a9301 | 182 | if ((ret = dot->send(send_data)) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 183 | logError("failed to send: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 184 | send_failure++; |
NataliaRequejo | 61:ebe1838a9301 | 185 | } else { |
NataliaRequejo | 61:ebe1838a9301 | 186 | logInfo("send data: %s", Text::bin2hexString(send_data).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 187 | //La funcion RECV() No funciona en peer to peer. La ventana de tiempo en que esta abierto |
NataliaRequejo | 61:ebe1838a9301 | 188 | //el canal despues de hacer el send, para escuchar la respuesta es |
NataliaRequejo | 61:ebe1838a9301 | 189 | //muy corta y seria muy dificil hacer la sincronizacion |
NataliaRequejo | 61:ebe1838a9301 | 190 | //En peer to peer el dispositivo nunca se pone en deep sleep y esta escuchando continumente. |
NataliaRequejo | 61:ebe1838a9301 | 191 | //Por lo tanto la respuesta unicamente vendra a traves de un evento. |
NataliaRequejo | 61:ebe1838a9301 | 192 | //Por el contrario cuando la comunicacion es OTA, con el gateway aqui si deberiamos obtener el mensaje. |
NataliaRequejo | 61:ebe1838a9301 | 193 | if ((ret = dot->recv(recv_data)) != mDot::MDOT_OK) { |
NataliaRequejo | 61:ebe1838a9301 | 194 | logError("failed to recv: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 195 | } else { |
NataliaRequejo | 61:ebe1838a9301 | 196 | logInfo("recv data: %s", Text::bin2hexString(recv_data).c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 197 | if (recv_data == send_data) { |
NataliaRequejo | 61:ebe1838a9301 | 198 | recv++; |
NataliaRequejo | 61:ebe1838a9301 | 199 | } else { |
NataliaRequejo | 61:ebe1838a9301 | 200 | recv_mismatch++; |
NataliaRequejo | 61:ebe1838a9301 | 201 | } |
NataliaRequejo | 61:ebe1838a9301 | 202 | } |
NataliaRequejo | 61:ebe1838a9301 | 203 | recv_data.clear(); |
NataliaRequejo | 61:ebe1838a9301 | 204 | } |
NataliaRequejo | 61:ebe1838a9301 | 205 | |
NataliaRequejo | 61:ebe1838a9301 | 206 | next_tx = dot->getNextTxMs() + 1; |
NataliaRequejo | 61:ebe1838a9301 | 207 | logInfo("waiting %ld ms to transmit again", next_tx); |
NataliaRequejo | 61:ebe1838a9301 | 208 | wait_ms(next_tx); |
NataliaRequejo | 61:ebe1838a9301 | 209 | logInfo("waiting another %d seconds", wait_time); |
NataliaRequejo | 61:ebe1838a9301 | 210 | wait(wait_time); |
NataliaRequejo | 61:ebe1838a9301 | 211 | } |
NataliaRequejo | 61:ebe1838a9301 | 212 | |
NataliaRequejo | 61:ebe1838a9301 | 213 | logInfo("Version: %s", dot->getId().c_str()); |
NataliaRequejo | 61:ebe1838a9301 | 214 | logInfo("Recv: %d/%d", recv, iterations); |
NataliaRequejo | 61:ebe1838a9301 | 215 | logInfo("Recv Mismatch: %d/%d", recv_mismatch, iterations); |
NataliaRequejo | 61:ebe1838a9301 | 216 | logInfo("Send Failure: %d/%d", send_failure, iterations); |
NataliaRequejo | 61:ebe1838a9301 | 217 | logInfo("Dropped: %d/%d", iterations - (recv + recv_mismatch + send_failure), iterations); |
NataliaRequejo | 61:ebe1838a9301 | 218 | |
NataliaRequejo | 61:ebe1838a9301 | 219 | return 0; |
NataliaRequejo | 61:ebe1838a9301 | 220 | } |