Remove extra logging, auth /cp/serial and add doc
This commit is contained in:
parent
557e35469f
commit
8cfdfb95f7
|
@ -286,6 +286,44 @@ not protected by basic auth in case the device is someone elses.
|
||||||
|
|
||||||
Only `GET` requests are supported and will return `405 Method Not Allowed` otherwise.
|
Only `GET` requests are supported and will return `405 Method Not Allowed` otherwise.
|
||||||
|
|
||||||
|
#### `/cp/devices.json`
|
||||||
|
|
||||||
|
Returns information about other devices found on the network using MDNS.
|
||||||
|
|
||||||
|
* `total`: Total MDNS response count. May be more than in `devices` if internal limits were hit.
|
||||||
|
* `devices`: List of discovered devices.
|
||||||
|
* `hostname`: MDNS hostname
|
||||||
|
* `instance_name`: MDNS instance name. Defaults to human readable board name.
|
||||||
|
* `port`: Port of CircuitPython Web API
|
||||||
|
* `ip`: IP address
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```sh
|
||||||
|
curl -v -L http://circuitpython.local/cp/devices.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total": 1,
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"hostname": "cpy-951032",
|
||||||
|
"instance_name": "Adafruit Feather ESP32-S2 TFT",
|
||||||
|
"port": 80,
|
||||||
|
"ip": "192.168.1.235"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `/cp/serial/`
|
||||||
|
|
||||||
|
|
||||||
|
Serves a basic serial terminal program when a `GET` request is received without the
|
||||||
|
`Upgrade: websocket` header. Otherwise the socket is upgraded to a WebSocket. See WebSockets below for more detail.
|
||||||
|
|
||||||
|
This is an authenticated endpoint in both modes.
|
||||||
|
|
||||||
#### `/cp/version.json`
|
#### `/cp/version.json`
|
||||||
|
|
||||||
Returns information about the device.
|
Returns information about the device.
|
||||||
|
@ -323,36 +361,6 @@ curl -v -L http://circuitpython.local/cp/version.json
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `/cp/devices.json`
|
|
||||||
|
|
||||||
Returns information about other devices found on the network using MDNS.
|
|
||||||
|
|
||||||
* `total`: Total MDNS response count. May be more than in `devices` if internal limits were hit.
|
|
||||||
* `devices`: List of discovered devices.
|
|
||||||
* `hostname`: MDNS hostname
|
|
||||||
* `instance_name`: MDNS instance name. Defaults to human readable board name.
|
|
||||||
* `port`: Port of CircuitPython Web API
|
|
||||||
* `ip`: IP address
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```sh
|
|
||||||
curl -v -L http://circuitpython.local/cp/devices.json
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"total": 1,
|
|
||||||
"devices": [
|
|
||||||
{
|
|
||||||
"hostname": "cpy-951032",
|
|
||||||
"instance_name": "Adafruit Feather ESP32-S2 TFT",
|
|
||||||
"port": 80,
|
|
||||||
"ip": "192.168.1.235"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Static files
|
### Static files
|
||||||
|
|
||||||
* `/favicon.ico` - Blinka
|
* `/favicon.ico` - Blinka
|
||||||
|
@ -361,4 +369,12 @@ curl -v -L http://circuitpython.local/cp/devices.json
|
||||||
|
|
||||||
### WebSocket
|
### WebSocket
|
||||||
|
|
||||||
Coming soon!
|
The CircuitPython serial interactions are available over a WebSocket. A WebSocket begins as a
|
||||||
|
special HTTP request that gets upgraded to a WebSocket. Authentication happens before upgrading.
|
||||||
|
|
||||||
|
WebSockets are *not* bare sockets once upgraded. Instead they have their own framing format for data.
|
||||||
|
CircuitPython can handle PING and CLOSE opcodes. All others are treated as TEXT. Data to
|
||||||
|
CircuitPython is expected to be masked UTF-8, as the spec requires. Data from CircuitPython to the
|
||||||
|
client is unmasked. It is also unbuffered so the client will get a variety of frame sizes.
|
||||||
|
|
||||||
|
Only one WebSocket at a time is supported.
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
<head>
|
<head>
|
||||||
<title>CircuitPython</title>
|
<title>CircuitPython</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<script src="/welcome.js" defer=true></script>
|
<script src="/welcome.js" defer=true></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1><a href="/"><img src="/favicon.ico"/></a> Welcome!</h1>
|
<h1><a href="/"><img src="/favicon.ico"/></a> Welcome!</h1>
|
||||||
Welcome to CircuitPython's Web API. Go to the <a href="/fs/">file browser</a> to work with files in the CIRCUITPY drive. Make sure you've set <code>CIRCUITPY_WEB_API_PASSWORD='somepassword'</code> in <code>/.env</code>. Provide the password when the browser prompts for it. Leave the username blank.
|
Welcome to CircuitPython's Web API. Go to the <a href="/fs/">file browser</a> to work with files in the CIRCUITPY drive. Go to the <a href="/cp/serial/">serial terminal</a> to see code output and interact with the REPL. Make sure you've set <code>CIRCUITPY_WEB_API_PASSWORD='somepassword'</code> in <code>/.env</code>. Provide the password when the browser prompts for it. Leave the username blank.
|
||||||
<h2>Device Info</h2>
|
<h2>Device Info</h2>
|
||||||
Board: <a id="board"></a><br>
|
Board: <a id="board"></a><br>
|
||||||
Version: <span id="version"></span><br>
|
Version: <span id="version"></span><br>
|
||||||
|
|
|
@ -1019,14 +1019,13 @@ static bool _reply(socketpool_socket_obj_t *socket, _request *request) {
|
||||||
} else if (strcmp(path, "/version.json") == 0) {
|
} else if (strcmp(path, "/version.json") == 0) {
|
||||||
_reply_with_version_json(socket, request);
|
_reply_with_version_json(socket, request);
|
||||||
} else if (strcmp(path, "/serial/") == 0) {
|
} else if (strcmp(path, "/serial/") == 0) {
|
||||||
if (false && !request->authenticated) {
|
if (!request->authenticated) {
|
||||||
if (_api_password[0] != '\0') {
|
if (_api_password[0] != '\0') {
|
||||||
_reply_unauthorized(socket, request);
|
_reply_unauthorized(socket, request);
|
||||||
} else {
|
} else {
|
||||||
_reply_forbidden(socket, request);
|
_reply_forbidden(socket, request);
|
||||||
}
|
}
|
||||||
} else if (request->websocket) {
|
} else if (request->websocket) {
|
||||||
ESP_LOGI(TAG, "websocket!");
|
|
||||||
_reply_websocket_upgrade(socket, request);
|
_reply_websocket_upgrade(socket, request);
|
||||||
} else {
|
} else {
|
||||||
_REPLY_STATIC(socket, request, serial_html);
|
_REPLY_STATIC(socket, request, serial_html);
|
||||||
|
@ -1059,7 +1058,6 @@ static bool _reply(socketpool_socket_obj_t *socket, _request *request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _reset_request(_request *request) {
|
static void _reset_request(_request *request) {
|
||||||
ESP_LOGI(TAG, "reset request");
|
|
||||||
request->state = STATE_METHOD;
|
request->state = STATE_METHOD;
|
||||||
request->origin[0] = '\0';
|
request->origin[0] = '\0';
|
||||||
request->content_length = 0;
|
request->content_length = 0;
|
||||||
|
|
|
@ -48,7 +48,6 @@ void websocket_init(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void websocket_handoff(socketpool_socket_obj_t *socket) {
|
void websocket_handoff(socketpool_socket_obj_t *socket) {
|
||||||
ESP_LOGI(TAG, "socket handed off");
|
|
||||||
cp_serial.socket = *socket;
|
cp_serial.socket = *socket;
|
||||||
cp_serial.closed = false;
|
cp_serial.closed = false;
|
||||||
cp_serial.opcode = 0;
|
cp_serial.opcode = 0;
|
||||||
|
@ -57,7 +56,6 @@ void websocket_handoff(socketpool_socket_obj_t *socket) {
|
||||||
// Mark the original socket object as closed without telling the lower level.
|
// Mark the original socket object as closed without telling the lower level.
|
||||||
socket->connected = false;
|
socket->connected = false;
|
||||||
socket->num = -1;
|
socket->num = -1;
|
||||||
ESP_LOGI(TAG, "socket hand off done");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool websocket_connected(void) {
|
bool websocket_connected(void) {
|
||||||
|
@ -90,7 +88,6 @@ static void _read_next_frame_header(void) {
|
||||||
if (cp_serial.frame_index == 0 && _read_byte(&h)) {
|
if (cp_serial.frame_index == 0 && _read_byte(&h)) {
|
||||||
cp_serial.frame_index++;
|
cp_serial.frame_index++;
|
||||||
cp_serial.opcode = h & 0xf;
|
cp_serial.opcode = h & 0xf;
|
||||||
ESP_LOGI(TAG, "fin %d opcode %x", h >> 7, cp_serial.opcode);
|
|
||||||
}
|
}
|
||||||
if (cp_serial.frame_index == 1 && _read_byte(&h)) {
|
if (cp_serial.frame_index == 1 && _read_byte(&h)) {
|
||||||
cp_serial.frame_index++;
|
cp_serial.frame_index++;
|
||||||
|
@ -108,8 +105,6 @@ static void _read_next_frame_header(void) {
|
||||||
if (cp_serial.masked) {
|
if (cp_serial.masked) {
|
||||||
cp_serial.frame_len += 4;
|
cp_serial.frame_len += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "mask %d length %x", cp_serial.masked, len);
|
|
||||||
}
|
}
|
||||||
while (cp_serial.frame_index >= 2 &&
|
while (cp_serial.frame_index >= 2 &&
|
||||||
cp_serial.frame_index < (cp_serial.payload_len_size + 2) &&
|
cp_serial.frame_index < (cp_serial.payload_len_size + 2) &&
|
||||||
|
@ -133,7 +128,6 @@ static void _read_next_frame_header(void) {
|
||||||
if (cp_serial.frame_index == cp_serial.frame_len) {
|
if (cp_serial.frame_index == cp_serial.frame_len) {
|
||||||
uint8_t opcode = 0x8; // CLOSE
|
uint8_t opcode = 0x8; // CLOSE
|
||||||
if (cp_serial.opcode == 0x9) {
|
if (cp_serial.opcode == 0x9) {
|
||||||
ESP_LOGI(TAG, "websocket ping");
|
|
||||||
opcode = 0xA; // PONG
|
opcode = 0xA; // PONG
|
||||||
} else {
|
} else {
|
||||||
// Set the TCP socket to send immediately so that we send the payload back before
|
// Set the TCP socket to send immediately so that we send the payload back before
|
||||||
|
@ -160,7 +154,6 @@ static void _read_next_frame_header(void) {
|
||||||
if (cp_serial.payload_remaining == 0) {
|
if (cp_serial.payload_remaining == 0) {
|
||||||
cp_serial.frame_index = 0;
|
cp_serial.frame_index = 0;
|
||||||
if (cp_serial.opcode == 0x8) {
|
if (cp_serial.opcode == 0x8) {
|
||||||
ESP_LOGI(TAG, "websocket closed");
|
|
||||||
cp_serial.closed = true;
|
cp_serial.closed = true;
|
||||||
|
|
||||||
common_hal_socketpool_socket_close(&cp_serial.socket);
|
common_hal_socketpool_socket_close(&cp_serial.socket);
|
||||||
|
@ -199,7 +192,6 @@ bool websocket_available(void) {
|
||||||
char websocket_read_char(void) {
|
char websocket_read_char(void) {
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
_read_next_payload_byte(&c);
|
_read_next_payload_byte(&c);
|
||||||
ESP_LOGI(TAG, "read %c", c);
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +224,6 @@ static void _websocket_send(_websocket *ws, const char *text, size_t len) {
|
||||||
char copy[len];
|
char copy[len];
|
||||||
memcpy(copy, text, len);
|
memcpy(copy, text, len);
|
||||||
copy[len] = '\0';
|
copy[len] = '\0';
|
||||||
ESP_LOGI(TAG, "sent over websocket: %s", copy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void websocket_write(const char *text, size_t len) {
|
void websocket_write(const char *text, size_t len) {
|
||||||
|
|
Loading…
Reference in New Issue