Subversion Repositories ESP8266_P1_Meter

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 raymond 1
/*
2
  Asynchronous TCP library for Espressif MCUs
3
 
4
  Copyright (c) 2016 Hristo Gochkov. All rights reserved.
5
  This file is part of the esp8266 core for Arduino environment.
6
 
7
  This library is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU Lesser General Public
9
  License as published by the Free Software Foundation; either
10
  version 2.1 of the License, or (at your option) any later version.
11
 
12
  This library is distributed in the hope that it will be useful,
13
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
  Lesser General Public License for more details.
16
 
17
  You should have received a copy of the GNU Lesser General Public
18
  License along with this library; if not, write to the Free Software
19
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
*/
21
 
22
#include "AsyncPrinter.h"
23
 
24
AsyncPrinter::AsyncPrinter()
25
  : _client(NULL)
26
  , _data_cb(NULL)
27
  , _data_arg(NULL)
28
  , _close_cb(NULL)
29
  , _close_arg(NULL)
30
  , _tx_buffer(NULL)
31
  , _tx_buffer_size(TCP_MSS)
32
  , next(NULL)
33
{}
34
 
35
AsyncPrinter::AsyncPrinter(AsyncClient *client, size_t txBufLen)
36
  : _client(client)
37
  , _data_cb(NULL)
38
  , _data_arg(NULL)
39
  , _close_cb(NULL)
40
  , _close_arg(NULL)
41
  , _tx_buffer(NULL)
42
  , _tx_buffer_size(txBufLen)
43
  , next(NULL)
44
{
45
  _attachCallbacks();
46
  _tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
47
  if(_tx_buffer == NULL) {
48
    panic(); //What should we do?
49
  }
50
}
51
 
52
AsyncPrinter::~AsyncPrinter(){
53
  _on_close();
54
}
55
 
56
void AsyncPrinter::onData(ApDataHandler cb, void *arg){
57
  _data_cb = cb;
58
  _data_arg = arg;
59
}
60
 
61
void AsyncPrinter::onClose(ApCloseHandler cb, void *arg){
62
  _close_cb = cb;
63
  _close_arg = arg;
64
}
65
 
66
int AsyncPrinter::connect(IPAddress ip, uint16_t port){
67
  if(_client != NULL && connected())
68
    return 0;
69
  _client = new (std::nothrow) AsyncClient();
70
  if (_client == NULL) {
71
    panic();
72
  }
73
 
74
  _client->onConnect([](void *obj, AsyncClient *c){ ((AsyncPrinter*)(obj))->_onConnect(c); }, this);
75
  if(_client->connect(ip, port)){
76
    while(_client && _client->state() < 4)
77
      delay(1);
78
    return connected();
79
  }
80
  return 0;
81
}
82
 
83
int AsyncPrinter::connect(const char *host, uint16_t port){
84
  if(_client != NULL && connected())
85
    return 0;
86
  _client = new (std::nothrow) AsyncClient();
87
  if (_client == NULL) {
88
    panic();
89
  }
90
 
91
  _client->onConnect([](void *obj, AsyncClient *c){ ((AsyncPrinter*)(obj))->_onConnect(c); }, this);
92
  if(_client->connect(host, port)){
93
    while(_client && _client->state() < 4)
94
      delay(1);
95
    return connected();
96
  }
97
  return 0;
98
}
99
 
100
void AsyncPrinter::_onConnect(AsyncClient *c){
101
  (void)c;
102
  if(_tx_buffer != NULL){
103
    cbuf *b = _tx_buffer;
104
    _tx_buffer = NULL;
105
    delete b;
106
  }
107
  _tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
108
  if(_tx_buffer) {
109
    panic();
110
  }
111
 
112
  _attachCallbacks();
113
}
114
 
115
AsyncPrinter::operator bool(){ return connected(); }
116
 
117
AsyncPrinter & AsyncPrinter::operator=(const AsyncPrinter &other){
118
  if(_client != NULL){
119
    _client->close(true);
120
    _client = NULL;
121
  }
122
  _tx_buffer_size = other._tx_buffer_size;
123
  if(_tx_buffer != NULL){
124
    cbuf *b = _tx_buffer;
125
    _tx_buffer = NULL;
126
    delete b;
127
  }
128
  _tx_buffer = new (std::nothrow) cbuf(other._tx_buffer_size);
129
  if(_tx_buffer == NULL) {
130
    panic();
131
  }
132
 
133
  _client = other._client;
134
  _attachCallbacks();
135
  return *this;
136
}
137
 
138
size_t AsyncPrinter::write(uint8_t data){
139
  return write(&data, 1);
140
}
141
 
142
size_t AsyncPrinter::write(const uint8_t *data, size_t len){
143
  if(_tx_buffer == NULL || !connected())
144
    return 0;
145
  size_t toWrite = 0;
146
  size_t toSend = len;
147
  while(_tx_buffer->room() < toSend){
148
    toWrite = _tx_buffer->room();
149
    _tx_buffer->write((const char*)data, toWrite);
150
    while(connected() && !_client->canSend())
151
      delay(0);
152
    if(!connected())
153
      return 0; // or len - toSend;
154
    _sendBuffer();
155
    toSend -= toWrite;
156
  }
157
  _tx_buffer->write((const char*)(data+(len - toSend)), toSend);
158
  while(connected() && !_client->canSend()) delay(0);
159
  if(!connected()) return 0; // or len - toSend;
160
  _sendBuffer();
161
  return len;
162
}
163
 
164
bool AsyncPrinter::connected(){
165
  return (_client != NULL && _client->connected());
166
}
167
 
168
void AsyncPrinter::close(){
169
  if(_client != NULL)
170
    _client->close(true);
171
}
172
 
173
size_t AsyncPrinter::_sendBuffer(){
174
  size_t available = _tx_buffer->available();
175
  if(!connected() || !_client->canSend() || available == 0)
176
    return 0;
177
  size_t sendable = _client->space();
178
  if(sendable < available)
179
    available= sendable;
180
  char *out = new (std::nothrow) char[available];
181
  if (out == NULL) {
182
    panic(); // Connection should be aborted instead
183
  }
184
 
185
  _tx_buffer->read(out, available);
186
  size_t sent = _client->write(out, available);
187
  delete out;
188
  return sent;
189
}
190
 
191
void AsyncPrinter::_onData(void *data, size_t len){
192
  if(_data_cb)
193
    _data_cb(_data_arg, this, (uint8_t*)data, len);
194
}
195
 
196
void AsyncPrinter::_on_close(){
197
  if(_client != NULL){
198
    _client = NULL;
199
  }
200
  if(_tx_buffer != NULL){
201
    cbuf *b = _tx_buffer;
202
    _tx_buffer = NULL;
203
    delete b;
204
  }
205
  if(_close_cb)
206
    _close_cb(_close_arg, this);
207
}
208
 
209
void AsyncPrinter::_attachCallbacks(){
210
  _client->onPoll([](void *obj, AsyncClient* c){ (void)c; ((AsyncPrinter*)(obj))->_sendBuffer(); }, this);
211
  _client->onAck([](void *obj, AsyncClient* c, size_t len, uint32_t time){  (void)c; (void)len; (void)time; ((AsyncPrinter*)(obj))->_sendBuffer(); }, this);
212
  _client->onDisconnect([](void *obj, AsyncClient* c){ ((AsyncPrinter*)(obj))->_on_close(); delete c; }, this);
213
  _client->onData([](void *obj, AsyncClient* c, void *data, size_t len){ (void)c; ((AsyncPrinter*)(obj))->_onData(data, len); }, this);
214
}