Cam_Viewer-test.ino


1
#define SSID_NAME "ESP32-CAM"
2
#define SSID_PASSWORD ""
3
#define URL "http://192.168.4.1/jpg"
4
5
//#define SSID_NAME "xxxxxxxx"
6
//#define SSID_PASSWORD "xxxxxxxx"
7
//#define URL "http://192.168.0.136/jpg"  // IP der Kamera anpassen als Sta
8
9
#include <WiFi.h>
10
#include <HTTPClient.h>
11
#include "TFT_eSPI.h"
12
#include <JPEGDecoder.h>
13
14
#define SD_CS 16
15
16
#define TFT_BL   13  // LED back-light
17
18
#define TOUCH_BUSY 27
19
#define TOUCH_IRQ  25
20
21
// Return the minimum of two values a and b
22
#define minimum(a,b)     (((a) < (b)) ? (a) : (b))
23
24
const int picBufferSize = 80*1024;
25
void *picBuffer = NULL;
26
27
TFT_eSPI tft = TFT_eSPI();
28
29
void setup()
30
{
31
  pinMode(TOUCH_BUSY,INPUT_PULLUP);
32
  pinMode(TOUCH_IRQ,INPUT_PULLUP);
33
34
  digitalWrite(TOUCH_CS, HIGH);                               // Touch controller chip select
35
  digitalWrite(TFT_CS, HIGH);                                 // TFT screen chip select 
36
37
  digitalWrite( SD_CS, HIGH);                                 // SD card chips select
38
  pinMode(SD_CS,OUTPUT);
39
  
40
  pinMode(TFT_BL,OUTPUT);                                     // Backlight an
41
  digitalWrite(TFT_BL,HIGH);
42
43
  Serial.begin(115200);
44
  Serial.println("\r\nReset");
45
46
  tft.begin();
47
  
48
  picBuffer = malloc(picBufferSize);        // Stream-File-Buffer
49
50
  WiFi.begin(SSID_NAME, SSID_PASSWORD);
51
}
52
53
void loop()
54
{
55
  Serial.print("WiFi connect");
56
  if (WiFi.status() != WL_CONNECTED)
57
  {
58
    // wait for WiFi connection
59
    delay(500);
60
  }
61
  else
62
  {
63
    Serial.println("OK");
64
    HTTPClient http;
65
66
    Serial.print("[HTTP] begin...\n");
67
    http.begin(URL);
68
69
    Serial.print("[HTTP] GET...\n");
70
    int httpCode = http.GET();
71
72
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);
73
    // HTTP header has been send and Server response header has been handled
74
    if (httpCode <= 0)
75
    {
76
      Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
77
    }
78
    else
79
    {
80
      if (httpCode != HTTP_CODE_OK)
81
      {
82
        Serial.printf("[HTTP] Not OK!\n");
83
      }
84
      else
85
      {
86
        // get lenght of document (is -1 when Server sends no Content-Length header)
87
        int len = http.getSize();
88
        Serial.printf("[HTTP] size: %d\n", len);
89
90
        if (len <= 0)
91
        {
92
          Serial.printf("[HTTP] Unknow content size: %d\n", len);
93
        }
94
        else
95
        {
96
97
          // get tcp stream
98
          WiFiClient * stream = http.getStreamPtr();
99
100
          // read all data from server
101
          uint8_t* p = (uint8_t*) picBuffer;
102
          int l = len;
103
          while (http.connected() && (l > 0 || len == -1))
104
          {
105
            // get available data size
106
            size_t size = stream->available();
107
108
            if (size)
109
            {
110
              int c = stream->readBytes(p, size);
111
              p += size;
112
113
              Serial.printf("[HTTP] read: %d\n", c);
114
            }
115
          }
116
117
          Serial.println();
118
          Serial.print("[HTTP] connection closed.\n");
119
120
          drawArrayJpeg((uint8_t*) picBuffer, len, 0, 0);
121
        }
122
      }
123
    }
124
125
    http.end();
126
  }
