Skip to content

Commit ca7583d

Browse files
committed
Added support for actually controlling the pins via the JSON API
1 parent 3689bf5 commit ca7583d

File tree

3 files changed

+124
-4
lines changed

3 files changed

+124
-4
lines changed

PicoHTTPServer/httpserver.c

+48
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <stdarg.h>
12
#include <pico/cyw43_arch.h>
23
#include <pico/stdlib.h>
34

@@ -8,6 +9,7 @@
89
#include <FreeRTOS.h>
910
#include <semphr.h>
1011
#include <task.h>
12+
1113
#include "debug_printf.h"
1214
#include "httpserver.h"
1315

@@ -25,6 +27,7 @@ struct _http_connection
2527
{
2628
http_server_instance server;
2729
int socket;
30+
size_t buffered_size;
2831
char buffer[1];
2932
};
3033

@@ -364,3 +367,48 @@ void http_server_send_reply(http_connection conn, const char *code, const char *
364367
send_all(conn->socket, conn->buffer, done);
365368
send_all(conn->socket, content, size);
366369
}
370+
371+
http_write_handle http_server_begin_write_reply(http_connection conn, const char *code, const char *contentType)
372+
{
373+
conn->buffered_size = snprintf(conn->buffer, conn->server->buffer_size, "HTTP/1.0 %s\r\nContent-Type: %s\r\nConnection: close\r\n\r\n", code, contentType);
374+
return (http_write_handle)conn;
375+
}
376+
377+
void http_server_write_reply(http_write_handle handle, const char *format, ...)
378+
{
379+
http_connection conn = (http_connection)handle;
380+
va_list args;
381+
va_start(args, format);
382+
int written = vsnprintf(conn->buffer + conn->buffered_size, conn->server->buffer_size - conn->buffered_size, format, args);
383+
va_end(args);
384+
if ((conn->buffered_size + written) < (conn->server->buffer_size - 16))
385+
{
386+
conn->buffered_size += written;
387+
return;
388+
}
389+
390+
send_all(conn->socket, conn->buffer, conn->buffered_size);
391+
va_start(args, format);
392+
conn->buffered_size = vsnprintf(conn->buffer, conn->server->buffer_size, format, args);
393+
va_end(args);
394+
}
395+
396+
void http_server_end_write_reply(http_write_handle handle, const char *footer)
397+
{
398+
http_connection conn = (http_connection)handle;
399+
int len = footer ? strlen(footer) : 0;
400+
if (len && len < (conn->server->buffer_size - conn->buffered_size))
401+
{
402+
memcpy(conn->buffer + conn->buffered_size, footer, len);
403+
conn->buffered_size += len;
404+
len = 0;
405+
}
406+
407+
if (conn->buffered_size)
408+
send_all(conn->socket, conn->buffer, conn->buffered_size);
409+
410+
if (len)
411+
send_all(conn->socket, footer, len);
412+
413+
conn->buffered_size = 0;
414+
}

PicoHTTPServer/httpserver.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

33
typedef struct _http_server_instance *http_server_instance;
4-
typedef struct _http_connection *http_connection;
4+
typedef struct _http_connection *http_connection, *http_write_handle;
55

66
typedef bool(*http_request_handler)(http_connection conn, char *path, void *context);
77

@@ -18,3 +18,7 @@ typedef struct http_zone
1818
http_server_instance http_server_create(const char *main_host, const char *main_domain, int max_thread_count, int buffer_size);
1919
void http_server_add_zone(http_server_instance server, http_zone *instance, const char *prefix, http_request_handler handler, void *context);
2020
void http_server_send_reply(http_connection conn, const char *code, const char *contentType, const char *content, int size);
21+
22+
http_write_handle http_server_begin_write_reply(http_connection conn, const char *code, const char *contentType);
23+
void http_server_write_reply(http_write_handle handle, const char *format, ...);
24+
void http_server_end_write_reply(http_write_handle handle, const char *footer);

