Mbed OS example of Pelion device management LGUPlus Client

Committer:
pimco01
Date:
Fri Feb 21 19:20:41 2020 +0000
Revision:
1:3f3d8bf46183
Parent:
0:9f917a7bf2da
Child:
2:34933ca5af82
LGU+ CAT.M1 Pelion version initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pimco01 1:3f3d8bf46183 1 /*
pimco01 1:3f3d8bf46183 2 * Copyright (c) 2017 ARM Limited. All rights reserved.
pimco01 1:3f3d8bf46183 3 * SPDX-License-Identifier: Apache-2.0
pimco01 1:3f3d8bf46183 4 * Licensed under the Apache License, Version 2.0 (the License); you may
pimco01 1:3f3d8bf46183 5 * not use this file except in compliance with the License.
pimco01 1:3f3d8bf46183 6 * You may obtain a copy of the License at
pimco01 1:3f3d8bf46183 7 *
pimco01 1:3f3d8bf46183 8 * http://www.apache.org/licenses/LICENSE-2.0
pimco01 1:3f3d8bf46183 9 *
pimco01 1:3f3d8bf46183 10 * Unless required by applicable law or agreed to in writing, software
pimco01 1:3f3d8bf46183 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
pimco01 1:3f3d8bf46183 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
pimco01 1:3f3d8bf46183 13 * See the License for the specific language governing permissions and
pimco01 1:3f3d8bf46183 14 * limitations under the License.
pimco01 1:3f3d8bf46183 15 */
pimco01 1:3f3d8bf46183 16
MACRUM 0:9f917a7bf2da 17 #include "mbed.h"
pimco01 1:3f3d8bf46183 18 #include "rtos.h"
pimco01 1:3f3d8bf46183 19 #include "common_functions.h"
pimco01 1:3f3d8bf46183 20 #include "CellularNonIPSocket.h"
pimco01 1:3f3d8bf46183 21 #include "CellularDevice.h"
pimco01 1:3f3d8bf46183 22 #include "UDPSocket.h"
pimco01 1:3f3d8bf46183 23 #include "CellularLog.h"
MACRUM 0:9f917a7bf2da 24
pimco01 1:3f3d8bf46183 25 #define UDP 0
pimco01 1:3f3d8bf46183 26 #define TCP 1
pimco01 1:3f3d8bf46183 27 #define NONIP 2
MACRUM 0:9f917a7bf2da 28
pimco01 1:3f3d8bf46183 29 // Number of retries /
pimco01 1:3f3d8bf46183 30 #define RETRY_COUNT 3
MACRUM 0:9f917a7bf2da 31
pimco01 1:3f3d8bf46183 32 void BG96_Modem_PowerON(void)
pimco01 1:3f3d8bf46183 33 {
pimco01 1:3f3d8bf46183 34 DigitalIn BG96_STATUS(D2);
pimco01 1:3f3d8bf46183 35 DigitalOut BG96_PWRKEY(D3);
MACRUM 0:9f917a7bf2da 36
pimco01 1:3f3d8bf46183 37 ThisThread::sleep_for(50);
pimco01 1:3f3d8bf46183 38 BG96_PWRKEY = 1;
pimco01 1:3f3d8bf46183 39 ThisThread::sleep_for(600);
pimco01 1:3f3d8bf46183 40 BG96_PWRKEY = 0;
pimco01 1:3f3d8bf46183 41 ThisThread::sleep_for(5000);
pimco01 1:3f3d8bf46183 42
pimco01 1:3f3d8bf46183 43 if(BG96_STATUS)
pimco01 1:3f3d8bf46183 44 printf("Module Power On\r\n");
pimco01 1:3f3d8bf46183 45 else
pimco01 1:3f3d8bf46183 46 printf("Check Module Power Line!!\r\n");
MACRUM 0:9f917a7bf2da 47 }
MACRUM 0:9f917a7bf2da 48
pimco01 1:3f3d8bf46183 49 void BG96_Modem_PowerOFF(void)
MACRUM 0:9f917a7bf2da 50 {
pimco01 1:3f3d8bf46183 51 DigitalIn BG96_STATUS(D2);
pimco01 1:3f3d8bf46183 52 DigitalOut BG96_PWRKEY(D3);
pimco01 1:3f3d8bf46183 53
pimco01 1:3f3d8bf46183 54 ThisThread::sleep_for(50);
pimco01 1:3f3d8bf46183 55 BG96_PWRKEY = 1;
pimco01 1:3f3d8bf46183 56 ThisThread::sleep_for(800);
pimco01 1:3f3d8bf46183 57 BG96_PWRKEY = 0;
pimco01 1:3f3d8bf46183 58 ThisThread::sleep_for(3000);
pimco01 1:3f3d8bf46183 59
pimco01 1:3f3d8bf46183 60 if(BG96_STATUS == 0)
pimco01 1:3f3d8bf46183 61 printf("Module Power Off\r\n");
pimco01 1:3f3d8bf46183 62 else
pimco01 1:3f3d8bf46183 63 printf("Check Module Power Line!!\r\n");
pimco01 1:3f3d8bf46183 64 }
pimco01 1:3f3d8bf46183 65
pimco01 1:3f3d8bf46183 66 NetworkInterface *iface;
pimco01 1:3f3d8bf46183 67
pimco01 1:3f3d8bf46183 68 // Echo server hostname
pimco01 1:3f3d8bf46183 69 const char *host_name = MBED_CONF_APP_ECHO_SERVER_HOSTNAME;
pimco01 1:3f3d8bf46183 70
pimco01 1:3f3d8bf46183 71 // Echo server port (same for TCP and UDP)
pimco01 1:3f3d8bf46183 72 const int port = MBED_CONF_APP_ECHO_SERVER_PORT;
pimco01 1:3f3d8bf46183 73
pimco01 1:3f3d8bf46183 74 static rtos::Mutex trace_mutex;
pimco01 1:3f3d8bf46183 75
pimco01 1:3f3d8bf46183 76 #if MBED_CONF_MBED_TRACE_ENABLE
pimco01 1:3f3d8bf46183 77 static void trace_wait()
pimco01 1:3f3d8bf46183 78 {
pimco01 1:3f3d8bf46183 79 trace_mutex.lock();
pimco01 1:3f3d8bf46183 80 }
pimco01 1:3f3d8bf46183 81
pimco01 1:3f3d8bf46183 82 static void trace_release()
pimco01 1:3f3d8bf46183 83 {
pimco01 1:3f3d8bf46183 84 trace_mutex.unlock();
pimco01 1:3f3d8bf46183 85 }
pimco01 1:3f3d8bf46183 86
pimco01 1:3f3d8bf46183 87 static char time_st[50];
pimco01 1:3f3d8bf46183 88
pimco01 1:3f3d8bf46183 89 static char* trace_time(size_t ss)
pimco01 1:3f3d8bf46183 90 {
pimco01 1:3f3d8bf46183 91 snprintf(time_st, 49, "[%08llums]", Kernel::get_ms_count());
pimco01 1:3f3d8bf46183 92 return time_st;
MACRUM 0:9f917a7bf2da 93 }
MACRUM 0:9f917a7bf2da 94
pimco01 1:3f3d8bf46183 95 static void trace_open()
MACRUM 0:9f917a7bf2da 96 {
pimco01 1:3f3d8bf46183 97 mbed_trace_init();
pimco01 1:3f3d8bf46183 98 mbed_trace_prefix_function_set( &trace_time );
MACRUM 0:9f917a7bf2da 99
pimco01 1:3f3d8bf46183 100 mbed_trace_mutex_wait_function_set(trace_wait);
pimco01 1:3f3d8bf46183 101 mbed_trace_mutex_release_function_set(trace_release);
pimco01 1:3f3d8bf46183 102
pimco01 1:3f3d8bf46183 103 mbed_cellular_trace::mutex_wait_function_set(trace_wait);
pimco01 1:3f3d8bf46183 104 mbed_cellular_trace::mutex_release_function_set(trace_release);
MACRUM 0:9f917a7bf2da 105 }
MACRUM 0:9f917a7bf2da 106
pimco01 1:3f3d8bf46183 107 static void trace_close()
MACRUM 0:9f917a7bf2da 108 {
pimco01 1:3f3d8bf46183 109 mbed_cellular_trace::mutex_wait_function_set(NULL);
pimco01 1:3f3d8bf46183 110 mbed_cellular_trace::mutex_release_function_set(NULL);
pimco01 1:3f3d8bf46183 111
pimco01 1:3f3d8bf46183 112 mbed_trace_free();
pimco01 1:3f3d8bf46183 113 }
pimco01 1:3f3d8bf46183 114 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
pimco01 1:3f3d8bf46183 115
pimco01 1:3f3d8bf46183 116 Thread dot_thread(osPriorityNormal, 512);
pimco01 1:3f3d8bf46183 117
pimco01 1:3f3d8bf46183 118 void print_function(const char *format, ...)
pimco01 1:3f3d8bf46183 119 {
pimco01 1:3f3d8bf46183 120 trace_mutex.lock();
pimco01 1:3f3d8bf46183 121 va_list arglist;
pimco01 1:3f3d8bf46183 122 va_start( arglist, format );
pimco01 1:3f3d8bf46183 123 vprintf(format, arglist);
pimco01 1:3f3d8bf46183 124 va_end( arglist );
pimco01 1:3f3d8bf46183 125 trace_mutex.unlock();
MACRUM 0:9f917a7bf2da 126 }
MACRUM 0:9f917a7bf2da 127
pimco01 1:3f3d8bf46183 128 void dot_event()
MACRUM 0:9f917a7bf2da 129 {
pimco01 1:3f3d8bf46183 130 while (true) {
pimco01 1:3f3d8bf46183 131 ThisThread::sleep_for(4000);
pimco01 1:3f3d8bf46183 132 if (iface && iface->get_connection_status() == NSAPI_STATUS_GLOBAL_UP) {
pimco01 1:3f3d8bf46183 133 break;
pimco01 1:3f3d8bf46183 134 } else {
pimco01 1:3f3d8bf46183 135 trace_mutex.lock();
pimco01 1:3f3d8bf46183 136 printf(".");
pimco01 1:3f3d8bf46183 137 fflush(stdout);
pimco01 1:3f3d8bf46183 138 trace_mutex.unlock();
pimco01 1:3f3d8bf46183 139 }
pimco01 1:3f3d8bf46183 140 }
MACRUM 0:9f917a7bf2da 141 }
MACRUM 0:9f917a7bf2da 142
pimco01 1:3f3d8bf46183 143 /**
pimco01 1:3f3d8bf46183 144 * Connects to the Cellular Network
pimco01 1:3f3d8bf46183 145 */
pimco01 1:3f3d8bf46183 146 nsapi_error_t do_connect()
MACRUM 0:9f917a7bf2da 147 {
pimco01 1:3f3d8bf46183 148 nsapi_error_t retcode = NSAPI_ERROR_OK;
pimco01 1:3f3d8bf46183 149 uint8_t retry_counter = 0;
MACRUM 0:9f917a7bf2da 150
pimco01 1:3f3d8bf46183 151 while (iface->get_connection_status() != NSAPI_STATUS_GLOBAL_UP) {
pimco01 1:3f3d8bf46183 152 retcode = iface->connect();
pimco01 1:3f3d8bf46183 153 if (retcode == NSAPI_ERROR_AUTH_FAILURE) {
pimco01 1:3f3d8bf46183 154 print_function("\n\nAuthentication Failure. Exiting application\n");
pimco01 1:3f3d8bf46183 155 } else if (retcode == NSAPI_ERROR_OK) {
pimco01 1:3f3d8bf46183 156 print_function("\n\nConnection Established.\n");
pimco01 1:3f3d8bf46183 157 } else if (retry_counter > RETRY_COUNT) {
pimco01 1:3f3d8bf46183 158 print_function("\n\nFatal connection failure: %d\n", retcode);
pimco01 1:3f3d8bf46183 159 } else {
pimco01 1:3f3d8bf46183 160 print_function("\n\nCouldn't connect: %d, will retry\n", retcode);
pimco01 1:3f3d8bf46183 161 retry_counter++;
pimco01 1:3f3d8bf46183 162 continue;
pimco01 1:3f3d8bf46183 163 }
pimco01 1:3f3d8bf46183 164 break;
pimco01 1:3f3d8bf46183 165 }
pimco01 1:3f3d8bf46183 166 return retcode;
MACRUM 0:9f917a7bf2da 167 }
MACRUM 0:9f917a7bf2da 168
pimco01 1:3f3d8bf46183 169 /**
pimco01 1:3f3d8bf46183 170 * Opens:
pimco01 1:3f3d8bf46183 171 * - UDP or TCP socket with the given echo server and performs an echo
pimco01 1:3f3d8bf46183 172 * transaction retrieving current.
pimco01 1:3f3d8bf46183 173 * - Cellular Non-IP socket for which the data delivery path is decided
pimco01 1:3f3d8bf46183 174 * by network's control plane CIoT optimisation setup, for the given APN.
pimco01 1:3f3d8bf46183 175 */
pimco01 1:3f3d8bf46183 176 nsapi_error_t test_send_recv()
MACRUM 0:9f917a7bf2da 177 {
pimco01 1:3f3d8bf46183 178 nsapi_size_or_error_t retcode;
pimco01 1:3f3d8bf46183 179 #if MBED_CONF_APP_SOCK_TYPE == TCP
pimco01 1:3f3d8bf46183 180 TCPSocket sock;
pimco01 1:3f3d8bf46183 181 #elif MBED_CONF_APP_SOCK_TYPE == UDP
pimco01 1:3f3d8bf46183 182 UDPSocket sock;
pimco01 1:3f3d8bf46183 183 #elif MBED_CONF_APP_SOCK_TYPE == NONIP
pimco01 1:3f3d8bf46183 184 CellularNonIPSocket sock;
pimco01 1:3f3d8bf46183 185 #endif
MACRUM 0:9f917a7bf2da 186
pimco01 1:3f3d8bf46183 187 #if MBED_CONF_APP_SOCK_TYPE == NONIP
pimco01 1:3f3d8bf46183 188 retcode = sock.open((CellularContext*)iface);
pimco01 1:3f3d8bf46183 189 #else
pimco01 1:3f3d8bf46183 190 retcode = sock.open(iface);
pimco01 1:3f3d8bf46183 191 #endif
MACRUM 0:9f917a7bf2da 192
pimco01 1:3f3d8bf46183 193 if (retcode != NSAPI_ERROR_OK) {
pimco01 1:3f3d8bf46183 194 #if MBED_CONF_APP_SOCK_TYPE == TCP
pimco01 1:3f3d8bf46183 195 print_function("TCPSocket.open() fails, code: %d\n", retcode);
pimco01 1:3f3d8bf46183 196 #elif MBED_CONF_APP_SOCK_TYPE == UDP
pimco01 1:3f3d8bf46183 197 print_function("UDPSocket.open() fails, code: %d\n", retcode);
pimco01 1:3f3d8bf46183 198 #elif MBED_CONF_APP_SOCK_TYPE == NONIP
pimco01 1:3f3d8bf46183 199 print_function("CellularNonIPSocket.open() fails, code: %d\n", retcode);
pimco01 1:3f3d8bf46183 200 #endif
MACRUM 0:9f917a7bf2da 201 return -1;
MACRUM 0:9f917a7bf2da 202 }
MACRUM 0:9f917a7bf2da 203
pimco01 1:3f3d8bf46183 204 int n = 0;
pimco01 1:3f3d8bf46183 205 const char *echo_string = "TEST";
pimco01 1:3f3d8bf46183 206 char recv_buf[4];
pimco01 1:3f3d8bf46183 207
pimco01 1:3f3d8bf46183 208 sock.set_timeout(15000);
MACRUM 0:9f917a7bf2da 209
pimco01 1:3f3d8bf46183 210 #if MBED_CONF_APP_SOCK_TYPE == NONIP
pimco01 1:3f3d8bf46183 211 retcode = sock.send((void*) echo_string, strlen(echo_string));
pimco01 1:3f3d8bf46183 212 if (retcode < 0) {
pimco01 1:3f3d8bf46183 213 print_function("CellularNonIPSocket.send() fails, code: %d\n", retcode);
MACRUM 0:9f917a7bf2da 214 return -1;
pimco01 1:3f3d8bf46183 215 } else {
pimco01 1:3f3d8bf46183 216 print_function("CellularNonIPSocket: Sent %d Bytes\n", retcode);
MACRUM 0:9f917a7bf2da 217 }
MACRUM 0:9f917a7bf2da 218
pimco01 1:3f3d8bf46183 219 n = sock.recv((void*) recv_buf, sizeof(recv_buf));
MACRUM 0:9f917a7bf2da 220
pimco01 1:3f3d8bf46183 221 #else
MACRUM 0:9f917a7bf2da 222
pimco01 1:3f3d8bf46183 223 SocketAddress sock_addr;
pimco01 1:3f3d8bf46183 224 retcode = iface->gethostbyname(host_name, &sock_addr);
pimco01 1:3f3d8bf46183 225 if (retcode != NSAPI_ERROR_OK) {
pimco01 1:3f3d8bf46183 226 print_function("Couldn't resolve remote host: %s, code: %d\n", host_name, retcode);
MACRUM 0:9f917a7bf2da 227 return -1;
MACRUM 0:9f917a7bf2da 228 }
MACRUM 0:9f917a7bf2da 229
pimco01 1:3f3d8bf46183 230 sock_addr.set_port(port);
pimco01 1:3f3d8bf46183 231
pimco01 1:3f3d8bf46183 232 #if MBED_CONF_APP_SOCK_TYPE == TCP
pimco01 1:3f3d8bf46183 233 retcode = sock.connect(sock_addr);
pimco01 1:3f3d8bf46183 234 if (retcode < 0) {
pimco01 1:3f3d8bf46183 235 print_function("TCPSocket.connect() fails, code: %d\n", retcode);
MACRUM 0:9f917a7bf2da 236 return -1;
pimco01 1:3f3d8bf46183 237 } else {
pimco01 1:3f3d8bf46183 238 print_function("TCP: connected with %s server\n", host_name);
MACRUM 0:9f917a7bf2da 239 }
pimco01 1:3f3d8bf46183 240 retcode = sock.send((void*) echo_string, strlen(echo_string));
pimco01 1:3f3d8bf46183 241 if (retcode < 0) {
pimco01 1:3f3d8bf46183 242 print_function("TCPSocket.send() fails, code: %d\n", retcode);
MACRUM 0:9f917a7bf2da 243 return -1;
pimco01 1:3f3d8bf46183 244 } else {
pimco01 1:3f3d8bf46183 245 print_function("TCP: Sent %d Bytes to %s\n", retcode, host_name);
MACRUM 0:9f917a7bf2da 246 }
MACRUM 0:9f917a7bf2da 247
pimco01 1:3f3d8bf46183 248 n = sock.recv((void*) recv_buf, sizeof(recv_buf));
pimco01 1:3f3d8bf46183 249 #else
pimco01 1:3f3d8bf46183 250
pimco01 1:3f3d8bf46183 251 retcode = sock.sendto(sock_addr, (void*) echo_string, strlen(echo_string));
pimco01 1:3f3d8bf46183 252 if (retcode < 0) {
pimco01 1:3f3d8bf46183 253 print_function("UDPSocket.sendto() fails, code: %d\n", retcode);
MACRUM 0:9f917a7bf2da 254 return -1;
pimco01 1:3f3d8bf46183 255 } else {
pimco01 1:3f3d8bf46183 256 print_function("UDP: Sent %d Bytes to %s\n", retcode, host_name);
pimco01 1:3f3d8bf46183 257 }
pimco01 1:3f3d8bf46183 258
pimco01 1:3f3d8bf46183 259 n = sock.recvfrom(&sock_addr, (void*) recv_buf, sizeof(recv_buf));
pimco01 1:3f3d8bf46183 260 #endif
pimco01 1:3f3d8bf46183 261 #endif
pimco01 1:3f3d8bf46183 262
pimco01 1:3f3d8bf46183 263 sock.close();
pimco01 1:3f3d8bf46183 264
pimco01 1:3f3d8bf46183 265 if (n > 0) {
pimco01 1:3f3d8bf46183 266 print_function("Received from echo server %d Bytes\n", n);
pimco01 1:3f3d8bf46183 267 return 0;
MACRUM 0:9f917a7bf2da 268 }
MACRUM 0:9f917a7bf2da 269
pimco01 1:3f3d8bf46183 270 return -1;
pimco01 1:3f3d8bf46183 271 }
pimco01 1:3f3d8bf46183 272
pimco01 1:3f3d8bf46183 273 int main()
pimco01 1:3f3d8bf46183 274 {
pimco01 1:3f3d8bf46183 275 print_function("\n\nmbed-os-example-cellular\n");
pimco01 1:3f3d8bf46183 276 print_function("\n\nBuilt: %s, %s\n", __DATE__, __TIME__);
pimco01 1:3f3d8bf46183 277 #ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN
pimco01 1:3f3d8bf46183 278 print_function("\n\n[MAIN], plmn: %s\n", (MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN ? MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN : "NULL"));
pimco01 1:3f3d8bf46183 279 #endif
MACRUM 0:9f917a7bf2da 280
pimco01 1:3f3d8bf46183 281 print_function("Establishing connection\n");
pimco01 1:3f3d8bf46183 282
pimco01 1:3f3d8bf46183 283 BG96_Modem_PowerON();
pimco01 1:3f3d8bf46183 284
pimco01 1:3f3d8bf46183 285 #if MBED_CONF_MBED_TRACE_ENABLE
pimco01 1:3f3d8bf46183 286 trace_open();
pimco01 1:3f3d8bf46183 287 #else
pimco01 1:3f3d8bf46183 288 dot_thread.start(dot_event);
pimco01 1:3f3d8bf46183 289 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
MACRUM 0:9f917a7bf2da 290
pimco01 1:3f3d8bf46183 291 #if MBED_CONF_APP_SOCK_TYPE == NONIP
pimco01 1:3f3d8bf46183 292 iface = CellularContext::get_default_nonip_instance();
pimco01 1:3f3d8bf46183 293 #else
pimco01 1:3f3d8bf46183 294 iface = CellularContext::get_default_instance();
pimco01 1:3f3d8bf46183 295 #endif
pimco01 1:3f3d8bf46183 296
pimco01 1:3f3d8bf46183 297 MBED_ASSERT(iface);
pimco01 1:3f3d8bf46183 298
pimco01 1:3f3d8bf46183 299 // sim pin, apn, credentials and possible plmn are taken automatically from json when using NetworkInterface::set_default_parameters()
pimco01 1:3f3d8bf46183 300 iface->set_default_parameters();
pimco01 1:3f3d8bf46183 301
pimco01 1:3f3d8bf46183 302 nsapi_error_t retcode = NSAPI_ERROR_NO_CONNECTION;
pimco01 1:3f3d8bf46183 303
pimco01 1:3f3d8bf46183 304 /* Attempt to connect to a cellular network */
pimco01 1:3f3d8bf46183 305 if (do_connect() == NSAPI_ERROR_OK) {
pimco01 1:3f3d8bf46183 306 retcode = test_send_recv();
MACRUM 0:9f917a7bf2da 307 }
MACRUM 0:9f917a7bf2da 308
pimco01 1:3f3d8bf46183 309 if (iface->disconnect() != NSAPI_ERROR_OK) {
pimco01 1:3f3d8bf46183 310 print_function("\n\n disconnect failed.\n\n");
pimco01 1:3f3d8bf46183 311 }
MACRUM 0:9f917a7bf2da 312
pimco01 1:3f3d8bf46183 313 if (retcode == NSAPI_ERROR_OK) {
pimco01 1:3f3d8bf46183 314 print_function("\n\nSuccess. Exiting \n\n");
pimco01 1:3f3d8bf46183 315 } else {
pimco01 1:3f3d8bf46183 316 print_function("\n\nFailure. Exiting \n\n");
MACRUM 0:9f917a7bf2da 317 }
pimco01 1:3f3d8bf46183 318
pimco01 1:3f3d8bf46183 319 #if MBED_CONF_MBED_TRACE_ENABLE
pimco01 1:3f3d8bf46183 320 trace_close();
pimco01 1:3f3d8bf46183 321 #else
pimco01 1:3f3d8bf46183 322 dot_thread.terminate();
pimco01 1:3f3d8bf46183 323 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
pimco01 1:3f3d8bf46183 324
MACRUM 0:9f917a7bf2da 325 return 0;
MACRUM 0:9f917a7bf2da 326 }
pimco01 1:3f3d8bf46183 327 // EOF