127
}
128
129
//####################################################################################################
130
// Draw a JPEG on the TFT pulled from a program memory array
131
//####################################################################################################
132
void drawArrayJpeg(const uint8_t arrayname[], uint32_t array_size, int xpos, int ypos) {
133
134
  int x = xpos;
135
  int y = ypos;
136
137
  JpegDec.decodeArray(arrayname, array_size);
138
  
139
  jpegInfo(); // Print information from the JPEG file (could comment this line out)
140
  
141
  renderJPEG(x, y);
142
  
143
  Serial.println("#########################");
144
}
145
146
//####################################################################################################
147
// Draw a JPEG on the TFT, images will be cropped on the right/bottom sides if they do not fit
148
//####################################################################################################
149
// This function assumes xpos,ypos is a valid screen coordinate. For convenience images that do not
150
// fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders.
151
void renderJPEG(int xpos, int ypos) {
152
153
  // retrieve infomration about the image
154
  uint16_t *pImg;
155
  uint16_t mcu_w = JpegDec.MCUWidth;
156
  uint16_t mcu_h = JpegDec.MCUHeight;
157
  uint32_t max_x = JpegDec.width;
158
  uint32_t max_y = JpegDec.height;
159
160
  // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
161
  // Typically these MCUs are 16x16 pixel blocks
162
  // Determine the width and height of the right and bottom edge image blocks
163
  uint32_t min_w = minimum(mcu_w, max_x % mcu_w);
164
  uint32_t min_h = minimum(mcu_h, max_y % mcu_h);
165
166
  // save the current image block size
167
  uint32_t win_w = mcu_w;
168
  uint32_t win_h = mcu_h;
169
170
  // record the current time so we can measure how long it takes to draw an image
171
  uint32_t drawTime = millis();
172
173
  // save the coordinate of the right and bottom edges to assist image cropping
174
  // to the screen size
175
  max_x += xpos;
176
  max_y += ypos;
177
178
  // read each MCU block until there are no more
179
  while (JpegDec.read()) {
180
    
181
    // save a pointer to the image block
182
    pImg = JpegDec.pImage ;
183
184
    // calculate where the image block should be drawn on the screen
185
    int mcu_x = JpegDec.MCUx * mcu_w + xpos;  // Calculate coordinates of top left corner of current MCU
186
    int mcu_y = JpegDec.MCUy * mcu_h + ypos;
187
188
    // check if the image block size needs to be changed for the right edge
189
    if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
190
    else win_w = min_w;
191
192
    // check if the image block size needs to be changed for the bottom edge
193
    if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
194
    else win_h = min_h;
195
196
    // copy pixels into a contiguous block
197
    if (win_w != mcu_w)
198
    {
199
      uint16_t *cImg;
200
      int p = 0;
201
      cImg = pImg + win_w;
202
      for (int h = 1; h < win_h; h++)
203
      {
204
        p += mcu_w;
205
        for (int w = 0; w < win_w; w++)
206
        {
207
          *cImg = *(pImg + w + p);
208
          cImg++;
209
        }
210
      }
211
    }
212
213
    // calculate how many pixels must be drawn
214
    uint32_t mcu_pixels = win_w * win_h;
215
216
    // draw image MCU block only if it will fit on the screen
217
    if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height())
218
    {
219
      // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
220
      tft.setWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1);
221
222
      // Write all MCU pixels to the TFT window
223
      while (mcu_pixels--) {
224
        // Push each pixel to the TFT MCU area
225
        tft.pushColor(*pImg++);
226
      }
227
228
    }
229
    else if ( (mcu_y + win_h) >= tft.height()) JpegDec.abort(); // Image has run off bottom of screen so abort decoding
230
  }
231
232
  // calculate how long it took to draw the image
233
  drawTime = millis() - drawTime;
234
235
  // print the results to the serial port
236
  Serial.print(F(  "Total render time was    : ")); Serial.print(drawTime); Serial.println(F(" ms"));
237
  Serial.println(F(""));
238
}
239
240
//####################################################################################################
241
// Print image information to the serial port (optional)
242
//####################################################################################################
243
void jpegInfo() {
244
  Serial.println(F("==============="));
245
  Serial.println(F("JPEG image info"));
246
  Serial.println(F("==============="));
247
  Serial.print(F(  "Width      :")); Serial.println(JpegDec.width);
248
  Serial.print(F(  "Height     :")); Serial.println(JpegDec.height);
249
  Serial.print(F(  "Components :")); Serial.println(JpegDec.comps);
250
  Serial.print(F(  "MCU / row  :")); Serial.println(JpegDec.MCUSPerRow);
251
  Serial.print(F(  "MCU / col  :")); Serial.println(JpegDec.MCUSPerCol);
252
  Serial.print(F(  "Scan type  :")); Serial.println(JpegDec.scanType);
253
  Serial.print(F(  "MCU width  :")); Serial.println(JpegDec.MCUWidth);
254
  Serial.print(F(  "MCU height :")); Serial.println(JpegDec.MCUHeight);
255
  Serial.println(F("==============="));
256
}
257
258
//####################################################################################################
259
// Show the execution time (optional)
260
//####################################################################################################
261
// WARNING: for UNO/AVR legacy reasons printing text to the screen with the Mega might not work for
262
// sketch sizes greater than ~70KBytes because 16 bit address pointers are used in some libraries.
263
264
// The Due will work fine with the HX8357_Due library.
265
266
void showTime(uint32_t msTime) {
267
  //tft.setCursor(0, 0);
268
  //tft.setTextFont(1);
269
  //tft.setTextSize(2);
270
  //tft.setTextColor(TFT_WHITE, TFT_BLACK);
271
  //tft.print(F(" JPEG drawn in "));
272
  //tft.print(msTime);
273
  //tft.println(F(" ms "));
274
  Serial.print(F(" JPEG drawn in "));
275
  Serial.print(msTime);
276
  Serial.println(F(" ms "));
277
}