Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Wed Jun 05 17:29:31 2019 +0000
Revision:
125:ce4045184366
Parent:
6:6f002d202f59
Added SnRateListner proto-class, publishing this version of the code in order to enable exporting of most recent features.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
uci1 6:6f002d202f59 1 #ifdef IGNORE_THIS_FILE
uci1 0:664899e0b988 2 #include "Websocket.h"
uci1 0:664899e0b988 3 #include <string>
uci1 0:664899e0b988 4
uci1 3:24c5f0f50bf1 5 #include "SnBase64.h"
uci1 3:24c5f0f50bf1 6
uci1 0:664899e0b988 7 //#define DEBUG
uci1 0:664899e0b988 8
uci1 3:24c5f0f50bf1 9 const bool Websocket::kUseB64 = true;
uci1 0:664899e0b988 10
uci1 0:664899e0b988 11 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 12 Websocket::Websocket(char * url) {
uci1 0:664899e0b988 13 server_ip = NULL;
uci1 0:664899e0b988 14 netif = ETH;
uci1 0:664899e0b988 15 eth_writeable = false;
uci1 0:664899e0b988 16 eth_readable = false;
uci1 0:664899e0b988 17 eth_connected = false;
uci1 0:664899e0b988 18 response_server_eth = false;
uci1 0:664899e0b988 19 new_msg = false;
uci1 0:664899e0b988 20 fillFields(url);
uci1 1:e392595b4b76 21
uci1 3:24c5f0f50bf1 22 memset(eth_rx, 0, RX_BUF_SIZE);
uci1 1:e392595b4b76 23
uci1 0:664899e0b988 24 eth = new EthernetNetIf(
uci1 0:664899e0b988 25 IpAddr(128,195,204,148), //IP Address
uci1 0:664899e0b988 26 IpAddr(255,255,255,0), //Network Mask
uci1 0:664899e0b988 27 IpAddr(128,195,204,1), //Gateway
uci1 0:664899e0b988 28 IpAddr(128,200,1,201) //DNS
uci1 0:664899e0b988 29 );
uci1 0:664899e0b988 30 sock = new TCPSocket();
uci1 0:664899e0b988 31
uci1 0:664899e0b988 32 EthernetErr ethErr = eth->setup();
uci1 0:664899e0b988 33 #ifdef DEBUG
uci1 0:664899e0b988 34 if (ethErr) {
uci1 0:664899e0b988 35 printf("\r\nERROR %d in setup.\r\n", ethErr);
uci1 0:664899e0b988 36 }
uci1 0:664899e0b988 37 #endif
uci1 0:664899e0b988 38
uci1 0:664899e0b988 39 //we must use dnsresolver to find the ip address
uci1 0:664899e0b988 40 if (server_ip == NULL) {
uci1 0:664899e0b988 41 DNSResolver dr;
uci1 0:664899e0b988 42 server_ip = new IpAddr();
uci1 0:664899e0b988 43 *server_ip = dr.resolveName(ip_domain.c_str());
uci1 0:664899e0b988 44 #ifdef DEBUG
uci1 0:664899e0b988 45 printf("\r\nserver with dns=%d.%d.%d.%d\r\n", (*server_ip)[0], (*server_ip)[1], (*server_ip)[2], (*server_ip)[3]);
uci1 0:664899e0b988 46 #endif
uci1 0:664899e0b988 47
uci1 0:664899e0b988 48 }
uci1 0:664899e0b988 49
uci1 0:664899e0b988 50 IpAddr ipt = eth->getIp();
uci1 0:664899e0b988 51 #ifdef DEBUG
uci1 0:664899e0b988 52 printf("\r\nmbed IP Address is %d.%d.%d.%d\r\n", ipt[0], ipt[1], ipt[2], ipt[3]);
uci1 0:664899e0b988 53 #endif
uci1 0:664899e0b988 54
uci1 0:664899e0b988 55 sock->setOnEvent(this, &Websocket::onTCPSocketEvent);
uci1 0:664899e0b988 56 }
uci1 0:664899e0b988 57 #endif //target
uci1 0:664899e0b988 58
uci1 0:664899e0b988 59
uci1 0:664899e0b988 60 void Websocket::fillFields(char * url)
uci1 0:664899e0b988 61 {
uci1 1:e392595b4b76 62 #ifdef DEBUG
uci1 0:664899e0b988 63 printf("FILLFIELDS\r\n");
uci1 1:e392595b4b76 64 #endif
uci1 0:664899e0b988 65 char *res = NULL;
uci1 0:664899e0b988 66 char *res1 = NULL;
uci1 0:664899e0b988 67
uci1 0:664899e0b988 68 char buf[50];
uci1 0:664899e0b988 69 strcpy(buf, url);
uci1 0:664899e0b988 70 printf("\r\nBuf is:");
uci1 0:664899e0b988 71 for(int i=0;i<50;i++)
uci1 0:664899e0b988 72 {
uci1 0:664899e0b988 73 printf("%d", buf[i]);
uci1 0:664899e0b988 74 }
uci1 0:664899e0b988 75 printf("\r\n");
uci1 0:664899e0b988 76 res = strtok(buf, ":");
uci1 0:664899e0b988 77 if (strcmp(res, "ws"))
uci1 0:664899e0b988 78 {
uci1 0:664899e0b988 79 #ifdef DEBUG
uci1 0:664899e0b988 80 printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n");
uci1 0:664899e0b988 81 #endif
uci1 0:664899e0b988 82 }
uci1 0:664899e0b988 83 else
uci1 0:664899e0b988 84 {
uci1 0:664899e0b988 85 //ip_domain and port
uci1 0:664899e0b988 86 res = strtok(NULL, "/");
uci1 0:664899e0b988 87
uci1 0:664899e0b988 88 //path
uci1 0:664899e0b988 89 res1 = strtok(NULL, " ");
uci1 0:664899e0b988 90 if (res1 != NULL)
uci1 0:664899e0b988 91 {
uci1 0:664899e0b988 92 path = res1;
uci1 0:664899e0b988 93 }
uci1 0:664899e0b988 94
uci1 0:664899e0b988 95 //ip_domain
uci1 0:664899e0b988 96 res = strtok(res, ":");
uci1 0:664899e0b988 97
uci1 0:664899e0b988 98 //port
uci1 0:664899e0b988 99 res1 = strtok(NULL, " ");
uci1 0:664899e0b988 100 //port
uci1 0:664899e0b988 101 if (res1 != NULL)
uci1 0:664899e0b988 102 {
uci1 0:664899e0b988 103 port = res1;
uci1 0:664899e0b988 104 } else
uci1 0:664899e0b988 105 {
uci1 0:664899e0b988 106 port = "80";
uci1 0:664899e0b988 107 }
uci1 0:664899e0b988 108
uci1 0:664899e0b988 109 if (res != NULL)
uci1 0:664899e0b988 110 {
uci1 0:664899e0b988 111 ip_domain = res;
uci1 0:664899e0b988 112
uci1 0:664899e0b988 113 //if we use ethernet, we must decode ip address or use dnsresolver
uci1 0:664899e0b988 114 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 115 if (netif == ETH) {
uci1 0:664899e0b988 116 strcpy(buf, res);
uci1 0:664899e0b988 117 //we try to decode the ip address
uci1 0:664899e0b988 118 if (buf[0] >= '0' && buf[0] <= '9') {
uci1 0:664899e0b988 119 res = strtok(buf, ".");
uci1 0:664899e0b988 120 int i = 0;
uci1 0:664899e0b988 121 int ip[4];
uci1 0:664899e0b988 122 while (res != NULL) {
uci1 0:664899e0b988 123 ip[i] = atoi(res);
uci1 0:664899e0b988 124 res = strtok(NULL, ".");
uci1 0:664899e0b988 125 i++;
uci1 0:664899e0b988 126 }
uci1 0:664899e0b988 127 server_ip = new IpAddr(ip[0], ip[1], ip[2], ip[3]);
uci1 0:664899e0b988 128 #ifdef DEBUG
uci1 0:664899e0b988 129 printf("server without dns=%i.%i.%i.%i\n",(*server_ip)[0],(*server_ip)[1],(*server_ip)[2],(*server_ip)[3]);
uci1 0:664899e0b988 130 #endif
uci1 0:664899e0b988 131 }
uci1 0:664899e0b988 132 }
uci1 0:664899e0b988 133 #endif //target
uci1 0:664899e0b988 134 }
uci1 0:664899e0b988 135 }
uci1 0:664899e0b988 136 }
uci1 0:664899e0b988 137
uci1 0:664899e0b988 138
uci1 1:e392595b4b76 139 bool Websocket::connect(const uint32_t timeout)
uci1 0:664899e0b988 140 {
uci1 1:e392595b4b76 141 #ifdef DEBUG
uci1 1:e392595b4b76 142 printf("CONNECT() Function\r\n");
uci1 1:e392595b4b76 143 #endif
uci1 0:664899e0b988 144 char cmd[50];
uci1 0:664899e0b988 145 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 146 //M: else if (netif == ETH)
uci1 0:664899e0b988 147 if (netif == ETH)
uci1 0:664899e0b988 148 {
uci1 0:664899e0b988 149 Host server (*server_ip, atoi(port.c_str()));
uci1 0:664899e0b988 150 sock->close();
uci1 0:664899e0b988 151 TCPSocketErr bindErr = sock->connect(server);
uci1 0:664899e0b988 152 if (bindErr)
uci1 0:664899e0b988 153 {
uci1 0:664899e0b988 154 #ifdef DEBUG
uci1 0:664899e0b988 155 printf("\r\nERROR binderr: %d\r\n", bindErr);
uci1 0:664899e0b988 156 #endif
uci1 0:664899e0b988 157 return false;
uci1 0:664899e0b988 158 }
uci1 0:664899e0b988 159 Timer tmr;
uci1 0:664899e0b988 160 tmr.start();
uci1 0:664899e0b988 161 int i = 0;
uci1 0:664899e0b988 162 while (true) {
uci1 0:664899e0b988 163 Net::poll();
uci1 1:e392595b4b76 164 if (time(0) > timeout) {
uci1 3:24c5f0f50bf1 165
uci1 2:e67f7c158087 166 printf("connect timeout %u > %u\r\n",
uci1 2:e67f7c158087 167 time(0), timeout);
uci1 3:24c5f0f50bf1 168
uci1 0:664899e0b988 169 return false;
uci1 1:e392595b4b76 170 }
uci1 0:664899e0b988 171 if (tmr.read() > 0.05) {
uci1 0:664899e0b988 172 tmr.reset();
uci1 0:664899e0b988 173 if (eth_connected) {
uci1 1:e392595b4b76 174 //printf("connect msg %d\r\n",i);
uci1 0:664899e0b988 175 switch (i) {
uci1 0:664899e0b988 176 case 0:
uci1 0:664899e0b988 177 sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str());
uci1 0:664899e0b988 178 sock->send(cmd, strlen(cmd));
uci1 0:664899e0b988 179 i++;
uci1 0:664899e0b988 180 break;
uci1 0:664899e0b988 181 case 1:
uci1 0:664899e0b988 182 sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str());
uci1 0:664899e0b988 183 sock->send(cmd, strlen(cmd));
uci1 0:664899e0b988 184 i++;
uci1 0:664899e0b988 185 break;
uci1 0:664899e0b988 186 case 2:
uci1 0:664899e0b988 187 sprintf(cmd, "Upgrade: WebSocket\r\n");
uci1 0:664899e0b988 188 sock->send(cmd, strlen(cmd));
uci1 0:664899e0b988 189 i++;
uci1 0:664899e0b988 190 break;
uci1 0:664899e0b988 191 case 3:
uci1 0:664899e0b988 192 sprintf(cmd, "Origin: null\r\n");
uci1 0:664899e0b988 193 sock->send(cmd, strlen(cmd));
uci1 0:664899e0b988 194 i++;
uci1 0:664899e0b988 195 break;
uci1 0:664899e0b988 196 case 4:
uci1 0:664899e0b988 197 sprintf(cmd, "Connection: Upgrade\r\n");
uci1 0:664899e0b988 198 sock->send(cmd, strlen(cmd));
uci1 0:664899e0b988 199 i++;
uci1 0:664899e0b988 200 break;
uci1 0:664899e0b988 201 case 5:
uci1 0:664899e0b988 202 sprintf(cmd, "Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n");
uci1 0:664899e0b988 203 sock->send(cmd, strlen(cmd));
uci1 0:664899e0b988 204 i++;
uci1 0:664899e0b988 205 break;
uci1 0:664899e0b988 206 case 6:
uci1 0:664899e0b988 207 sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n");
uci1 0:664899e0b988 208 sock->send(cmd, strlen(cmd));
uci1 0:664899e0b988 209 i++;
uci1 0:664899e0b988 210 break;
uci1 0:664899e0b988 211 case 7:
uci1 0:664899e0b988 212 if (response_server_eth)
uci1 0:664899e0b988 213 i++;
uci1 0:664899e0b988 214 else
uci1 0:664899e0b988 215 break;
uci1 0:664899e0b988 216
uci1 0:664899e0b988 217 default:
uci1 0:664899e0b988 218 break;
uci1 0:664899e0b988 219 }
uci1 0:664899e0b988 220 }
uci1 0:664899e0b988 221 if (i==8) {
uci1 0:664899e0b988 222 #ifdef DEBUG
uci1 0:664899e0b988 223 printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain.c_str(), this->path.c_str(), this->port.c_str());
uci1 0:664899e0b988 224 #endif
uci1 0:664899e0b988 225 return true;
uci1 0:664899e0b988 226 }
uci1 0:664899e0b988 227 }
uci1 0:664899e0b988 228 }
uci1 0:664899e0b988 229 }
uci1 0:664899e0b988 230 #endif //target
uci1 0:664899e0b988 231 //the program shouldn't be here
uci1 0:664899e0b988 232 return false;
uci1 0:664899e0b988 233 }
uci1 0:664899e0b988 234
uci1 0:664899e0b988 235 void Websocket::sendLength(uint32_t len)
uci1 0:664899e0b988 236 {
uci1 0:664899e0b988 237 //printf("SENDLENGTH(), Send Length: %d\r\n", len);
uci1 0:664899e0b988 238 if (len < 126)
uci1 0:664899e0b988 239 {
uci1 0:664899e0b988 240 sendChar(len | (1<<7));
uci1 0:664899e0b988 241 }
uci1 0:664899e0b988 242 else if (len < 65535)
uci1 0:664899e0b988 243 { // use 2 bytes
uci1 0:664899e0b988 244 sendChar(126 | (1<<7));
uci1 0:664899e0b988 245 //M: reverce these two lines
uci1 0:664899e0b988 246 sendChar((len >> 8) & 0xff); //2
uci1 0:664899e0b988 247 sendChar(len & 0xff); //1
uci1 0:664899e0b988 248 // sendChar((len >> 8) & 0xff); //2
uci1 0:664899e0b988 249 }
uci1 0:664899e0b988 250 else
uci1 0:664899e0b988 251 {
uci1 0:664899e0b988 252 sendChar(127 | (1<<7));
uci1 0:664899e0b988 253 for (int i = 0; i < 8; i++)
uci1 0:664899e0b988 254 {
uci1 0:664899e0b988 255 sendChar((len >> i*8) & 0xff);
uci1 0:664899e0b988 256 }
uci1 0:664899e0b988 257 }
uci1 0:664899e0b988 258 }
uci1 0:664899e0b988 259
uci1 0:664899e0b988 260 int Websocket::sendChar(uint8_t c)
uci1 0:664899e0b988 261 {
uci1 0:664899e0b988 262 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 263 if (netif == ETH) {
uci1 0:664899e0b988 264 Net::poll();
uci1 0:664899e0b988 265 return sock->send((const char *)&c, 1);
uci1 0:664899e0b988 266 // printf("SENDCHAR(), Sendchar %d \r\n", c);
uci1 0:664899e0b988 267 }
uci1 0:664899e0b988 268 #endif
uci1 0:664899e0b988 269 return 0;
uci1 0:664899e0b988 270 }
uci1 0:664899e0b988 271
uci1 0:664899e0b988 272 void Websocket::sendOpcode(uint8_t opcode)
uci1 0:664899e0b988 273 {
uci1 0:664899e0b988 274 // printf("SENDOPCODE()\r\n");
uci1 0:664899e0b988 275 sendChar(0x80 | (opcode & 0x0f));
uci1 0:664899e0b988 276 // printf("SendOpcode: 0x%X\r\n", opcode);
uci1 0:664899e0b988 277 }
uci1 0:664899e0b988 278
uci1 0:664899e0b988 279 /*Masking-key: 0 or 4 bytes
uci1 0:664899e0b988 280 All frames sent from the client to the server are masked by a 32-
uci1 0:664899e0b988 281 bit value that is contained within the frame. This field is
uci1 0:664899e0b988 282 present if the mask bit is set to 1, and is absent if the mask bit
uci1 0:664899e0b988 283 is set to 0.
uci1 0:664899e0b988 284 */
uci1 0:664899e0b988 285 void Websocket::sendMask()
uci1 0:664899e0b988 286 {
uci1 0:664899e0b988 287 // printf("SENDMASK()\r\n");
uci1 0:664899e0b988 288 for (int i = 0; i < 4; i++) {
uci1 0:664899e0b988 289 sendChar(0); //no frame masking
uci1 0:664899e0b988 290 }
uci1 0:664899e0b988 291 }
uci1 0:664899e0b988 292
uci1 3:24c5f0f50bf1 293 void Websocket::send(const char * str)
uci1 0:664899e0b988 294 {
uci1 1:e392595b4b76 295 #ifdef DEBUG
uci1 1:e392595b4b76 296 printf("SEND(%s)\r\n",str);
uci1 1:e392595b4b76 297 #endif
uci1 0:664899e0b988 298 /* Opcode: 4 bits
uci1 0:664899e0b988 299 The opcode denotes the frame type of the WebSocket frame
uci1 0:664899e0b988 300 Defines the interpretation of the payload data. If an unknown
uci1 0:664899e0b988 301 opcode is received, the receiving endpoint MUST _Fail the
uci1 0:664899e0b988 302 WebSocket Connection_. The following values are defined.
uci1 0:664899e0b988 303 * %x0 denotes a continuation frame
uci1 0:664899e0b988 304 * %x1 denotes a text frame
uci1 0:664899e0b988 305 * %x2 denotes a binary frame
uci1 0:664899e0b988 306 * %x3-7 are reserved for further non-control frames
uci1 0:664899e0b988 307 * %x8 denotes a connection close
uci1 0:664899e0b988 308 * %x9 denotes a pingg
uci1 0:664899e0b988 309 * %xA denotes a pong
uci1 0:664899e0b988 310 * %xB-F are reserved for further control frames
uci1 0:664899e0b988 311
uci1 0:664899e0b988 312 */
uci1 0:664899e0b988 313 sendOpcode(0x01);
uci1 0:664899e0b988 314 sendLength(strlen(str));
uci1 0:664899e0b988 315 sendMask();
uci1 0:664899e0b988 316
uci1 0:664899e0b988 317 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 318 //M: else if (netif == ETH) {
uci1 0:664899e0b988 319 if (netif == ETH)
uci1 0:664899e0b988 320 {
uci1 0:664899e0b988 321 Net::poll();
uci1 0:664899e0b988 322 sock->send(str, strlen(str));
uci1 0:664899e0b988 323 }
uci1 0:664899e0b988 324 #endif //target
uci1 0:664899e0b988 325 }
uci1 0:664899e0b988 326
uci1 3:24c5f0f50bf1 327 bool Websocket::sendBinary(const char* hbuf, const uint32_t hlen,
uci1 3:24c5f0f50bf1 328 FILE* f, const uint32_t nbytes,
uci1 3:24c5f0f50bf1 329 char* const bbuf) {
uci1 3:24c5f0f50bf1 330 if (kUseB64) {
uci1 3:24c5f0f50bf1 331 return sendBinaryB64txt(hbuf, hlen, f, nbytes, bbuf);
uci1 3:24c5f0f50bf1 332 } else {
uci1 3:24c5f0f50bf1 333 return sendBinaryDirect(hbuf, hlen, f, nbytes);
uci1 3:24c5f0f50bf1 334 }
uci1 3:24c5f0f50bf1 335 }
uci1 3:24c5f0f50bf1 336
uci1 3:24c5f0f50bf1 337 bool Websocket::sendBinaryB64txt(const char* hbuf, const uint32_t hlen,
uci1 3:24c5f0f50bf1 338 FILE* f, const uint32_t nbytes,
uci1 3:24c5f0f50bf1 339 char* const bbuf) {
uci1 3:24c5f0f50bf1 340 #ifdef DEBUG
uci1 3:24c5f0f50bf1 341 printf("SENDbinaryB64txt(%s)\r\n",str);
uci1 3:24c5f0f50bf1 342 #endif
uci1 3:24c5f0f50bf1 343 /* Opcode: 4 bits
uci1 3:24c5f0f50bf1 344 The opcode denotes the frame type of the WebSocket frame
uci1 3:24c5f0f50bf1 345 Defines the interpretation of the payload data. If an unknown
uci1 3:24c5f0f50bf1 346 opcode is received, the receiving endpoint MUST _Fail the
uci1 3:24c5f0f50bf1 347 WebSocket Connection_. The following values are defined.
uci1 3:24c5f0f50bf1 348 * %x0 denotes a continuation frame
uci1 3:24c5f0f50bf1 349 * %x1 denotes a text frame
uci1 3:24c5f0f50bf1 350 * %x2 denotes a binary frame
uci1 3:24c5f0f50bf1 351 * %x3-7 are reserved for further non-control frames
uci1 3:24c5f0f50bf1 352 * %x8 denotes a connection close
uci1 3:24c5f0f50bf1 353 * %x9 denotes a pingg
uci1 3:24c5f0f50bf1 354 * %xA denotes a pong
uci1 3:24c5f0f50bf1 355 * %xB-F are reserved for further control frames
uci1 3:24c5f0f50bf1 356
uci1 3:24c5f0f50bf1 357 */
uci1 3:24c5f0f50bf1 358 sendOpcode(0x01);
uci1 3:24c5f0f50bf1 359 sendLength(BASE64ENC_LEN(nbytes));
uci1 3:24c5f0f50bf1 360 sendMask();
uci1 3:24c5f0f50bf1 361
uci1 3:24c5f0f50bf1 362 #ifdef TARGET_LPC1768
uci1 3:24c5f0f50bf1 363 //M: else if (netif == ETH) {
uci1 3:24c5f0f50bf1 364 if (netif == ETH)
uci1 3:24c5f0f50bf1 365 {
uci1 3:24c5f0f50bf1 366 Net::poll();
uci1 3:24c5f0f50bf1 367 //sock->send(str, strlen(str));
uci1 3:24c5f0f50bf1 368 // read 3 bytes at a time
uci1 3:24c5f0f50bf1 369 static const uint8_t cbytes = 3; // must be multiple of 3
uci1 3:24c5f0f50bf1 370 static const uint32_t clen = BASE64ENC_LEN(cbytes)+1;
uci1 3:24c5f0f50bf1 371 char chunk[clen];
uci1 3:24c5f0f50bf1 372 char fbuf[cbytes];
uci1 3:24c5f0f50bf1 373 const uint32_t nchunks = nbytes / cbytes;
uci1 3:24c5f0f50bf1 374 for (uint32_t i=0; i<nchunks; i++) {
uci1 3:24c5f0f50bf1 375 fread(fbuf, cbytes, 1, f);
uci1 3:24c5f0f50bf1 376 B64::modp_b64_encode(fbuf, cbytes, chunk);
uci1 3:24c5f0f50bf1 377 sock->send(chunk, clen-1);
uci1 3:24c5f0f50bf1 378 }
uci1 3:24c5f0f50bf1 379 // now the remainder
uci1 3:24c5f0f50bf1 380 const uint32_t rem = nbytes-(nchunks*cbytes);
uci1 3:24c5f0f50bf1 381 if (rem>0) {
uci1 3:24c5f0f50bf1 382 fread(fbuf, rem, 1, f);
uci1 3:24c5f0f50bf1 383 B64::modp_b64_encode(fbuf, rem, chunk);
uci1 3:24c5f0f50bf1 384 sock->send(chunk, strlen(chunk));
uci1 3:24c5f0f50bf1 385 }
uci1 3:24c5f0f50bf1 386 }
uci1 3:24c5f0f50bf1 387 #endif //target
uci1 3:24c5f0f50bf1 388 return true;
uci1 3:24c5f0f50bf1 389 }
uci1 3:24c5f0f50bf1 390
uci1 3:24c5f0f50bf1 391 bool Websocket::sendBinary(const char* str, const uint32_t len,
uci1 3:24c5f0f50bf1 392 char* const bbuf) {
uci1 3:24c5f0f50bf1 393 if (kUseB64) {
uci1 3:24c5f0f50bf1 394 return sendBinaryB64txt(str, len, bbuf);
uci1 3:24c5f0f50bf1 395 } else {
uci1 3:24c5f0f50bf1 396 return sendBinaryDirect(str, len);
uci1 3:24c5f0f50bf1 397 }
uci1 3:24c5f0f50bf1 398 }
uci1 3:24c5f0f50bf1 399
uci1 3:24c5f0f50bf1 400 bool Websocket::sendBinaryB64txt(const char* str, const uint32_t len,
uci1 3:24c5f0f50bf1 401 char* const bbuf) {
uci1 3:24c5f0f50bf1 402 B64::modp_b64_encode(str, len, bbuf);
uci1 3:24c5f0f50bf1 403 send(bbuf);
uci1 3:24c5f0f50bf1 404 return true;
uci1 3:24c5f0f50bf1 405 }
uci1 3:24c5f0f50bf1 406
uci1 3:24c5f0f50bf1 407 bool Websocket::sendBinaryDirect(const char* str, const uint32_t len)
uci1 0:664899e0b988 408 {
uci1 0:664899e0b988 409 // CJR: add function for sending binary
uci1 2:e67f7c158087 410 // force header info to be sent on each call
uci1 1:e392595b4b76 411 #ifdef DEBUG
uci1 1:e392595b4b76 412 printf("SENDBINARY()\r\n");
uci1 1:e392595b4b76 413 #endif
uci1 0:664899e0b988 414 /* Opcode: 4 bits
uci1 0:664899e0b988 415 The opcode denotes the frame type of the WebSocket frame
uci1 0:664899e0b988 416 Defines the interpretation of the payload data. If an unknown
uci1 0:664899e0b988 417 opcode is received, the receiving endpoint MUST _Fail the
uci1 0:664899e0b988 418 WebSocket Connection_. The following values are defined.
uci1 0:664899e0b988 419 * %x0 denotes a continuation frame
uci1 0:664899e0b988 420 * %x1 denotes a text frame
uci1 0:664899e0b988 421 * %x2 denotes a binary frame
uci1 0:664899e0b988 422 * %x3-7 are reserved for further non-control frames
uci1 0:664899e0b988 423 * %x8 denotes a connection close
uci1 0:664899e0b988 424 * %x9 denotes a pingg
uci1 0:664899e0b988 425 * %xA denotes a pong
uci1 0:664899e0b988 426 * %xB-F are reserved for further control frames
uci1 0:664899e0b988 427
uci1 0:664899e0b988 428 */
uci1 3:24c5f0f50bf1 429 printf("send binary: 0x02 %u 0\r\n", len);
uci1 0:664899e0b988 430 sendOpcode(0x02);
uci1 0:664899e0b988 431 sendLength(len);
uci1 0:664899e0b988 432 sendMask();
uci1 0:664899e0b988 433
uci1 0:664899e0b988 434 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 435 //M: else if (netif == ETH) {
uci1 0:664899e0b988 436 if (netif == ETH)
uci1 0:664899e0b988 437 {
uci1 0:664899e0b988 438 Net::poll();
uci1 3:24c5f0f50bf1 439 /*
uci1 2:e67f7c158087 440 // first send the header
uci1 2:e67f7c158087 441 const char* hh = hbuf;
uci1 2:e67f7c158087 442 for (uint32_t j=0; j<hlen; j++, hh++) {
uci1 2:e67f7c158087 443 sendChar(*hh);
uci1 3:24c5f0f50bf1 444 printf("%02x ",*hh);
uci1 2:e67f7c158087 445 }
uci1 3:24c5f0f50bf1 446 */
uci1 2:e67f7c158087 447 // now send the message
uci1 0:664899e0b988 448 uint32_t nbytes=0;
uci1 3:24c5f0f50bf1 449 const char* ss = str;
uci1 3:24c5f0f50bf1 450 for (uint32_t i=0; i<len; i++, ss++) {
uci1 3:24c5f0f50bf1 451 nbytes += sendChar(*ss);
uci1 3:24c5f0f50bf1 452 printf("%02x ",*ss);
uci1 0:664899e0b988 453 }
uci1 3:24c5f0f50bf1 454 printf("\r\n");
uci1 0:664899e0b988 455 //const int32_t nbytes = sock->send(str, len);
uci1 0:664899e0b988 456 return nbytes==len;
uci1 0:664899e0b988 457 }
uci1 0:664899e0b988 458 #endif //target
uci1 0:664899e0b988 459 return false;
uci1 0:664899e0b988 460 }
uci1 0:664899e0b988 461
uci1 3:24c5f0f50bf1 462 bool Websocket::sendBinaryDirect(const char* hbuf, const uint32_t hlen,
uci1 3:24c5f0f50bf1 463 FILE* f, const uint32_t nbytes)
uci1 0:664899e0b988 464 {
uci1 1:e392595b4b76 465 #ifdef DEBUG
uci1 1:e392595b4b76 466 printf("SENDBINARY(FILE*)\r\n");
uci1 1:e392595b4b76 467 #endif
uci1 0:664899e0b988 468 // CJR: add function for sending binary
uci1 2:e67f7c158087 469 // force header info to be sent on each call
uci1 0:664899e0b988 470 // return false if EOF or file error before nbytes sent
uci1 0:664899e0b988 471
uci1 0:664899e0b988 472 //printf("SEND()\r\n");
uci1 0:664899e0b988 473 /* Opcode: 4 bits
uci1 0:664899e0b988 474 The opcode denotes the frame type of the WebSocket frame
uci1 0:664899e0b988 475 Defines the interpretation of the payload data. If an unknown
uci1 0:664899e0b988 476 opcode is received, the receiving endpoint MUST _Fail the
uci1 0:664899e0b988 477 WebSocket Connection_. The following values are defined.
uci1 0:664899e0b988 478 * %x0 denotes a continuation frame
uci1 0:664899e0b988 479 * %x1 denotes a text frame
uci1 0:664899e0b988 480 * %x2 denotes a binary frame
uci1 0:664899e0b988 481 * %x3-7 are reserved for further non-control frames
uci1 0:664899e0b988 482 * %x8 denotes a connection close
uci1 0:664899e0b988 483 * %x9 denotes a pingg
uci1 0:664899e0b988 484 * %xA denotes a pong
uci1 0:664899e0b988 485 * %xB-F are reserved for further control frames
uci1 0:664899e0b988 486
uci1 0:664899e0b988 487 */
uci1 0:664899e0b988 488 sendOpcode(0x02);
uci1 0:664899e0b988 489 sendLength(nbytes);
uci1 0:664899e0b988 490 sendMask();
uci1 0:664899e0b988 491
uci1 0:664899e0b988 492 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 493 //M: else if (netif == ETH) {
uci1 0:664899e0b988 494 if (netif == ETH)
uci1 0:664899e0b988 495 {
uci1 0:664899e0b988 496 Net::poll();
uci1 2:e67f7c158087 497 // first send the header
uci1 2:e67f7c158087 498 const char* hh = hbuf;
uci1 2:e67f7c158087 499 for (uint32_t j=0; j<hlen; j++, hh++) {
uci1 2:e67f7c158087 500 sendChar(*hh);
uci1 2:e67f7c158087 501 }
uci1 2:e67f7c158087 502 // conserve mbed memory by reading byte-by-byte
uci1 0:664899e0b988 503 uint8_t c;
uci1 0:664899e0b988 504 for (uint32_t i=0; i<nbytes; i++) {
uci1 0:664899e0b988 505 fread(&c, 1, 1, f);
uci1 0:664899e0b988 506 if ((feof(f)==0) && (ferror(f)==0)) {
uci1 0:664899e0b988 507 sendChar(c);
uci1 0:664899e0b988 508 } else {
uci1 0:664899e0b988 509 return false;
uci1 0:664899e0b988 510 }
uci1 0:664899e0b988 511 }
uci1 0:664899e0b988 512
uci1 0:664899e0b988 513 }
uci1 0:664899e0b988 514 #endif //target
uci1 0:664899e0b988 515 return true;
uci1 0:664899e0b988 516 }
uci1 0:664899e0b988 517
uci1 3:24c5f0f50bf1 518 bool Websocket::read(char * message, uint32_t& len_msg, const uint32_t maxlen,
uci1 3:24c5f0f50bf1 519 const uint32_t timeout,
uci1 3:24c5f0f50bf1 520 char* const bbuf, const uint32_t bbsize)
uci1 0:664899e0b988 521 {
uci1 1:e392595b4b76 522 #ifdef DEBUG
uci1 1:e392595b4b76 523 printf("READ()\r\n");
uci1 1:e392595b4b76 524 #endif
uci1 2:e67f7c158087 525 //uint32_t len_msg; //32 bit size
uci1 0:664899e0b988 526 char opcode = 0; //continuation frame
uci1 0:664899e0b988 527 char mask[4] = {0, 0, 0, 0}; //no mask
uci1 0:664899e0b988 528 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 529 if (netif == ETH)
uci1 0:664899e0b988 530 {
uci1 1:e392595b4b76 531 #ifdef DEBUG
uci1 1:e392595b4b76 532 printf("Current opcode in read() 0x%X\r\n", opcode);
uci1 1:e392595b4b76 533 #endif
uci1 0:664899e0b988 534 uint32_t index = 0;
uci1 0:664899e0b988 535 Net::poll();
uci1 0:664899e0b988 536 if (new_msg) //from webserver
uci1 0:664899e0b988 537 {
uci1 1:e392595b4b76 538 #ifdef DEBUG
uci1 0:664899e0b988 539 printf("There is new message from webserver\r\n");
uci1 1:e392595b4b76 540 #endif
uci1 0:664899e0b988 541 // read the opcode
uci1 0:664899e0b988 542 while (true)
uci1 0:664899e0b988 543 {
uci1 1:e392595b4b76 544 if (time(0) > timeout)
uci1 0:664899e0b988 545 {
uci1 1:e392595b4b76 546 printf("read: timing out %d > %u \r\n",
uci1 1:e392595b4b76 547 time(0), timeout);
uci1 1:e392595b4b76 548 wait(2);
uci1 0:664899e0b988 549 return false;
uci1 3:24c5f0f50bf1 550 } else if (index>=RX_BUF_SIZE) {
uci1 1:e392595b4b76 551 index=0;
uci1 1:e392595b4b76 552 continue;
uci1 0:664899e0b988 553 }
uci1 0:664899e0b988 554 opcode = eth_rx[index++];
uci1 1:e392595b4b76 555 #ifdef DEBUG
uci1 0:664899e0b988 556 printf("new opcode in read() func: 0x%X\r\n", opcode); //0x81
uci1 1:e392595b4b76 557 #endif
uci1 1:e392595b4b76 558 if (opcode == 0x81 || opcode==0x82)
uci1 0:664899e0b988 559 {
uci1 0:664899e0b988 560 break;
uci1 0:664899e0b988 561 }
uci1 0:664899e0b988 562 }// end of while(true)
uci1 1:e392595b4b76 563
uci1 1:e392595b4b76 564 // redo search in case opcode is actually inside a byte message
uci1 1:e392595b4b76 565 // and a race-condition occurred
uci1 1:e392595b4b76 566 int32_t ix=0;
uci1 1:e392595b4b76 567 const char* erx = eth_rx;
uci1 3:24c5f0f50bf1 568 for (ix=0; ix<RX_BUF_SIZE; ix++, erx++) { // 1024 or 512? (since sock->read is called with 512)
uci1 1:e392595b4b76 569 if ( (*erx==0x81) || (*erx==0x82) ) {
uci1 1:e392595b4b76 570 index = ix+1;
uci1 3:24c5f0f50bf1 571 opcode = *erx;
uci1 1:e392595b4b76 572 break;
uci1 1:e392595b4b76 573 }
uci1 1:e392595b4b76 574 }
uci1 3:24c5f0f50bf1 575 if (ix==RX_BUF_SIZE) {
uci1 1:e392595b4b76 576 // some new non-websocket message came in during the redoing of the search?
uci1 1:e392595b4b76 577 // anyway opcode not found
uci1 1:e392595b4b76 578 printf("opcode re-search failed\r\n");
uci1 1:e392595b4b76 579 return false;
uci1 1:e392595b4b76 580 }
uci1 1:e392595b4b76 581 //#ifdef DEBUG
uci1 1:e392595b4b76 582 printf("opcode: 0x%X @ index=%u\r\n", opcode, index-1);
uci1 3:24c5f0f50bf1 583 for (int i=0; i<RX_BUF_SIZE; i++) {
uci1 1:e392595b4b76 584 printf("%02x ",eth_rx[i]);
uci1 1:e392595b4b76 585 }
uci1 1:e392595b4b76 586 printf("\r\n");
uci1 1:e392595b4b76 587 //#endif
uci1 1:e392595b4b76 588 printf("eth_rx[i-1]=%x, eth_rx[i]=%x , eth_rx[i+1]=%x\r\n",
uci1 1:e392595b4b76 589 index>0?eth_rx[index-1]:eth_rx[index],eth_rx[index],eth_rx[index+1]);
uci1 0:664899e0b988 590 len_msg = eth_rx[index++] & 0x7f;
uci1 0:664899e0b988 591 printf("length_message2 : %d\r\n", len_msg); //
uci1 0:664899e0b988 592 if (len_msg == 126)
uci1 0:664899e0b988 593 {
uci1 0:664899e0b988 594 len_msg += eth_rx[index++] << 8;
uci1 0:664899e0b988 595 len_msg = eth_rx[index++];
uci1 3:24c5f0f50bf1 596 printf("len message is greater than 126 %d\r\n", len_msg);
uci1 0:664899e0b988 597 }
uci1 0:664899e0b988 598 else if (len_msg == 127)
uci1 0:664899e0b988 599 {
uci1 0:664899e0b988 600 len_msg = 0;
uci1 0:664899e0b988 601 for (int i = 0; i < 8; i++)
uci1 0:664899e0b988 602 {
uci1 0:664899e0b988 603 len_msg += eth_rx[index++] << i*8;
uci1 0:664899e0b988 604 }
uci1 0:664899e0b988 605 }
uci1 0:664899e0b988 606 if(len_msg == 0)
uci1 0:664899e0b988 607 {
uci1 0:664899e0b988 608 return false;
uci1 3:24c5f0f50bf1 609 } else if (len_msg>=maxlen) {
uci1 3:24c5f0f50bf1 610 return false;
uci1 0:664899e0b988 611 }
uci1 1:e392595b4b76 612 //#ifdef DEBUG
uci1 1:e392595b4b76 613 printf("length: %d\r\n", len_msg);
uci1 1:e392595b4b76 614 //#endif
uci1 0:664899e0b988 615 if ((len_msg & 0x80))
uci1 0:664899e0b988 616 {
uci1 0:664899e0b988 617 printf("print mask bit %d\r\n", len_msg & 0x80);
uci1 0:664899e0b988 618 for (int j = 0; j < 4; j++){
uci1 0:664899e0b988 619 mask[j] = eth_rx[index++];
uci1 0:664899e0b988 620 printf(" mask index %i is %i, ", j, mask[j]);
uci1 3:24c5f0f50bf1 621 }
uci1 0:664899e0b988 622 }
uci1 0:664899e0b988 623 printf("\r\n");
uci1 3:24c5f0f50bf1 624
uci1 3:24c5f0f50bf1 625 // read the actual message
uci1 0:664899e0b988 626 for (int i = 0; i < len_msg; i++)
uci1 0:664899e0b988 627 {
uci1 3:24c5f0f50bf1 628 if (len_msg < 126) {
uci1 3:24c5f0f50bf1 629 message[i] = eth_rx[i+2];
uci1 3:24c5f0f50bf1 630 } else {
uci1 3:24c5f0f50bf1 631 message[i] = eth_rx[i+4];
uci1 3:24c5f0f50bf1 632 }
uci1 0:664899e0b988 633 }
uci1 0:664899e0b988 634 message[len_msg] = 0;
uci1 1:e392595b4b76 635
uci1 3:24c5f0f50bf1 636 if ( kUseB64 && ((opcode & 0x01)!=0) ) {
uci1 3:24c5f0f50bf1 637 // decode the message
uci1 3:24c5f0f50bf1 638 printf("need to b64decode\r\n");
uci1 3:24c5f0f50bf1 639 const uint8_t pads = len_msg%4;
uci1 3:24c5f0f50bf1 640 if ((len_msg+pads+1)<maxlen) {
uci1 3:24c5f0f50bf1 641 char* mm = message+len_msg;
uci1 3:24c5f0f50bf1 642 for (uint8_t k=0; k<pads; k++, mm++) {
uci1 3:24c5f0f50bf1 643 *mm = CHARPAD;
uci1 3:24c5f0f50bf1 644 }
uci1 3:24c5f0f50bf1 645 *mm=0;
uci1 3:24c5f0f50bf1 646 if (BASE64ENC_LEN(len_msg+pads)<bbsize) {
uci1 3:24c5f0f50bf1 647 len_msg = B64::modp_b64_decode(message, len_msg+pads, bbuf);
uci1 3:24c5f0f50bf1 648 if (len_msg<maxlen) {
uci1 3:24c5f0f50bf1 649 memcpy(message, bbuf, len_msg);
uci1 3:24c5f0f50bf1 650 } else {
uci1 3:24c5f0f50bf1 651 return false;
uci1 3:24c5f0f50bf1 652 }
uci1 3:24c5f0f50bf1 653 } else {
uci1 3:24c5f0f50bf1 654 return false;
uci1 3:24c5f0f50bf1 655 }
uci1 3:24c5f0f50bf1 656 } else {
uci1 3:24c5f0f50bf1 657 return false;
uci1 3:24c5f0f50bf1 658 }
uci1 3:24c5f0f50bf1 659 }
uci1 3:24c5f0f50bf1 660
uci1 1:e392595b4b76 661 for (int i=0; i<len_msg; i++) {
uci1 1:e392595b4b76 662 printf("%02x ",message[i]);
uci1 1:e392595b4b76 663 }
uci1 1:e392595b4b76 664 printf("\r\n");
uci1 1:e392595b4b76 665
uci1 3:24c5f0f50bf1 666 new_msg = false;
uci1 3:24c5f0f50bf1 667 return true;
uci1 0:664899e0b988 668 }//if new message
uci1 1:e392595b4b76 669 //printf("no new message!\r\n");
uci1 0:664899e0b988 670 return false;
uci1 0:664899e0b988 671 }//end of if(eth)
uci1 0:664899e0b988 672 #endif //target
uci1 0:664899e0b988 673 //the program shouldn't be here
uci1 0:664899e0b988 674 return false;
uci1 0:664899e0b988 675 } // end of read func
uci1 0:664899e0b988 676
uci1 0:664899e0b988 677 bool Websocket::close()
uci1 0:664899e0b988 678 {
uci1 1:e392595b4b76 679 #ifdef DEBUG
uci1 1:e392595b4b76 680 printf("CLOSE()\r\n");
uci1 1:e392595b4b76 681 #endif
uci1 0:664899e0b988 682 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 683 if (netif == ETH)
uci1 0:664899e0b988 684 {
uci1 0:664899e0b988 685 if (sock->close())
uci1 0:664899e0b988 686 return false;
uci1 0:664899e0b988 687 return true;
uci1 0:664899e0b988 688 }
uci1 0:664899e0b988 689 #endif //target
uci1 0:664899e0b988 690 //the program shouldn't be here
uci1 0:664899e0b988 691 return false;
uci1 0:664899e0b988 692 }
uci1 0:664899e0b988 693
uci1 0:664899e0b988 694 bool Websocket::connected() {
uci1 0:664899e0b988 695 // printf("CONNECTED()\r\n");
uci1 0:664899e0b988 696
uci1 0:664899e0b988 697 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 698
uci1 0:664899e0b988 699 if (netif == ETH)
uci1 0:664899e0b988 700 {
uci1 0:664899e0b988 701 return eth_connected;
uci1 0:664899e0b988 702 }
uci1 0:664899e0b988 703 #endif //target
uci1 0:664899e0b988 704 //the program shouldn't be here
uci1 0:664899e0b988 705 return false;
uci1 0:664899e0b988 706 }
uci1 0:664899e0b988 707
uci1 0:664899e0b988 708 std::string Websocket::getPath()
uci1 0:664899e0b988 709 {
uci1 0:664899e0b988 710 return path;
uci1 0:664899e0b988 711 }
uci1 0:664899e0b988 712
uci1 0:664899e0b988 713 #ifdef TARGET_LPC1768
uci1 0:664899e0b988 714 void Websocket::onTCPSocketEvent(TCPSocketEvent e)
uci1 0:664899e0b988 715 {
uci1 1:e392595b4b76 716 #ifdef DEBUG
uci1 1:e392595b4b76 717 printf("TCPSocketEvent is ");
uci1 1:e392595b4b76 718 #endif
uci1 0:664899e0b988 719 if (e == TCPSOCKET_CONNECTED)
uci1 0:664899e0b988 720 {
uci1 0:664899e0b988 721 eth_connected = true;
uci1 0:664899e0b988 722 #ifdef DEBUG
uci1 1:e392595b4b76 723 printf("TCP Socket Connected\r\n");
uci1 0:664899e0b988 724 #endif
uci1 0:664899e0b988 725 }
uci1 0:664899e0b988 726 else if (e == TCPSOCKET_WRITEABLE) {
uci1 1:e392595b4b76 727 #ifdef DEBUG
uci1 1:e392595b4b76 728 printf("TCPSOCKET_WRITEABLE\r\n");
uci1 1:e392595b4b76 729 #endif
uci1 0:664899e0b988 730 }
uci1 0:664899e0b988 731 else if (e == TCPSOCKET_READABLE)
uci1 0:664899e0b988 732 {
uci1 1:e392595b4b76 733 #ifdef DEBUG
uci1 1:e392595b4b76 734 printf("TCPSOCKET_READABLE\r\n");
uci1 1:e392595b4b76 735 #endif
uci1 3:24c5f0f50bf1 736 const int len = sock->recv(eth_rx, RX_RECV_BYTES);
uci1 0:664899e0b988 737 eth_rx[len] = 0;
uci1 0:664899e0b988 738 new_msg = true;
uci1 1:e392595b4b76 739 printf("sock recv len %d\r\n",len);
uci1 1:e392595b4b76 740 printf("eth_rx:");
uci1 1:e392595b4b76 741 for (int i=0; i<len; i++) {
uci1 1:e392595b4b76 742 printf("%02x ",eth_rx[i]);
uci1 1:e392595b4b76 743 }
uci1 1:e392595b4b76 744 printf("\r\n");
uci1 0:664899e0b988 745 if (!response_server_eth)
uci1 0:664899e0b988 746 {
uci1 0:664899e0b988 747 string checking;
uci1 0:664899e0b988 748 size_t found = string::npos;
uci1 0:664899e0b988 749 checking = eth_rx;
uci1 0:664899e0b988 750 found = checking.find("DdLWT/1JcX+nQFHebYP+rqEx5xI=");
uci1 1:e392595b4b76 751 if (found != string::npos) {
uci1 1:e392595b4b76 752 printf("response_server_eth true. found=%u\r\n",found);
uci1 0:664899e0b988 753 response_server_eth = true;
uci1 1:e392595b4b76 754 }
uci1 0:664899e0b988 755 }
uci1 0:664899e0b988 756 }
uci1 0:664899e0b988 757 else
uci1 0:664899e0b988 758 {
uci1 0:664899e0b988 759 #ifdef DEBUG
uci1 1:e392595b4b76 760 printf("TCP Socket Fail (%d)\r\n",(int)e);
uci1 0:664899e0b988 761 #endif
uci1 0:664899e0b988 762 eth_connected = false;
uci1 0:664899e0b988 763 }
uci1 0:664899e0b988 764 }
uci1 0:664899e0b988 765 #endif //target
uci1 0:664899e0b988 766
uci1 6:6f002d202f59 767 #endif