PicoHTTPServer/main.c

+71-3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,73 @@ static bool do_retrieve_file(http_connection conn, char *path, void *context)
5353
return false;
5454
}
5555

56+
static bool do_handle_api_call(http_connection conn, char *path, void *context)
57+
{
58+
static int s_InitializedMask = 0;
59+
60+
if (!strcmp(path, "readpins"))
61+
{
62+
http_write_handle reply = http_server_begin_write_reply(conn, "200 OK", "text/json");
63+
http_server_write_reply(reply, "{\"led0v\": \"%d\"", cyw43_arch_gpio_get(0));
64+
65+
int values = gpio_get_all();
66+
67+
for (int i = 0; i < 29; i++)
68+
{
69+
if (i > 22 && i < 26)
70+
continue;
71+
72+
if (s_InitializedMask & (1 << i))
73+
http_server_write_reply(reply, ",\"gpio%dd\": \"%s\",\"gpio%dv\": \"%d\"", i, gpio_get_dir(i) ? "OUT" : "IN", i, (values >> i) & 1);
74+
}
75+
76+
http_server_end_write_reply(reply, "}");
77+
return true;
78+
}
79+
else if (!memcmp(path, "writepin/", 9))
80+
{
81+
//e.g. 'writepin/led0?v=1'
82+
char *port = path + 9;
83+
char *arg = strchr(port, '?');
84+
if (arg)
85+
{
86+
*arg++ = 0;
87+
char *value = strchr(arg, '=');
88+
*value++ = 0;
89+
90+
if (!strcmp(port, "led0"))
91+
cyw43_arch_gpio_put(0, value[0] == '1');
92+
else if (!memcmp(port, "gpio", 4))
93+
{
94+
int gpio = atoi(port + 4);
95+
if (!(s_InitializedMask & (1 << gpio)))
96+
{
97+
gpio_init(gpio);
98+
s_InitializedMask |= (1 << gpio);
99+
}
100+
101+
if (arg[0] == 'd' && value[0] == 'I')
102+
{
103+
gpio_set_pulls(gpio, true, false);
104+
gpio_set_dir(gpio, GPIO_IN);
105+
}
106+
else
107+
{
108+
gpio_set_pulls(gpio, false, false);
109+
gpio_set_dir(gpio, GPIO_OUT);
110+
111+
if (arg[0] == 'v')
112+
gpio_put(gpio, value[0] == '1');
113+
}
114+
}
115+
116+
return true;
117+
}
118+
}
119+
120+
return false;
121+
}
122+
56123

57124
static void main_task(__unused void *params)
58125
{
@@ -83,8 +150,9 @@ static void main_task(__unused void *params)
83150
dhcp_server_init(&dhcp_server, &netif->ip_addr, &netif->netmask, settings->domain_name);
84151
dns_server_init(netif->ip_addr.addr, settings->secondary_address, settings->hostname, settings->domain_name);
85152
http_server_instance server = http_server_create(settings->hostname, settings->domain_name, 4, 4096);
86-
static http_zone zone;
87-
http_server_add_zone(server, &zone, "", do_retrieve_file, NULL);
153+
static http_zone zone1, zone2;
154+
http_server_add_zone(server, &zone1, "", do_retrieve_file, NULL);
155+
http_server_add_zone(server, &zone2, "/api", do_handle_api_call, NULL);
88156
vTaskDelete(NULL);
89157
}
90158

@@ -96,8 +164,8 @@ void debug_printf(const char *format, ...)
96164
va_start(args, format);
97165
xSemaphoreTake(s_PrintfSemaphore, portMAX_DELAY);
98166
vprintf(format, args);
99-
xSemaphoreGive(s_PrintfSemaphore);
100167
va_end(args);
168+
xSemaphoreGive(s_PrintfSemaphore);
101169
}
102170

103171
void debug_write(const void *data, int size)

0 commit comments

Comments
 (0)