1/*
2 * lws-minimal-esp32
3 *
4 * Written in 2010-2020 by Andy Green <andy@warmcat.com>
5 *
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
8 *
9 * Based on espressif Public Domain sample
10 */
11
12#define LWIP_PROVIDE_ERRNO 1
13#define _ESP_PLATFORM_ERRNO_H_
14
15#include <stdio.h>
16#include "sdkconfig.h"
17#include "freertos/FreeRTOS.h"
18#include "freertos/task.h"
19
20#include <driver/gpio.h>
21
22#include <libwebsockets.h>
23
24struct lws_context *context;
25extern struct lws_led_state *lls;
26extern lws_display_state_t lds;
27extern lws_netdev_instance_wifi_t *wnd;
28
29extern int init_plat_devices(struct lws_context *);
30
31static const uint8_t img[] = {
32#include "../banded-img.h"
33};
34
35#include "policy.h"
36
37static uint8_t flip;
38
39typedef struct myss {
40	struct lws_ss_handle 		*ss;
41	void				*opaque_data;
42	/* ... application specific state ... */
43
44	size_t				amount;
45
46} myss_t;
47
48static int
49myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
50{
51	myss_t *m = (myss_t *)userobj;
52
53	lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags);
54//	lwsl_hexdump_info(buf, len);
55	m->amount += len;
56
57	if (flags & LWSSS_FLAG_EOM) {
58
59		/*
60		 * If we received the whole message, for our example it means
61		 * we are done.
62		 */
63
64		lwsl_notice("%s: received %u bytes\n", __func__,
65			    (unsigned int)m->amount);
66
67		/*
68		 * In CI, we use sai-expect to look for this
69		 * string for success
70		 */
71
72		lwsl_notice("Completed: PASS\n");
73	}
74
75	return 0;
76}
77
78static int
79myss_state(void *userobj, void *sh, lws_ss_constate_t state,
80	   lws_ss_tx_ordinal_t ack)
81{
82	myss_t *m = (myss_t *)userobj;
83
84	lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state),
85		  (unsigned int)ack);
86
87	switch (state) {
88	case LWSSSCS_CREATING:
89		return lws_ss_client_connect(m->ss);
90		break;
91	default:
92		break;
93	}
94
95	return 0;
96}
97
98static const lws_ss_info_t ssi = {
99	.handle_offset			= offsetof(myss_t, ss),
100	.opaque_user_data_offset	= offsetof(myss_t, opaque_data),
101	.rx				= myss_rx,
102	.state				= myss_state,
103	.user_alloc			= sizeof(myss_t),
104	.streamtype			= "test_stream",
105};
106
107static const lws_led_sequence_def_t *seqs[] = {
108	&lws_pwmseq_static_on,
109	&lws_pwmseq_static_off,
110	&lws_pwmseq_sine_endless_slow,
111	&lws_pwmseq_sine_endless_fast,
112};
113
114static int
115smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf,
116       size_t len)
117{
118
119	if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user") &&
120	    !lws_json_simple_strcmp(buf, len, "\"event\":", "click")) {
121		lws_led_transition(lls, "alert", seqs[flip & 3],
122				   &lws_pwmseq_linear_wipe);
123		flip++;
124	}
125
126	lwsl_hexdump_notice(buf, len);
127
128	if ((_class & LWSSMDCL_SYSTEM_STATE) &&
129	    !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) {
130
131		/* create the secure stream */
132
133		lwsl_notice("%s: creating test secure stream\n", __func__);
134
135		if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) {
136			lwsl_err("%s: failed to create secure stream\n",
137				 __func__);
138			return -1;
139		}
140	}
141
142	if (_class & LWSSMDCL_INTERACTION)
143		/*
144		 * Any kind of user interaction brings the display back up and
145		 * resets the dimming / blanking timers
146		 */
147		lws_display_state_active(&lds);
148
149	return 0;
150}
151
152void
153app_main(void)
154{
155	struct lws_context_creation_info *info;
156
157	lws_set_log_level(1024 | 15, NULL);
158
159        lws_netdev_plat_init();
160        lws_netdev_plat_wifi_init();
161
162        info = malloc(sizeof(*info));
163        if (!info)
164        	goto spin;
165
166	memset(info, 0, sizeof(*info));
167
168	lwsl_notice("LWS test for Heltec WB32 ESP32 board\n");
169
170	info->pss_policies_json		= ss_policy;
171	info->options			= LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
172					  LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
173	info->port			= CONTEXT_PORT_NO_LISTEN;
174	info->early_smd_cb		= smd_cb;
175	info->early_smd_class_filter	= LWSSMDCL_INTERACTION |
176					  LWSSMDCL_SYSTEM_STATE |
177					  LWSSMDCL_NETWORK;
178
179	context = lws_create_context(info);
180	if (!context) {
181		lwsl_err("lws init failed\n");
182		return;
183	}
184
185	/*
186	 * We don't need this after context creation... things it pointed to
187	 * still need to exist though since the context copied the pointers.
188	 */
189
190	free(info);
191
192	/* devices and init are in devices.c */
193
194	if (init_plat_devices(context))
195		goto spin;
196
197	/* put the logo on the OLED display */
198
199	lds.disp->blit(lds.disp, img, 0, 0, 128, 64);
200	lws_display_state_active(&lds);
201
202	/* the lws event loop */
203
204	do {
205		taskYIELD();
206	} while (lws_service(context, 0) >= 0);
207
208
209spin:
210	vTaskDelay(10);
211	taskYIELD();
212	goto spin;
213}
214