mirror of
https://github.com/0015/ThatProject.git
synced 2026-01-12 17:27:43 +03:00
Mini E-Paper | Ep1. Uploading Emoji to E-Paper from Flutter App(iOS & Android)
This commit is contained in:
@@ -0,0 +1,368 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
Mini E-Paper | Ep1. Uploading Emoji to E-Paper from Flutter App(iOS & Android)
|
||||||
|
Video Tutorial: https://youtu.be/-RhEiKldfDc
|
||||||
|
Created by Eric N. (ThatProject)
|
||||||
|
*/
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <GxEPD2_BW.h>
|
||||||
|
#include "GxEPD2_display_selection_new_style.h"
|
||||||
|
#include <Fonts/FreeMonoBold9pt7b.h>
|
||||||
|
#include <BLEDevice.h>
|
||||||
|
#include <BLEServer.h>
|
||||||
|
#include <BLEUtils.h>
|
||||||
|
#include <BLE2902.h>
|
||||||
|
#include "SPIFFS.h"
|
||||||
|
#define FileClass fs::File
|
||||||
|
|
||||||
|
BLEServer *pServer = NULL;
|
||||||
|
BLECharacteristic *pTxCharacteristic;
|
||||||
|
#define SERVICE_UUID "713d0001-503e-4c75-ba94-3148f18d941e"
|
||||||
|
#define CHARACTERISTIC_UUID_RX "713d0002-503e-4c75-ba94-3148f18d941e"
|
||||||
|
|
||||||
|
const char temp_filename[] = "/new_image.bmp";
|
||||||
|
const char BLE_Device_Name[] = "MINI E-PAPER";
|
||||||
|
class BLEServerCB : public BLEServerCallbacks {
|
||||||
|
void onConnect(BLEServer *pServer){};
|
||||||
|
|
||||||
|
void onDisconnect(BLEServer *pServer) {
|
||||||
|
pServer->startAdvertising();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BLERxCallback : public BLECharacteristicCallbacks {
|
||||||
|
|
||||||
|
uint16_t read16(fs::File &f) {
|
||||||
|
// BMP data is stored little-endian, same as Arduino.
|
||||||
|
uint16_t result;
|
||||||
|
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||||
|
((uint8_t *)&result)[1] = f.read(); // MSB
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t read32(fs::File &f) {
|
||||||
|
// BMP data is stored little-endian, same as Arduino.
|
||||||
|
uint32_t result;
|
||||||
|
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||||
|
((uint8_t *)&result)[1] = f.read();
|
||||||
|
((uint8_t *)&result)[2] = f.read();
|
||||||
|
((uint8_t *)&result)[3] = f.read(); // MSB
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint16_t input_buffer_pixels = 800; // may affect performance
|
||||||
|
static const uint16_t max_row_width = 80; // for up to 6" display 1448x1072
|
||||||
|
static const uint16_t max_palette_pixels = 256; // for depth <= 8
|
||||||
|
|
||||||
|
uint8_t input_buffer[3 * input_buffer_pixels]; // up to depth 24
|
||||||
|
uint8_t output_row_mono_buffer[max_row_width / 8]; // buffer for at least one row of b/w bits
|
||||||
|
uint8_t output_row_color_buffer[max_row_width / 8]; // buffer for at least one row of color bits
|
||||||
|
uint8_t mono_palette_buffer[max_palette_pixels / 8]; // palette buffer for depth <= 8 b/w
|
||||||
|
uint8_t color_palette_buffer[max_palette_pixels / 8]; // palette buffer for depth <= 8 c/w
|
||||||
|
uint16_t rgb_palette_buffer[max_palette_pixels]; // palette buffer for depth <= 8 for buffered graphics, needed for 7-color display
|
||||||
|
|
||||||
|
bool isEnd = true;
|
||||||
|
File file;
|
||||||
|
|
||||||
|
void onWrite(BLECharacteristic *pCharacteristic) {
|
||||||
|
std::string rxValue = pCharacteristic->getValue();
|
||||||
|
|
||||||
|
Serial.printf("RX length: %d\n", rxValue.length());
|
||||||
|
if (rxValue.length() > 0) {
|
||||||
|
file.write((const byte *)pCharacteristic->getData(), rxValue.length());
|
||||||
|
} else {
|
||||||
|
Serial.println("***GET START/END TRIGGER****");
|
||||||
|
isEnd = !isEnd;
|
||||||
|
|
||||||
|
if (!isEnd) {
|
||||||
|
file = SPIFFS.open(temp_filename, FILE_WRITE);
|
||||||
|
if (!file) {
|
||||||
|
Serial.println("File is not available!");
|
||||||
|
}else{
|
||||||
|
Serial.println("File is ready to write!");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
file.close();
|
||||||
|
Serial.println("File Closed!");
|
||||||
|
drawBitmapFromSpiffs_Buffered(temp_filename, 0, 0, false, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawBitmapFromSpiffs_Buffered(const char *filename, int16_t x, int16_t y, bool with_color, bool partial_update, bool overwrite) {
|
||||||
|
fs::File file;
|
||||||
|
bool valid = false; // valid format to be handled
|
||||||
|
bool flip = true; // bitmap is stored bottom-to-top
|
||||||
|
bool has_multicolors = display.epd2.panel == GxEPD2::ACeP565;
|
||||||
|
uint32_t startTime = millis();
|
||||||
|
if ((x >= display.width()) || (y >= display.height())) return;
|
||||||
|
Serial.println();
|
||||||
|
Serial.print("Loading image '");
|
||||||
|
Serial.print(filename);
|
||||||
|
Serial.println('\'');
|
||||||
|
file = SPIFFS.open(filename, "r");
|
||||||
|
if (!file) {
|
||||||
|
Serial.print("File not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Parse BMP header
|
||||||
|
if (read16(file) == 0x4D42) // BMP signature
|
||||||
|
{
|
||||||
|
uint32_t fileSize = read32(file);
|
||||||
|
uint32_t creatorBytes = read32(file);
|
||||||
|
uint32_t imageOffset = read32(file); // Start of image data
|
||||||
|
uint32_t headerSize = read32(file);
|
||||||
|
uint32_t width = read32(file);
|
||||||
|
uint32_t height = read32(file);
|
||||||
|
uint16_t planes = read16(file);
|
||||||
|
uint16_t depth = read16(file); // bits per pixel
|
||||||
|
uint32_t format = read32(file);
|
||||||
|
if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
|
||||||
|
{
|
||||||
|
Serial.print("File size: ");
|
||||||
|
Serial.println(fileSize);
|
||||||
|
Serial.print("Image Offset: ");
|
||||||
|
Serial.println(imageOffset);
|
||||||
|
Serial.print("Header size: ");
|
||||||
|
Serial.println(headerSize);
|
||||||
|
Serial.print("Bit Depth: ");
|
||||||
|
Serial.println(depth);
|
||||||
|
Serial.print("Image size: ");
|
||||||
|
Serial.print(width);
|
||||||
|
Serial.print('x');
|
||||||
|
Serial.println(height);
|
||||||
|
// BMP rows are padded (if needed) to 4-byte boundary
|
||||||
|
uint32_t rowSize = (width * depth / 8 + 3) & ~3;
|
||||||
|
if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
|
||||||
|
if (height < 0) {
|
||||||
|
height = -height;
|
||||||
|
flip = false;
|
||||||
|
}
|
||||||
|
uint16_t w = width;
|
||||||
|
uint16_t h = height;
|
||||||
|
if ((x + w - 1) >= display.width()) w = display.width() - x;
|
||||||
|
if ((y + h - 1) >= display.height()) h = display.height() - y;
|
||||||
|
//if (w <= max_row_width) // handle with direct drawing
|
||||||
|
{
|
||||||
|
valid = true;
|
||||||
|
uint8_t bitmask = 0xFF;
|
||||||
|
uint8_t bitshift = 8 - depth;
|
||||||
|
uint16_t red, green, blue;
|
||||||
|
bool whitish, colored;
|
||||||
|
if (depth == 1) with_color = false;
|
||||||
|
if (depth <= 8) {
|
||||||
|
if (depth < 8) bitmask >>= depth;
|
||||||
|
//file.seek(54); //palette is always @ 54
|
||||||
|
file.seek(imageOffset - (4 << depth)); // 54 for regular, diff for colorsimportant
|
||||||
|
for (uint16_t pn = 0; pn < (1 << depth); pn++) {
|
||||||
|
blue = file.read();
|
||||||
|
green = file.read();
|
||||||
|
red = file.read();
|
||||||
|
file.read();
|
||||||
|
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
|
||||||
|
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
|
||||||
|
if (0 == pn % 8) mono_palette_buffer[pn / 8] = 0;
|
||||||
|
mono_palette_buffer[pn / 8] |= whitish << pn % 8;
|
||||||
|
if (0 == pn % 8) color_palette_buffer[pn / 8] = 0;
|
||||||
|
color_palette_buffer[pn / 8] |= colored << pn % 8;
|
||||||
|
rgb_palette_buffer[pn] = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (partial_update) display.setPartialWindow(x, y, w, h);
|
||||||
|
else
|
||||||
|
display.setFullWindow();
|
||||||
|
display.firstPage();
|
||||||
|
do {
|
||||||
|
if (!overwrite) display.fillScreen(GxEPD_WHITE);
|
||||||
|
uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
|
||||||
|
for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
|
||||||
|
{
|
||||||
|
uint32_t in_remain = rowSize;
|
||||||
|
uint32_t in_idx = 0;
|
||||||
|
uint32_t in_bytes = 0;
|
||||||
|
uint8_t in_byte = 0; // for depth <= 8
|
||||||
|
uint8_t in_bits = 0; // for depth <= 8
|
||||||
|
uint16_t color = GxEPD_WHITE;
|
||||||
|
file.seek(rowPosition);
|
||||||
|
for (uint16_t col = 0; col < w; col++) // for each pixel
|
||||||
|
{
|
||||||
|
// Time to read more pixel data?
|
||||||
|
if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
|
||||||
|
{
|
||||||
|
in_bytes = file.read(input_buffer, in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain);
|
||||||
|
in_remain -= in_bytes;
|
||||||
|
in_idx = 0;
|
||||||
|
}
|
||||||
|
switch (depth) {
|
||||||
|
case 24:
|
||||||
|
blue = input_buffer[in_idx++];
|
||||||
|
green = input_buffer[in_idx++];
|
||||||
|
red = input_buffer[in_idx++];
|
||||||
|
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
|
||||||
|
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
|
||||||
|
color = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
{
|
||||||
|
uint8_t lsb = input_buffer[in_idx++];
|
||||||
|
uint8_t msb = input_buffer[in_idx++];
|
||||||
|
if (format == 0) // 555
|
||||||
|
{
|
||||||
|
blue = (lsb & 0x1F) << 3;
|
||||||
|
green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
|
||||||
|
red = (msb & 0x7C) << 1;
|
||||||
|
color = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
|
||||||
|
} else // 565
|
||||||
|
{
|
||||||
|
blue = (lsb & 0x1F) << 3;
|
||||||
|
green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
|
||||||
|
red = (msb & 0xF8);
|
||||||
|
color = (msb << 8) | lsb;
|
||||||
|
}
|
||||||
|
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
|
||||||
|
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
if (0 == in_bits) {
|
||||||
|
in_byte = input_buffer[in_idx++];
|
||||||
|
in_bits = 8;
|
||||||
|
}
|
||||||
|
uint16_t pn = (in_byte >> bitshift) & bitmask;
|
||||||
|
whitish = mono_palette_buffer[pn / 8] & (0x1 << pn % 8);
|
||||||
|
colored = color_palette_buffer[pn / 8] & (0x1 << pn % 8);
|
||||||
|
in_byte <<= depth;
|
||||||
|
in_bits -= depth;
|
||||||
|
color = rgb_palette_buffer[pn];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (with_color && has_multicolors) {
|
||||||
|
// keep color
|
||||||
|
} else if (whitish) {
|
||||||
|
color = GxEPD_WHITE;
|
||||||
|
} else if (colored && with_color) {
|
||||||
|
color = GxEPD_COLORED;
|
||||||
|
} else {
|
||||||
|
color = GxEPD_BLACK;
|
||||||
|
}
|
||||||
|
uint16_t yrow = y + (flip ? h - row - 1 : row);
|
||||||
|
display.drawPixel(x + col, yrow, color);
|
||||||
|
} // end pixel
|
||||||
|
} // end line
|
||||||
|
} while (display.nextPage());
|
||||||
|
Serial.print("loaded in ");
|
||||||
|
Serial.print(millis() - startTime);
|
||||||
|
Serial.println(" ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
if (!valid) {
|
||||||
|
Serial.println("bitmap format not handled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println();
|
||||||
|
initDisplay();
|
||||||
|
initSPIFFS();
|
||||||
|
initBLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(void) {}
|
||||||
|
|
||||||
|
void initDisplay() {
|
||||||
|
SPI.begin(EPD_SCLK, EPD_MISO, EPD_MOSI);
|
||||||
|
display.init(115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initSPIFFS() {
|
||||||
|
|
||||||
|
if (!SPIFFS.begin()) {
|
||||||
|
Serial.println("SPIFFS initialisation failed!");
|
||||||
|
while (1) yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("SPIFFS started");
|
||||||
|
listSPIFFS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void listSPIFFS(void) {
|
||||||
|
Serial.println(F("\r\nListing SPIFFS files:"));
|
||||||
|
static const char line[] PROGMEM = "=================================================";
|
||||||
|
|
||||||
|
Serial.println(FPSTR(line));
|
||||||
|
Serial.println(F(" File name Size"));
|
||||||
|
Serial.println(FPSTR(line));
|
||||||
|
|
||||||
|
fs::File root = SPIFFS.open("/");
|
||||||
|
if (!root) {
|
||||||
|
Serial.println(F("Failed to open directory"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!root.isDirectory()) {
|
||||||
|
Serial.println(F("Not a directory"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::File file = root.openNextFile();
|
||||||
|
while (file) {
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
Serial.print("DIR : ");
|
||||||
|
String fileName = file.name();
|
||||||
|
Serial.print(fileName);
|
||||||
|
} else {
|
||||||
|
String fileName = file.name();
|
||||||
|
Serial.print(" " + fileName);
|
||||||
|
// File path can be 31 characters maximum in SPIFFS
|
||||||
|
int spaces = 33 - fileName.length(); // Tabulate nicely
|
||||||
|
if (spaces < 1) spaces = 1;
|
||||||
|
while (spaces--) Serial.print(" ");
|
||||||
|
String fileSize = (String) file.size();
|
||||||
|
spaces = 10 - fileSize.length(); // Tabulate nicely
|
||||||
|
if (spaces < 1) spaces = 1;
|
||||||
|
while (spaces--) Serial.print(" ");
|
||||||
|
Serial.println(fileSize + " bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
file = root.openNextFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println(FPSTR(line));
|
||||||
|
Serial.println();
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initBLE() {
|
||||||
|
Serial.println("**** INIT BLE ****");
|
||||||
|
// Create the BLE Device
|
||||||
|
|
||||||
|
BLEDevice::init(BLE_Device_Name);
|
||||||
|
// Create the BLE Server
|
||||||
|
pServer = BLEDevice::createServer();
|
||||||
|
pServer->setCallbacks(new BLEServerCB());
|
||||||
|
|
||||||
|
// Create the BLE Service
|
||||||
|
BLEService *pService = pServer->createService(SERVICE_UUID);
|
||||||
|
BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
|
||||||
|
CHARACTERISTIC_UUID_RX,
|
||||||
|
BLECharacteristic::PROPERTY_WRITE);
|
||||||
|
pRxCharacteristic->setCallbacks(new BLERxCallback());
|
||||||
|
|
||||||
|
// Start the service
|
||||||
|
pService->start();
|
||||||
|
|
||||||
|
// Start advertising
|
||||||
|
pServer->getAdvertising()->start();
|
||||||
|
Serial.println("Start advertising");
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
// Display Library example for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||||
|
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||||
|
//
|
||||||
|
// Display Library based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
|
||||||
|
//
|
||||||
|
// Author: Jean-Marc Zingg
|
||||||
|
//
|
||||||
|
// Version: see library.properties
|
||||||
|
//
|
||||||
|
// Library: https://github.com/ZinggJM/GxEPD2
|
||||||
|
|
||||||
|
// Supporting Arduino Forum Topics:
|
||||||
|
// Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0
|
||||||
|
// Good Display ePaper for Arduino: https://forum.arduino.cc/index.php?topic=436411.0
|
||||||
|
|
||||||
|
// select the display class (only one), matching the kind of display panel
|
||||||
|
|
||||||
|
#define EPD_MOSI (21)
|
||||||
|
#define EPD_MISO (-1)
|
||||||
|
#define EPD_SCLK (22)
|
||||||
|
#define EPD_CS (5)
|
||||||
|
|
||||||
|
#define EPD_BUSY (34)
|
||||||
|
#define EPD_RSET (4)
|
||||||
|
#define EPD_DC (19)
|
||||||
|
|
||||||
|
#define GxEPD2_DISPLAY_CLASS GxEPD2_BW
|
||||||
|
//#define GxEPD2_DISPLAY_CLASS GxEPD2_3C
|
||||||
|
//#define GxEPD2_DISPLAY_CLASS GxEPD2_7C
|
||||||
|
|
||||||
|
// select the display driver class (only one) for your panel
|
||||||
|
#define GxEPD2_DRIVER_CLASS GxEPD2_102 // GxEPD2_102 80x128, UC8175
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_154 // GDEP015OC1 200x200, IL3829, no longer available
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_154_D67 // GDEH0154D67 200x200, SSD1681
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_154_T8 // GDEW0154T8 152x152, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_154_M09 // GDEW0154M09 200x200, JD79653A
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_154_M10 // GDEW0154M10 152x152, UC8151D
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213 // GDE0213B1 128x250, IL3895, phased out
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213_B72 // GDEH0213B72 128x250, SSD1675A (IL3897)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213_B73 // GDEH0213B73 128x250, SSD1675B
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213_B74 // GDEM0213B74 128x250, SSD1680
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213_flex // GDEW0213I5F 104x212, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213_M21 // GDEW0213M21 104x212, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213_T5D // GDEW0213T5D 104x212, UC8151D
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290 // GDEH029A1 128x296, SSD1608 (IL3820)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290_T5 // GDEW029T5 128x296, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290_T5D // GDEW029T5D 128x296, UC8151D
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290_T94 // GDEM029T94 128x296, SSD1680
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290_T94_V2 // GDEM029T94 128x296, SSD1680, Waveshare 2.9" V2 variant
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290_M06 // GDEW029M06 128x296, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_260 // GDEW026T0 152x296, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_260_M01 // GDEW026M01 152x296, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_270 // GDEW027W3 176x264, EK79652 (IL91874)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_371 // GDEW0371W7 240x416, UC8171 (IL0324)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_420 // GDEW042T2 400x300, UC8176 (IL0398)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01 400x300, UC8176 (IL0398)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_583 // GDEW0583T7 600x448, UC8179 (IL0371)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_583_T8 // GDEW0583T8 648x480, GD7965
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_750 // GDEW075T8 640x384, UC8179 (IL0371)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_750_T7 // GDEW075T7 800x480, GD7965
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_1160_T91 // GDEH116T91 960x640, SSD1677
|
||||||
|
// 3-color e-papers
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_154c // GDEW0154Z04 200x200, IL0376F, no longer available
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_154_Z90c // GDEH0154Z90 200x200, SSD1682
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213c // GDEW0213Z16 104x212, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_213_Z19c // GDEW0213Z19 104x212, UC8151D
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290c // GDEW029Z10 128x296, UC8151 (IL0373)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290_Z13c // GDEH029Z13 128x296, UC8151D
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_290_C90c // GDEM029C90 128x296, SSD1680
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_270c // GDEW027C44 176x264, IL91874
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_420c // GDEW042Z15 400x300, UC8176 (IL0398)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_583c // GDEW0583Z21 600x448, UC8179 (IL0371)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_750c // GDEW075Z09 640x384, UC8179 (IL0371)
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_750c_Z08 // GDEW075Z08 800x480, GD7965
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_750c_Z90 // GDEH075Z90 880x528, SSD1677
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_1248 // GDEW1248T3 1303x984, UC8179
|
||||||
|
// 7-color e-paper
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_565c // Waveshare 5.65" 7-color (3C graphics)
|
||||||
|
// grey levels parallel IF e-papers on Waveshare e-Paper IT8951 Driver HAT
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_it60 // ED060SCT 800x600
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_it60_1448x1072 // ED060KC1 1448x1072
|
||||||
|
//#define GxEPD2_DRIVER_CLASS GxEPD2_it78_1872x1404 // ED078KC2 1872x1404
|
||||||
|
|
||||||
|
// SS is usually used for CS. define here for easy change
|
||||||
|
#ifndef EPD_CS
|
||||||
|
#define EPD_CS SS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GxEPD2_DISPLAY_CLASS) && defined(GxEPD2_DRIVER_CLASS)
|
||||||
|
|
||||||
|
// somehow there should be an easier way to do this
|
||||||
|
#define GxEPD2_BW_IS_GxEPD2_BW true
|
||||||
|
#define GxEPD2_3C_IS_GxEPD2_3C true
|
||||||
|
#define GxEPD2_7C_IS_GxEPD2_7C true
|
||||||
|
#define GxEPD2_1248_IS_GxEPD2_1248 true
|
||||||
|
#define IS_GxEPD(c, x) (c##x)
|
||||||
|
#define IS_GxEPD2_BW(x) IS_GxEPD(GxEPD2_BW_IS_, x)
|
||||||
|
#define IS_GxEPD2_3C(x) IS_GxEPD(GxEPD2_3C_IS_, x)
|
||||||
|
#define IS_GxEPD2_7C(x) IS_GxEPD(GxEPD2_7C_IS_, x)
|
||||||
|
#define IS_GxEPD2_1248(x) IS_GxEPD(GxEPD2_1248_IS_, x)
|
||||||
|
|
||||||
|
#include "GxEPD2_selection_check.h"
|
||||||
|
|
||||||
|
#if defined (ESP8266)
|
||||||
|
#define MAX_DISPLAY_BUFFER_SIZE (81920ul-34000ul-5000ul) // ~34000 base use, change 5000 to your application use
|
||||||
|
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_3C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_7C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2))
|
||||||
|
#endif
|
||||||
|
// adapt the constructor parameters to your wiring
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
|
||||||
|
// mapping of Waveshare e-Paper ESP8266 Driver Board, new version
|
||||||
|
//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=15*/ EPD_CS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
|
||||||
|
// mapping of Waveshare e-Paper ESP8266 Driver Board, old version
|
||||||
|
//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=15*/ EPD_CS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ESP32)
|
||||||
|
#define MAX_DISPLAY_BUFFER_SIZE 65536ul // e.g.
|
||||||
|
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_3C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_7C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2))
|
||||||
|
#endif
|
||||||
|
// adapt the constructor parameters to your wiring
|
||||||
|
#if !IS_GxEPD2_1248(GxEPD2_DRIVER_CLASS)
|
||||||
|
#if defined(ARDUINO_LOLIN_D32_PRO)
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=5*/ EPD_CS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15));
|
||||||
|
#elif defined(ARDUINO_ESP32_DEV) // e.g. TTGO T8 ESP32-WROVER
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=5*/ EPD_CS, /*DC=*/ 2, /*RST=*/ 0, /*BUSY=*/ 4));
|
||||||
|
#else
|
||||||
|
//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=5*/ EPD_CS, /*DC=*/ EPD_DC, /*RST=*/ EPD_RSET, /*BUSY=*/ EPD_BUSY));
|
||||||
|
#endif
|
||||||
|
#else // GxEPD2_1248
|
||||||
|
// Waveshare 12.48 b/w SPI display board and frame or Good Display 12.48 b/w panel GDEW1248T3
|
||||||
|
// general constructor for use with all parameters, e.g. for Waveshare ESP32 driver board mounted on connection board
|
||||||
|
GxEPD2_BW < GxEPD2_1248, GxEPD2_1248::HEIGHT / 4 > display(GxEPD2_1248(/*sck=*/ 13, /*miso=*/ 12, /*mosi=*/ 14,
|
||||||
|
/*cs_m1=*/ 23, /*cs_s1=*/ 22, /*cs_m2=*/ 16, /*cs_s2=*/ 19,
|
||||||
|
/*dc1=*/ 25, /*dc2=*/ 17, /*rst1=*/ 33, /*rst2=*/ 5,
|
||||||
|
/*busy_m1=*/ 32, /*busy_s1=*/ 26, /*busy_m2=*/ 18, /*busy_s2=*/ 4));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// can't use package "STMF1 Boards (STM32Duino.com)" (Roger Clark) anymore with Adafruit_GFX, use "STM32 Boards (selected from submenu)" (STMicroelectronics)
|
||||||
|
#if defined(ARDUINO_ARCH_STM32)
|
||||||
|
#define MAX_DISPLAY_BUFFER_SIZE 15000ul // ~15k is a good compromise
|
||||||
|
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_3C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_7C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2))
|
||||||
|
#endif
|
||||||
|
// adapt the constructor parameters to your wiring
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__AVR)
|
||||||
|
#if defined (ARDUINO_AVR_MEGA2560) // Note: SS is on 53 on MEGA
|
||||||
|
#define MAX_DISPLAY_BUFFER_SIZE 5000 // e.g. full height for 200x200
|
||||||
|
#else // Note: SS is on 10 on UNO, NANO
|
||||||
|
#define MAX_DISPLAY_BUFFER_SIZE 800 //
|
||||||
|
#endif
|
||||||
|
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_3C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_7C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2))
|
||||||
|
#endif
|
||||||
|
// adapt the constructor parameters to your wiring
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_SAM)
|
||||||
|
#define MAX_DISPLAY_BUFFER_SIZE 32768ul // e.g., up to 96k
|
||||||
|
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_3C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_7C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2))
|
||||||
|
#endif
|
||||||
|
// adapt the constructor parameters to your wiring
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=77*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_SAMD)
|
||||||
|
#define MAX_DISPLAY_BUFFER_SIZE 15000ul // ~15k is a good compromise
|
||||||
|
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_3C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_7C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2))
|
||||||
|
#endif
|
||||||
|
// adapt the constructor parameters to your wiring
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));
|
||||||
|
//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ 4, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1)); // my Seed XIOA0
|
||||||
|
//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ 3, /*DC=*/ 2, /*RST=*/ 1, /*BUSY=*/ 0)); // my other Seed XIOA0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_RP2040)
|
||||||
|
#define MAX_DISPLAY_BUFFER_SIZE 131072ul // e.g. half of available ram
|
||||||
|
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_3C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8))
|
||||||
|
#elif IS_GxEPD2_7C(GxEPD2_DISPLAY_CLASS)
|
||||||
|
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2))
|
||||||
|
#endif
|
||||||
|
// adapt the constructor parameters to your wiring
|
||||||
|
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
// Display Library example for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||||
|
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||||
|
//
|
||||||
|
// Display Library based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
|
||||||
|
//
|
||||||
|
// Author: Jean-Marc Zingg
|
||||||
|
//
|
||||||
|
// Version: see library.properties
|
||||||
|
//
|
||||||
|
// Library: https://github.com/ZinggJM/GxEPD2
|
||||||
|
|
||||||
|
// Supporting Arduino Forum Topics:
|
||||||
|
// Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0
|
||||||
|
// Good Display ePaper for Arduino: https://forum.arduino.cc/index.php?topic=436411.0
|
||||||
|
|
||||||
|
#define GxEPD2_102_IS_BW true
|
||||||
|
#define GxEPD2_154_IS_BW true
|
||||||
|
#define GxEPD2_154_D67_IS_BW true
|
||||||
|
#define GxEPD2_154_T8_IS_BW true
|
||||||
|
#define GxEPD2_154_M09_IS_BW true
|
||||||
|
#define GxEPD2_154_M10_IS_BW true
|
||||||
|
#define GxEPD2_213_IS_BW true
|
||||||
|
#define GxEPD2_213_B72_IS_BW true
|
||||||
|
#define GxEPD2_213_B73_IS_BW true
|
||||||
|
#define GxEPD2_213_B74_IS_BW true
|
||||||
|
#define GxEPD2_213_flex_IS_BW true
|
||||||
|
#define GxEPD2_213_M21_IS_BW true
|
||||||
|
#define GxEPD2_213_T5D_IS_BW true
|
||||||
|
#define GxEPD2_290_IS_BW true
|
||||||
|
#define GxEPD2_290_T5_IS_BW true
|
||||||
|
#define GxEPD2_290_T5D_IS_BW true
|
||||||
|
#define GxEPD2_290_T94_IS_BW true
|
||||||
|
#define GxEPD2_290_T94_V2_IS_BW true
|
||||||
|
#define GxEPD2_290_M06_IS_BW true
|
||||||
|
#define GxEPD2_260_IS_BW true
|
||||||
|
#define GxEPD2_260_M01_IS_BW true
|
||||||
|
#define GxEPD2_270_IS_BW true
|
||||||
|
#define GxEPD2_371_IS_BW true
|
||||||
|
#define GxEPD2_420_IS_BW true
|
||||||
|
#define GxEPD2_420_M01_IS_BW true
|
||||||
|
#define GxEPD2_583_IS_BW true
|
||||||
|
#define GxEPD2_583_T8_IS_BW true
|
||||||
|
#define GxEPD2_750_IS_BW true
|
||||||
|
#define GxEPD2_750_T7_IS_BW true
|
||||||
|
#define GxEPD2_1160_T91_IS_BW true
|
||||||
|
// 3-color e-papers
|
||||||
|
#define GxEPD2_154c_IS_3C true
|
||||||
|
#define GxEPD2_154_Z90c_IS_3C true
|
||||||
|
#define GxEPD2_213c_IS_3C true
|
||||||
|
#define GxEPD2_213_Z19c_IS_3C true
|
||||||
|
#define GxEPD2_290c_IS_3C true
|
||||||
|
#define GxEPD2_290_Z13c_IS_3C true
|
||||||
|
#define GxEPD2_290_C90c_IS_3C true
|
||||||
|
#define GxEPD2_270c_IS_3C true
|
||||||
|
#define GxEPD2_420c_IS_3C true
|
||||||
|
#define GxEPD2_583c_IS_3C true
|
||||||
|
#define GxEPD2_750c_IS_3C true
|
||||||
|
#define GxEPD2_750c_Z08_IS_3C true
|
||||||
|
#define GxEPD2_750c_Z90_IS_3C true
|
||||||
|
#define GxEPD2_1248_IS_3C true
|
||||||
|
// 7-color e-paper
|
||||||
|
#define GxEPD2_565c_IS_7C true
|
||||||
|
|
||||||
|
#if defined(GxEPD2_DISPLAY_CLASS) && defined(GxEPD2_DRIVER_CLASS)
|
||||||
|
#define IS_GxEPD2_DRIVER(c, x) (c##x)
|
||||||
|
#define IS_GxEPD2_DRIVER_BW(x) IS_GxEPD2_DRIVER(x, _IS_BW)
|
||||||
|
#define IS_GxEPD2_DRIVER_3C(x) IS_GxEPD2_DRIVER(x, _IS_3C)
|
||||||
|
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS) && IS_GxEPD2_DRIVER_3C(GxEPD2_DRIVER_CLASS)
|
||||||
|
#error "GxEPD2_BW used with 3-color driver class"
|
||||||
|
#endif
|
||||||
|
#if IS_GxEPD2_3C(GxEPD2_DISPLAY_CLASS) && IS_GxEPD2_DRIVER_BW(GxEPD2_DRIVER_CLASS)
|
||||||
|
#error "GxEPD2_3C used with b/w driver class"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
46
E-Paper_Projects/01_Emoji2MiniE-Paper/FlutterApp_epaper_emoji_ble/.gitignore
vendored
Normal file
46
E-Paper_Projects/01_Emoji2MiniE-Paper/FlutterApp_epaper_emoji_ble/.gitignore
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Miscellaneous
|
||||||
|
*.class
|
||||||
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# The .vscode folder contains launch configuration and tasks you configure in
|
||||||
|
# VS Code which you may wish to be included in version control, so this line
|
||||||
|
# is commented out by default.
|
||||||
|
#.vscode/
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
**/doc/api/
|
||||||
|
**/ios/Flutter/.last_build_id
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
.packages
|
||||||
|
.pub-cache/
|
||||||
|
.pub/
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Web related
|
||||||
|
lib/generated_plugin_registrant.dart
|
||||||
|
|
||||||
|
# Symbolication related
|
||||||
|
app.*.symbols
|
||||||
|
|
||||||
|
# Obfuscation related
|
||||||
|
app.*.map.json
|
||||||
|
|
||||||
|
# Android Studio will place build artifacts here
|
||||||
|
/android/app/debug
|
||||||
|
/android/app/profile
|
||||||
|
/android/app/release
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# This file tracks properties of this Flutter project.
|
||||||
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
|
#
|
||||||
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
|
version:
|
||||||
|
revision: 4cc385b4b84ac2f816d939a49ea1f328c4e0b48e
|
||||||
|
channel: stable
|
||||||
|
|
||||||
|
project_type: app
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Mini E-Paper | Ep1. Uploading Emoji to E-Paper from Flutter App(iOS & Android)
|
||||||
|
https://youtu.be/-RhEiKldfDc
|
||||||
|
|
||||||
|
# My Channel
|
||||||
|
www.that-project.com
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
|
# check for errors, warnings, and lints.
|
||||||
|
#
|
||||||
|
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||||
|
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||||
|
# invoked from the command line by running `flutter analyze`.
|
||||||
|
|
||||||
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
linter:
|
||||||
|
# The lint rules applied to this project can be customized in the
|
||||||
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
|
# included above or to enable additional rules. A list of all available lints
|
||||||
|
# and their documentation is published at
|
||||||
|
# https://dart-lang.github.io/linter/lints/index.html.
|
||||||
|
#
|
||||||
|
# Instead of disabling a lint rule for the entire project in the
|
||||||
|
# section below, it can also be suppressed for a single line of code
|
||||||
|
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||||
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
|
# producing the lint.
|
||||||
|
rules:
|
||||||
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,6 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
const kMainBG = Color(0xff191720);
|
||||||
|
const kTextFieldFill = Color(0xff1E1C24);
|
||||||
|
const kCardBG = Color(0xffffffff);
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const kHeadline = TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 34,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
);
|
||||||
|
|
||||||
|
const kBodyText = TextStyle(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 15,
|
||||||
|
);
|
||||||
|
|
||||||
|
const kButtonText = TextStyle(
|
||||||
|
color: Colors.black87,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
);
|
||||||
|
|
||||||
|
const kBodyText2 =
|
||||||
|
TextStyle(fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white);
|
||||||
|
|
||||||
|
const kSubtitleText = TextStyle(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 12,
|
||||||
|
);
|
||||||
@@ -0,0 +1,848 @@
|
|||||||
|
const emojiArray = [
|
||||||
|
"😄",
|
||||||
|
"😆",
|
||||||
|
"😊",
|
||||||
|
"😃",
|
||||||
|
"😏",
|
||||||
|
"😍",
|
||||||
|
"😘",
|
||||||
|
"😚",
|
||||||
|
"😳",
|
||||||
|
"😌",
|
||||||
|
"😆",
|
||||||
|
"😁",
|
||||||
|
"😉",
|
||||||
|
"😜",
|
||||||
|
"😝",
|
||||||
|
"😀",
|
||||||
|
"😗",
|
||||||
|
"😙",
|
||||||
|
"😛",
|
||||||
|
"😴",
|
||||||
|
"😟",
|
||||||
|
"😦",
|
||||||
|
"😧",
|
||||||
|
"😮",
|
||||||
|
"😬",
|
||||||
|
"😕",
|
||||||
|
"😯",
|
||||||
|
"😑",
|
||||||
|
"😒",
|
||||||
|
"😅",
|
||||||
|
"😓",
|
||||||
|
"😥",
|
||||||
|
"😩",
|
||||||
|
"😔",
|
||||||
|
"😞",
|
||||||
|
"😖",
|
||||||
|
"😨",
|
||||||
|
"😰",
|
||||||
|
"😣",
|
||||||
|
"😢",
|
||||||
|
"😭",
|
||||||
|
"😂",
|
||||||
|
"😲",
|
||||||
|
"😱",
|
||||||
|
"😫",
|
||||||
|
"😠",
|
||||||
|
"😡",
|
||||||
|
"😤",
|
||||||
|
"😪",
|
||||||
|
"😋",
|
||||||
|
"😷",
|
||||||
|
"😎",
|
||||||
|
"😵",
|
||||||
|
"👿",
|
||||||
|
"😈",
|
||||||
|
"😐",
|
||||||
|
"😶",
|
||||||
|
"😇",
|
||||||
|
"👽",
|
||||||
|
"💛",
|
||||||
|
"💙",
|
||||||
|
"💜",
|
||||||
|
"💚",
|
||||||
|
"💔",
|
||||||
|
"💓",
|
||||||
|
"💗",
|
||||||
|
"💕",
|
||||||
|
"💞",
|
||||||
|
"💘",
|
||||||
|
"💖",
|
||||||
|
"✨",
|
||||||
|
"⭐",
|
||||||
|
"🌟",
|
||||||
|
"💫",
|
||||||
|
"💥",
|
||||||
|
"💢",
|
||||||
|
"❗",
|
||||||
|
"❓",
|
||||||
|
"❕",
|
||||||
|
"❔",
|
||||||
|
"💤",
|
||||||
|
"💨",
|
||||||
|
"💦",
|
||||||
|
"🎶",
|
||||||
|
"🎵",
|
||||||
|
"🔥",
|
||||||
|
"💩",
|
||||||
|
"👍",
|
||||||
|
"👎",
|
||||||
|
"👌",
|
||||||
|
"👊",
|
||||||
|
"✊",
|
||||||
|
"✌️",
|
||||||
|
"👋",
|
||||||
|
"✋",
|
||||||
|
"👐",
|
||||||
|
"☝️",
|
||||||
|
"👇",
|
||||||
|
"👈",
|
||||||
|
"👉",
|
||||||
|
"🙌",
|
||||||
|
"🙏",
|
||||||
|
"👆",
|
||||||
|
"👏",
|
||||||
|
"💪",
|
||||||
|
"🤘",
|
||||||
|
"🖕",
|
||||||
|
"🚶",
|
||||||
|
"🏃",
|
||||||
|
"👫",
|
||||||
|
"👪",
|
||||||
|
"👬",
|
||||||
|
"👭",
|
||||||
|
"💃",
|
||||||
|
"👯",
|
||||||
|
"🙆",
|
||||||
|
"🙅",
|
||||||
|
"💁",
|
||||||
|
"🙋",
|
||||||
|
"👰",
|
||||||
|
"🙇",
|
||||||
|
"💏",
|
||||||
|
"💑",
|
||||||
|
"💆",
|
||||||
|
"💇",
|
||||||
|
"💅",
|
||||||
|
"👦",
|
||||||
|
"👧",
|
||||||
|
"👩",
|
||||||
|
"👨",
|
||||||
|
"👶",
|
||||||
|
"👵",
|
||||||
|
"👴",
|
||||||
|
"👲",
|
||||||
|
"👳",
|
||||||
|
"👷",
|
||||||
|
"👮",
|
||||||
|
"👼",
|
||||||
|
"👸",
|
||||||
|
"😺",
|
||||||
|
"😸",
|
||||||
|
"😻",
|
||||||
|
"😽",
|
||||||
|
"😼",
|
||||||
|
"🙀",
|
||||||
|
"😿",
|
||||||
|
"😹",
|
||||||
|
"😾",
|
||||||
|
"👹",
|
||||||
|
"👺",
|
||||||
|
"🙈",
|
||||||
|
"🙉",
|
||||||
|
"🙊",
|
||||||
|
"💂",
|
||||||
|
"💀",
|
||||||
|
"🐾",
|
||||||
|
"👄",
|
||||||
|
"💋",
|
||||||
|
"💧",
|
||||||
|
"👂",
|
||||||
|
"👀",
|
||||||
|
"👃",
|
||||||
|
"👅",
|
||||||
|
"💌",
|
||||||
|
"👤",
|
||||||
|
"👥",
|
||||||
|
"💬",
|
||||||
|
"💭",
|
||||||
|
"☀️",
|
||||||
|
"☁️",
|
||||||
|
"❄️",
|
||||||
|
"⛄",
|
||||||
|
"⚡",
|
||||||
|
"🌀",
|
||||||
|
"🌁",
|
||||||
|
"🌊",
|
||||||
|
"🐱",
|
||||||
|
"🐶",
|
||||||
|
"🐭",
|
||||||
|
"🐹",
|
||||||
|
"🐰",
|
||||||
|
"🐺",
|
||||||
|
"🐸",
|
||||||
|
"🐯",
|
||||||
|
"🐨",
|
||||||
|
"🐻",
|
||||||
|
"🐷",
|
||||||
|
"🐽",
|
||||||
|
"🐮",
|
||||||
|
"🐗",
|
||||||
|
"🐵",
|
||||||
|
"🐒",
|
||||||
|
"🐴",
|
||||||
|
"🐎",
|
||||||
|
"🐫",
|
||||||
|
"🐑",
|
||||||
|
"🐘",
|
||||||
|
"🐼",
|
||||||
|
"🐍",
|
||||||
|
"🐦",
|
||||||
|
"🐤",
|
||||||
|
"🐥",
|
||||||
|
"🐣",
|
||||||
|
"🐔",
|
||||||
|
"🐧",
|
||||||
|
"🐢",
|
||||||
|
"🐛",
|
||||||
|
"🐝",
|
||||||
|
"🐜",
|
||||||
|
"🐞",
|
||||||
|
"🐌",
|
||||||
|
"🐙",
|
||||||
|
"🐠",
|
||||||
|
"🐟",
|
||||||
|
"🐳",
|
||||||
|
"🐋",
|
||||||
|
"🐬",
|
||||||
|
"🐄",
|
||||||
|
"🐏",
|
||||||
|
"🐀",
|
||||||
|
"🐃",
|
||||||
|
"🐅",
|
||||||
|
"🐇",
|
||||||
|
"🐉",
|
||||||
|
"🐐",
|
||||||
|
"🐓",
|
||||||
|
"🐕",
|
||||||
|
"🐖",
|
||||||
|
"🐁",
|
||||||
|
"🐂",
|
||||||
|
"🐲",
|
||||||
|
"🐡",
|
||||||
|
"🐊",
|
||||||
|
"🐪",
|
||||||
|
"🐆",
|
||||||
|
"🐈",
|
||||||
|
"🐩",
|
||||||
|
"🐾",
|
||||||
|
"💐",
|
||||||
|
"🌸",
|
||||||
|
"🌷",
|
||||||
|
"🍀",
|
||||||
|
"🌹",
|
||||||
|
"🌻",
|
||||||
|
"🌺",
|
||||||
|
"🍁",
|
||||||
|
"🍃",
|
||||||
|
"🍂",
|
||||||
|
"🌿",
|
||||||
|
"🍄",
|
||||||
|
"🌵",
|
||||||
|
"🌴",
|
||||||
|
"🌲",
|
||||||
|
"🌳",
|
||||||
|
"🌰",
|
||||||
|
"🌱",
|
||||||
|
"🌼",
|
||||||
|
"🌾",
|
||||||
|
"🐚",
|
||||||
|
"🌐",
|
||||||
|
"🌞",
|
||||||
|
"🌝",
|
||||||
|
"🌚",
|
||||||
|
"🌑",
|
||||||
|
"🌒",
|
||||||
|
"🌓",
|
||||||
|
"🌔",
|
||||||
|
"🌕",
|
||||||
|
"🌖",
|
||||||
|
"🌗",
|
||||||
|
"🌘",
|
||||||
|
"🌜",
|
||||||
|
"🌛",
|
||||||
|
"🌔",
|
||||||
|
"🌍",
|
||||||
|
"🌎",
|
||||||
|
"🌏",
|
||||||
|
"🌋",
|
||||||
|
"🌌",
|
||||||
|
"⛅",
|
||||||
|
"🎍",
|
||||||
|
"💝",
|
||||||
|
"🎎",
|
||||||
|
"🎒",
|
||||||
|
"🎓",
|
||||||
|
"🎏",
|
||||||
|
"🎆",
|
||||||
|
"🎇",
|
||||||
|
"🎐",
|
||||||
|
"🎑",
|
||||||
|
"🎃",
|
||||||
|
"👻",
|
||||||
|
"🎅",
|
||||||
|
"🎄",
|
||||||
|
"🎁",
|
||||||
|
"🔔",
|
||||||
|
"🔕",
|
||||||
|
"🎋",
|
||||||
|
"🎉",
|
||||||
|
"🎊",
|
||||||
|
"🎈",
|
||||||
|
"🔮",
|
||||||
|
"💿",
|
||||||
|
"📀",
|
||||||
|
"💾",
|
||||||
|
"📷",
|
||||||
|
"📹",
|
||||||
|
"🎥",
|
||||||
|
"💻",
|
||||||
|
"📺",
|
||||||
|
"📱",
|
||||||
|
"☎️",
|
||||||
|
"☎️",
|
||||||
|
"📞",
|
||||||
|
"📟",
|
||||||
|
"📠",
|
||||||
|
"💽",
|
||||||
|
"📼",
|
||||||
|
"🔉",
|
||||||
|
"🔈",
|
||||||
|
"🔇",
|
||||||
|
"📢",
|
||||||
|
"📣",
|
||||||
|
"⌛",
|
||||||
|
"⏳",
|
||||||
|
"⏰",
|
||||||
|
"⌚",
|
||||||
|
"📻",
|
||||||
|
"📡",
|
||||||
|
"➿",
|
||||||
|
"🔍",
|
||||||
|
"🔎",
|
||||||
|
"🔓",
|
||||||
|
"🔒",
|
||||||
|
"🔏",
|
||||||
|
"🔐",
|
||||||
|
"🔑",
|
||||||
|
"💡",
|
||||||
|
"🔦",
|
||||||
|
"🔆",
|
||||||
|
"🔅",
|
||||||
|
"🔌",
|
||||||
|
"🔋",
|
||||||
|
"📲",
|
||||||
|
"✉️",
|
||||||
|
"📫",
|
||||||
|
"📮",
|
||||||
|
"🛀",
|
||||||
|
"🛁",
|
||||||
|
"🚿",
|
||||||
|
"🚽",
|
||||||
|
"🔧",
|
||||||
|
"🔩",
|
||||||
|
"🔨",
|
||||||
|
"💺",
|
||||||
|
"💰",
|
||||||
|
"💴",
|
||||||
|
"💵",
|
||||||
|
"💷",
|
||||||
|
"💶",
|
||||||
|
"💳",
|
||||||
|
"💸",
|
||||||
|
"📧",
|
||||||
|
"📥",
|
||||||
|
"📤",
|
||||||
|
"✉️",
|
||||||
|
"📨",
|
||||||
|
"📯",
|
||||||
|
"📪",
|
||||||
|
"📬",
|
||||||
|
"📭",
|
||||||
|
"📦",
|
||||||
|
"🚪",
|
||||||
|
"🚬",
|
||||||
|
"💣",
|
||||||
|
"🔫",
|
||||||
|
"🔪",
|
||||||
|
"💊",
|
||||||
|
"💉",
|
||||||
|
"📄",
|
||||||
|
"📃",
|
||||||
|
"📑",
|
||||||
|
"📊",
|
||||||
|
"📈",
|
||||||
|
"📉",
|
||||||
|
"📜",
|
||||||
|
"📋",
|
||||||
|
"📆",
|
||||||
|
"📅",
|
||||||
|
"📇",
|
||||||
|
"📁",
|
||||||
|
"📂",
|
||||||
|
"✂️",
|
||||||
|
"📌",
|
||||||
|
"📎",
|
||||||
|
"✒️",
|
||||||
|
"✏️",
|
||||||
|
"📏",
|
||||||
|
"📐",
|
||||||
|
"📕",
|
||||||
|
"📗",
|
||||||
|
"📘",
|
||||||
|
"📙",
|
||||||
|
"📓",
|
||||||
|
"📔",
|
||||||
|
"📒",
|
||||||
|
"📚",
|
||||||
|
"🔖",
|
||||||
|
"📛",
|
||||||
|
"🔬",
|
||||||
|
"🔭",
|
||||||
|
"📰",
|
||||||
|
"🏈",
|
||||||
|
"🏀",
|
||||||
|
"⚽",
|
||||||
|
"⚾",
|
||||||
|
"🎾",
|
||||||
|
"🎱",
|
||||||
|
"🏉",
|
||||||
|
"🎳",
|
||||||
|
"⛳",
|
||||||
|
"🚵",
|
||||||
|
"🚴",
|
||||||
|
"🏇",
|
||||||
|
"🏂",
|
||||||
|
"🏊",
|
||||||
|
"🏄",
|
||||||
|
"🎿",
|
||||||
|
"♠️",
|
||||||
|
"♥️",
|
||||||
|
"♣️",
|
||||||
|
"♦️",
|
||||||
|
"💎",
|
||||||
|
"💍",
|
||||||
|
"🏆",
|
||||||
|
"🎼",
|
||||||
|
"🎹",
|
||||||
|
"🎻",
|
||||||
|
"👾",
|
||||||
|
"🎮",
|
||||||
|
"🃏",
|
||||||
|
"🎴",
|
||||||
|
"🎲",
|
||||||
|
"🎯",
|
||||||
|
"🀄",
|
||||||
|
"🎬",
|
||||||
|
"📝",
|
||||||
|
"📝",
|
||||||
|
"📖",
|
||||||
|
"🎨",
|
||||||
|
"🎤",
|
||||||
|
"🎧",
|
||||||
|
"🎺",
|
||||||
|
"🎷",
|
||||||
|
"🎸",
|
||||||
|
"👞",
|
||||||
|
"👡",
|
||||||
|
"👠",
|
||||||
|
"💄",
|
||||||
|
"👢",
|
||||||
|
"👕",
|
||||||
|
"👕",
|
||||||
|
"👔",
|
||||||
|
"👚",
|
||||||
|
"👗",
|
||||||
|
"🎽",
|
||||||
|
"👖",
|
||||||
|
"👘",
|
||||||
|
"👙",
|
||||||
|
"🎀",
|
||||||
|
"🎩",
|
||||||
|
"👑",
|
||||||
|
"👒",
|
||||||
|
"👞",
|
||||||
|
"🌂",
|
||||||
|
"💼",
|
||||||
|
"👜",
|
||||||
|
"👝",
|
||||||
|
"👛",
|
||||||
|
"👓",
|
||||||
|
"🎣",
|
||||||
|
"☕",
|
||||||
|
"🍵",
|
||||||
|
"🍶",
|
||||||
|
"🍼",
|
||||||
|
"🍺",
|
||||||
|
"🍻",
|
||||||
|
"🍸",
|
||||||
|
"🍹",
|
||||||
|
"🍷",
|
||||||
|
"🍴",
|
||||||
|
"🍕",
|
||||||
|
"🍔",
|
||||||
|
"🍟",
|
||||||
|
"🍗",
|
||||||
|
"🍖",
|
||||||
|
"🍝",
|
||||||
|
"🍛",
|
||||||
|
"🍤",
|
||||||
|
"🍱",
|
||||||
|
"🍣",
|
||||||
|
"🍥",
|
||||||
|
"🍙",
|
||||||
|
"🍘",
|
||||||
|
"🍚",
|
||||||
|
"🍜",
|
||||||
|
"🍲",
|
||||||
|
"🍢",
|
||||||
|
"🍡",
|
||||||
|
"🥚",
|
||||||
|
"🍞",
|
||||||
|
"🍩",
|
||||||
|
"🍮",
|
||||||
|
"🍦",
|
||||||
|
"🍨",
|
||||||
|
"🍧",
|
||||||
|
"🎂",
|
||||||
|
"🍰",
|
||||||
|
"🍪",
|
||||||
|
"🍫",
|
||||||
|
"🍬",
|
||||||
|
"🍭",
|
||||||
|
"🍯",
|
||||||
|
"🍎",
|
||||||
|
"🍏",
|
||||||
|
"🍊",
|
||||||
|
"🍋",
|
||||||
|
"🍒",
|
||||||
|
"🍇",
|
||||||
|
"🍉",
|
||||||
|
"🍓",
|
||||||
|
"🍑",
|
||||||
|
"🍈",
|
||||||
|
"🍌",
|
||||||
|
"🍐",
|
||||||
|
"🍍",
|
||||||
|
"🍠",
|
||||||
|
"🍆",
|
||||||
|
"🍅",
|
||||||
|
"🌽",
|
||||||
|
"🏠",
|
||||||
|
"🏡",
|
||||||
|
"🏫",
|
||||||
|
"🏢",
|
||||||
|
"🏣",
|
||||||
|
"🏥",
|
||||||
|
"🏦",
|
||||||
|
"🏪",
|
||||||
|
"🏩",
|
||||||
|
"🏨",
|
||||||
|
"💒",
|
||||||
|
"⛪",
|
||||||
|
"🏬",
|
||||||
|
"🏤",
|
||||||
|
"🌇",
|
||||||
|
"🌆",
|
||||||
|
"🏯",
|
||||||
|
"🏰",
|
||||||
|
"⛺",
|
||||||
|
"🏭",
|
||||||
|
"🗼",
|
||||||
|
"🗾",
|
||||||
|
"🗻",
|
||||||
|
"🌄",
|
||||||
|
"🌅",
|
||||||
|
"🌠",
|
||||||
|
"🗽",
|
||||||
|
"🌉",
|
||||||
|
"🎠",
|
||||||
|
"🌈",
|
||||||
|
"🎡",
|
||||||
|
"⛲",
|
||||||
|
"🎢",
|
||||||
|
"🚢",
|
||||||
|
"🚤",
|
||||||
|
"⛵",
|
||||||
|
"⛵",
|
||||||
|
"🚣",
|
||||||
|
"⚓",
|
||||||
|
"🚀",
|
||||||
|
"✈️",
|
||||||
|
"🚁",
|
||||||
|
"🚂",
|
||||||
|
"🚊",
|
||||||
|
"🚞",
|
||||||
|
"🚲",
|
||||||
|
"🚡",
|
||||||
|
"🚟",
|
||||||
|
"🚠",
|
||||||
|
"🚜",
|
||||||
|
"🚙",
|
||||||
|
"🚘",
|
||||||
|
"🚗",
|
||||||
|
"🚗",
|
||||||
|
"🚕",
|
||||||
|
"🚖",
|
||||||
|
"🚛",
|
||||||
|
"🚌",
|
||||||
|
"🚍",
|
||||||
|
"🚨",
|
||||||
|
"🚓",
|
||||||
|
"🚔",
|
||||||
|
"🚒",
|
||||||
|
"🚑",
|
||||||
|
"🚐",
|
||||||
|
"🚚",
|
||||||
|
"🚋",
|
||||||
|
"🚉",
|
||||||
|
"🚆",
|
||||||
|
"🚅",
|
||||||
|
"🚄",
|
||||||
|
"🚈",
|
||||||
|
"🚝",
|
||||||
|
"🚃",
|
||||||
|
"🚎",
|
||||||
|
"🎫",
|
||||||
|
"⛽",
|
||||||
|
"🚦",
|
||||||
|
"🚥",
|
||||||
|
"⚠️",
|
||||||
|
"🚧",
|
||||||
|
"🔰",
|
||||||
|
"🏧",
|
||||||
|
"🎰",
|
||||||
|
"🚏",
|
||||||
|
"💈",
|
||||||
|
"♨️",
|
||||||
|
"🏁",
|
||||||
|
"🎌",
|
||||||
|
"🏮",
|
||||||
|
"🗿",
|
||||||
|
"🎪",
|
||||||
|
"🎭",
|
||||||
|
"📍",
|
||||||
|
"🚩",
|
||||||
|
"🇯🇵",
|
||||||
|
"🇰🇷",
|
||||||
|
"🇨🇳",
|
||||||
|
"🇺🇸",
|
||||||
|
"🇫🇷",
|
||||||
|
"🇪🇸",
|
||||||
|
"🇮🇹",
|
||||||
|
"🇷🇺",
|
||||||
|
"🇬🇧",
|
||||||
|
"🇩🇪",
|
||||||
|
"1️⃣",
|
||||||
|
"2️⃣",
|
||||||
|
"3️⃣",
|
||||||
|
"4️⃣",
|
||||||
|
"5️⃣",
|
||||||
|
"6️⃣",
|
||||||
|
"7️⃣",
|
||||||
|
"8️⃣",
|
||||||
|
"9️⃣",
|
||||||
|
"🔟",
|
||||||
|
"🔢",
|
||||||
|
"0️⃣",
|
||||||
|
"#️⃣",
|
||||||
|
"🔣",
|
||||||
|
"◀️",
|
||||||
|
"⬇️",
|
||||||
|
"▶️",
|
||||||
|
"⬅️",
|
||||||
|
"🔠",
|
||||||
|
"🔡",
|
||||||
|
"🔤",
|
||||||
|
"↙️",
|
||||||
|
"↘️",
|
||||||
|
"➡️",
|
||||||
|
"⬆️",
|
||||||
|
"↖️",
|
||||||
|
"↗️",
|
||||||
|
"⏬",
|
||||||
|
"⏫",
|
||||||
|
"🔽",
|
||||||
|
"⤵️",
|
||||||
|
"⤴️",
|
||||||
|
"↩️",
|
||||||
|
"↪️",
|
||||||
|
"↔️",
|
||||||
|
"↕️",
|
||||||
|
"🔼",
|
||||||
|
"🔃",
|
||||||
|
"🔄",
|
||||||
|
"⏪",
|
||||||
|
"⏩",
|
||||||
|
"ℹ️",
|
||||||
|
"🆗",
|
||||||
|
"🔀",
|
||||||
|
"🔁",
|
||||||
|
"🔂",
|
||||||
|
"🆕",
|
||||||
|
"🔝",
|
||||||
|
"🆙",
|
||||||
|
"🆒",
|
||||||
|
"🆓",
|
||||||
|
"🆖",
|
||||||
|
"🎦",
|
||||||
|
"🈁",
|
||||||
|
"📶",
|
||||||
|
"🈹",
|
||||||
|
"🈴",
|
||||||
|
"🈺",
|
||||||
|
"🈯",
|
||||||
|
"🈷️",
|
||||||
|
"🈶",
|
||||||
|
"🈵",
|
||||||
|
"🈚",
|
||||||
|
"🈸",
|
||||||
|
"🈳",
|
||||||
|
"🈲",
|
||||||
|
"🈂️",
|
||||||
|
"🚻",
|
||||||
|
"🚹",
|
||||||
|
"🚺",
|
||||||
|
"🚼",
|
||||||
|
"🚭",
|
||||||
|
"🅿️",
|
||||||
|
"♿",
|
||||||
|
"🚇",
|
||||||
|
"🛄",
|
||||||
|
"🉑",
|
||||||
|
"🚾",
|
||||||
|
"🚰",
|
||||||
|
"🚮",
|
||||||
|
"㊙️",
|
||||||
|
"㊗️",
|
||||||
|
"Ⓜ️",
|
||||||
|
"🛂",
|
||||||
|
"🛅",
|
||||||
|
"🛃",
|
||||||
|
"🉐",
|
||||||
|
"🆑",
|
||||||
|
"🆘",
|
||||||
|
"🆔",
|
||||||
|
"🚫",
|
||||||
|
"🔞",
|
||||||
|
"📵",
|
||||||
|
"🚯",
|
||||||
|
"🚱",
|
||||||
|
"🚳",
|
||||||
|
"🚷",
|
||||||
|
"🚸",
|
||||||
|
"⛔",
|
||||||
|
"✳️",
|
||||||
|
"❇️",
|
||||||
|
"✴️",
|
||||||
|
"💟",
|
||||||
|
"🆚",
|
||||||
|
"📳",
|
||||||
|
"📴",
|
||||||
|
"💹",
|
||||||
|
"💱",
|
||||||
|
"♈",
|
||||||
|
"♉",
|
||||||
|
"♊",
|
||||||
|
"♋",
|
||||||
|
"♌",
|
||||||
|
"♍",
|
||||||
|
"♎",
|
||||||
|
"♏",
|
||||||
|
"♐",
|
||||||
|
"♑",
|
||||||
|
"♒",
|
||||||
|
"♓",
|
||||||
|
"⛎",
|
||||||
|
"🔯",
|
||||||
|
"❎",
|
||||||
|
"🅰️",
|
||||||
|
"🅱️",
|
||||||
|
"🆎",
|
||||||
|
"🅾️",
|
||||||
|
"💠",
|
||||||
|
"♻️",
|
||||||
|
"🔚",
|
||||||
|
"🔙",
|
||||||
|
"🔛",
|
||||||
|
"🔜",
|
||||||
|
"🕐",
|
||||||
|
"🕜",
|
||||||
|
"🕙",
|
||||||
|
"🕥",
|
||||||
|
"🕚",
|
||||||
|
"🕦",
|
||||||
|
"🕛",
|
||||||
|
"🕧",
|
||||||
|
"🕑",
|
||||||
|
"🕝",
|
||||||
|
"🕒",
|
||||||
|
"🕞",
|
||||||
|
"🕓",
|
||||||
|
"🕟",
|
||||||
|
"🕔",
|
||||||
|
"🕠",
|
||||||
|
"🕕",
|
||||||
|
"🕡",
|
||||||
|
"🕖",
|
||||||
|
"🕢",
|
||||||
|
"🕗",
|
||||||
|
"🕣",
|
||||||
|
"🕘",
|
||||||
|
"🕤",
|
||||||
|
"💲",
|
||||||
|
"©️",
|
||||||
|
"®️",
|
||||||
|
"™️",
|
||||||
|
"❌",
|
||||||
|
"❗",
|
||||||
|
"‼️",
|
||||||
|
"⁉️",
|
||||||
|
"⭕",
|
||||||
|
"✖️",
|
||||||
|
"➕",
|
||||||
|
"➖",
|
||||||
|
"➗",
|
||||||
|
"💮",
|
||||||
|
"💯",
|
||||||
|
"✔️",
|
||||||
|
"☑️",
|
||||||
|
"🔘",
|
||||||
|
"🔗",
|
||||||
|
"➰",
|
||||||
|
"〰️",
|
||||||
|
"〽️",
|
||||||
|
"🔱",
|
||||||
|
"▪️",
|
||||||
|
"▫️",
|
||||||
|
"◾",
|
||||||
|
"◽",
|
||||||
|
"◼️",
|
||||||
|
"◻️",
|
||||||
|
"⬛",
|
||||||
|
"⬜",
|
||||||
|
"✅",
|
||||||
|
"🔲",
|
||||||
|
"🔳",
|
||||||
|
"⚫",
|
||||||
|
"⚪",
|
||||||
|
"🔴",
|
||||||
|
"🔵",
|
||||||
|
"🔷",
|
||||||
|
"🔶",
|
||||||
|
"🔹",
|
||||||
|
"🔸",
|
||||||
|
"🔺",
|
||||||
|
"🔻"
|
||||||
|
];
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
Mini E-Paper | Ep1. Uploading Emoji to E-Paper from Flutter App(iOS & Android)
|
||||||
|
Video Tutorial: https://youtu.be/-RhEiKldfDc
|
||||||
|
Created by Eric N. (ThatProject)
|
||||||
|
*/
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
import 'package:epaper_emoji_ble/route/router.dart' as router;
|
||||||
|
import 'package:epaper_emoji_ble/route/routing_constants.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import 'const/custom_colors.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
title: 'Emoji -> E-Paper App',
|
||||||
|
theme: ThemeData(
|
||||||
|
textTheme: GoogleFonts.poppinsTextTheme(Theme.of(context).textTheme),
|
||||||
|
scaffoldBackgroundColor: kMainBG,
|
||||||
|
primarySwatch: Colors.amber,
|
||||||
|
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||||
|
),
|
||||||
|
onGenerateRoute: router.generateRoute,
|
||||||
|
initialRoute: SplashScreenRoute,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:epaper_emoji_ble/route/routing_constants.dart';
|
||||||
|
import 'package:epaper_emoji_ble/screens/ble_list_screen.dart';
|
||||||
|
import 'package:epaper_emoji_ble/screens/emji_converter_screen.dart';
|
||||||
|
import 'package:epaper_emoji_ble/screens/emoji_screen.dart';
|
||||||
|
import 'package:epaper_emoji_ble/screens/splash_screen.dart';
|
||||||
|
import 'package:epaper_emoji_ble/screens/undefined_screen.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
|
switch (settings.name) {
|
||||||
|
case SplashScreenRoute:
|
||||||
|
return MaterialPageRoute(builder: (context) => const SplashScreen());
|
||||||
|
|
||||||
|
case EmojiScreenRoute:
|
||||||
|
return MaterialPageRoute(builder: (context) => const EmojiScreen());
|
||||||
|
|
||||||
|
case EmojiConverterScreenRoute:
|
||||||
|
return MaterialPageRoute(
|
||||||
|
builder: (context) => EmojiConverterScreen(
|
||||||
|
selectedEmoji: settings.arguments as String));
|
||||||
|
|
||||||
|
case BLEScreenRoute:
|
||||||
|
return MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
BleListScreen(headedBitmap: settings.arguments as Uint8List));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return MaterialPageRoute(
|
||||||
|
builder: (context) => UndefinedView(
|
||||||
|
name: settings.name!,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
const String SplashScreenRoute = '/';
|
||||||
|
const String EmojiScreenRoute = '/Emoji';
|
||||||
|
const String EmojiConverterScreenRoute = '/EmojiConverter';
|
||||||
|
const String BLEScreenRoute = '/BLEList';
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:epaper_emoji_ble/const/custom_styles.dart';
|
||||||
|
import 'package:epaper_emoji_ble/widgets/ble_widget.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_blue/flutter_blue.dart';
|
||||||
|
import 'package:quiver/iterables.dart';
|
||||||
|
import 'package:sn_progress_dialog/progress_dialog.dart';
|
||||||
|
import 'package:wakelock/wakelock.dart';
|
||||||
|
|
||||||
|
class BleListScreen extends StatelessWidget {
|
||||||
|
final Uint8List headedBitmap;
|
||||||
|
|
||||||
|
const BleListScreen({Key? key, required this.headedBitmap}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StreamBuilder<BluetoothState>(
|
||||||
|
stream: FlutterBlue.instance.state,
|
||||||
|
initialData: BluetoothState.unknown,
|
||||||
|
builder: (c, snapshot) {
|
||||||
|
final state = snapshot.data;
|
||||||
|
if (state == BluetoothState.on) {
|
||||||
|
return FindDevicesScreen(
|
||||||
|
headedBitmap: headedBitmap,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return BluetoothOffScreen(state: state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BluetoothOffScreen extends StatelessWidget {
|
||||||
|
const BluetoothOffScreen({Key? key, this.state}) : super(key: key);
|
||||||
|
|
||||||
|
final BluetoothState? state;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.lightBlue,
|
||||||
|
body: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
const Icon(
|
||||||
|
Icons.bluetooth_disabled,
|
||||||
|
size: 200.0,
|
||||||
|
color: Colors.white54,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Bluetooth Adapter is ${state != null ? state.toString().substring(15) : 'not available'}.',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.primaryTextTheme
|
||||||
|
.headline1
|
||||||
|
?.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FindDevicesScreen extends StatelessWidget {
|
||||||
|
final Uint8List headedBitmap;
|
||||||
|
|
||||||
|
const FindDevicesScreen({Key? key, required this.headedBitmap})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Find Devices'),
|
||||||
|
),
|
||||||
|
body: RefreshIndicator(
|
||||||
|
onRefresh: () =>
|
||||||
|
FlutterBlue.instance.startScan(timeout: const Duration(seconds: 4)),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
StreamBuilder<List<BluetoothDevice>>(
|
||||||
|
stream: Stream.periodic(const Duration(seconds: 2))
|
||||||
|
.asyncMap((_) => FlutterBlue.instance.connectedDevices),
|
||||||
|
initialData: [],
|
||||||
|
builder: (c, snapshot) => Column(
|
||||||
|
children: snapshot.data!
|
||||||
|
.map((d) => ListTile(
|
||||||
|
title: Text(
|
||||||
|
d.name,
|
||||||
|
style: kButtonText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
d.id.toString(),
|
||||||
|
style:
|
||||||
|
kSubtitleText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
trailing: StreamBuilder<BluetoothDeviceState>(
|
||||||
|
stream: d.state,
|
||||||
|
initialData: BluetoothDeviceState.disconnected,
|
||||||
|
builder: (c, snapshot) {
|
||||||
|
if (snapshot.data ==
|
||||||
|
BluetoothDeviceState.connected) {
|
||||||
|
return TextButton(
|
||||||
|
child: Text(
|
||||||
|
'Send',
|
||||||
|
style: kButtonText.copyWith(
|
||||||
|
color: Colors.white),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
_findTargetUUID(context, d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Text(snapshot.data.toString());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
StreamBuilder<List<ScanResult>>(
|
||||||
|
stream: FlutterBlue.instance.scanResults,
|
||||||
|
initialData: [],
|
||||||
|
builder: (c, snapshot) => Column(
|
||||||
|
children: snapshot.data!
|
||||||
|
.map(
|
||||||
|
(r) => ScanResultTile(
|
||||||
|
result: r,
|
||||||
|
onTap: () {
|
||||||
|
r.device.connect();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
floatingActionButton: StreamBuilder<bool>(
|
||||||
|
stream: FlutterBlue.instance.isScanning,
|
||||||
|
initialData: false,
|
||||||
|
builder: (c, snapshot) {
|
||||||
|
if (snapshot.data!) {
|
||||||
|
return FloatingActionButton(
|
||||||
|
child: const Icon(Icons.stop),
|
||||||
|
onPressed: () => FlutterBlue.instance.stopScan(),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return FloatingActionButton(
|
||||||
|
child: const Icon(Icons.search),
|
||||||
|
onPressed: () => FlutterBlue.instance
|
||||||
|
.startScan(timeout: const Duration(seconds: 4)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String SERVICE_UUID = "713d0001-503e-4c75-ba94-3148f18d941e";
|
||||||
|
final String CHARACTERISTIC_UUID = "713d0002-503e-4c75-ba94-3148f18d941e";
|
||||||
|
|
||||||
|
_findTargetUUID(BuildContext context, BluetoothDevice device) async {
|
||||||
|
print("device :${device.id}");
|
||||||
|
try {
|
||||||
|
List<BluetoothService> services = await device.discoverServices();
|
||||||
|
|
||||||
|
for (var service in services) {
|
||||||
|
print('service!!! : ${service}');
|
||||||
|
print('service last uuid!!! : ${service.uuid.toString()}');
|
||||||
|
|
||||||
|
if (service.uuid.toString() == SERVICE_UUID) {
|
||||||
|
for (var characteristic in service.characteristics) {
|
||||||
|
if (characteristic.uuid.toString() == CHARACTERISTIC_UUID) {
|
||||||
|
print(
|
||||||
|
'characteristic uuid!!! : ${characteristic.uuid.toString()}');
|
||||||
|
|
||||||
|
_sendData(context, characteristic);
|
||||||
|
// for (var pair in pairs) {
|
||||||
|
// print(pair);
|
||||||
|
// await characteristic.write(pair, withoutResponse: false);
|
||||||
|
//
|
||||||
|
// print('SENT!');
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
await showOkAlertDialog(
|
||||||
|
context: context,
|
||||||
|
title: 'Error',
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_sendData(
|
||||||
|
BuildContext context, BluetoothCharacteristic characteristic) async {
|
||||||
|
Wakelock.enable();
|
||||||
|
print('headedBitmap length: ${headedBitmap.length}');
|
||||||
|
var pairs = partition(headedBitmap, 20);
|
||||||
|
|
||||||
|
var startSignal = await characteristic.write([], withoutResponse: false);
|
||||||
|
print('startSignal: $startSignal');
|
||||||
|
ProgressDialog pd = ProgressDialog(context: context);
|
||||||
|
|
||||||
|
pd.show(
|
||||||
|
max: pairs.length,
|
||||||
|
msg: 'Preparing Upload...',
|
||||||
|
progressType: ProgressType.valuable,
|
||||||
|
backgroundColor: const Color(0xff212121),
|
||||||
|
progressValueColor: Colors.amberAccent,
|
||||||
|
progressBgColor: Colors.white70,
|
||||||
|
msgColor: Colors.white,
|
||||||
|
valueColor: Colors.white);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (var pair in pairs) {
|
||||||
|
++i;
|
||||||
|
print(pair);
|
||||||
|
pd.update(value: i, msg: 'Bitmap Uploading...');
|
||||||
|
|
||||||
|
await characteristic.write(pair, withoutResponse: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var endSignal = await characteristic.write([], withoutResponse: false);
|
||||||
|
print('endSignal: $endSignal');
|
||||||
|
Wakelock.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
import 'dart:typed_data';
|
||||||
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:bitmap/bitmap.dart';
|
||||||
|
import 'package:epaper_emoji_ble/const/custom_styles.dart';
|
||||||
|
import 'package:epaper_emoji_ble/route/routing_constants.dart';
|
||||||
|
import 'package:epaper_emoji_ble/util/bitmap24.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/rendering.dart';
|
||||||
|
import 'package:image/image.dart' as img;
|
||||||
|
|
||||||
|
class EmojiConverterScreen extends StatefulWidget {
|
||||||
|
final String selectedEmoji;
|
||||||
|
|
||||||
|
const EmojiConverterScreen({Key? key, required this.selectedEmoji})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_EmojiConverterScreenState createState() => _EmojiConverterScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmojiConverterScreenState extends State<EmojiConverterScreen> {
|
||||||
|
GlobalKey globalKey = GlobalKey();
|
||||||
|
Uint8List? bitmap24WithHeader;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Emoji Converter'),
|
||||||
|
),
|
||||||
|
body: ListView(children: [
|
||||||
|
Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
),
|
||||||
|
RepaintBoundary(
|
||||||
|
key: globalKey,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
widget.selectedEmoji,
|
||||||
|
style: const TextStyle(fontSize: 160),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
),
|
||||||
|
bitmap24WithHeader == null
|
||||||
|
? Container(
|
||||||
|
height: 60,
|
||||||
|
width: MediaQuery.of(context).size.width * 0.8,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[850],
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
),
|
||||||
|
child: TextButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
overlayColor: MaterialStateProperty.resolveWith(
|
||||||
|
(states) => Colors.black12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: _convertImage,
|
||||||
|
child: Text(
|
||||||
|
'Convert to Bitmap',
|
||||||
|
style: kButtonText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
: Container(
|
||||||
|
height: 100,
|
||||||
|
width: 100,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[300],
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
),
|
||||||
|
child: Image.memory(
|
||||||
|
bitmap24WithHeader!,
|
||||||
|
)),
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
),
|
||||||
|
bitmap24WithHeader != null
|
||||||
|
? Container(
|
||||||
|
height: 60,
|
||||||
|
width: MediaQuery.of(context).size.width * 0.8,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[850],
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
),
|
||||||
|
child: TextButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
overlayColor: MaterialStateProperty.resolveWith(
|
||||||
|
(states) => Colors.black12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: _findBLEDevice,
|
||||||
|
child: Text(
|
||||||
|
'Find & Select Your Mini E-Paper',
|
||||||
|
style: kButtonText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
: Container()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_convertImage() async {
|
||||||
|
final RenderRepaintBoundary boundary =
|
||||||
|
globalKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
|
||||||
|
final ui.Image image = await boundary.toImage();
|
||||||
|
final ByteData? byteData =
|
||||||
|
await image.toByteData(format: ui.ImageByteFormat.png);
|
||||||
|
final Uint8List pngBytes = byteData!.buffer.asUint8List();
|
||||||
|
|
||||||
|
var pngImage;
|
||||||
|
try {
|
||||||
|
pngImage = img.decodePng(pngBytes);
|
||||||
|
} catch (e) {
|
||||||
|
await showOkAlertDialog(
|
||||||
|
context: context,
|
||||||
|
title: 'Error',
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resizedImage = img.copyResize(pngImage, width: 80, height: 80);
|
||||||
|
var grayImage = img.grayscale(resizedImage);
|
||||||
|
var imgThreeColor = img.quantize(grayImage, numberOfColors: 3);
|
||||||
|
var flipImage = img.flip(imgThreeColor, img.Flip.vertical);
|
||||||
|
|
||||||
|
Bitmap bitmap = Bitmap.fromHeadless(
|
||||||
|
resizedImage.width, resizedImage.height, flipImage.getBytes());
|
||||||
|
|
||||||
|
Uint8List bitmap24Data = Bitmap24.fromBitMap32(
|
||||||
|
resizedImage.width, resizedImage.height, bitmap.content);
|
||||||
|
Bitmap24 bitmap24 = Bitmap24.fromHeadless(
|
||||||
|
resizedImage.width, resizedImage.height, bitmap24Data);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
bitmap24WithHeader = bitmap24.buildHeaded();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_findBLEDevice() async {
|
||||||
|
if (bitmap24WithHeader == null) {
|
||||||
|
await showOkAlertDialog(
|
||||||
|
context: context,
|
||||||
|
title: 'Error',
|
||||||
|
message: 'Check the Bitmap Emoji',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Navigator.pushNamed(context, BLEScreenRoute, arguments: bitmap24WithHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import 'package:epaper_emoji_ble/const/emoji_data.dart';
|
||||||
|
import 'package:epaper_emoji_ble/route/routing_constants.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class EmojiScreen extends StatelessWidget {
|
||||||
|
const EmojiScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 40, bottom: 10),
|
||||||
|
child: Center(child: emojiGridView(context)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget emojiGridView(BuildContext context) {
|
||||||
|
return MediaQuery.removePadding(
|
||||||
|
context: context,
|
||||||
|
removeTop: true,
|
||||||
|
child: GridView.builder(
|
||||||
|
physics: const BouncingScrollPhysics(),
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: MediaQuery.of(context).size.width >
|
||||||
|
MediaQuery.of(context).size.height
|
||||||
|
? 10
|
||||||
|
: 5,
|
||||||
|
),
|
||||||
|
itemCount: emojiArray.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return Card(
|
||||||
|
color: Colors.amber,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pushNamed(context, EmojiConverterScreenRoute,
|
||||||
|
arguments: emojiArray[index]);
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
emojiArray[index],
|
||||||
|
style: const TextStyle(fontSize: 30),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import 'package:epaper_emoji_ble/const/custom_styles.dart';
|
||||||
|
import 'package:epaper_emoji_ble/route/routing_constants.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SplashScreen extends StatelessWidget {
|
||||||
|
const SplashScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
_getScreen(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getScreen(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 20, right: 20, top: 40, bottom: 10),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Container(
|
||||||
|
child: const Image(
|
||||||
|
image: AssetImage(
|
||||||
|
'assets/images/iot_image.png',
|
||||||
|
),
|
||||||
|
height: 200,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"E-Paper\n^\n|\nBLE\n|\nEmoji😃",
|
||||||
|
style: kHeadline,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width * 0.8,
|
||||||
|
child: const Text(
|
||||||
|
"It's a project that allows you to send emojis to Mini E-Paper. For detail, check out my channel. www.that-project.com",
|
||||||
|
style: kBodyText,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 50,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 60,
|
||||||
|
width: MediaQuery.of(context).size.width * 0.8,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[850],
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
),
|
||||||
|
child: TextButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
overlayColor: MaterialStateProperty.resolveWith(
|
||||||
|
(states) => Colors.black12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pushNamedAndRemoveUntil(context, EmojiScreenRoute,
|
||||||
|
(Route<dynamic> route) => false);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'GET STARTED',
|
||||||
|
style: kButtonText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class UndefinedView extends StatelessWidget {
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
const UndefinedView({Key? key, required this.name}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: Text('Route for $name is not defined'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
class Bitmap24 {
|
||||||
|
/// The width in pixels of the image.
|
||||||
|
final int width;
|
||||||
|
|
||||||
|
/// The width in pixels of the image.
|
||||||
|
final int height;
|
||||||
|
|
||||||
|
/// A [Uint8List] of bytes in a RGB format.
|
||||||
|
final Uint8List content;
|
||||||
|
|
||||||
|
int get size => (width * height) * RGB24BitmapHeader.pixelLength;
|
||||||
|
|
||||||
|
Bitmap24.fromHeadless(this.width, this.height, this.content);
|
||||||
|
|
||||||
|
Bitmap24.fromHeadful(this.width, this.height, Uint8List headedIntList)
|
||||||
|
: content = headedIntList.sublist(
|
||||||
|
RGB24BitmapHeader.RGB24HeaderSize,
|
||||||
|
headedIntList.length,
|
||||||
|
);
|
||||||
|
|
||||||
|
Bitmap24.blank(
|
||||||
|
this.width,
|
||||||
|
this.height,
|
||||||
|
) : content = Uint8List.fromList(
|
||||||
|
List.filled(width * height * RGB24BitmapHeader.pixelLength, 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
Uint8List buildHeaded() {
|
||||||
|
final header = RGB24BitmapHeader(size, width, height)
|
||||||
|
..applyContent(content);
|
||||||
|
return header.headerIntList;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint8List fromBitMap32(int width, int height, Uint8List bitmap32) {
|
||||||
|
Uint8List R8G8B8 = Uint8List(width * height * 3);
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < (bitmap32.length - 3); i = i + 4) {
|
||||||
|
var Red = bitmap32[i + 2];
|
||||||
|
var Green = bitmap32[i + 1];
|
||||||
|
var Blue = bitmap32[i];
|
||||||
|
|
||||||
|
R8G8B8[j] = Red;
|
||||||
|
R8G8B8[j + 1] = Green;
|
||||||
|
R8G8B8[j + 2] = Blue;
|
||||||
|
j = j + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return R8G8B8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RGB24BitmapHeader {
|
||||||
|
static const int pixelLength = 3;
|
||||||
|
static const int RGB24HeaderSize = 54;
|
||||||
|
|
||||||
|
RGB24BitmapHeader(this.contentSize, int width, int height) {
|
||||||
|
headerIntList = Uint8List(fileLength);
|
||||||
|
|
||||||
|
final ByteData bd = headerIntList.buffer.asByteData();
|
||||||
|
bd.setUint8(0x0, 0x42);
|
||||||
|
bd.setUint8(0x1, 0x4d);
|
||||||
|
bd.setInt32(0x2, fileLength, Endian.little);
|
||||||
|
bd.setInt32(0xa, RGB24HeaderSize, Endian.little);
|
||||||
|
bd.setUint32(0xe, 28, Endian.little);
|
||||||
|
bd.setUint32(0x12, width, Endian.little);
|
||||||
|
bd.setUint32(0x16, height, Endian.little);
|
||||||
|
bd.setUint16(0x1a, 1, Endian.little);
|
||||||
|
bd.setUint32(0x1c, 24, Endian.little); // pixel size
|
||||||
|
bd.setUint32(0x1e, 0, Endian.little); //BI_BITFIELDS
|
||||||
|
bd.setUint32(0x22, contentSize, Endian.little);
|
||||||
|
}
|
||||||
|
|
||||||
|
int contentSize;
|
||||||
|
|
||||||
|
void applyContent(Uint8List contentIntList) {
|
||||||
|
headerIntList.setRange(
|
||||||
|
RGB24HeaderSize,
|
||||||
|
fileLength,
|
||||||
|
contentIntList,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late Uint8List headerIntList;
|
||||||
|
|
||||||
|
int get fileLength => contentSize + RGB24HeaderSize;
|
||||||
|
}
|
||||||
@@ -0,0 +1,314 @@
|
|||||||
|
// Copyright 2017, Paul DeMarco.
|
||||||
|
// All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:epaper_emoji_ble/const/custom_styles.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_blue/flutter_blue.dart';
|
||||||
|
|
||||||
|
class ScanResultTile extends StatelessWidget {
|
||||||
|
const ScanResultTile({Key? key, required this.result, this.onTap})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
final ScanResult result;
|
||||||
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
|
Widget _buildTitle(BuildContext context) {
|
||||||
|
if (result.device.name.isNotEmpty) {
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
result.device.name,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: kButtonText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
result.device.id.toString(),
|
||||||
|
style: kSubtitleText.copyWith(color: Colors.white),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Text(result.device.id.toString(),
|
||||||
|
style: kSubtitleText.copyWith(color: Colors.white));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAdvRow(BuildContext context, String title, String value) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: kSubtitleText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12.0,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
value,
|
||||||
|
style: kSubtitleText.copyWith(color: Colors.white),
|
||||||
|
softWrap: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getNiceHexArray(List<int> bytes) {
|
||||||
|
return '[${bytes.map((i) => i.toRadixString(16).padLeft(2, '0')).join(', ')}]'
|
||||||
|
.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
String getNiceManufacturerData(Map<int, List<int>> data) {
|
||||||
|
if (data.isEmpty) {
|
||||||
|
return 'N/A';
|
||||||
|
}
|
||||||
|
List<String> res = [];
|
||||||
|
data.forEach((id, bytes) {
|
||||||
|
res.add(
|
||||||
|
'${id.toRadixString(16).toUpperCase()}: ${getNiceHexArray(bytes)}');
|
||||||
|
});
|
||||||
|
return res.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
String getNiceServiceData(Map<String, List<int>> data) {
|
||||||
|
if (data.isEmpty) {
|
||||||
|
return 'N/A';
|
||||||
|
}
|
||||||
|
List<String> res = [];
|
||||||
|
data.forEach((id, bytes) {
|
||||||
|
res.add('${id.toUpperCase()}: ${getNiceHexArray(bytes)}');
|
||||||
|
});
|
||||||
|
return res.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ExpansionTile(
|
||||||
|
title: _buildTitle(context),
|
||||||
|
leading: Text(
|
||||||
|
result.rssi.toString(),
|
||||||
|
style: kButtonText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
trailing: TextButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
overlayColor: MaterialStateProperty.resolveWith(
|
||||||
|
(states) => Colors.black12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'CONNECT',
|
||||||
|
style: kButtonText.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
onPressed: (result.advertisementData.connectable) ? onTap : null,
|
||||||
|
),
|
||||||
|
children: <Widget>[
|
||||||
|
_buildAdvRow(
|
||||||
|
context, 'Complete Local Name', result.advertisementData.localName),
|
||||||
|
_buildAdvRow(context, 'Tx Power Level',
|
||||||
|
'${result.advertisementData.txPowerLevel ?? 'N/A'}'),
|
||||||
|
_buildAdvRow(context, 'Manufacturer Data',
|
||||||
|
getNiceManufacturerData(result.advertisementData.manufacturerData)),
|
||||||
|
_buildAdvRow(
|
||||||
|
context,
|
||||||
|
'Service UUIDs',
|
||||||
|
(result.advertisementData.serviceUuids.isNotEmpty)
|
||||||
|
? result.advertisementData.serviceUuids.join(', ').toUpperCase()
|
||||||
|
: 'N/A'),
|
||||||
|
_buildAdvRow(context, 'Service Data',
|
||||||
|
getNiceServiceData(result.advertisementData.serviceData)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ServiceTile extends StatelessWidget {
|
||||||
|
final BluetoothService service;
|
||||||
|
final List<CharacteristicTile> characteristicTiles;
|
||||||
|
|
||||||
|
const ServiceTile(
|
||||||
|
{Key? key, required this.service, required this.characteristicTiles})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (characteristicTiles.isNotEmpty) {
|
||||||
|
return ExpansionTile(
|
||||||
|
title: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
const Text('Service'),
|
||||||
|
Text(
|
||||||
|
'0x${service.uuid.toString().toUpperCase().substring(4, 8)}',
|
||||||
|
style: kSubtitleText.copyWith(color: Colors.white),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
children: characteristicTiles,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return ListTile(
|
||||||
|
title: const Text('Service'),
|
||||||
|
subtitle:
|
||||||
|
Text('0x${service.uuid.toString().toUpperCase().substring(4, 8)}'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CharacteristicTile extends StatelessWidget {
|
||||||
|
final BluetoothCharacteristic characteristic;
|
||||||
|
final List<DescriptorTile> descriptorTiles;
|
||||||
|
final VoidCallback? onReadPressed;
|
||||||
|
final VoidCallback? onWritePressed;
|
||||||
|
final VoidCallback? onNotificationPressed;
|
||||||
|
|
||||||
|
const CharacteristicTile(
|
||||||
|
{Key? key,
|
||||||
|
required this.characteristic,
|
||||||
|
required this.descriptorTiles,
|
||||||
|
this.onReadPressed,
|
||||||
|
this.onWritePressed,
|
||||||
|
this.onNotificationPressed})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StreamBuilder<List<int>>(
|
||||||
|
stream: characteristic.value,
|
||||||
|
initialData: characteristic.lastValue,
|
||||||
|
builder: (c, snapshot) {
|
||||||
|
final value = snapshot.data;
|
||||||
|
return ExpansionTile(
|
||||||
|
title: ListTile(
|
||||||
|
title: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
const Text('Characteristic'),
|
||||||
|
Text(
|
||||||
|
'0x${characteristic.uuid.toString().toUpperCase().substring(4, 8)}',
|
||||||
|
style: Theme.of(context).textTheme.bodyText1?.copyWith(
|
||||||
|
color: Theme.of(context).textTheme.caption?.color))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: Text(value.toString()),
|
||||||
|
contentPadding: const EdgeInsets.all(0.0),
|
||||||
|
),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.file_download,
|
||||||
|
color: Theme.of(context).iconTheme.color?.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
onPressed: onReadPressed,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.file_upload,
|
||||||
|
color: Theme.of(context).iconTheme.color?.withOpacity(0.5)),
|
||||||
|
onPressed: onWritePressed,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
characteristic.isNotifying
|
||||||
|
? Icons.sync_disabled
|
||||||
|
: Icons.sync,
|
||||||
|
color: Theme.of(context).iconTheme.color?.withOpacity(0.5)),
|
||||||
|
onPressed: onNotificationPressed,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
children: descriptorTiles,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DescriptorTile extends StatelessWidget {
|
||||||
|
final BluetoothDescriptor descriptor;
|
||||||
|
final VoidCallback? onReadPressed;
|
||||||
|
final VoidCallback? onWritePressed;
|
||||||
|
|
||||||
|
const DescriptorTile(
|
||||||
|
{Key? key,
|
||||||
|
required this.descriptor,
|
||||||
|
this.onReadPressed,
|
||||||
|
this.onWritePressed})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
title: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
const Text('Descriptor'),
|
||||||
|
Text('0x${descriptor.uuid.toString().toUpperCase().substring(4, 8)}',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyText1
|
||||||
|
?.copyWith(color: Theme.of(context).textTheme.caption?.color))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: StreamBuilder<List<int>>(
|
||||||
|
stream: descriptor.value,
|
||||||
|
initialData: descriptor.lastValue,
|
||||||
|
builder: (c, snapshot) => Text(snapshot.data.toString()),
|
||||||
|
),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.file_download,
|
||||||
|
color: Theme.of(context).iconTheme.color?.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
onPressed: onReadPressed,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.file_upload,
|
||||||
|
color: Theme.of(context).iconTheme.color?.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
onPressed: onWritePressed,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AdapterStateTile extends StatelessWidget {
|
||||||
|
const AdapterStateTile({Key? key, required this.state}) : super(key: key);
|
||||||
|
|
||||||
|
final BluetoothState state;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.redAccent,
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(
|
||||||
|
'Bluetooth adapter is ${state.toString().substring(15)}',
|
||||||
|
style: Theme.of(context).primaryTextTheme.headline1,
|
||||||
|
),
|
||||||
|
trailing: Icon(
|
||||||
|
Icons.error,
|
||||||
|
color: Theme.of(context).primaryTextTheme.subtitle1?.color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,439 @@
|
|||||||
|
# Generated by pub
|
||||||
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
|
packages:
|
||||||
|
adaptive_dialog:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: adaptive_dialog
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
animations:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: animations
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.2"
|
||||||
|
async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: async
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.8.1"
|
||||||
|
bitmap:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: bitmap
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2"
|
||||||
|
boolean_selector:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: boolean_selector
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
characters:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: characters
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
charcode:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: charcode
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.1"
|
||||||
|
clock:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: clock
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
collection:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: collection
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.15.0"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
|
fake_async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fake_async
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.2"
|
||||||
|
fixnum:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fixnum
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
|
flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
flutter_blue:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_blue
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.8.0"
|
||||||
|
flutter_lints:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: flutter_lints
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
|
flutter_test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
flutter_web_plugins:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
font_awesome_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: font_awesome_flutter
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "9.1.0"
|
||||||
|
google_fonts:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: google_fonts
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
http:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.13.3"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.0"
|
||||||
|
image:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.3"
|
||||||
|
lints:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: lints
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
matcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: matcher
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.10"
|
||||||
|
meta:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: meta
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.7.0"
|
||||||
|
path:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.8.0"
|
||||||
|
path_provider:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
|
path_provider_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_linux
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
path_provider_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_macos
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
path_provider_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
|
path_provider_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_windows
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
|
pedantic:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pedantic
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.11.1"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.0"
|
||||||
|
platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
|
plugin_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: plugin_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
|
process:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: process
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.3"
|
||||||
|
protobuf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: protobuf
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
quiver:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: quiver
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
rxdart:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: rxdart
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.26.0"
|
||||||
|
sky_engine:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.99"
|
||||||
|
sn_progress_dialog:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: sn_progress_dialog
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
|
source_span:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_span
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.8.1"
|
||||||
|
stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stack_trace
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.10.0"
|
||||||
|
stream_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_channel
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
string_scanner:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: string_scanner
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
term_glyph:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: term_glyph
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
test_api:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_api
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.2"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
|
vector_math:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_math
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
wakelock:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: wakelock
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.3+3"
|
||||||
|
wakelock_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock_macos
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.0+2"
|
||||||
|
wakelock_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1+2"
|
||||||
|
wakelock_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0+2"
|
||||||
|
wakelock_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock_windows
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.0+1"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.9"
|
||||||
|
xdg_directories:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xdg_directories
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.2.0"
|
||||||
|
sdks:
|
||||||
|
dart: ">=2.13.0 <3.0.0"
|
||||||
|
flutter: ">=2.0.0"
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
name: epaper_emoji_ble
|
||||||
|
description: App allows to send the emoji you choose to your e-paper via ble
|
||||||
|
|
||||||
|
# The following line prevents the package from being accidentally published to
|
||||||
|
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||||
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
|
# The following defines the version and build number for your application.
|
||||||
|
# A version number is three numbers separated by dots, like 1.2.43
|
||||||
|
# followed by an optional build number separated by a +.
|
||||||
|
# Both the version and the builder number may be overridden in flutter
|
||||||
|
# build by specifying --build-name and --build-number, respectively.
|
||||||
|
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||||
|
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||||
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
|
# Read more about iOS versioning at
|
||||||
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
|
version: 1.0.0+1
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ">=2.12.0 <3.0.0"
|
||||||
|
|
||||||
|
# Dependencies specify other packages that your package needs in order to work.
|
||||||
|
# To automatically upgrade your package dependencies to the latest versions
|
||||||
|
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||||
|
# dependencies can be manually updated by changing the version numbers below to
|
||||||
|
# the latest version available on pub.dev. To see which dependencies have newer
|
||||||
|
# versions available, run `flutter pub outdated`.
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
|
# The following adds the Cupertino Icons font to your application.
|
||||||
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
cupertino_icons: ^1.0.2
|
||||||
|
google_fonts: ^2.1.0
|
||||||
|
adaptive_dialog: ^1.1.0
|
||||||
|
font_awesome_flutter: ^9.1.0
|
||||||
|
bitmap: ^0.1.2
|
||||||
|
image: ^3.0.2
|
||||||
|
flutter_blue: ^0.8.0
|
||||||
|
quiver: ^3.0.1
|
||||||
|
sn_progress_dialog: ^1.0.3
|
||||||
|
wakelock: ^0.5.3+3
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
|
# The "flutter_lints" package below contains a set of recommended lints to
|
||||||
|
# encourage good coding practices. The lint set provided by the package is
|
||||||
|
# activated in the `analysis_options.yaml` file located at the root of your
|
||||||
|
# package. See that file for information about deactivating specific lint
|
||||||
|
# rules and activating additional ones.
|
||||||
|
flutter_lints: ^1.0.0
|
||||||
|
|
||||||
|
# For information on the generic Dart part of this file, see the
|
||||||
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
|
# The following section is specific to Flutter.
|
||||||
|
flutter:
|
||||||
|
|
||||||
|
# The following line ensures that the Material Icons font is
|
||||||
|
# included with your application, so that you can use the icons in
|
||||||
|
# the material Icons class.
|
||||||
|
uses-material-design: true
|
||||||
|
assets:
|
||||||
|
- assets/images/
|
||||||
|
|
||||||
|
# To add assets to your application, add an assets section, like this:
|
||||||
|
# assets:
|
||||||
|
# - images/a_dot_burr.jpeg
|
||||||
|
# - images/a_dot_ham.jpeg
|
||||||
|
|
||||||
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
|
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||||
|
|
||||||
|
# For details regarding adding assets from package dependencies, see
|
||||||
|
# https://flutter.dev/assets-and-images/#from-packages
|
||||||
|
|
||||||
|
# To add custom fonts to your application, add a fonts section here,
|
||||||
|
# in this "flutter" section. Each entry in this list should have a
|
||||||
|
# "family" key with the font family name, and a "fonts" key with a
|
||||||
|
# list giving the asset and other descriptors for the font. For
|
||||||
|
# example:
|
||||||
|
# fonts:
|
||||||
|
# - family: Schyler
|
||||||
|
# fonts:
|
||||||
|
# - asset: fonts/Schyler-Regular.ttf
|
||||||
|
# - asset: fonts/Schyler-Italic.ttf
|
||||||
|
# style: italic
|
||||||
|
# - family: Trajan Pro
|
||||||
|
# fonts:
|
||||||
|
# - asset: fonts/TrajanPro.ttf
|
||||||
|
# - asset: fonts/TrajanPro_Bold.ttf
|
||||||
|
# weight: 700
|
||||||
|
#
|
||||||
|
# For details regarding fonts from package dependencies,
|
||||||
|
# see https://flutter.dev/custom-fonts/#from-packages
|
||||||
Reference in New Issue
Block a user