Compare commits

..

1 commit

Author SHA1 Message Date
ee7ce8cac9 stash 2021-07-29 15:00:08 +02:00
23 changed files with 305578 additions and 478 deletions

View file

@ -57,7 +57,6 @@ steps:
base_url: https://git.neulandlabor.de/
files:
- firmware/firmware/fiatlux.bin
- firmware/otaflash.py
- pcb/pcb.zip
checksum:
- sha512

View file

@ -27,7 +27,6 @@ git submodule update --init --recursive
- ncurses-dev libexpat-dev
- python3 python3-serial python-dev
- pip install websocket-client (for otaflash.py, optional)
### Build Steps

BIN
case/case-Body.3mf Normal file

Binary file not shown.

BIN
case/case-Body.stl Normal file

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

BIN
case/case-Top.stl Normal file

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

BIN
case/case.FCStd Normal file

Binary file not shown.

BIN
case/case.FCStd1 Normal file

Binary file not shown.

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.9" />
</facet>
</component>
</module>

View file

@ -2,7 +2,7 @@ PROGRAM=fiatlux
EXTRA_CFLAGS=-O3 -Ifsdata
EXTRA_COMPONENTS=extras/i2s_dma extras/ws2812_i2s extras/dhcpserver extras/rboot-ota extras/mbedtls extras/httpd extras/sntp extras/cpp_support
EXTRA_COMPONENTS=extras/i2s_dma extras/ws2812_i2s extras/dhcpserver extras/mbedtls extras/httpd extras/sntp extras/cpp_support
LIBS = hal m
@ -10,9 +10,7 @@ FLASH_MODE = dio
include ../modules/rtos/common.mk
html: fsdata/fsdata.c
fsdata/fsdata.c: fsdata/fs/index.html fsdata/fs/404.html fsdata/fs/css/picnic.min.css fsdata/fs/css/style.css fsdata/fs/js/smoothie_min.js
html:
@echo "Generating fsdata.."
cd fsdata && ./makefsdata

View file

@ -1,71 +0,0 @@
//
// Created by jedi on 02.08.21.
//
#include "crc32.h"
#define UPDC32(octet, crc) (crc_32_tab[((crc)\
^ ((uint8_t)octet)) & 0xff] ^ ((crc) >> 8))
static uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t updateCRC32(uint8_t ch, uint32_t crc) {
return UPDC32(ch, crc);
}
uint32_t crc32_partial(uint32_t init, uint8_t *buf, uint32_t len) {
register uint32_t oldcrc32;
oldcrc32 = ~init;
for (; len; --len, ++buf) {
oldcrc32 = UPDC32(*buf, oldcrc32);
}
return ~oldcrc32;
}
uint32_t crc32(uint8_t *data, uint32_t len) {
return crc32_partial(0, data, len);
}

View file

@ -1,14 +0,0 @@
//
// Created by jedi on 02.08.21.
//
#ifndef FIRMWARE_CRC32_H
#define FIRMWARE_CRC32_H
#include <stdint.h>
uint32_t crc32_partial(uint32_t init, uint8_t *data, uint32_t len);
uint32_t crc32(uint8_t *data, uint32_t len);
#endif //FIRMWARE_CRC32_H

View file

@ -22,9 +22,9 @@ void user_init(void)
wifi_available_semaphore = xSemaphoreCreateBinary();
xTaskCreate(wifi_task, "wifi_task", 1024, NULL, 1, NULL);
xTaskCreate(wifi_task, "wifi_task", 512, NULL, 2, NULL);
xTaskCreate(&httpd_task, "httpd_task", 1024, NULL, 2, NULL);
xTaskCreate(&httpd_task, "httpd_task", 512, NULL, 2, NULL);
xTaskCreate(&lux_task, "lux_task", 512, NULL, 1, NULL);
}

View file

