INSAT_MiniPRoject

Dependencies:   MQTT NDefLib NetworkSocketAPI Servo Light_Sensor_Nucleo X_NUCLEO_IDW01M1v2 mbed

Fork of IDW01M1_Cloud_IBM by ST

Committer:
mapellil
Date:
Thu Nov 24 13:22:03 2016 +0000
Revision:
24:a59eb8bdc431
Parent:
23:43f9e34781f2
Child:
25:9dab18979609
Updated libraries

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mridup 10:c7b62ce013ad 1 /* SpwfInterface NetworkSocketAPI Example Program
mridup 10:c7b62ce013ad 2 * Copyright (c) 2015 ARM Limited
mridup 10:c7b62ce013ad 3 *
mridup 10:c7b62ce013ad 4 * Licensed under the Apache License, Version 2.0 (the "License");
mridup 10:c7b62ce013ad 5 * you may not use this file except in compliance with the License.
mridup 10:c7b62ce013ad 6 * You may obtain a copy of the License at
mridup 10:c7b62ce013ad 7 *
mridup 10:c7b62ce013ad 8 * http://www.apache.org/licenses/LICENSE-2.0
mridup 10:c7b62ce013ad 9 *
mridup 10:c7b62ce013ad 10 * Unless required by applicable law or agreed to in writing, software
mridup 10:c7b62ce013ad 11 * distributed under the License is distributed on an "AS IS" BASIS,
mridup 10:c7b62ce013ad 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mridup 10:c7b62ce013ad 13 * See the License for the specific language governing permissions and
mridup 10:c7b62ce013ad 14 * limitations under the License.
mridup 10:c7b62ce013ad 15 */
mridup 10:c7b62ce013ad 16
mridup 0:cbf8bc43bc9e 17 #include "mbed.h"
mapellil 14:641560b57584 18 #include "SpwfInterface.h"
mridup 4:1ed7f173eec5 19 #include "TCPSocket.h"
fabiombed 13:0b31131bf711 20 #include "MQTTClient.h"
mapellil 14:641560b57584 21 #include "MQTTWiFi.h"
mapellil 14:641560b57584 22 #include <ctype.h>
mapellil 14:641560b57584 23 #include "x_nucleo_iks01a1.h"
mapellil 23:43f9e34781f2 24 #include "X_NUCLEO_NFC01A1.h"
mapellil 23:43f9e34781f2 25 #include "NDefLib/NDefNfcTag.h"
mapellil 23:43f9e34781f2 26 #include "NDefLib/RecordType/RecordURI.h"
fabiombed 13:0b31131bf711 27
mridup 0:cbf8bc43bc9e 28 //------------------------------------
mridup 0:cbf8bc43bc9e 29 // Hyperterminal configuration
mridup 0:cbf8bc43bc9e 30 // 9600 bauds, 8-bit data, no parity
mridup 0:cbf8bc43bc9e 31 //------------------------------------
mridup 8:6df01cb43137 32 Serial pc(SERIAL_TX, SERIAL_RX);
mridup 3:dfb8c6c8c31b 33 DigitalOut myled(LED1);
mapellil 14:641560b57584 34 bool quickstartMode = true;
mapellil 17:83d0cd810ed3 35
mapellil 23:43f9e34781f2 36 #define ORG_QUICKSTART // comment to connect to play.internetofthings.ibmcloud.com
mapellil 23:43f9e34781f2 37 //#define SUBSCRIBE // uncomment to subscribe to broker msgs (not to be used with IBM broker)
mapellil 23:43f9e34781f2 38 #define X_NUCLEO_NFC01A1_PRESENT // uncomment to add NFC support
mapellil 14:641560b57584 39
mapellil 14:641560b57584 40 #define MQTT_MAX_PACKET_SIZE 250
mapellil 14:641560b57584 41 #define MQTT_MAX_PAYLOAD_SIZE 300
mapellil 17:83d0cd810ed3 42
mapellil 14:641560b57584 43 // Configuration values needed to connect to IBM IoT Cloud
mapellil 23:43f9e34781f2 44 #define BROKER_URL ".messaging.internetofthings.ibmcloud.com";
mapellil 17:83d0cd810ed3 45 #ifdef ORG_QUICKSTART
mapellil 17:83d0cd810ed3 46 #define ORG "quickstart" // connect to quickstart.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
mapellil 17:83d0cd810ed3 47 #define ID ""
mapellil 17:83d0cd810ed3 48 #define AUTH_TOKEN ""
mapellil 21:78fac4c1b0fa 49 #define DEFAULT_TYPE_NAME "iotsample-mbed-Nucleo"
mapellil 23:43f9e34781f2 50 #else // not def ORG_QUICKSTART
mapellil 17:83d0cd810ed3 51 #define ORG "play" // connect to play.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
mapellil 23:43f9e34781f2 52 #define ID "" // For a registered connection, replace with your id
mapellil 23:43f9e34781f2 53 #define AUTH_TOKEN ""// For a registered connection, replace with your auth-token
mapellil 17:83d0cd810ed3 54 #define DEFAULT_TYPE_NAME "sensor"
mapellil 17:83d0cd810ed3 55 #endif
mapellil 23:43f9e34781f2 56 #define TOPIC "iot-2/evt/status/fmt/json"
mapellil 17:83d0cd810ed3 57
mapellil 14:641560b57584 58 #define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type
mapellil 14:641560b57584 59 #define MQTT_PORT 1883
mapellil 14:641560b57584 60 #define MQTT_TLS_PORT 8883
mapellil 14:641560b57584 61 #define IBM_IOT_PORT MQTT_PORT
mapellil 16:233b89a6b72f 62 // WiFi network credential
mapellil 22:d278e4bb5ded 63 #define SSID "" // Network must be visible otherwise it can't connect
mapellil 22:d278e4bb5ded 64 #define PASSW ""
nikapov 20:517b559ce91d 65 #warning "Wifi SSID & password empty"
mapellil 14:641560b57584 66
mapellil 14:641560b57584 67 char id[30] = ID; // mac without colons
mapellil 14:641560b57584 68 char org[12] = ORG;
mapellil 14:641560b57584 69 int connack_rc = 0; // MQTT connack return code
mapellil 14:641560b57584 70 const char* ip_addr = "";
mapellil 14:641560b57584 71 char* host_addr = "";
mapellil 14:641560b57584 72 char type[30] = TYPE;
mapellil 14:641560b57584 73 char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
mapellil 14:641560b57584 74 bool netConnecting = false;
mapellil 23:43f9e34781f2 75 int connectTimeout = 1000;
mapellil 14:641560b57584 76 bool mqttConnecting = false;
mapellil 14:641560b57584 77 bool netConnected = false;
mapellil 14:641560b57584 78 bool connected = false;
mapellil 14:641560b57584 79 int retryAttempt = 0;
mapellil 23:43f9e34781f2 80 char subscription_url[MQTT_MAX_PAYLOAD_SIZE];
mapellil 14:641560b57584 81
mapellil 14:641560b57584 82 PressureSensor *pressure_sensor;
mapellil 14:641560b57584 83 HumiditySensor *humidity_sensor;
mapellil 14:641560b57584 84 TempSensor *temp_sensor1;
mapellil 14:641560b57584 85
mapellil 23:43f9e34781f2 86 MQTT::Message message;
mapellil 23:43f9e34781f2 87 MQTTString TopicName={TOPIC};
mapellil 23:43f9e34781f2 88 MQTT::MessageData MsgData(TopicName, message);
mapellil 23:43f9e34781f2 89
mapellil 23:43f9e34781f2 90 void subscribe_cb(MQTT::MessageData & msgMQTT) {
mapellil 23:43f9e34781f2 91 char msg[MQTT_MAX_PAYLOAD_SIZE];
mapellil 23:43f9e34781f2 92 msg[0]='\0';
mapellil 23:43f9e34781f2 93 strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen);
mapellil 23:43f9e34781f2 94 printf ("--->>> subscribe_cb msg: %s\n\r", msg);
mapellil 23:43f9e34781f2 95 }
mapellil 23:43f9e34781f2 96
mapellil 23:43f9e34781f2 97 int subscribe(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
mapellil 23:43f9e34781f2 98 {
mapellil 23:43f9e34781f2 99 char* pubTopic = TOPIC;
mapellil 23:43f9e34781f2 100 return client->subscribe(pubTopic, MQTT::QOS1, subscribe_cb);
mapellil 23:43f9e34781f2 101 }
mapellil 14:641560b57584 102
mapellil 14:641560b57584 103 int connect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
mapellil 23:43f9e34781f2 104 {
mapellil 23:43f9e34781f2 105 const char* iot_ibm = BROKER_URL;
mapellil 23:43f9e34781f2 106
mapellil 14:641560b57584 107
mapellil 14:641560b57584 108 char hostname[strlen(org) + strlen(iot_ibm) + 1];
mapellil 14:641560b57584 109 sprintf(hostname, "%s%s", org, iot_ibm);
mapellil 14:641560b57584 110 SpwfSAInterface& WiFi = ipstack->getWiFi();
mapellil 24:a59eb8bdc431 111 // ip_addr = WiFi.get_ip_address();
mapellil 14:641560b57584 112 // Construct clientId - d:org:type:id
mapellil 23:43f9e34781f2 113 char clientId[strlen(org) + strlen(type) + strlen(id) + 5];
mapellil 23:43f9e34781f2 114 sprintf(clientId, "d:%s:%s:%s", org, type, id);
mapellil 23:43f9e34781f2 115 sprintf(subscription_url, "%s.%s/#/device/%s/sensor/", org, "internetofthings.ibmcloud.com",id);
mapellil 23:43f9e34781f2 116
mapellil 14:641560b57584 117 // Network debug statements
mapellil 14:641560b57584 118 LOG("=====================================\n\r");
mapellil 14:641560b57584 119 LOG("Connecting WiFi.\n\r");
mapellil 23:43f9e34781f2 120 LOG("Nucleo IP ADDRESS: %s\n\r", WiFi.get_ip_address());
mapellil 23:43f9e34781f2 121 LOG("Nucleo MAC ADDRESS: %s\n\r", WiFi.get_mac_address());
mapellil 23:43f9e34781f2 122 LOG("Server Hostname: %s port: %d\n\r", hostname, IBM_IOT_PORT);
mapellil 24:a59eb8bdc431 123 // for(int i = 0; clientId[i]; i++){ // set lowercase mac
mapellil 24:a59eb8bdc431 124 // clientId[i] = tolower(clientId[i]);
mapellil 17:83d0cd810ed3 125 // }
mapellil 24:a59eb8bdc431 126 LOG("Client ID: %s\n\r", clientId);
mapellil 23:43f9e34781f2 127 LOG("Topic: %s\n\r",TOPIC);
mapellil 23:43f9e34781f2 128 LOG("Subscription URL: %s\n\r", subscription_url);
mapellil 14:641560b57584 129 LOG("=====================================\n\r");
mapellil 14:641560b57584 130
mapellil 14:641560b57584 131 netConnecting = true;
mapellil 14:641560b57584 132 ipstack->open(&ipstack->getWiFi());
mapellil 23:43f9e34781f2 133 int rc = ipstack->connect(hostname, IBM_IOT_PORT, connectTimeout);
mapellil 14:641560b57584 134 if (rc != 0)
mapellil 14:641560b57584 135 {
mapellil 14:641560b57584 136 WARN("IP Stack connect returned: %d\n", rc);
mapellil 14:641560b57584 137 return rc;
mapellil 14:641560b57584 138 }
mapellil 23:43f9e34781f2 139 printf ("--->TCP Connected\n\r");
mapellil 14:641560b57584 140 netConnected = true;
mapellil 14:641560b57584 141 netConnecting = false;
mapellil 14:641560b57584 142
mapellil 14:641560b57584 143 // MQTT Connect
mapellil 14:641560b57584 144 mqttConnecting = true;
mapellil 14:641560b57584 145 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
mapellil 17:83d0cd810ed3 146 data.MQTTVersion = 4;
mapellil 17:83d0cd810ed3 147 data.struct_version=0;
mapellil 14:641560b57584 148 data.clientID.cstring = clientId;
mapellil 14:641560b57584 149
mapellil 14:641560b57584 150 if (!quickstartMode)
mapellil 14:641560b57584 151 {
mapellil 14:641560b57584 152 data.username.cstring = "use-token-auth";
mapellil 14:641560b57584 153 data.password.cstring = auth_token;
mapellil 23:43f9e34781f2 154 }
mapellil 14:641560b57584 155 if ((rc = client->connect(data)) == 0)
mapellil 14:641560b57584 156 {
mapellil 14:641560b57584 157 connected = true;
mapellil 23:43f9e34781f2 158 printf ("--->MQTT Connected\n\r");
mapellil 23:43f9e34781f2 159 #ifdef SUBSCRIBE
mapellil 23:43f9e34781f2 160 if (!subscribe(client, ipstack)) printf ("--->>>MQTT subscribed to: %s\n\r",TOPIC);
mapellil 23:43f9e34781f2 161 #endif
mapellil 14:641560b57584 162 }
mapellil 14:641560b57584 163 else {
mapellil 14:641560b57584 164 WARN("MQTT connect returned %d\n", rc);
mapellil 14:641560b57584 165 }
mapellil 14:641560b57584 166 if (rc >= 0)
mapellil 14:641560b57584 167 connack_rc = rc;
mapellil 14:641560b57584 168 mqttConnecting = false;
mapellil 14:641560b57584 169 return rc;
mapellil 14:641560b57584 170 }
mapellil 14:641560b57584 171
mapellil 14:641560b57584 172 int getConnTimeout(int attemptNumber)
mapellil 14:641560b57584 173 { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
mapellil 14:641560b57584 174 // after 20 attempts, retry every 10 minutes
mapellil 14:641560b57584 175 return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
mapellil 14:641560b57584 176 }
mapellil 14:641560b57584 177
mapellil 14:641560b57584 178 void attemptConnect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
mapellil 14:641560b57584 179 {
mapellil 14:641560b57584 180 connected = false;
mapellil 14:641560b57584 181
mapellil 14:641560b57584 182 while (connect(client, ipstack) != MQTT_CONNECTION_ACCEPTED)
mapellil 14:641560b57584 183 {
mapellil 14:641560b57584 184 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
mapellil 23:43f9e34781f2 185 printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc);
mapellil 14:641560b57584 186 return; // don't reattempt to connect if credentials are wrong
mapellil 23:43f9e34781f2 187 }
mapellil 14:641560b57584 188 int timeout = getConnTimeout(++retryAttempt);
mapellil 14:641560b57584 189 WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
mapellil 14:641560b57584 190
mapellil 14:641560b57584 191 // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
mapellil 23:43f9e34781f2 192 // or maybe just add the proper members to do this disconnect and call attemptConnect(...)
mapellil 14:641560b57584 193 // this works - reset the system when the retry count gets to a threshold
mapellil 14:641560b57584 194 if (retryAttempt == 5)
mapellil 14:641560b57584 195 NVIC_SystemReset();
mapellil 14:641560b57584 196 else
mapellil 14:641560b57584 197 wait(timeout);
mapellil 14:641560b57584 198 }
mapellil 14:641560b57584 199 }
mapellil 14:641560b57584 200
mapellil 14:641560b57584 201 int publish(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
mapellil 14:641560b57584 202 {
mapellil 14:641560b57584 203 MQTT::Message message;
mapellil 23:43f9e34781f2 204 char* pubTopic = TOPIC;
mapellil 14:641560b57584 205
mapellil 14:641560b57584 206 char buf[MQTT_MAX_PAYLOAD_SIZE];
mapellil 14:641560b57584 207 float temp, press, hum;
mapellil 14:641560b57584 208 temp_sensor1->GetTemperature(&temp);
mapellil 14:641560b57584 209 pressure_sensor->GetPressure(&press);
mapellil 14:641560b57584 210 humidity_sensor->GetHumidity(&hum);
mapellil 14:641560b57584 211 sprintf(buf,
mapellil 21:78fac4c1b0fa 212 "{\"d\":{\"ST\":\"Nucleo-IoT-mbed\",\"Temp\":%0.4f,\"Pressure\":%0.4f,\"Humidity\":%0.4f}}",
mapellil 14:641560b57584 213 temp, press, hum);
mapellil 14:641560b57584 214 message.qos = MQTT::QOS0;
mapellil 14:641560b57584 215 message.retained = false;
mapellil 14:641560b57584 216 message.dup = false;
mapellil 14:641560b57584 217 message.payload = (void*)buf;
mapellil 14:641560b57584 218 message.payloadlen = strlen(buf);
mapellil 14:641560b57584 219
mapellil 24:a59eb8bdc431 220 // LOG("Publishing %s\n\r", buf);
mapellil 24:a59eb8bdc431 221 printf("Publishing %s\n\r", buf);
mapellil 14:641560b57584 222 return client->publish(pubTopic, message);
mapellil 14:641560b57584 223 }
mridup 4:1ed7f173eec5 224
fabiombed 13:0b31131bf711 225 int main()
fabiombed 13:0b31131bf711 226 {
mapellil 16:233b89a6b72f 227 const char * ssid = SSID; // Network must be visible otherwise it can't connect
mapellil 16:233b89a6b72f 228 const char * seckey = PASSW;
mapellil 24:a59eb8bdc431 229 SpwfSAInterface spwf(D8, D2, false);
mapellil 14:641560b57584 230
mapellil 14:641560b57584 231 // Timer tyeld;
mapellil 24:a59eb8bdc431 232 myled=0;
mapellil 14:641560b57584 233 DevI2C *i2c = new DevI2C(I2C_SDA, I2C_SCL);
mapellil 14:641560b57584 234 i2c->frequency(400000);
mapellil 14:641560b57584 235
mapellil 23:43f9e34781f2 236 X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(i2c);
mapellil 14:641560b57584 237 pressure_sensor = mems_expansion_board->pt_sensor;
mapellil 14:641560b57584 238 temp_sensor1 = mems_expansion_board->ht_sensor;
mapellil 14:641560b57584 239 humidity_sensor = mems_expansion_board->ht_sensor;
mridup 4:1ed7f173eec5 240
mridup 6:0d838d564181 241 pc.printf("\r\nX-NUCLEO-IDW01M1 mbed Application\r\n");
mapellil 14:641560b57584 242 pc.printf("\r\nconnecting to AP\r\n");
fabiombed 13:0b31131bf711 243
mapellil 17:83d0cd810ed3 244 quickstartMode=false;
mapellil 16:233b89a6b72f 245 if (strcmp(org, "quickstart") == 0){quickstartMode = true;}
mapellil 16:233b89a6b72f 246 MQTTWiFi ipstack(spwf, ssid, seckey, NSAPI_SECURITY_WPA2);
mapellil 16:233b89a6b72f 247 MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
mapellil 16:233b89a6b72f 248 if (quickstartMode){
mapellil 24:a59eb8bdc431 249 char mac[50]; // remove all : from mac
mapellil 17:83d0cd810ed3 250 char *digit=NULL;
mapellil 17:83d0cd810ed3 251 sprintf (id,"%s", "");
mapellil 14:641560b57584 252 sprintf (mac,"%s",ipstack.getWiFi().get_mac_address());
mapellil 14:641560b57584 253 digit = strtok (mac,":");
mapellil 14:641560b57584 254 while (digit != NULL)
mapellil 14:641560b57584 255 {
mapellil 14:641560b57584 256 strcat (id, digit);
mapellil 14:641560b57584 257 digit = strtok (NULL, ":");
mapellil 24:a59eb8bdc431 258 }
mapellil 16:233b89a6b72f 259 }
mapellil 16:233b89a6b72f 260 attemptConnect(&client, &ipstack);
mapellil 16:233b89a6b72f 261 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD)
mapellil 16:233b89a6b72f 262 {
mapellil 16:233b89a6b72f 263 while (true)
mapellil 16:233b89a6b72f 264 wait(1.0); // Permanent failures - don't retry
mapellil 16:233b89a6b72f 265 }
mapellil 23:43f9e34781f2 266 #ifdef X_NUCLEO_NFC01A1_PRESENT
mapellil 23:43f9e34781f2 267 // program NFC with broker URL
mapellil 23:43f9e34781f2 268 X_NUCLEO_NFC01A1 *nfcNucleo = X_NUCLEO_NFC01A1::Instance(*i2c, NULL, X_NUCLEO_NFC01A1::DEFAULT_GPO_PIN, X_NUCLEO_NFC01A1::DEFAULT_RF_DISABLE_PIN, NC,NC,NC);
mapellil 23:43f9e34781f2 269 NDefLib::NDefNfcTag& tag = nfcNucleo->getM24SR().getNDefTag();
mapellil 23:43f9e34781f2 270 printf("NFC Init done: !\r\n");
mapellil 23:43f9e34781f2 271 //open the i2c session with the nfc chip
mapellil 23:43f9e34781f2 272 if(tag.openSession()){
mapellil 23:43f9e34781f2 273 //create the NDef message and record
mapellil 23:43f9e34781f2 274 NDefLib::Message msg;
mapellil 23:43f9e34781f2 275 NDefLib::RecordURI rUri(NDefLib::RecordURI::HTTPS, subscription_url);
mapellil 23:43f9e34781f2 276 msg.addRecord(&rUri);
mapellil 23:43f9e34781f2 277 //write the tag
mapellil 23:43f9e34781f2 278 if(tag.write(msg)){
mapellil 23:43f9e34781f2 279 printf("Tag writed \r\n");
mapellil 23:43f9e34781f2 280 }
mapellil 23:43f9e34781f2 281 //close the i2c session
mapellil 23:43f9e34781f2 282 if(!tag.closeSession()){
mapellil 23:43f9e34781f2 283 printf("Error Closing the session\r\n");
mapellil 23:43f9e34781f2 284 }
mapellil 23:43f9e34781f2 285 }else printf("Error open Session\r\n");
mapellil 24:a59eb8bdc431 286 #endif
mapellil 24:a59eb8bdc431 287 myled=1;
mapellil 16:233b89a6b72f 288 int count = 0;
mapellil 16:233b89a6b72f 289 // tyeld.start();
mapellil 14:641560b57584 290 while (true)
mridup 8:6df01cb43137 291 {
mapellil 24:a59eb8bdc431 292 if (++count == 100)
mapellil 14:641560b57584 293 { // Publish a message every second
mapellil 23:43f9e34781f2 294 if (publish(&client, &ipstack) != 0) {
mapellil 24:a59eb8bdc431 295 myled=0;
mapellil 23:43f9e34781f2 296 attemptConnect(&client, &ipstack); // if we have lost the connection
mapellil 24:a59eb8bdc431 297 } else myled=1;
mapellil 14:641560b57584 298 count = 0;
mapellil 14:641560b57584 299 }
mapellil 14:641560b57584 300 // int start = tyeld.read_ms();
mapellil 24:a59eb8bdc431 301 client.yield(10); // allow the MQTT client to receive messages
mapellil 14:641560b57584 302 // printf ("tyeld: %d\n\r",tyeld.read_ms()-start);
mridup 3:dfb8c6c8c31b 303 }
mridup 4:1ed7f173eec5 304 }