summaryrefslogtreecommitdiff
path: root/src/draw_qrcode.cpp
blob: 1d2edc8c8b4e8ae66261e8b9e47ad6bc28003fcf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <GxEPD2_BW.h>
#include <U8g2_for_Adafruit_GFX.h>
#include <qrcode.h>

#define BLOCK_WIDTH 4

extern GxEPD2_GFX_BASE_CLASS &get_display();
extern U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;

static uint16_t sizes[] = {
	17, 32, 53, 78, 106, 134, 154, 192, 230,
};

static void escape_strings(String &text) {
	text.replace("\\", "\\\\");
	text.replace("\"", "\\\"");
	text.replace(";", "\\;");
	text.replace(",", "\\,");
	text.replace(":", "\\:");
}

static int version_for_len(int length) {
	/* assuming ECC_LOW byte qrcodes
	   sizes taken from table in https://github.com/ricmoo/QRCode/blob/master/README.md */

	for (int i = 0; i < sizeof(sizes)/sizeof(uint16_t); i++) {
		if (length <= sizes[i])
			return i + 1;
	}
	return -1;
}

int draw_qrcode(int16_t x, int16_t y, String &text) {
	QRCode qrcode;
	int version = version_for_len(text.length());
	if (version <= 0)
		return 0;

	uint8_t bytes[qrcode_getBufferSize(version)];
	qrcode_initText(&qrcode, bytes, version, ECC_LOW, text.c_str());

	/* add quiet zone */
	x += 4 * BLOCK_WIDTH;
	y += 4 * BLOCK_WIDTH;

	for (int row = 0; row < qrcode.size; row++) {
		for (int col = 0; col < qrcode.size; col++) {
			if (!qrcode_getModule(&qrcode, row, col)) {
				continue;
			}
			get_display().fillRect(x + BLOCK_WIDTH * row, y + BLOCK_WIDTH * col, BLOCK_WIDTH, BLOCK_WIDTH, GxEPD_BLACK);
		}
	}
	return qrcode.size * BLOCK_WIDTH + 8 * BLOCK_WIDTH;
}

void draw_qrcode_wlan(int16_t x, int16_t y, const char *ssid, const char *psk) {
	String ssid_str = String(ssid);
	String psk_str = String(psk);
	escape_strings(ssid_str);
	escape_strings(psk_str);

	/* assuming WPA network; (H)idden attribute is kept at default */
	String wifi_str = "WIFI:S:" + ssid_str;
	if (psk_str.length() == 0) {
		/* open network */
		wifi_str += ";;;;";
	} else {
		wifi_str += ";P:" + psk_str + ";T:WPA;;";
	}

	int size = draw_qrcode(x, y, wifi_str);

	/* draw text */
	uint16_t w, h;
	h = 10; /* assume 10px height */
	String text_ssid = String("SSID:");
	String text_psk = String("PSK:");

	u8g2Fonts.setFont(u8g2_font_helvB10_tf);
	w = u8g2Fonts.getUTF8Width(text_ssid.c_str());
	u8g2Fonts.setCursor(x, y + size + h);
	u8g2Fonts.print(text_ssid);
	u8g2Fonts.setFont(u8g2_font_helvR10_tf);
	u8g2Fonts.setCursor(x + w, y + size + h);
	u8g2Fonts.print("  " + ssid_str);

	if (psk_str.length() > 0) {
		u8g2Fonts.setFont(u8g2_font_helvB10_tf);
		u8g2Fonts.setCursor(x, y + size + 2 * h + 10);
		u8g2Fonts.print(text_psk);
		u8g2Fonts.setFont(u8g2_font_helvR10_tf);
		u8g2Fonts.setCursor(x + w, y + size + 2 * h + 10);
		u8g2Fonts.print("  " + psk_str);
	}
}