@ -5,17 +5,28 @@ main {
margin-left: auto;
margin-right: auto;
}
section {
display: none;
}
canvas{
width: 100%;
}
main section:target ~ section, main section#io, main section#wifi, main section#ota {
display: none;
main[data-page="dashboard"] section[id="dashboard"] {
display: block;
}
main section:target{
display: block !important;
main[data-page="ota"] section[id="ota"] {
display: block;
}
main[data-page="wifi"] section[id="wifi"] {
display: block;
}
main[data-page="io"] section[id="io"] {
display: block;
}
.table {

View file

@ -12,52 +12,8 @@
<span>fiatlux v0.2</span>
<span class="label warning" id="status_box">Loading...</span>
</a>
<input id="bmenub" type="checkbox" class="show">
<label for="bmenub" class="burger pseudo button">&#9776;</label>
<div class="menu">
<a href="/#" class="button icon-picture">Dashboard</a>
<a href="/#ota" class="button icon-picture">System</a>
</div>
</nav>
<main id="page">
<section id="ota">
<h2>System</h2>
<article class="card">
<header>
<h3>Firmware Update</h3>
</header>
<div class="table">
<div class="row">
<span><input id="firmware_file" type="file" onchange="load_firmware(event)"/></span>
</div>
<div class="row">
<span><input id="transmit_firmware" disabled type="submit" value="Upload"
onclick="transmit_firmware(event)"></span>
</div>
</div>
</article>
<article class="card">
<header>
<h3>Restart</h3>
</header>
<div class="table">
<div class="row">
<span><input type="submit" value="Restart" onclick="wsWrite('R')"></span>
</div>
</div>
</article>
<article class="card">
<header>
<h3>Reset Config</h3>
</header>
<div class="table">
<div class="row">
<span><input type="submit" class="warning" value="Reset" onclick="wsWrite('X')"></span>
</div>
</div>
</article>
</section>
<main data-page="dashboard" id="page">
<section id="dashboard">
<h2>Status</h2>
<div class="flex">
@ -177,13 +133,13 @@
var unused_values = {};
DataView.prototype.setChar = function (pos, char) {
DataView.prototype.setChar = function(pos, char) {
this.setInt8(pos++, char.charCodeAt(0));
return pos;
};
DataView.prototype.setString = function (pos, str) {
for (var i = 0; i < str.length; i++) {
DataView.prototype.setString = function(pos, str) {
for(var i = 0; i < str.length; i++) {
this.setInt8(pos++, str.charCodeAt(i));
}
this.setInt8(pos++, 0);
@ -213,9 +169,6 @@
chart.streamTo(canvas, 500);
}
var receive_chunk_confirmation = () => {
};
function onMessage(evt) {
retries = 0;
if (typeof evt.data == 'string') {
@ -237,9 +190,7 @@
if (cmd === 'G')
console.log("LED switched", val);
else if (cmd === 'F') {
receive_chunk_confirmation(dv);
} else if (cmd === 'V') {
else if (cmd === 'V') {
voltage.innerHTML = (val * 13 / 1024).toFixed(2);
series.append(new Date().getTime(), val);
} else
@ -276,7 +227,7 @@
}
function wsWrite(data) {
//console.info(buf2hex(data));
console.info(buf2hex(data));
if (ws.readyState === 3 || retries++ > 5)
wsOpen();
else if (ws.readyState === 1)
@ -295,105 +246,6 @@
startPolling();
}
var makeCRCTable = function () {
var c;
var crcTable = [];
for (var n = 0; n < 256; n++) {
c = n;
for (var k = 0; k < 8; k++) {
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
}
crcTable[n] = c;
}
return crcTable;
}
var crc32 = function (buf) {
const bufview = new DataView(buf);
var crcTable = window.crcTable || (window.crcTable = makeCRCTable());
var crc = 0 ^ (-1);
for (var i = 0; i < bufview.byteLength; i++) {
crc = (crc >>> 8) ^ crcTable[(crc ^ bufview.getInt8(i)) & 0xFF];
}
return (crc ^ (-1)) >>> 0;
};
var firmware_file;
function load_firmware(evt) {
var file = evt.target.files[0];
if (!file) {
return;
}
var reader = new FileReader();
reader.onload = function (e) {
firmware_file = e.target.result;
document.getElementById("transmit_firmware").disabled = false;
};
reader.readAsArrayBuffer(file)
}
const chunk_size = 512;
function transmit_firmware_chunk(buf, i) {
return new Promise((resolve, reject) => {
const begin = i * chunk_size;
const end = Math.min((i + 1) * chunk_size, buf.byteLength);
const slice = buf.slice(begin, end)
var header = new ArrayBuffer(12);
var headerview = new DataView(header);
headerview.setChar(0, 'F');
headerview.setInt16(4, i);
headerview.setInt16(6, (end - begin));
headerview.setInt32(8, crc32(slice));
var frame = new Uint8Array(12 + slice.byteLength);
frame.set(new Uint8Array(header), 0);
frame.set(new Uint8Array(slice), 12);
receive_chunk_confirmation = (dv) => {
setTimeout(() => {
resolve(i);
}, 50);
}
setTimeout(() => {
reject(i);
}, 2000);
wsWrite(frame.buffer);
});
}
function transmit_firmware_final(buf, hash) {
return new Promise((resolve, reject) => {
var frame = new ArrayBuffer(12);
var headerview = new DataView(frame);
headerview.setChar(0, 'C');
headerview.setInt32(4, buf.byteLength);
headerview.setInt32(8, hash);
receive_chunk_confirmation = (dv) => {
resolve(i);
}
setTimeout(() => {
reject(i);
}, 500);
wsWrite(frame);
});
}
function transmit_firmware(evt) {
console.log("transmit_firmware begin");
if (firmware_file) {
(async () => {
const ash = crc32(firmware_file);
for (var i = 0; i * chunk_size < firmware_file.byteLength; i++) {
await transmit_firmware_chunk(firmware_file, i);
}
await transmit_firmware_final(firmware_file, crc32(firmware_file));
})().then(() => {
console.log("transmit_firmware done");
})
}
}
</script>
</body>
</html>

View file

@ -1,44 +0,0 @@
#!/usr/bin/env python3
import time
import websocket
import argparse
import zlib
parser = argparse.ArgumentParser(description='Update fiatlux firmware via websocket.')
parser.add_argument("binfile")
args = parser.parse_args()
with open(args.binfile, "rb") as f:
try:
ws = websocket.WebSocket()
ws.connect("ws://172.16.0.1")
i = 0
rolling = 0
total = 0
while True:
bytes = f.read(512)
rolling = zlib.crc32(bytes, rolling)
total += len(bytes)
msg = b'F\x00\x00\x00'
msg += i.to_bytes(2, 'big')
msg += len(bytes).to_bytes(2, 'big')
msg += (zlib.crc32(bytes) & 0xffffffff).to_bytes(4, 'big')
msg += bytes
ws.send(msg)
reply = ws.recv()
time.sleep(0.05)
i += 1
if len(bytes) != 512:
break
msg = b'C\x00\x00\x00'
msg += total.to_bytes(4, 'big')
msg += rolling.to_bytes(4, 'big')
ws.send(msg)
print(ws.recv())
ws.close()
except ConnectionResetError:
pass
except KeyboardInterrupt:
pass

View file

@ -3,114 +3,35 @@
//
#include "system.h"
#include "crc32.h"
#include <FreeRTOS.h>
#include <task.h>
#include <sysparam.h>
#include <spiflash.h>
#include <espressif/esp_common.h>
#include <espressif/user_interface.h>
#include <espressif/esp_system.h>
#include <rboot/rboot.h>
#include <rboot-ota/rboot-api.h>
#include <string.h>
#define min(a, b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
void system_clear_config() {
void system_clear_config(){
vPortEnterCritical();
uint32_t num_sectors = 0x2000 / sdk_flashchip.sector_size;
uint32_t start = 0x00100000;
uint32_t num_sectors = 5 + DEFAULT_SYSPARAM_SECTORS;
uint32_t start = sdk_flashchip.chip_size - num_sectors * sdk_flashchip.sector_size;
for (uint32_t i = 0; i < num_sectors; i++) {
spiflash_erase_sector(start + i * sdk_flashchip.sector_size);
}
if(sysparam_create_area(start, num_sectors, true) == SYSPARAM_OK) {
sysparam_init(start, 0);
}
sysparam_init(start, start + 0x2000);
sdk_system_restart();
}
void system_init_config() {
uint32_t base_addr = 0x00100000;
void system_init_config(){
uint32_t base_addr;
uint32_t num_sectors;
sysparam_init(base_addr, 0);
if(sysparam_get_info(&base_addr, &num_sectors) != SYSPARAM_OK) {
printf("Warning: WiFi config, sysparam not initialized\n");
num_sectors = 0x2000 / sdk_flashchip.sector_size;
num_sectors = DEFAULT_SYSPARAM_SECTORS;
base_addr = sdk_flashchip.chip_size - (5 + num_sectors) * sdk_flashchip.sector_size;
if(sysparam_create_area(base_addr, num_sectors, true) == SYSPARAM_OK) {
sysparam_init(base_addr, 0);
}
sdk_system_restart();
}
}
#define MAX_IMAGE_SIZE 0x100000
struct {
rboot_write_status status;
uint32_t head;
uint32_t base;
uint16_t seq;
uint8_t slot;
} otaflash_context;
void system_otaflash_init() {
rboot_config conf;
conf = rboot_get_config();
otaflash_context.slot = (conf.current_rom + 1) % conf.count;
otaflash_context.base = rboot_get_slot_offset(otaflash_context.slot);
otaflash_context.status = rboot_write_init(otaflash_context.base);
otaflash_context.head = otaflash_context.base;
otaflash_context.seq = 0;
}
int system_otaflash_chunk(uint8_t *data, uint16_t len, uint16_t seq, uint32_t hash) {
uint32_t local_hash = crc32(data, len);
if(hash == local_hash && otaflash_context.seq == seq) {
if(otaflash_context.head % SECTOR_SIZE == 0) {
sdk_spi_flash_erase_sector(otaflash_context.head / SECTOR_SIZE);
}
if(((uint32_t) data) % 4) {
uint32 buf[len / 4];
memcpy(buf, data, len);
sdk_spi_flash_write(otaflash_context.head, buf, len);
} else {
sdk_spi_flash_write(otaflash_context.head, (uint32_t *) data, len);
}
otaflash_context.head += len;
otaflash_context.seq++;
return 0x88;
} else {
return 0xff;
}
}
void system_otaflash_verify_chunk(void *ctx, void *data, size_t len) {
uint32_t digest = *(uint32_t *) ctx;
digest = crc32_partial(digest, data, len);
*(uint32_t *) ctx = digest;
}
int system_otaflash_verify_and_switch(uint32_t len, uint32_t hash) {
uint32_t digest = 0;
rboot_digest_image(otaflash_context.base, min(len, MAX_IMAGE_SIZE), system_otaflash_verify_chunk, &digest);
if(hash != digest) {
printf("OTA failed to verify firmware\r\n");
return 0x99;
}
vPortEnterCritical();
if(!rboot_set_current_rom(otaflash_context.slot)) {
printf("OTA failed to set new rboot slot\r\n");
}
sdk_system_restart();
vPortExitCritical(); // | should not be reached
return 0x77; // |
}

View file

@ -5,22 +5,13 @@
#ifndef FIRMWARE_SYSTEM_H
#define FIRMWARE_SYSTEM_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void system_clear_config();
void system_init_config();
void system_otaflash_init();
int system_otaflash_chunk(uint8_t *data, uint16_t len, uint16_t seq, uint32_t hash);
int system_otaflash_verify_and_switch(uint32_t len, uint32_t hash);
#ifdef __cplusplus
}
#endif

View file

@ -38,7 +38,7 @@ void websocket_task(void *pvParameter) {
has_changed = {true, true, true};
for (;;) {
if(pcb == nullptr || pcb->state != ESTABLISHED) {
if(pcb == NULL || pcb->state != ESTABLISHED) {
printf("Connection closed, deleting task\n");
break;
}
@ -46,14 +46,14 @@ void websocket_task(void *pvParameter) {
//Global Info
if(has_changed.global) {
has_changed.global = false;
timeval tv{};
gettimeofday(&tv, nullptr);
size_t uptime = xTaskGetTickCount() * portTICK_PERIOD_MS / 1000;
timeval tv;
gettimeofday(&tv, NULL);
int uptime = xTaskGetTickCount() * portTICK_PERIOD_MS / 1000;
int heap = (int) xPortGetFreeHeapSize();
uint32_t chip_id = sdk_system_get_chip_id();
uint32_t flash_id = sdk_spi_flash_get_id();
uint32_t flash_size = sdk_flashchip.chip_size >> 10;
char *hostname = nullptr;
char *hostname = NULL;
sysparam_get_string("hostname", &hostname);
/* Generate response in JSON format */
@ -80,16 +80,21 @@ void websocket_task(void *pvParameter) {
//Connection Info
if(has_changed.connection) {
has_changed.connection = false;
timeval tv{};
gettimeofday(&tv, nullptr);
size_t connuptime = (xTaskGetTickCount() - connstarttime) * portTICK_PERIOD_MS / 1000;
timeval tv;
gettimeofday(&tv, NULL);
int connuptime = (xTaskGetTickCount() - connstarttime) * portTICK_PERIOD_MS / 1000;
printf("conn %d: " IPSTR " <-> " IPSTR " \n", pcb->netif_idx, IP2STR(&pcb->local_ip),
IP2STR(&pcb->remote_ip));
printf("conn %d: "
IPSTR
" <-> "
IPSTR
" \n", pcb->netif_idx, IP2STR(&pcb->local_ip), IP2STR(&pcb->remote_ip));
char response[160];
size_t len = snprintf(response, sizeof(response),
"{\"connage\" : \"%d\","
"\"clientip\" : \"" IPSTR "\""
"\"clientip\" : \""
IPSTR
"\""
"}", connuptime, IP2STR(&pcb->remote_ip));
if(len < sizeof(response)) {
LOCK_TCPIP_CORE();
@ -132,10 +137,10 @@ void websocket_task(void *pvParameter) {
if(opmode == SOFTAP_MODE || opmode == STATIONAP_MODE) {
uint8_t hwaddr[6];
sdk_wifi_get_macaddr(SOFTAP_IF, hwaddr);
ip_info info{};
ip_info info;
sdk_wifi_get_ip_info(SOFTAP_IF, &info);
char *apssid = nullptr;
char *apssid = NULL;
sysparam_get_string("wifi_ap_ssid", &apssid);
/* Generate response in JSON format */
@ -143,8 +148,12 @@ void websocket_task(void *pvParameter) {
size_t len = snprintf(response, sizeof(response),
"{\"opmode\" : \"%s\","
" \"apssid\" : \"%s\","
" \"apip\" : \"" IPSTR "\","
" \"apmac\" : \"" MACSTR "\""
" \"apip\" : \""
IPSTR
"\","
" \"apmac\" : \""
MACSTR
"\""
"}", opmode_str, apssid, IP2STR(&info.ip), MAC2STR(hwaddr));
free(apssid);
if(len < sizeof(response)) {
@ -160,7 +169,7 @@ void websocket_task(void *pvParameter) {
if(opmode == STATION_MODE || opmode == STATIONAP_MODE) {
uint8_t hwaddr[6];
sdk_wifi_get_macaddr(STATION_IF, hwaddr);
ip_info info{};
ip_info info;
sdk_wifi_get_ip_info(STATION_IF, &info);
char *stassid = nullptr;
sysparam_get_string("wifi_sta_ssid", &stassid);
@ -170,8 +179,12 @@ void websocket_task(void *pvParameter) {
size_t len = snprintf(response, sizeof(response),
"{\"opmode\" : \"%s\","
" \"stassid\" : \"%s\","
" \"staip\" : \"" IPSTR "\","
" \"stamac\" : \"" MACSTR "\""
" \"staip\" : \""
IPSTR
"\","
" \"stamac\" : \""
MACSTR
"\""
"}", opmode_str, stassid, IP2STR(&info.ip), MAC2STR(hwaddr));
free(stassid);
if(len < sizeof(response)) {
@ -185,49 +198,34 @@ void websocket_task(void *pvParameter) {
}
vTaskDelayMs(500);
{
uint8_t response[3];
uint16_t val = 0;
val = sdk_system_adc_read();
response[2] = (uint8_t) val;
response[1] = val >> 8;
response[0] = 'V';
websocket_write(pcb, response, 3, WS_BIN_MODE);
}
vTaskDelayMs(500);
}
vTaskDelete(nullptr);
vTaskDelete(NULL);
}
struct fw_frame {
char t;
uint8_t reserved[3];
uint16_t seq;
uint16_t len;
uint32_t hash;
uint8_t data[];
} __attribute__((packed));
struct fw_check {
char t;
uint8_t reserved[3];
uint32_t len;
uint32_t hash;
} __attribute__((packed));
/**
* This function is called when websocket frame is received.
*
* Note: this function is executed on TCP thread and should return as soon
* as possible.
*/
void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len,
uint8_t /*mode*/) { //mode should be WS_BIN_MODE or WS_TEXT_MODE
void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len, uint8_t mode) {
uint8_t response[3];
uint16_t val = 0;
char cmd = '0';
bool togl = 0;
switch (data[0]) {
case 'R': // Restart
cmd = 'R';
break;
case 'X': // Clear Config
cmd = 'X';
break;
case 'D': // Disable LED
signal_led(false);
val = 1;
@ -238,29 +236,9 @@ void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len,
val = 0;
cmd = 'G';
break;
case 'F':
togl = ~togl;
signal_led(togl);
{
auto *f = (fw_frame *) data;
if(f->seq == 0) {
system_otaflash_init();
}
val = system_otaflash_chunk(f->data, ntohs(f->len), ntohs(f->seq), ntohl(f->hash));
}
cmd = 'F';
break;
case 'C':
signal_led(false);
{
auto *f = (fw_check *) data;
val = system_otaflash_verify_and_switch(ntohl(f->len), ntohl(f->hash));
}
cmd = 'C';
break;
default:
printf("[websocket_callback]:\n%.*s\n", (int) data_len, (char *) data);
printf("Unknown command %c\n", data[0]);
printf("Unknown command\n");
val = 0;
break;
}
@ -269,18 +247,7 @@ void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len,
response[1] = val >> 8;
response[0] = cmd;
LOCK_TCPIP_CORE();
websocket_write(pcb, response, 3, WS_BIN_MODE);
UNLOCK_TCPIP_CORE();
if(data[0] == 'R') { // Restart
vTaskDelay(500 / portTICK_PERIOD_MS);
vPortEnterCritical();
sdk_system_restart();
} else if(data[0] == 'X') { // Clear Config
vTaskDelay(500 / portTICK_PERIOD_MS);
system_clear_config();
}
}
/**
@ -295,10 +262,10 @@ void websocket_open_cb(struct tcp_pcb *pcb, const char *uri) {
}
extern "C" void httpd_task(void *pvParameters) {
(void) pvParameters;
while (!uxSemaphoreGetCount(wifi_available_semaphore))
vTaskDelay(500 / portTICK_PERIOD_MS);
websocket_register_callbacks((tWsOpenHandler) websocket_open_cb, (tWsHandler) websocket_cb);
httpd_init();