From 6e80d1141d471b8dfa97cef589f0296fbe8b98b3 Mon Sep 17 00:00:00 2001 From: ollo Date: Sun, 30 Dec 2018 19:10:14 +0100 Subject: [PATCH 001/204] Files needed, for initial flashing procedure --- os/blank.bin | 1 + os/esp_init_data_default.bin | Bin 0 -> 128 bytes os/flash.sh | 3 +-- 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 os/blank.bin create mode 100644 os/esp_init_data_default.bin diff --git a/os/blank.bin b/os/blank.bin new file mode 100644 index 0000000..7de9e36 --- /dev/null +++ b/os/blank.bin @@ -0,0 +1 @@ +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file diff --git a/os/esp_init_data_default.bin b/os/esp_init_data_default.bin new file mode 100644 index 0000000000000000000000000000000000000000..3db53ccbad9f34989570ff13679c3e4778f04713 GIT binary patch literal 128 zcmZQ&U}0iqWo2SzU}0qip?`n>fB5j>!Gi}6x&HtE!SLfpke`=}g9QTvBO? Date: Fri, 19 Apr 2019 21:49:27 +0200 Subject: [PATCH 002/204] set an default color if not already set --- webserver.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/webserver.lua b/webserver.lua index 70bcbf8..9ffba93 100644 --- a/webserver.lua +++ b/webserver.lua @@ -65,8 +65,10 @@ function sendPage(conn, nameOfFile, replaceMap) --reset amount of sent bytes, as we reached the end sentBytes=0 -- send the rest - conn:send(buf) - print("Sent rest") + if (string.len(buf) > 0) then + conn:send(buf) + print("Sent rest") + end end end @@ -153,6 +155,9 @@ function startWebServer() if (payload:find("GET /") ~= nil) then httpSending=true stopWordclock() + if (color == nil) then + color=string.char(0,128,0) + end ws2812.write(string.char(0,0,0):rep(56) .. color:rep(2) .. string.char(0,0,0):rep(4) .. color:rep(2) .. string.char(0,0,0):rep(48)) -- Start Time after 3 minute tmr.alarm(5, 180000, 0 ,function() From 32106035c245ba9c70bf4dc90ba5f254c744445b Mon Sep 17 00:00:00 2001 From: ollo Date: Fri, 10 May 2019 22:58:42 +0200 Subject: [PATCH 003/204] Refactoring line generation --- displayword.lua | 170 +++++++++++++++++++++++++++--------------------- 1 file changed, 96 insertions(+), 74 deletions(-) diff --git a/displayword.lua b/displayword.lua index c1358e7..eedf0e9 100644 --- a/displayword.lua +++ b/displayword.lua @@ -6,10 +6,7 @@ local updateColor = function (data, inverseRow) return data.colorFg end -local drawLEDs = function(data, numberNewChars, inverseRow) - if (inverseRow == nil) then - inverseRow=false - end +local drawLEDs = function(data, numberNewChars) if (numberNewChars == nil) then numberNewChars=0 end @@ -87,7 +84,7 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color -- Set the foreground color as the default color local buf=colorFg - + local line=space -- line 1---------------------------------------------- if (words.it==1) then buf=drawLEDs(data,2) -- ES @@ -109,120 +106,145 @@ if (words.fiveMin== 1) then buf= buf .. space:rep(4) end -- line 2-- even row (so inverted) -------------------- - if (words.twenty == 1) then - buf= buf .. drawLEDs(data,7,true) -- ZWANZIG - else - buf= buf .. space:rep(7) - end if (words.tenMin == 1) then - buf= buf .. drawLEDs(data,4,true) -- ZEHN + line= drawLEDs(data,4) -- ZEHN else - buf= buf .. space:rep(4) + line= space:rep(4) end + if (words.twenty == 1) then + line= line .. drawLEDs(data,7) -- ZWANZIG + else + line= line .. space:rep(7) + end + -- fill, the buffer + for i = 0,10 do + buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + end + -- line3---------------------------------------------- if (words.threequater == 1) then - buf= buf .. drawLEDs(data,11) -- Dreiviertel + line= drawLEDs(data,11) -- Dreiviertel elseif (words.quater == 1) then - buf= buf .. space:rep(4) - buf= buf .. drawLEDs(data,7) -- VIERTEL + line= space:rep(4) + line= line .. drawLEDs(data,7) -- VIERTEL else - buf= buf .. space:rep(11) + line= space:rep(11) end + -- fill, the buffer + buf = buf .. line --line 4-------- even row (so inverted) ------------- - if (words.before == 1) then - buf=buf .. space:rep(2) - buf= buf .. drawLEDs(data,3,true) -- VOR - else - buf= buf .. space:rep(5) - end if (words.after == 1) then - buf= buf .. drawLEDs(data,4,true) -- NACH - buf= buf .. space:rep(2) -- TG + line= line .. space:rep(2) -- TG + line= drawLEDs(data,4) -- NACH else - buf= buf .. space:rep(6) + line= space:rep(6) + end + if (words.before == 1) then + line= line .. drawLEDs(data,3) -- VOR + line= line .. space:rep(2) + else + line= line .. space:rep(5) + end + for i = 0,10 do + buf = buf .. line:sub((11-i)*3-2,(11-i)*3) end ------------------------------------------------ if (words.half == 1) then - buf= buf .. drawLEDs(data,4) -- HALB - buf= buf .. space:rep(1) -- X + line= drawLEDs(data,4) -- HALB + line= line .. space:rep(1) -- X else - buf= buf .. space:rep(5) + line= space:rep(5) end if (words.twelve == 1) then - buf= buf .. drawLEDs(data,5) -- ZWOELF - buf= buf .. space:rep(1) -- P + line= line .. drawLEDs(data,5) -- ZWOELF + line= line .. space:rep(1) -- P else - buf= buf .. space:rep(6) + line= line .. space:rep(6) end + buf=buf .. line ------------even row (so inverted) --------------------- if (words.seven == 1) then - buf= buf .. drawLEDs(data,6,true) -- SIEBEN - buf= buf .. space:rep(5) + line= space:rep(5) + line= line .. drawLEDs(data,6) -- SIEBEN elseif (words.oneLong == 1) then - buf= buf .. space:rep(5) - buf= buf .. drawLEDs(data,4,true) -- EINS - buf= buf .. space:rep(2) + line= space:rep(2) + line= line .. drawLEDs(data,4) -- EINS + line= line .. space:rep(5) elseif (words.one == 1) then - buf= buf .. space:rep(6) - buf= buf .. drawLEDs(data,3,true) -- EIN - buf= buf .. space:rep(2) + line= space:rep(2) + line= line .. drawLEDs(data,3) -- EIN + line= line .. space:rep(6) elseif (words.two == 1) then - buf= buf .. space:rep(7) - buf= buf .. drawLEDs(data,4,true) -- ZWEI + line= drawLEDs(data,4) -- ZWEI + line= line .. space:rep(7) else - buf= buf .. space:rep(11) + line= space:rep(11) + end + + for i = 0,10 do + buf = buf .. line:sub((11-i)*3-2,(11-i)*3) end ------------------------------------------------ if (words.three == 1) then - buf= buf .. space:rep(1) - buf= buf .. drawLEDs(data,4) -- DREI - buf= buf .. space:rep(6) - elseif (words.five == 1) then - buf= buf .. space:rep(7) - buf= buf .. drawLEDs(data,4) -- FUENF + line= space:rep(1) + line= line .. drawLEDs(data,4) -- DREI + line= line .. space:rep(6) + elseif (words.five == 1) then + line= space:rep(7) + line= line .. drawLEDs(data,4) -- FUENF else - buf= buf .. space:rep(11) + line= space:rep(11) end + buf = buf .. line ------------even row (so inverted) --------------------- if (words.four == 1) then - buf= buf .. drawLEDs(data,4,true) -- VIER - buf= buf .. space:rep(7) + line= space:rep(7) + line= line .. drawLEDs(data,4) -- VIER elseif (words.nine == 1) then - buf= buf .. space:rep(4) - buf= buf .. drawLEDs(data,4,true) -- NEUN - buf= buf .. space:rep(3) + line= space:rep(3) + line= line .. drawLEDs(data,4) -- NEUN + line= line .. space:rep(4) elseif (words.eleven == 1) then - buf= buf .. space:rep(8) - buf= buf .. drawLEDs(data,3,true) -- ELEVEN + line= drawLEDs(data,3) -- ELEVEN + line= line .. space:rep(8) else - buf= buf .. space:rep(11) + line= space:rep(11) + end + + for i = 0,10 do + buf = buf .. line:sub((11-i)*3-2,(11-i)*3) end ------------------------------------------------ if (words.eight == 1) then - buf= buf .. space:rep(1) - buf= buf .. drawLEDs(data,4) -- ACHT - buf= buf .. space:rep(6) + line= space:rep(1) + line= line .. drawLEDs(data,4) -- ACHT + line= line .. space:rep(6) elseif (words.ten == 1) then - buf= buf .. space:rep(5) - buf= buf .. drawLEDs(data,4) -- ZEHN - buf= buf .. space:rep(2) + line= space:rep(5) + line= line .. drawLEDs(data,4) -- ZEHN + line= line .. space:rep(2) else - buf= buf .. space:rep(11) + line= space:rep(11) end + buf = buf .. line ------------even row (so inverted) --------------------- - if (words.clock == 1) then - buf= buf .. drawLEDs(data,3,true) -- UHR - else - buf= buf .. space:rep(3) - end if (words.six == 1) then - buf= buf .. space:rep(2) - buf= buf .. drawLEDs(data,5,true) -- SECHS - buf= buf .. space:rep(1) + line= space:rep(1) + line= line .. drawLEDs(data,5) -- SECHS + line= line .. space:rep(2) else - buf= buf .. space:rep(8) + line= space:rep(8) end - + if (words.clock == 1) then + line= line .. drawLEDs(data,3) -- UHR + else + line= line .. space:rep(3) + end + + for i = 0,10 do + buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + end +------ Minutes ----------- if (words.min1 == 1) then buf= buf .. colorFg else From a81cf8f31da6a56851e1675008cd6623a912f7b3 Mon Sep 17 00:00:00 2001 From: ollo Date: Fri, 10 May 2019 23:42:20 +0200 Subject: [PATCH 004/204] new algorithom works --- displayword.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/displayword.lua b/displayword.lua index eedf0e9..d03cd0d 100644 --- a/displayword.lua +++ b/displayword.lua @@ -1,7 +1,7 @@ -- Module filling a buffer, sent to the LEDs local M do -local updateColor = function (data, inverseRow) +local updateColor = function (data) --FIXME magic missing to start on the left side return data.colorFg end @@ -13,9 +13,9 @@ local drawLEDs = function(data, numberNewChars) local tmpBuf=nil for i=1,numberNewChars do if (tmpBuf == nil) then - tmpBuf = updateColor(data, inverseRow) + tmpBuf = updateColor(data) else - tmpBuf=tmpBuf .. updateColor(data, inverseRow) + tmpBuf=tmpBuf .. updateColor(data) end data.drawnCharacters=data.drawnCharacters+1 end @@ -134,8 +134,8 @@ if (words.fiveMin== 1) then buf = buf .. line --line 4-------- even row (so inverted) ------------- if (words.after == 1) then - line= line .. space:rep(2) -- TG - line= drawLEDs(data,4) -- NACH + line= space:rep(2) -- TG + line= line .. drawLEDs(data,4) -- NACH else line= space:rep(6) end From e68ab9f715846a5c38e361ffb7733a9aef8ba847 Mon Sep 17 00:00:00 2001 From: ollo Date: Sat, 11 May 2019 12:09:44 +0200 Subject: [PATCH 005/204] Display amount of used characers --- displayword.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/displayword.lua b/displayword.lua index d03cd0d..2ec301b 100644 --- a/displayword.lua +++ b/displayword.lua @@ -40,8 +40,6 @@ local data={} -- Module displaying of the words local generateLEDs = function(words, colorForground, colorMin1, colorMin2, colorMin3, colorMin4) -- Set the local variables needed for the colored progress bar - data={} - if (words == nil) then return nil end @@ -73,9 +71,7 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color data.colorMin3=colorMin3 data.colorMin4=colorMin4 end - data.words=words data.drawnCharacters=0 - data.drawnWords=0 local charsPerLine=11 -- Space / background has no color by default local space=string.char(0,0,0) From 26b16a1e3f35138415e6832f67050469316badd8 Mon Sep 17 00:00:00 2001 From: ollo Date: Sat, 11 May 2019 12:16:16 +0200 Subject: [PATCH 006/204] Fixed minute bug --- displayword.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/displayword.lua b/displayword.lua index 2ec301b..f1436f3 100644 --- a/displayword.lua +++ b/displayword.lua @@ -44,7 +44,7 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color return nil end - local minutes=1 + local minutes=0 if (words.min1 == 1) then minutes = minutes + 1 elseif (words.min2 == 1) then From a7f566f7061d061fd75db5b945dc34a1babda991 Mon Sep 17 00:00:00 2001 From: ollo Date: Sat, 11 May 2019 12:28:23 +0200 Subject: [PATCH 007/204] Refactored swapping of line 4,5 and 6 --- displayword.lua | 33 ++++++++++++++++++++++++++------- main.lua | 30 +++++++++++++++--------------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/displayword.lua b/displayword.lua index f1436f3..b5f02f9 100644 --- a/displayword.lua +++ b/displayword.lua @@ -38,11 +38,17 @@ end local data={} -- Module displaying of the words -local generateLEDs = function(words, colorForground, colorMin1, colorMin2, colorMin3, colorMin4) +local generateLEDs = function(words, colorForground, colorMin1, colorMin2, colorMin3, colorMin4, invertRows) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil end + if (invertRows == nil) then + invertRows=false + end + + -- DEBUG code, to determine, if the color argmuments are necessary or not + print(tostring(color) .. " " .. tostring(color1)) local minutes=0 if (words.min1 == 1) then @@ -141,8 +147,12 @@ if (words.fiveMin== 1) then else line= line .. space:rep(5) end - for i = 0,10 do - buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + if (invertRows == true) then + buf = buf .. line + else + for i = 0,10 do + buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + end end ------------------------------------------------ if (words.half == 1) then @@ -157,7 +167,13 @@ if (words.fiveMin== 1) then else line= line .. space:rep(6) end - buf=buf .. line + if (invertRows == true) then + for i = 0,10 do + buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + end + else + buf=buf .. line + end ------------even row (so inverted) --------------------- if (words.seven == 1) then line= space:rep(5) @@ -176,9 +192,12 @@ if (words.fiveMin== 1) then else line= space:rep(11) end - - for i = 0,10 do - buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + if (invertRows == true) then + buf = buf .. line + else + for i = 0,10 do + buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + end end ------------------------------------------------ if (words.three == 1) then diff --git a/main.lua b/main.lua index 29fc813..ca40d99 100644 --- a/main.lua +++ b/main.lua @@ -58,26 +58,26 @@ function displayTime() end dofile("displayword.lc") if (displayword ~= nil) then - ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4) + --if lines 4 to 6 are inverted due to hardware-fuckup, unfuck it here + local invertRows=false + if ((inv46 ~= nil) and (inv46 == "on")) then + invertRows=true + end + ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows) print("Local time : " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. " char: " .. tostring(displayword.data.drawnCharacters)) end displayword = nil if (ledBuf ~= nil) then - --if lines 4 to 6 are inverted due to hardware-fuckup, unfuck it here - if ((inv46 ~= nil) and (inv46 == "on")) then - tempstring = ledBuf:sub(1,99) -- first 33 leds - rowend = {44,55,66} - for _, startled in ipairs(rowend) do - for i = 0,10 do - tempstring = tempstring .. ledBuf:sub((startled-i)*3-2,(startled-i)*3) - end - end - tempstring = tempstring .. ledBuf:sub((67*3)-2,ledBuf:len()) - ws2812.write(tempstring) - tempstring=nil + ws2812.write(ledBuf) else - ws2812.write(ledBuf) - ledBuf=nil + if ((colorBg ~= nil) and (color ~= nil)) then + ws2812.write(colorBg:rep(107) .. color:rep(3)) + else + local space=string.char(0,0,0) + -- set FG to fix value: + colorFg = string.char(255,0,0) + ws2812.write(space:rep(107) .. colorFg:rep(3)) + end end end -- Used for debugging From 70602f1095e19aa04edb51beefa3de48ec87bf85 Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 15 May 2019 20:15:43 +0200 Subject: [PATCH 008/204] Fixed syntax --- main.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/main.lua b/main.lua index ca40d99..002bfa0 100644 --- a/main.lua +++ b/main.lua @@ -78,7 +78,6 @@ function displayTime() colorFg = string.char(255,0,0) ws2812.write(space:rep(107) .. colorFg:rep(3)) end - end end -- Used for debugging if (clockdebug ~= nil) then From 401c4fd293fc1d0270dc93f1808f21528cf95918 Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 15 May 2019 20:17:48 +0200 Subject: [PATCH 009/204] Removed debugging for dofile from the simulation --- simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java b/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java index c9e6250..0d3d741 100644 --- a/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java +++ b/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java @@ -26,8 +26,6 @@ public class DoFileFunction extends OneArgFunction { public LuaValue call(LuaValue luaFilename) { String filename = luaFilename.checkjstring(); - System.out.println("[Nodemcu] dofile " + filename); - File f = new File(workingDir.getAbsolutePath() + File.separator + filename); if (f.exists()) { From e7d0ce1c43d6443754fd8c1e4a103a643a1da24d Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 15 May 2019 20:40:41 +0200 Subject: [PATCH 010/204] Refactored color --- displayword.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/displayword.lua b/displayword.lua index b5f02f9..0a9ed63 100644 --- a/displayword.lua +++ b/displayword.lua @@ -60,18 +60,25 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color elseif (words.min4 == 1) then minutes = minutes + 4 end + -- always set a foreground value + local colorFg = string.char(255,255,255) + + if (colorForground ~= nil) then + colorFg = colorForground + end + if ( (adc ~= nil) and (words.briPercent ~= nil) ) then local per = math.floor(100*adc.read(0)/1000) words.briPercent = tonumber( ((words.briPercent * 4) + per) / 5) print("Minutes : " .. tostring(minutes) .. " bright: " .. tostring(words.briPercent) .. "% current: " .. tostring(per) .. "%") - data.colorFg = string.char(string.byte(colorForground,1) * briPercent / 100, string.byte(colorForground,2) * briPercent / 100, string.byte(colorForground,3) * briPercent / 100) + data.colorFg = string.char(string.byte(colorFg,1) * briPercent / 100, string.byte(colorFg,2) * briPercent / 100, string.byte(colorFg,3) * briPercent / 100) data.colorMin1 = string.char(string.byte(colorMin1,1) * briPercent / 100, string.byte(colorMin1,2) * briPercent / 100, string.byte(colorMin1,3) * briPercent / 100) data.colorMin2 = string.char(string.byte(colorMin2,1) * briPercent / 100, string.byte(colorMin2,2) * briPercent / 100, string.byte(colorMin2,3) * briPercent / 100) data.colorMin3 = string.char(string.byte(colorMin3,1) * briPercent / 100, string.byte(colorMin3,2) * briPercent / 100, string.byte(colorMin3,3) * briPercent / 100) data.colorMin4 = string.char(string.byte(colorMin4,1) * briPercent / 100, string.byte(colorMin4,2) * briPercent / 100, string.byte(colorMin4,3) * briPercent / 100) else -- devide by five (Minute 0, Minute 1 to Minute 4 takes the last chars) - data.colorFg=colorForground + data.colorFg=colorFg data.colorMin1=colorMin1 data.colorMin2=colorMin2 data.colorMin3=colorMin3 @@ -81,11 +88,9 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color local charsPerLine=11 -- Space / background has no color by default local space=string.char(0,0,0) - -- set FG to fix value: - colorFg = string.char(255,255,255) -- Set the foreground color as the default color - local buf=colorFg + local buf=data.colorFg local line=space -- line 1---------------------------------------------- if (words.it==1) then From 7bc6ec1fbe897f78370b860f6e6341621372db35 Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 15 May 2019 20:59:31 +0200 Subject: [PATCH 011/204] Added parameter with the amount of characters --- displayword.lua | 12 +++++++----- main.lua | 3 ++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/displayword.lua b/displayword.lua index 0a9ed63..714b74c 100644 --- a/displayword.lua +++ b/displayword.lua @@ -38,7 +38,7 @@ end local data={} -- Module displaying of the words -local generateLEDs = function(words, colorForground, colorMin1, colorMin2, colorMin3, colorMin4, invertRows) +local generateLEDs = function(words, colorForground, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil @@ -47,9 +47,6 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color invertRows=false end - -- DEBUG code, to determine, if the color argmuments are necessary or not - print(tostring(color) .. " " .. tostring(color1)) - local minutes=0 if (words.min1 == 1) then minutes = minutes + 1 @@ -62,11 +59,16 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color end -- always set a foreground value local colorFg = string.char(255,255,255) - if (colorForground ~= nil) then colorFg = colorForground end + if (amountOfChars ~= nil) then + data.amountOfChars = amountOfChars + else + data.amountOfChars = 0 + end + if ( (adc ~= nil) and (words.briPercent ~= nil) ) then local per = math.floor(100*adc.read(0)/1000) words.briPercent = tonumber( ((words.briPercent * 4) + per) / 5) diff --git a/main.lua b/main.lua index 002bfa0..b230fb8 100644 --- a/main.lua +++ b/main.lua @@ -63,7 +63,8 @@ function displayTime() if ((inv46 ~= nil) and (inv46 == "on")) then invertRows=true end - ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows) + displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows) + ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, displayword.data.drawnCharacters) print("Local time : " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. " char: " .. tostring(displayword.data.drawnCharacters)) end displayword = nil From 91c0a1521217c0d9f74bb4670f3c296b9b1f2824 Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 22 May 2019 21:25:33 +0200 Subject: [PATCH 012/204] Display one color after the other --- displayword.lua | 37 +++++++++++++++++++++++++++++-------- main.lua | 7 +++++-- simulation/config.lua | 15 +++++++-------- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/displayword.lua b/displayword.lua index 714b74c..93c8eaf 100644 --- a/displayword.lua +++ b/displayword.lua @@ -2,8 +2,30 @@ local M do local updateColor = function (data) - --FIXME magic missing to start on the left side - return data.colorFg + if (data.amountOfChars > 0) then + local div = tonumber(data.drawnCharacters/data.amountOfChars) + if (div < 1) then + print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " FG " .. tostring(string.byte(data.colorFg,1)) .. "x" .. tostring(string.byte(data.colorFg,2)) .. "x" .. tostring(string.byte(data.colorFg,3)) ) + return data.colorFg + elseif (div < 2) then + print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " C1") + return data.colorMin1 + elseif (div < 3) then + print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " C2") + return data.colorMin2 + elseif (div < 4) then + print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " C3") + return data.colorMin3 + elseif (div < 5) then + print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " C4") + return data.colorMin4 + else + print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " ELSE") + return data.colorFg + end + else + return data.colorFg + end end local drawLEDs = function(data, numberNewChars) @@ -38,7 +60,7 @@ end local data={} -- Module displaying of the words -local generateLEDs = function(words, colorForground, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars) +local generateLEDs = function(words, colorFg, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil @@ -47,7 +69,7 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color invertRows=false end - local minutes=0 + local minutes=1 if (words.min1 == 1) then minutes = minutes + 1 elseif (words.min2 == 1) then @@ -58,13 +80,12 @@ local generateLEDs = function(words, colorForground, colorMin1, colorMin2, color minutes = minutes + 4 end -- always set a foreground value - local colorFg = string.char(255,255,255) - if (colorForground ~= nil) then - colorFg = colorForground + if (colorFg == nil) then + colorFg = string.char(255,255,255) end if (amountOfChars ~= nil) then - data.amountOfChars = amountOfChars + data.amountOfChars = amountOfChars/minutes else data.amountOfChars = 0 end diff --git a/main.lua b/main.lua index b230fb8..928bd81 100644 --- a/main.lua +++ b/main.lua @@ -64,8 +64,10 @@ function displayTime() invertRows=true end displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows) - ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, displayword.data.drawnCharacters) - print("Local time : " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. " char: " .. tostring(displayword.data.drawnCharacters)) + if (displayword.data.drawnCharacters ~= nil) then + ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, displayword.data.drawnCharacters) + print("Local time : " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. " char: " .. tostring(displayword.data.drawnCharacters)) + end end displayword = nil if (ledBuf ~= nil) then @@ -101,6 +103,7 @@ function normalOperation() -- Color is defined as GREEN, RED, BLUE color=string.char(0,0,250) end + print("Fg Color: " .. tostring(string.byte(color,1)) .. "x" .. tostring(string.byte(color,2)) .. "x" .. tostring(string.byte(color,3)) ) connect_counter=0 -- Wait to be connect to the WiFi access point. diff --git a/simulation/config.lua b/simulation/config.lua index 7c38a41..c6b8f5e 100644 --- a/simulation/config.lua +++ b/simulation/config.lua @@ -1,13 +1,12 @@ -green=0 -green2=128 +green2=200 red=128 -blue=0 +blue=200 -color=string.char(0, 0, 128) -color1=string.char(128, 0, 0) -color2=string.char(tonumber(green2*0.8), 0, 0) -color3=string.char(tonumber(green2*0.4), 0, 0) -color4=string.char(tonumber(green2*0.2), 0, 0) +color=string.char(0, 0, blue) +color1=string.char(red, 0, 0) +color2=string.char(tonumber(red*0.8), 0, 0) +color3=string.char(0, tonumber(green2*0.4), 0) +color4=string.char(0,0 ,tonumber(blue*0.2)) colorBg=string.char(0,0,0) -- black is the default background color sntpserverhostname="ptbtime1.ptb.de" From aed713a1ff4d0b152a3d25d2951673d1610b40b4 Mon Sep 17 00:00:00 2001 From: Felix Rublack Date: Fri, 26 Jul 2019 21:33:48 +0200 Subject: [PATCH 013/204] clarification of initial flash process --- Readme.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 36f3cf0..813d863 100644 --- a/Readme.md +++ b/Readme.md @@ -11,11 +11,10 @@ cd os/ ./flash.sh ttyUSB0 -Reboot the ESP, with a serial terminal, -format the filesystem with the following command and reboot it: +Connect to the ESP via a terminal emulator like screen using a baud rate of 115200. Then format the filesystem and reboot the ESP with the following commands:
 file.format()
-node.reboot()
+node.restart()
 
Then disconnect the serial terminal and copy the required files to the microcontroller: From c9b248531a27d23c9d8b2bed0cd1404c76812ebd Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 12 Feb 2020 20:14:01 +0100 Subject: [PATCH 014/204] Reduced html stuff --- index.html | 22 ---------------------- webpage.html | 9 --------- 2 files changed, 31 deletions(-) delete mode 100644 index.html diff --git a/index.html b/index.html deleted file mode 100644 index a938ea3..0000000 --- a/index.html +++ /dev/null @@ -1,22 +0,0 @@ - -WordClock Setup Page - -

Welcome to the WordClock

-
- - - - - - -" -" -" -" - - - - -
WIFI-SSID
WIFI-Password
SNTP Serverntp server to sync the time
Offset to UTC timeDefine the offset to UTC time in hours. E.g +1
Color
1. Minute Color
2. Minute Color
3. Minute Color
4. Minute Color
Three quaterDreiviertel Joa/nei
ColorModeIf checked, words are dark, rest is colored
-$ADDITIONAL_LINE - diff --git a/webpage.html b/webpage.html index 25d1c80..7266fa7 100644 --- a/webpage.html +++ b/webpage.html @@ -48,15 +48,6 @@ Please note that all settings are mandatory

SNTP ServerServer to sync the time with. Only one ntp server is allowed. Offset to UTC timeDefine the offset to UTC time in hours. For example +1 hour for Germany Foreground ColorLED Color for all minutes, divisible by five -Background ColorBackground LED Color -1. Minute ColorFirst minute after -2. Minute ColorSecond minute after -3. Minute ColorThird minute after -4. Minute ColorFourth minute after -Three quaterDreiviertel Joa/nei -Invert lines 4-6invert -Adjust brightnesAdjust brightness of LEDs -
From c85e3b34e01be3df65b8a72fa70153d979081c99 Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 12 Feb 2020 20:52:31 +0100 Subject: [PATCH 015/204] Disable Webserver during runtime --- main.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/main.lua b/main.lua index 928bd81..3a03567 100644 --- a/main.lua +++ b/main.lua @@ -157,9 +157,8 @@ function normalOperation() syncTimeFromInternet() end) tmr.alarm(3, 2000, 0 ,function() - print("Start webserver...") - mydofile("webserver") - startWebServer() + -- FIXME start telent server + print("Load telnet") end) displayTime() -- Start the time Thread From ba6193ff5b10d350938248c47752ed137f6c6afd Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 21 Feb 2020 20:21:54 +0100 Subject: [PATCH 016/204] Telnet included --- main.lua | 9 ++++++--- telnet.lua | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 telnet.lua diff --git a/main.lua b/main.lua index 3a03567..8c85f37 100644 --- a/main.lua +++ b/main.lua @@ -147,7 +147,7 @@ function normalOperation() print('IP: ',wifi.sta.getip()) -- Here the WLAN is found, and something is done print("Solving dependencies") - local dependModules = { "timecore" , "wordclock" } + local dependModules = { "timecore" , "wordclock", "telnet" } for _,mod in pairs(dependModules) do print("Loading " .. mod) mydofile(mod) @@ -157,8 +157,11 @@ function normalOperation() syncTimeFromInternet() end) tmr.alarm(3, 2000, 0 ,function() - -- FIXME start telent server - print("Load telnet") + if (startTelnetServer ~= nil) then + startTelnetServer() + else + print("NO Telent found") + end end) displayTime() -- Start the time Thread diff --git a/telnet.lua b/telnet.lua new file mode 100644 index 0000000..ab55c21 --- /dev/null +++ b/telnet.lua @@ -0,0 +1,35 @@ +-- Telnet Server +function startTelnetServer() + s=net.createServer(net.TCP, 180) + s:listen(23,function(c) + global_c=c + printlines = {} + function s_output(str) + if(global_c~=nil) then + if #printlines > 0 then + printlines[ #printlines + 1] = str + else + printlines[ #printlines + 1] = str + global_c:send("\r") -- Send something, so the queue is read after sending + end + end + end + node.output(s_output, 0) + c:on("receive",function(c,l) + node.input(l) + end) + c:on("disconnection",function(c) + node.output(nil) + global_c=nil + end) + c:on("sent", function() + if #printlines > 0 then + global_c:send(table.remove(printlines, 1)) + end + end) + print("Welcome to the Wordclock.") + print("Visite https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en for further commands") + end) + print("Telnetserver is up") +end + From 3bd4fc8cb6afca06b537dfe92c9708952bcd493c Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 21 Feb 2020 23:31:05 +0100 Subject: [PATCH 017/204] configuration parameter added --- telnet.lua | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/telnet.lua b/telnet.lua index ab55c21..57e0902 100644 --- a/telnet.lua +++ b/telnet.lua @@ -28,8 +28,161 @@ function startTelnetServer() end end) print("Welcome to the Wordclock.") + print("- storeConfig()") print("Visite https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en for further commands") end) print("Telnetserver is up") end +function storeConfig(_ssid, _password, _timezoneoffset, _inv46, _dim, _fcolor, _colorMin1, _colorMin2, _colorMin3, _colorMin4, _bcolor, _threequater) + +if ( (_ssid == nil) and + (_password == nil) and + (_timezoneoffset == nil) and + (_inv46 == nil) and + (_dim == nil) and + (_fcolor == nil) and + (_colorMin1 == nil) and + (_colorMin2 == nil) and + (_colorMin3 == nil) and + (_colorMin4 == nil) and + (_bcolor == nil) and + (_threequater == nil) ) then + print("one parameter is mandatory:") + print("storeConfig(ssid, password, timezoneoffset, inv46, dim, fcolor, colorMin1, colorMin2, colorMin3, colorMin4, bcolor, threequater)") +end + +if (_password==nil) then + _, password, _, _ = wifi.sta.getconfig() + print("Restore password") +else + password = _password +end +if (_ssid==nil) then + ssid, _, _, _ = wifi.sta.getconfig() +else + ssid = _ssid +end + +if (_timezoneoffset==nil) then +timezoneoffset = _timezoneoffset +end +if (_inv46 == nil) then +inv46 = _inv46 +end +if (_dim == nil) then +dim = _dim +end +if (_fcolor == nil) then +fcolor = _fcolor +end +if (_bcolor == nil) then +bcolor = _bcolor +end +if (_colorMin1 == nil) then +colorMin1 = _colorMin1 +end +if (_colorMin2 == nil) then +colorMin2 = _colorMin2 +end +if (_colorMin3 == nil) then +colorMin3 = _colorMin3 +end +if (_colorMin4 == nil) then +colorMin4 = _colorMin4 +end +if (_threequater == nil) then +threequater = _threequater +end + +print("SSID = " .. tostring(ssid)) +print("TZNE = " .. tostring(timezoneoffset)) +print("INVT = " .. tostring(inv46)) +print("DIM = " .. tostring(dim)) +print("FCOL = " .. tostring(fcolor)) +print("BCOL = " .. tostring(bcolor)) +print("MIN1 = " .. tostring(colorMin1)) +print("MIN2 = " .. tostring(colorMin2)) +print("MIN3 = " .. tostring(colorMin3)) +print("MIN4 = " .. tostring(colorMin4)) +print("3QRT = " .. tostring(threequater)) + +-- Safe configuration: +file.remove(configFile .. ".new") +sec, _ = rtctime.get() +file.open(configFile.. ".new", "w+") +file.write("-- Config\n" .. "station_cfg={}\nstation_cfg.ssid=\"" .. ssid .. "\"\nstation_cfg.pwd=\"" .. password .. "\"\nstation_cfg.save=false\nwifi.sta.config(station_cfg)\n") +file.write("sntpserverhostname=\"" .. sntpserver .. "\"\n" .. "timezoneoffset=\"" .. timezoneoffset .. "\"\n".. "inv46=\"" .. tostring(inv46) .. "\"\n" .. "dim=\"" .. tostring(dim) .. "\"\n") + +if (fcolor ~= nil) then + local hexColor=string.sub(fcolor, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + -- fill the current values + color=string.char(green, red, blue) +end +if (colorMin1 ~= nil) then + local hexColor=string.sub(colorMin1, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color1=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + color1=string.char(green, red, blue) +end +if ( colorMin2 ~= nil) then + local hexColor=string.sub(colorMin2, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color2=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + color2=string.char(green, red, blue) +end +if ( colorMin3 ~= nil) then + local hexColor=string.sub(colorMin3, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color3=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + color3=string.char(green, red, blue) +end +if ( colorMin4 ~= nil) then + local hexColor=string.sub(colorMin4, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color4=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + color4=string.char(green, red, blue) +end +if ( bcolor ~= nil) then + local hexColor=string.sub(bcolor, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("colorBg=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + -- fill the current values + colorBg=string.char(green, red, blue) +end +if (getTime ~= nil) then + time = getTime(sec, timezoneoffset) + file.write("print(\"Config from " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. "\")\n") +end +if ( threequater ~= nil) then + file.write("threequater=true\n") + -- fill the current values + threequater=true +else + file.write("threequater=nil\n") -- unset threequater + -- fill the current values + threequater=nil +end +file.close() +collectgarbage() +sec=nil +file.remove(configFile) +if (file.rename(configFile .. ".new", configFile)) then + print("Rename Successfully") +end + +end From 77ebc55dbb5d89bdbdb3576684a54d6d2b483526 Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 4 Mar 2020 19:10:37 +0100 Subject: [PATCH 018/204] Remove debugging --- displayword.lua | 6 ------ main.lua | 1 - 2 files changed, 7 deletions(-) diff --git a/displayword.lua b/displayword.lua index 93c8eaf..58752c9 100644 --- a/displayword.lua +++ b/displayword.lua @@ -5,22 +5,16 @@ local updateColor = function (data) if (data.amountOfChars > 0) then local div = tonumber(data.drawnCharacters/data.amountOfChars) if (div < 1) then - print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " FG " .. tostring(string.byte(data.colorFg,1)) .. "x" .. tostring(string.byte(data.colorFg,2)) .. "x" .. tostring(string.byte(data.colorFg,3)) ) return data.colorFg elseif (div < 2) then - print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " C1") return data.colorMin1 elseif (div < 3) then - print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " C2") return data.colorMin2 elseif (div < 4) then - print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " C3") return data.colorMin3 elseif (div < 5) then - print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " C4") return data.colorMin4 else - print(tostring(data.drawnCharacters) .. " blocks: " .. tostring(data.amountOfChars) .. " ELSE") return data.colorFg end else diff --git a/main.lua b/main.lua index 8c85f37..59aca40 100644 --- a/main.lua +++ b/main.lua @@ -66,7 +66,6 @@ function displayTime() displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows) if (displayword.data.drawnCharacters ~= nil) then ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, displayword.data.drawnCharacters) - print("Local time : " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. " char: " .. tostring(displayword.data.drawnCharacters)) end end displayword = nil From edfb9f2803da37a73f1f0b113c7b9f99906bd320 Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 4 Mar 2020 20:54:00 +0100 Subject: [PATCH 019/204] Not forced to format ESP, when flashing serial --- tools/initialFlash.sh | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index b54d309..14e28ee 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -12,21 +12,35 @@ if [ ! -c $DEVICE ]; then fi -if [ $# -ne 1 ]; then +if [ $# -eq 0 ]; then echo "" - echo "e.g. usage $0 " + echo "e.g. usage $0 []" exit 1 fi -FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua wordclock.lua init.lua" +if [ $# -eq 1 ]; then + FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua wordclock.lua init.lua" +else + FILES=$2 +fi + # Format filesystem first -echo "Format the complete ESP" -$LUATOOL -p $DEVICE -w -b 115200 -if [ $? -ne 0 ]; then - echo "STOOOOP" - exit 1 -fi +#echo "Format the complete ESP" +#$LUATOOL -p $DEVICE -w -b 115200 +#if [ $? -ne 0 ]; then +# echo "STOOOOP" +# exit 1 +#fi + +echo "Reboot the ESP" +echo "node.restart()" >> $DEVICE +sleep 1 +for i in $(seq 0 5); do + echo "Stop TMR $i" + echo "tmr.stop($i)" >> $DEVICE + sleep 1 +done echo echo "Start Flasing ..." From 65d2de68018a1284fc11dab5de09b64375c34391 Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 4 Mar 2020 21:01:13 +0100 Subject: [PATCH 020/204] Specify config file --- telnet.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/telnet.lua b/telnet.lua index 57e0902..6cd3812 100644 --- a/telnet.lua +++ b/telnet.lua @@ -107,6 +107,7 @@ print("MIN3 = " .. tostring(colorMin3)) print("MIN4 = " .. tostring(colorMin4)) print("3QRT = " .. tostring(threequater)) +local configFile="config.lua" -- Safe configuration: file.remove(configFile .. ".new") sec, _ = rtctime.get() From 17a9416607199019cd8610e2f3e09de9ab7e96dd Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 4 Mar 2020 21:01:30 +0100 Subject: [PATCH 021/204] Set telnet IP address --- tools/tcpFlash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/tcpFlash.py b/tools/tcpFlash.py index 2c32002..8ff527e 100755 --- a/tools/tcpFlash.py +++ b/tools/tcpFlash.py @@ -49,7 +49,7 @@ def main(nodeip, luafile, volatile=None): else: try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((nodeip, 80)) + s.connect((nodeip, 23)) time.sleep(0.050) s.sendall("\n") # Receive the hello Message of answer of the ESP From 2f9f9fdc6852676dd5c5d10b41648fb13b5c1d2a Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 4 Mar 2020 22:00:15 +0100 Subject: [PATCH 022/204] Restore old parameter, if not set --- telnet.lua | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/telnet.lua b/telnet.lua index 6cd3812..8b81bbf 100644 --- a/telnet.lua +++ b/telnet.lua @@ -34,11 +34,12 @@ function startTelnetServer() print("Telnetserver is up") end -function storeConfig(_ssid, _password, _timezoneoffset, _inv46, _dim, _fcolor, _colorMin1, _colorMin2, _colorMin3, _colorMin4, _bcolor, _threequater) +function storeConfig(_ssid, _password, _timezoneoffset, _sntpserver, _inv46, _dim, _fcolor, _colorMin1, _colorMin2, _colorMin3, _colorMin4, _bcolor, _threequater) if ( (_ssid == nil) and (_password == nil) and (_timezoneoffset == nil) and + (_sntpserver == nil) and (_inv46 == nil) and (_dim == nil) and (_fcolor == nil) and @@ -49,7 +50,8 @@ if ( (_ssid == nil) and (_bcolor == nil) and (_threequater == nil) ) then print("one parameter is mandatory:") - print("storeConfig(ssid, password, timezoneoffset, inv46, dim, fcolor, colorMin1, colorMin2, colorMin3, colorMin4, bcolor, threequater)") + print("storeConfig(ssid, password, timezoneoffset, sntpserver, inv46, dim, fcolor, colorMin1, colorMin2, colorMin3, colorMin4, bcolor, threequater)") + return end if (_password==nil) then @@ -64,39 +66,53 @@ else ssid = _ssid end -if (_timezoneoffset==nil) then +if (_sntpserver == nil) then + sntpserver = sntpserverhostname + print("Restore SNTP: " .. tostring(sntpserver)) +else + sntpserver = _sntpserver +end + +if (_timezoneoffset ~= nil) then timezoneoffset = _timezoneoffset end -if (_inv46 == nil) then -inv46 = _inv46 +if (_inv46 ~= nil) then +if ((_inv46 == true) or (_inv == "on")) then + inv46 = "on" +elseif ((_inv46 == false) or (_inv == "off")) then + inv46 = "off" +else + inv46 = "off" end -if (_dim == nil) then +end +if (_dim ~= nil) then dim = _dim end -if (_fcolor == nil) then +if (_fcolor ~= nil) then fcolor = _fcolor end -if (_bcolor == nil) then +if (_bcolor ~= nil) then bcolor = _bcolor end -if (_colorMin1 == nil) then +if (_colorMin1 ~= nil) then colorMin1 = _colorMin1 end -if (_colorMin2 == nil) then +if (_colorMin2 ~= nil) then colorMin2 = _colorMin2 end -if (_colorMin3 == nil) then +if (_colorMin3 ~= nil) then colorMin3 = _colorMin3 end -if (_colorMin4 == nil) then +if (_colorMin4 ~= nil) then colorMin4 = _colorMin4 end -if (_threequater == nil) then +if (_threequater ~= nil) then threequater = _threequater end print("SSID = " .. tostring(ssid)) print("TZNE = " .. tostring(timezoneoffset)) +print("NTP = " .. tostring(sntpserver)) print("INVT = " .. tostring(inv46)) print("DIM = " .. tostring(dim)) print("FCOL = " .. tostring(fcolor)) @@ -184,6 +200,8 @@ sec=nil file.remove(configFile) if (file.rename(configFile .. ".new", configFile)) then print("Rename Successfully") +else + print("Cannot rename " .. configFile .. ".new") end end From 344fb0ab9a93c1331bc937ae92ab36fe7510c8b8 Mon Sep 17 00:00:00 2001 From: ollo Date: Wed, 4 Mar 2020 22:24:13 +0100 Subject: [PATCH 023/204] Added example for telnet command --- init.lua | 2 +- telnet.lua | 17 ++++++++++++++++- tools/initialFlash.sh | 2 +- tools/tcpFlash.py | 2 +- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/init.lua b/init.lua index 5a107f2..1b60740 100644 --- a/init.lua +++ b/init.lua @@ -49,7 +49,7 @@ tmr.alarm(1, 5000, 0, function() (file.open("timecore.lua")) or (file.open("wordclock.lua")) or (file.open("displayword.lua")) or - (file.open("webserver.lua")) + (file.open("telnet.lua")) ) then c = string.char(0,128,0) w = string.char(0,0,0) diff --git a/telnet.lua b/telnet.lua index 8b81bbf..fa6fb09 100644 --- a/telnet.lua +++ b/telnet.lua @@ -50,7 +50,22 @@ if ( (_ssid == nil) and (_bcolor == nil) and (_threequater == nil) ) then print("one parameter is mandatory:") - print("storeConfig(ssid, password, timezoneoffset, sntpserver, inv46, dim, fcolor, colorMin1, colorMin2, colorMin3, colorMin4, bcolor, threequater)") + print("storeConfig(ssid, ") + print(" password,") + print(" timezoneoffset,") + print(" sntpserver,") + print(" inv46,") + print(" dim,") + print(" fcolor,") + print(" colorMin1,") + print(" colorMin2,") + print(" colorMin3,") + print(" colorMin4,") + print(" bcolor,") + print(" threequater)") + print(" ") + print("e.g.:") + print('storeConfig(nil, nil, 1, nil, "on", true, "00FF00", "00FF88", "008888", "00FF44", "004488", "000000", true)') return end diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index 14e28ee..a3bfdb9 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -59,6 +59,6 @@ for f in $FILES; do done echo "Reboot the ESP" -$LUATOOL -p $DEVICE -r -b 115200 +echo "node.restart()" >> $DEVICE exit 0 diff --git a/tools/tcpFlash.py b/tools/tcpFlash.py index 8ff527e..4f7526b 100755 --- a/tools/tcpFlash.py +++ b/tools/tcpFlash.py @@ -94,7 +94,7 @@ def main(nodeip, luafile, volatile=None): print "add a space at the end" if (volatile is None): - if (not sendCmd(s, "w([[" + l + "]]);")): + if (not sendCmd(s, "w([==[" + l + "]==]);")): print "Cannot write line " + str(i) s.close() sys.exit(4) From b5f46a14d2745cb219e4ec93fca62ebb8c6d1ba8 Mon Sep 17 00:00:00 2001 From: ollo Date: Fri, 6 Mar 2020 23:55:14 +0100 Subject: [PATCH 024/204] Indention improved --- telnet.lua | 18 +++++++++--------- tools/initialFlash.sh | 36 +++++++++++++++++++----------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/telnet.lua b/telnet.lua index fa6fb09..a2ad090 100644 --- a/telnet.lua +++ b/telnet.lua @@ -100,29 +100,29 @@ else inv46 = "off" end end -if (_dim ~= nil) then -dim = _dim +if ( _dim ~= nil) then + dim = _dim end if (_fcolor ~= nil) then -fcolor = _fcolor + fcolor = _fcolor end if (_bcolor ~= nil) then -bcolor = _bcolor + bcolor = _bcolor end if (_colorMin1 ~= nil) then -colorMin1 = _colorMin1 + colorMin1 = _colorMin1 end if (_colorMin2 ~= nil) then -colorMin2 = _colorMin2 + colorMin2 = _colorMin2 end if (_colorMin3 ~= nil) then -colorMin3 = _colorMin3 + colorMin3 = _colorMin3 end if (_colorMin4 ~= nil) then -colorMin4 = _colorMin4 + colorMin4 = _colorMin4 end if (_threequater ~= nil) then -threequater = _threequater + threequater = _threequater end print("SSID = " .. tostring(ssid)) diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index a3bfdb9..a6270ad 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -3,6 +3,7 @@ LUATOOL=./tools/luatool.py DEVICE=$1 +BAUD=115200 # check the serial connection @@ -19,30 +20,31 @@ if [ $# -eq 0 ]; then fi if [ $# -eq 1 ]; then - FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua wordclock.lua init.lua" + FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua telnet.lua wordclock.lua init.lua" else FILES=$2 fi # Format filesystem first -#echo "Format the complete ESP" -#$LUATOOL -p $DEVICE -w -b 115200 -#if [ $? -ne 0 ]; then -# echo "STOOOOP" -# exit 1 -#fi +echo "Format the complete ESP" +$LUATOOL -p $DEVICE -w -b $BAUD +if [ $? -ne 0 ]; then + echo "STOOOOP" + exit 1 +fi -echo "Reboot the ESP" -echo "node.restart()" >> $DEVICE -sleep 1 -for i in $(seq 0 5); do - echo "Stop TMR $i" - echo "tmr.stop($i)" >> $DEVICE - sleep 1 -done +#stty -F $DEVICE $BAUD +#echo "Reboot the ESP" +#echo "node.restart()" >> $DEVICE +#sleep 1 +#for i in $(seq 0 5); do +# echo "Stop TMR $i" +# echo "tmr.stop($i)" >> $DEVICE +# sleep 1 +#done -echo +#echo echo "Start Flasing ..." for f in $FILES; do if [ ! -f $f ]; then @@ -51,7 +53,7 @@ for f in $FILES; do exit 1 fi echo "------------- $f ------------" - $LUATOOL -p $DEVICE -f $f -b 115200 -t $f + $LUATOOL -p $DEVICE -f $f -b $BAUD -t $f if [ $? -ne 0 ]; then echo "STOOOOP" exit 1 From ebacc86f01a3ec254d787a674cee2b84c8a54335 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 7 Dec 2020 20:02:01 +0100 Subject: [PATCH 025/204] Upgraded esptool to python3 --- os/esptool.py | 4166 +++++++++++++++++++++++++++++++++++++++++-------- os/flash.sh | 13 +- 2 files changed, 3480 insertions(+), 699 deletions(-) diff --git a/os/esptool.py b/os/esptool.py index 38ffb72..6a9a97f 100755 --- a/os/esptool.py +++ b/os/esptool.py @@ -1,10 +1,8 @@ #!/usr/bin/env python -# NB: Before sending a PR to change the above line to '#!/usr/bin/env python2', please read https://github.com/themadinventor/esptool/issues/21 # -# ESP8266 ROM Bootloader Utility -# https://github.com/themadinventor/esptool -# -# Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton, other contributors as noted. +# ESP8266 & ESP32 family ROM Bootloader Utility +# Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton, Espressif Systems (Shanghai) PTE LTD, other contributors as noted. +# https://github.com/espressif/esptool # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software @@ -18,24 +16,179 @@ # this program; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301 USA. +from __future__ import division, print_function + import argparse +import base64 +import binascii +import copy import hashlib import inspect -import json +import io +import itertools import os -import serial +import shlex +import string import struct -import subprocess import sys -import tempfile import time +import zlib + +try: + import serial +except ImportError: + print("Pyserial is not installed for %s. Check the README for installation instructions." % (sys.executable)) + raise + +# check 'serial' is 'pyserial' and not 'serial' https://github.com/espressif/esptool/issues/269 +try: + if "serialization" in serial.__doc__ and "deserialization" in serial.__doc__: + raise ImportError(""" +esptool.py depends on pyserial, but there is a conflict with a currently installed package named 'serial'. + +You may be able to work around this by 'pip uninstall serial; pip install pyserial' \ +but this may break other installed Python software that depends on 'serial'. + +There is no good fix for this right now, apart from configuring virtualenvs. \ +See https://github.com/espressif/esptool/issues/269#issuecomment-385298196 for discussion of the underlying issue(s).""") +except TypeError: + pass # __doc__ returns None for pyserial + +try: + import serial.tools.list_ports as list_ports +except ImportError: + print("The installed version (%s) of pyserial appears to be too old for esptool.py (Python interpreter %s). " + "Check the README for installation instructions." % (sys.VERSION, sys.executable)) + raise +except Exception: + if sys.platform == "darwin": + # swallow the exception, this is a known issue in pyserial+macOS Big Sur preview ref https://github.com/espressif/esptool/issues/540 + list_ports = None + else: + raise -__version__ = "1.2-dev" +__version__ = "3.1-dev" + +MAX_UINT32 = 0xffffffff +MAX_UINT24 = 0xffffff + +DEFAULT_TIMEOUT = 3 # timeout for most flash operations +START_FLASH_TIMEOUT = 20 # timeout for starting flash (may perform erase) +CHIP_ERASE_TIMEOUT = 120 # timeout for full chip erase +MAX_TIMEOUT = CHIP_ERASE_TIMEOUT * 2 # longest any command can run +SYNC_TIMEOUT = 0.1 # timeout for syncing with bootloader +MD5_TIMEOUT_PER_MB = 8 # timeout (per megabyte) for calculating md5sum +ERASE_REGION_TIMEOUT_PER_MB = 30 # timeout (per megabyte) for erasing a region +COMP_BLOCK_WRITE_TIMEOUT_PER_MB = 3 # timeout (per megabyte) for writing compressed data +MEM_END_ROM_TIMEOUT = 0.05 # special short timeout for ESP_MEM_END, as it may never respond +DEFAULT_SERIAL_WRITE_TIMEOUT = 10 # timeout for serial port write +DEFAULT_CONNECT_ATTEMPTS = 7 # default number of times to try connection -class ESPROM(object): - # These are the currently known commands supported by the ROM +def timeout_per_mb(seconds_per_mb, size_bytes): + """ Scales timeouts which are size-specific """ + result = seconds_per_mb * (size_bytes / 1e6) + if result < DEFAULT_TIMEOUT: + return DEFAULT_TIMEOUT + return result + + +DETECTED_FLASH_SIZES = {0x12: '256KB', 0x13: '512KB', 0x14: '1MB', + 0x15: '2MB', 0x16: '4MB', 0x17: '8MB', 0x18: '16MB'} + + +def check_supported_function(func, check_func): + """ + Decorator implementation that wraps a check around an ESPLoader + bootloader function to check if it's supported. + + This is used to capture the multidimensional differences in + functionality between the ESP8266 & ESP32/32S2/32S3/32C3 ROM loaders, and the + software stub that runs on both. Not possible to do this cleanly + via inheritance alone. + """ + def inner(*args, **kwargs): + obj = args[0] + if check_func(obj): + return func(*args, **kwargs) + else: + raise NotImplementedInROMError(obj, func) + return inner + + +def stub_function_only(func): + """ Attribute for a function only supported in the software stub loader """ + return check_supported_function(func, lambda o: o.IS_STUB) + + +def stub_and_esp32_function_only(func): + """ Attribute for a function only supported by software stubs or ESP32/32S2/32S3/32C3 ROM """ + return check_supported_function(func, lambda o: o.IS_STUB or isinstance(o, ESP32ROM)) + + +PYTHON2 = sys.version_info[0] < 3 # True if on pre-Python 3 + +# Function to return nth byte of a bitstring +# Different behaviour on Python 2 vs 3 +if PYTHON2: + def byte(bitstr, index): + return ord(bitstr[index]) +else: + def byte(bitstr, index): + return bitstr[index] + +# Provide a 'basestring' class on Python 3 +try: + basestring +except NameError: + basestring = str + + +def print_overwrite(message, last_line=False): + """ Print a message, overwriting the currently printed line. + + If last_line is False, don't append a newline at the end (expecting another subsequent call will overwrite this one.) + + After a sequence of calls with last_line=False, call once with last_line=True. + + If output is not a TTY (for example redirected a pipe), no overwriting happens and this function is the same as print(). + """ + if sys.stdout.isatty(): + print("\r%s" % message, end='\n' if last_line else '') + else: + print(message) + + +def _mask_to_shift(mask): + """ Return the index of the least significant bit in the mask """ + shift = 0 + while mask & 0x1 == 0: + shift += 1 + mask >>= 1 + return shift + + +def esp8266_function_only(func): + """ Attribute for a function only supported on ESP8266 """ + return check_supported_function(func, lambda o: o.CHIP_NAME == "ESP8266") + + +class ESPLoader(object): + """ Base class providing access to ESP ROM & software stub bootloaders. + Subclasses provide ESP8266 & ESP32 specific functionality. + + Don't instantiate this base class directly, either instantiate a subclass or + call ESPLoader.detect_chip() which will interrogate the chip and return the + appropriate subclass instance. + + """ + CHIP_NAME = "Espressif device" + IS_STUB = False + + DEFAULT_PORT = "/dev/ttyUSB0" + + # Commands supported by ESP8266 ROM bootloader ESP_FLASH_BEGIN = 0x02 ESP_FLASH_DATA = 0x03 ESP_FLASH_END = 0x04 @@ -46,9 +199,35 @@ class ESPROM(object): ESP_WRITE_REG = 0x09 ESP_READ_REG = 0x0a + # Some comands supported by ESP32 ROM bootloader (or -8266 w/ stub) + ESP_SPI_SET_PARAMS = 0x0B + ESP_SPI_ATTACH = 0x0D + ESP_READ_FLASH_SLOW = 0x0e # ROM only, much slower than the stub flash read + ESP_CHANGE_BAUDRATE = 0x0F + ESP_FLASH_DEFL_BEGIN = 0x10 + ESP_FLASH_DEFL_DATA = 0x11 + ESP_FLASH_DEFL_END = 0x12 + ESP_SPI_FLASH_MD5 = 0x13 + + # Commands supported by ESP32-S2/S3/C3 ROM bootloader only + ESP_GET_SECURITY_INFO = 0x14 + + # Some commands supported by stub only + ESP_ERASE_FLASH = 0xD0 + ESP_ERASE_REGION = 0xD1 + ESP_READ_FLASH = 0xD2 + ESP_RUN_USER_CODE = 0xD3 + + # Flash encryption encrypted data command + ESP_FLASH_ENCRYPT_DATA = 0xD4 + + # Response code(s) sent by ROM + ROM_INVALID_RECV_MSG = 0x05 # response if an invalid message is received + # Maximum block sized for RAM and Flash writes, respectively. ESP_RAM_BLOCK = 0x1800 - ESP_FLASH_BLOCK = 0x400 + + FLASH_WRITE_SIZE = 0x400 # Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want. ESP_ROM_BAUD = 115200 @@ -59,174 +238,444 @@ class ESPROM(object): # Initial state for the checksum routine ESP_CHECKSUM_MAGIC = 0xef - # OTP ROM addresses - ESP_OTP_MAC0 = 0x3ff00050 - ESP_OTP_MAC1 = 0x3ff00054 - ESP_OTP_MAC3 = 0x3ff0005c - # Flash sector size, minimum unit of erase. - ESP_FLASH_SECTOR = 0x1000 + FLASH_SECTOR_SIZE = 0x1000 - def __init__(self, port=0, baud=ESP_ROM_BAUD): - self._port = serial.Serial(port) - self._slip_reader = slip_reader(port) + UART_DATE_REG_ADDR = 0x60000078 + + CHIP_DETECT_MAGIC_REG_ADDR = 0x40001000 # This ROM address has a different value on each chip model + + UART_CLKDIV_MASK = 0xFFFFF + + # Memory addresses + IROM_MAP_START = 0x40200000 + IROM_MAP_END = 0x40300000 + + # The number of bytes in the UART response that signify command status + STATUS_BYTES_LENGTH = 2 + + def __init__(self, port=DEFAULT_PORT, baud=ESP_ROM_BAUD, trace_enabled=False): + """Base constructor for ESPLoader bootloader interaction + + Don't call this constructor, either instantiate ESP8266ROM + or ESP32ROM, or use ESPLoader.detect_chip(). + + This base class has all of the instance methods for bootloader + functionality supported across various chips & stub + loaders. Subclasses replace the functions they don't support + with ones which throw NotImplementedInROMError(). + + """ + self.secure_download_mode = False # flag is set to True if esptool detects the ROM is in Secure Download Mode + + if isinstance(port, basestring): + self._port = serial.serial_for_url(port) + else: + self._port = port + self._slip_reader = slip_reader(self._port, self.trace) # setting baud rate in a separate step is a workaround for # CH341 driver on some Linux versions (this opens at 9600 then # sets), shouldn't matter for other platforms/drivers. See - # https://github.com/themadinventor/esptool/issues/44#issuecomment-107094446 - self._port.baudrate = baud + # https://github.com/espressif/esptool/issues/44#issuecomment-107094446 + self._set_port_baudrate(baud) + self._trace_enabled = trace_enabled + # set write timeout, to prevent esptool blocked at write forever. + try: + self._port.write_timeout = DEFAULT_SERIAL_WRITE_TIMEOUT + except NotImplementedError: + # no write timeout for RFC2217 ports + # need to set the property back to None or it will continue to fail + self._port.write_timeout = None + + def _set_port_baudrate(self, baud): + try: + self._port.baudrate = baud + except IOError: + raise FatalError("Failed to set baud rate %d. The driver may not support this rate." % baud) + + @staticmethod + def detect_chip(port=DEFAULT_PORT, baud=ESP_ROM_BAUD, connect_mode='default_reset', trace_enabled=False, + connect_attempts=DEFAULT_CONNECT_ATTEMPTS): + """ Use serial access to detect the chip type. + + We use the UART's datecode register for this, it's mapped at + the same address on ESP8266 & ESP32 so we can use one + memory read and compare to the datecode register for each chip + type. + + This routine automatically performs ESPLoader.connect() (passing + connect_mode parameter) as part of querying the chip. + """ + detect_port = ESPLoader(port, baud, trace_enabled=trace_enabled) + detect_port.connect(connect_mode, connect_attempts, detecting=True) + try: + print('Detecting chip type...', end='') + sys.stdout.flush() + chip_magic_value = detect_port.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR) + + for cls in [ESP8266ROM, ESP32ROM, ESP32S2ROM, ESP32S3BETA2ROM, ESP32C3ROM]: + if chip_magic_value == cls.CHIP_DETECT_MAGIC_VALUE: + # don't connect a second time + inst = cls(detect_port._port, baud, trace_enabled=trace_enabled) + inst._post_connect() + print(' %s' % inst.CHIP_NAME, end='') + return inst + except UnsupportedCommandError: + raise FatalError("Unsupported Command Error received. Probably this means Secure Download Mode is enabled, " + "autodetection will not work. Need to manually specify the chip.") + finally: + print('') # end line + raise FatalError("Unexpected CHIP magic value 0x%08x. Failed to autodetect chip type." % (chip_magic_value)) """ Read a SLIP packet from the serial port """ def read(self): - return self._slip_reader.next() + return next(self._slip_reader) """ Write bytes to the serial port while performing SLIP escaping """ def write(self, packet): - buf = '\xc0' \ - + (packet.replace('\xdb','\xdb\xdd').replace('\xc0','\xdb\xdc')) \ - + '\xc0' + buf = b'\xc0' \ + + (packet.replace(b'\xdb', b'\xdb\xdd').replace(b'\xc0', b'\xdb\xdc')) \ + + b'\xc0' + self.trace("Write %d bytes: %s", len(buf), HexFormatter(buf)) self._port.write(buf) + def trace(self, message, *format_args): + if self._trace_enabled: + now = time.time() + try: + + delta = now - self._last_trace + except AttributeError: + delta = 0.0 + self._last_trace = now + prefix = "TRACE +%.3f " % delta + print(prefix + (message % format_args)) + """ Calculate checksum of a blob, as it is defined by the ROM """ @staticmethod def checksum(data, state=ESP_CHECKSUM_MAGIC): for b in data: - state ^= ord(b) + if type(b) is int: # python 2/3 compat + state ^= b + else: + state ^= ord(b) + return state """ Send a request and read the response """ - def command(self, op=None, data=None, chk=0): - if op is not None: - pkt = struct.pack(' self.STATUS_BYTES_LENGTH: + return data[:-self.STATUS_BYTES_LENGTH] + else: # otherwise, just return the 'val' field which comes from the reply header (this is used by read_reg) + return val + + def flush_input(self): + self._port.flushInput() + self._slip_reader = slip_reader(self._port, self.trace) + def sync(self): - self.command(ESPROM.ESP_SYNC, '\x07\x07\x12\x20' + 32 * '\x55') - for i in xrange(7): + self.command(self.ESP_SYNC, b'\x07\x07\x12\x20' + 32 * b'\x55', + timeout=SYNC_TIMEOUT) + for i in range(7): self.command() - """ Try connecting repeatedly until successful, or giving up """ - def connect(self): - print 'Connecting...' + def _setDTR(self, state): + self._port.setDTR(state) - for _ in xrange(4): - # issue reset-to-bootloader: - # RTS = either CH_PD or nRESET (both active low = chip in reset) - # DTR = GPIO0 (active low = boot to flasher) - self._port.setDTR(False) - self._port.setRTS(True) + def _setRTS(self, state): + self._port.setRTS(state) + # Work-around for adapters on Windows using the usbser.sys driver: + # generate a dummy change to DTR so that the set-control-line-state + # request is sent with the updated RTS state and the same DTR state + self._port.setDTR(self._port.dtr) + + def _connect_attempt(self, mode='default_reset', esp32r0_delay=False): + """ A single connection attempt, with esp32r0 workaround options """ + # esp32r0_delay is a workaround for bugs with the most common auto reset + # circuit and Windows, if the EN pin on the dev board does not have + # enough capacitance. + # + # Newer dev boards shouldn't have this problem (higher value capacitor + # on the EN pin), and ESP32 revision 1 can't use this workaround as it + # relies on a silicon bug. + # + # Details: https://github.com/espressif/esptool/issues/136 + last_error = None + + # If we're doing no_sync, we're likely communicating as a pass through + # with an intermediate device to the ESP32 + if mode == "no_reset_no_sync": + return last_error + + # issue reset-to-bootloader: + # RTS = either CH_PD/EN or nRESET (both active low = chip in reset + # DTR = GPIO0 (active low = boot to flasher) + # + # DTR & RTS are active low signals, + # ie True = pin @ 0V, False = pin @ VCC. + if mode != 'no_reset': + self._setDTR(False) # IO0=HIGH + self._setRTS(True) # EN=LOW, chip in reset + time.sleep(0.1) + if esp32r0_delay: + # Some chips are more likely to trigger the esp32r0 + # watchdog reset silicon bug if they're held with EN=LOW + # for a longer period + time.sleep(1.2) + self._setDTR(True) # IO0=LOW + self._setRTS(False) # EN=HIGH, chip out of reset + if esp32r0_delay: + # Sleep longer after reset. + # This workaround only works on revision 0 ESP32 chips, + # it exploits a silicon bug spurious watchdog reset. + time.sleep(0.4) # allow watchdog reset to occur time.sleep(0.05) - self._port.setDTR(True) - self._port.setRTS(False) - time.sleep(0.05) - self._port.setDTR(False) + self._setDTR(False) # IO0=HIGH, done - # worst-case latency timer should be 255ms (probably <20ms) - self._port.timeout = 0.3 - for _ in xrange(4): - try: - self._port.flushInput() - self._slip_reader = slip_reader(self._port) - self._port.flushOutput() - self.sync() - self._port.timeout = 5 - return - except: - time.sleep(0.05) - raise FatalError('Failed to connect to ESP8266') + for _ in range(5): + try: + self.flush_input() + self._port.flushOutput() + self.sync() + return None + except FatalError as e: + if esp32r0_delay: + print('_', end='') + else: + print('.', end='') + sys.stdout.flush() + time.sleep(0.05) + last_error = e + return last_error + + def connect(self, mode='default_reset', attempts=DEFAULT_CONNECT_ATTEMPTS, detecting=False): + """ Try connecting repeatedly until successful, or giving up """ + print('Connecting...', end='') + sys.stdout.flush() + last_error = None + + try: + for _ in range(attempts) if attempts > 0 else itertools.count(): + last_error = self._connect_attempt(mode=mode, esp32r0_delay=False) + if last_error is None: + break + last_error = self._connect_attempt(mode=mode, esp32r0_delay=True) + if last_error is None: + break + finally: + print('') # end 'Connecting...' line + + if last_error is not None: + raise FatalError('Failed to connect to %s: %s' % (self.CHIP_NAME, last_error)) + + if not detecting: + try: + # check the date code registers match what we expect to see + chip_magic_value = self.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR) + if chip_magic_value != self.CHIP_DETECT_MAGIC_VALUE: + actually = None + for cls in [ESP8266ROM, ESP32ROM, ESP32S2ROM, ESP32S3BETA2ROM, ESP32C3ROM]: + if chip_magic_value == cls.CHIP_DETECT_MAGIC_VALUE: + actually = cls + break + if actually is None: + print(("WARNING: This chip doesn't appear to be a %s (chip magic value 0x%08x). " + "Probably it is unsupported by this version of esptool.") % (self.CHIP_NAME, chip_magic_value)) + else: + raise FatalError("This chip is %s not %s. Wrong --chip argument?" % (actually.CHIP_NAME, self.CHIP_NAME)) + except UnsupportedCommandError: + self.secure_download_mode = True + self._post_connect() + + def _post_connect(self): + """ + Additional initialization hook, may be overridden by the chip-specific class. + Gets called after connect, and after auto-detection. + """ + pass - """ Read memory address in target """ def read_reg(self, addr): - res = self.command(ESPROM.ESP_READ_REG, struct.pack(' 0: + # add a dummy write to a date register as an excuse to have a delay + command += struct.pack(' start: + raise FatalError(("Software loader is resident at 0x%08x-0x%08x. " + "Can't load binary at overlapping address range 0x%08x-0x%08x. " + "Either change binary loading address, or use the --no-stub " + "option to disable the software loader.") % (start, end, load_start, load_end)) + + return self.check_command("enter RAM download mode", self.ESP_MEM_BEGIN, + struct.pack(' length: + raise FatalError('Read more than expected') + + digest_frame = self.read() + if len(digest_frame) != 16: + raise FatalError('Expected digest, got: %s' % hexify(digest_frame)) + expected_digest = hexify(digest_frame).upper() + digest = hashlib.md5(data).hexdigest().upper() + if digest != expected_digest: + raise FatalError('Digest mismatch: expected %s, got %s' % (expected_digest, digest)) + return data + + def flash_spi_attach(self, hspi_arg): + """Send SPI attach command to enable the SPI flash pins + + ESP8266 ROM does this when you send flash_begin, ESP32 ROM + has it as a SPI command. + """ + # last 3 bytes in ESP_SPI_ATTACH argument are reserved values + arg = struct.pack(' 0: + self.write_reg(SPI_MOSI_DLEN_REG, mosi_bits - 1) + if miso_bits > 0: + self.write_reg(SPI_MISO_DLEN_REG, miso_bits - 1) + else: + + def set_data_lengths(mosi_bits, miso_bits): + SPI_DATA_LEN_REG = SPI_USR1_REG + SPI_MOSI_BITLEN_S = 17 + SPI_MISO_BITLEN_S = 8 + mosi_mask = 0 if (mosi_bits == 0) else (mosi_bits - 1) + miso_mask = 0 if (miso_bits == 0) else (miso_bits - 1) + self.write_reg(SPI_DATA_LEN_REG, + (miso_mask << SPI_MISO_BITLEN_S) | ( + mosi_mask << SPI_MOSI_BITLEN_S)) + + # SPI peripheral "command" bitmasks for SPI_CMD_REG + SPI_CMD_USR = (1 << 18) + + # shift values + SPI_USR2_COMMAND_LEN_SHIFT = 28 + + if read_bits > 32: + raise FatalError("Reading more than 32 bits back from a SPI flash operation is unsupported") + if len(data) > 64: + raise FatalError("Writing more than 64 bytes of data with one SPI command is unsupported") + + data_bits = len(data) * 8 + old_spi_usr = self.read_reg(SPI_USR_REG) + old_spi_usr2 = self.read_reg(SPI_USR2_REG) + flags = SPI_USR_COMMAND + if read_bits > 0: + flags |= SPI_USR_MISO + if data_bits > 0: + flags |= SPI_USR_MOSI + set_data_lengths(data_bits, read_bits) + self.write_reg(SPI_USR_REG, flags) + self.write_reg(SPI_USR2_REG, + (7 << SPI_USR2_COMMAND_LEN_SHIFT) | spiflash_command) + if data_bits == 0: + self.write_reg(SPI_W0_REG, 0) # clear data register before we read it + else: + data = pad_to(data, 4, b'\00') # pad to 32-bit multiple + words = struct.unpack("I" * (len(data) // 4), data) + next_reg = SPI_W0_REG + for word in words: + self.write_reg(next_reg, word) + next_reg += 4 + self.write_reg(SPI_CMD_REG, SPI_CMD_USR) + + def wait_done(): + for _ in range(10): + if (self.read_reg(SPI_CMD_REG) & SPI_CMD_USR) == 0: + return + raise FatalError("SPI command did not complete in time") + wait_done() + + status = self.read_reg(SPI_W0_REG) + # restore some SPI controller registers + self.write_reg(SPI_USR_REG, old_spi_usr) + self.write_reg(SPI_USR2_REG, old_spi_usr2) + return status + + def read_status(self, num_bytes=2): + """Read up to 24 bits (num_bytes) of SPI flash status register contents + via RDSR, RDSR2, RDSR3 commands + + Not all SPI flash supports all three commands. The upper 1 or 2 + bytes may be 0xFF. + """ + SPIFLASH_RDSR = 0x05 + SPIFLASH_RDSR2 = 0x35 + SPIFLASH_RDSR3 = 0x15 + + status = 0 + shift = 0 + for cmd in [SPIFLASH_RDSR, SPIFLASH_RDSR2, SPIFLASH_RDSR3][0:num_bytes]: + status += self.run_spiflash_command(cmd, read_bits=8) << shift + shift += 8 + return status + + def write_status(self, new_status, num_bytes=2, set_non_volatile=False): + """Write up to 24 bits (num_bytes) of new status register + + num_bytes can be 1, 2 or 3. + + Not all flash supports the additional commands to write the + second and third byte of the status register. When writing 2 + bytes, esptool also sends a 16-byte WRSR command (as some + flash types use this instead of WRSR2.) + + If the set_non_volatile flag is set, non-volatile bits will + be set as well as volatile ones (WREN used instead of WEVSR). + + """ + SPIFLASH_WRSR = 0x01 + SPIFLASH_WRSR2 = 0x31 + SPIFLASH_WRSR3 = 0x11 + SPIFLASH_WEVSR = 0x50 + SPIFLASH_WREN = 0x06 + SPIFLASH_WRDI = 0x04 + + enable_cmd = SPIFLASH_WREN if set_non_volatile else SPIFLASH_WEVSR + + # try using a 16-bit WRSR (not supported by all chips) + # this may be redundant, but shouldn't hurt + if num_bytes == 2: + self.run_spiflash_command(enable_cmd) + self.run_spiflash_command(SPIFLASH_WRSR, struct.pack(">= 8 + + self.run_spiflash_command(SPIFLASH_WRDI) + + def get_crystal_freq(self): + # Figure out the crystal frequency from the UART clock divider + # Returns a normalized value in integer MHz (40 or 26 are the only supported values) + # + # The logic here is: + # - We know that our baud rate and the ESP UART baud rate are roughly the same, or we couldn't communicate + # - We can read the UART clock divider register to know how the ESP derives this from the APB bus frequency + # - Multiplying these two together gives us the bus frequency which is either the crystal frequency (ESP32) + # or double the crystal frequency (ESP8266). See the self.XTAL_CLK_DIVIDER parameter for this factor. + uart_div = self.read_reg(self.UART_CLKDIV_REG) & self.UART_CLKDIV_MASK + est_xtal = (self._port.baudrate * uart_div) / 1e6 / self.XTAL_CLK_DIVIDER + norm_xtal = 40 if est_xtal > 33 else 26 + if abs(norm_xtal - est_xtal) > 1: + print("WARNING: Detected crystal freq %.2fMHz is quite different to normalized freq %dMHz. Unsupported crystal in use?" % (est_xtal, norm_xtal)) + return norm_xtal + + def hard_reset(self): + self._setRTS(True) # EN->LOW + time.sleep(0.1) + self._setRTS(False) + + def soft_reset(self, stay_in_bootloader): + if not self.IS_STUB: + if stay_in_bootloader: + return # ROM bootloader is already in bootloader! + else: + # 'run user code' is as close to a soft reset as we can do + self.flash_begin(0, 0) + self.flash_finish(False) + else: + if stay_in_bootloader: + # soft resetting from the stub loader + # will re-load the ROM bootloader + self.flash_begin(0, 0) + self.flash_finish(True) + elif self.CHIP_NAME != "ESP8266": + raise FatalError("Soft resetting is currently only supported on ESP8266") + else: + # running user code from stub loader requires some hacks + # in the stub loader + self.command(self.ESP_RUN_USER_CODE, wait_response=False) + + +class ESP8266ROM(ESPLoader): + """ Access class for ESP8266 ROM bootloader + """ + CHIP_NAME = "ESP8266" + IS_STUB = False + + CHIP_DETECT_MAGIC_VALUE = 0xfff0c101 + + # OTP ROM addresses + ESP_OTP_MAC0 = 0x3ff00050 + ESP_OTP_MAC1 = 0x3ff00054 + ESP_OTP_MAC3 = 0x3ff0005c + + SPI_REG_BASE = 0x60000200 + SPI_USR_OFFS = 0x1c + SPI_USR1_OFFS = 0x20 + SPI_USR2_OFFS = 0x24 + SPI_MOSI_DLEN_OFFS = None + SPI_MISO_DLEN_OFFS = None + SPI_W0_OFFS = 0x40 + + UART_CLKDIV_REG = 0x60000014 + + XTAL_CLK_DIVIDER = 2 + + FLASH_SIZES = { + '512KB': 0x00, + '256KB': 0x10, + '1MB': 0x20, + '2MB': 0x30, + '4MB': 0x40, + '2MB-c1': 0x50, + '4MB-c1': 0x60, + '8MB': 0x80, + '16MB': 0x90, + } + + BOOTLOADER_FLASH_OFFSET = 0 + + MEMORY_MAP = [[0x3FF00000, 0x3FF00010, "DPORT"], + [0x3FFE8000, 0x40000000, "DRAM"], + [0x40100000, 0x40108000, "IRAM"], + [0x40201010, 0x402E1010, "IROM"]] + + def get_efuses(self): + # Return the 128 bits of ESP8266 efuse as a single Python integer + result = self.read_reg(0x3ff0005c) << 96 + result |= self.read_reg(0x3ff00058) << 64 + result |= self.read_reg(0x3ff00054) << 32 + result |= self.read_reg(0x3ff00050) + return result + + def get_chip_description(self): + efuses = self.get_efuses() + is_8285 = (efuses & ((1 << 4) | 1 << 80)) != 0 # One or the other efuse bit is set for ESP8285 + return "ESP8285" if is_8285 else "ESP8266EX" + + def get_chip_features(self): + features = ["WiFi"] + if self.get_chip_description() == "ESP8285": + features += ["Embedded Flash"] + return features + + def flash_spi_attach(self, hspi_arg): + if self.IS_STUB: + super(ESP8266ROM, self).flash_spi_attach(hspi_arg) + else: + # ESP8266 ROM has no flash_spi_attach command in serial protocol, + # but flash_begin will do it + self.flash_begin(0, 0) + + def flash_set_parameters(self, size): + # not implemented in ROM, but OK to silently skip for ROM + if self.IS_STUB: + super(ESP8266ROM, self).flash_set_parameters(size) + + def chip_id(self): + """ Read Chip ID from efuse - the equivalent of the SDK system_get_chip_id() function """ + id0 = self.read_reg(self.ESP_OTP_MAC0) + id1 = self.read_reg(self.ESP_OTP_MAC1) + return (id0 >> 24) | ((id1 & MAX_UINT24) << 8) + def read_mac(self): + """ Read MAC from OTP ROM """ mac0 = self.read_reg(self.ESP_OTP_MAC0) mac1 = self.read_reg(self.ESP_OTP_MAC1) mac3 = self.read_reg(self.ESP_OTP_MAC3) @@ -249,72 +1176,740 @@ class ESPROM(object): raise FatalError("Unknown OUI") return oui + ((mac1 >> 8) & 0xff, mac1 & 0xff, (mac0 >> 24) & 0xff) - """ Read Chip ID from OTP ROM - see http://esp8266-re.foogod.com/wiki/System_get_chip_id_%28IoT_RTOS_SDK_0.9.9%29 """ + def get_erase_size(self, offset, size): + """ Calculate an erase size given a specific size in bytes. + + Provides a workaround for the bootloader erase bug.""" + + sectors_per_block = 16 + sector_size = self.FLASH_SECTOR_SIZE + num_sectors = (size + sector_size - 1) // sector_size + start_sector = offset // sector_size + + head_sectors = sectors_per_block - (start_sector % sectors_per_block) + if num_sectors < head_sectors: + head_sectors = num_sectors + + if num_sectors < 2 * head_sectors: + return (num_sectors + 1) // 2 * sector_size + else: + return (num_sectors - head_sectors) * sector_size + + def override_vddsdio(self, new_voltage): + raise NotImplementedInROMError("Overriding VDDSDIO setting only applies to ESP32") + + +class ESP8266StubLoader(ESP8266ROM): + """ Access class for ESP8266 stub loader, runs on top of ROM. + """ + FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c + IS_STUB = True + + def __init__(self, rom_loader): + self.secure_download_mode = rom_loader.secure_download_mode + self._port = rom_loader._port + self._trace_enabled = rom_loader._trace_enabled + self.flush_input() # resets _slip_reader + + def get_erase_size(self, offset, size): + return size # stub doesn't have same size bug as ROM loader + + +ESP8266ROM.STUB_CLASS = ESP8266StubLoader + + +class ESP32ROM(ESPLoader): + """Access class for ESP32 ROM bootloader + + """ + CHIP_NAME = "ESP32" + IMAGE_CHIP_ID = 0 + IS_STUB = False + + CHIP_DETECT_MAGIC_VALUE = 0x00f01d83 + + IROM_MAP_START = 0x400d0000 + IROM_MAP_END = 0x40400000 + + DROM_MAP_START = 0x3F400000 + DROM_MAP_END = 0x3F800000 + + # ESP32 uses a 4 byte status reply + STATUS_BYTES_LENGTH = 4 + + SPI_REG_BASE = 0x3ff42000 + SPI_USR_OFFS = 0x1c + SPI_USR1_OFFS = 0x20 + SPI_USR2_OFFS = 0x24 + SPI_MOSI_DLEN_OFFS = 0x28 + SPI_MISO_DLEN_OFFS = 0x2c + EFUSE_RD_REG_BASE = 0x3ff5a000 + + EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE + 0x18 + EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = (1 << 7) # EFUSE_RD_DISABLE_DL_ENCRYPT + + DR_REG_SYSCON_BASE = 0x3ff66000 + + SPI_W0_OFFS = 0x80 + + UART_CLKDIV_REG = 0x3ff40014 + + XTAL_CLK_DIVIDER = 1 + + FLASH_SIZES = { + '1MB': 0x00, + '2MB': 0x10, + '4MB': 0x20, + '8MB': 0x30, + '16MB': 0x40 + } + + BOOTLOADER_FLASH_OFFSET = 0x1000 + + OVERRIDE_VDDSDIO_CHOICES = ["1.8V", "1.9V", "OFF"] + + MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], + [0x3F400000, 0x3F800000, "DROM"], + [0x3F800000, 0x3FC00000, "EXTRAM_DATA"], + [0x3FF80000, 0x3FF82000, "RTC_DRAM"], + [0x3FF90000, 0x40000000, "BYTE_ACCESSIBLE"], + [0x3FFAE000, 0x40000000, "DRAM"], + [0x3FFE0000, 0x3FFFFFFC, "DIRAM_DRAM"], + [0x40000000, 0x40070000, "IROM"], + [0x40070000, 0x40078000, "CACHE_PRO"], + [0x40078000, 0x40080000, "CACHE_APP"], + [0x40080000, 0x400A0000, "IRAM"], + [0x400A0000, 0x400BFFFC, "DIRAM_IRAM"], + [0x400C0000, 0x400C2000, "RTC_IRAM"], + [0x400D0000, 0x40400000, "IROM"], + [0x50000000, 0x50002000, "RTC_DATA"]] + + FLASH_ENCRYPTED_WRITE_ALIGN = 32 + + """ Try to read the BLOCK1 (encryption key) and check if it is valid """ + + def is_flash_encryption_key_valid(self): + + """ Bit 0 of efuse_rd_disable[3:0] is mapped to BLOCK1 + this bit is at position 16 in EFUSE_BLK0_RDATA0_REG """ + word0 = self.read_efuse(0) + rd_disable = (word0 >> 16) & 0x1 + + # reading of BLOCK1 is NOT ALLOWED so we assume valid key is programmed + if rd_disable: + return True + else: + # reading of BLOCK1 is ALLOWED so we will read and verify for non-zero. + # When ESP32 has not generated AES/encryption key in BLOCK1, the contents will be readable and 0. + # If the flash encryption is enabled it is expected to have a valid non-zero key. We break out on + # first occurance of non-zero value + key_word = [0] * 7 + for i in range(len(key_word)): + key_word[i] = self.read_efuse(14 + i) + # key is non-zero so break & return + if key_word[i] != 0: + return True + return False + + def get_flash_crypt_config(self): + """ For flash encryption related commands we need to make sure + user has programmed all the relevant efuse correctly so before + writing encrypted write_flash_encrypt esptool will verify the values + of flash_crypt_config to be non zero if they are not read + protected. If the values are zero a warning will be printed + + bit 3 in efuse_rd_disable[3:0] is mapped to flash_crypt_config + this bit is at position 19 in EFUSE_BLK0_RDATA0_REG """ + word0 = self.read_efuse(0) + rd_disable = (word0 >> 19) & 0x1 + + if rd_disable == 0: + """ we can read the flash_crypt_config efuse value + so go & read it (EFUSE_BLK0_RDATA5_REG[31:28]) """ + word5 = self.read_efuse(5) + word5 = (word5 >> 28) & 0xF + return word5 + else: + # if read of the efuse is disabled we assume it is set correctly + return 0xF + + def get_encrypted_download_disabled(self): + if self.read_reg(self.EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG) & self.EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT: + return True + else: + return False + + def get_pkg_version(self): + word3 = self.read_efuse(3) + pkg_version = (word3 >> 9) & 0x07 + pkg_version += ((word3 >> 2) & 0x1) << 3 + return pkg_version + + def get_chip_revision(self): + word3 = self.read_efuse(3) + word5 = self.read_efuse(5) + apb_ctl_date = self.read_reg(self.DR_REG_SYSCON_BASE + 0x7C) + + rev_bit0 = (word3 >> 15) & 0x1 + rev_bit1 = (word5 >> 20) & 0x1 + rev_bit2 = (apb_ctl_date >> 31) & 0x1 + if rev_bit0: + if rev_bit1: + if rev_bit2: + return 3 + else: + return 2 + else: + return 1 + return 0 + + def get_chip_description(self): + pkg_version = self.get_pkg_version() + chip_revision = self.get_chip_revision() + rev3 = (chip_revision == 3) + single_core = self.read_efuse(3) & (1 << 0) # CHIP_VER DIS_APP_CPU + + chip_name = { + 0: "ESP32-S0WDQ6" if single_core else "ESP32-D0WDQ6", + 1: "ESP32-S0WD" if single_core else "ESP32-D0WD", + 2: "ESP32-D2WD", + 4: "ESP32-U4WDH", + 5: "ESP32-PICO-V3" if rev3 else "ESP32-PICO-D4", + 6: "ESP32-PICO-V3-02", + }.get(pkg_version, "unknown ESP32") + + # ESP32-D0WD-V3, ESP32-D0WDQ6-V3 + if chip_name.startswith("ESP32-D0WD") and rev3: + chip_name += "-V3" + + return "%s (revision %d)" % (chip_name, chip_revision) + + def get_chip_features(self): + features = ["WiFi"] + word3 = self.read_efuse(3) + + # names of variables in this section are lowercase + # versions of EFUSE names as documented in TRM and + # ESP-IDF efuse_reg.h + + chip_ver_dis_bt = word3 & (1 << 1) + if chip_ver_dis_bt == 0: + features += ["BT"] + + chip_ver_dis_app_cpu = word3 & (1 << 0) + if chip_ver_dis_app_cpu: + features += ["Single Core"] + else: + features += ["Dual Core"] + + chip_cpu_freq_rated = word3 & (1 << 13) + if chip_cpu_freq_rated: + chip_cpu_freq_low = word3 & (1 << 12) + if chip_cpu_freq_low: + features += ["160MHz"] + else: + features += ["240MHz"] + + pkg_version = self.get_pkg_version() + if pkg_version in [2, 4, 5, 6]: + features += ["Embedded Flash"] + + if pkg_version == 6: + features += ["Embedded PSRAM"] + + word4 = self.read_efuse(4) + adc_vref = (word4 >> 8) & 0x1F + if adc_vref: + features += ["VRef calibration in efuse"] + + blk3_part_res = word3 >> 14 & 0x1 + if blk3_part_res: + features += ["BLK3 partially reserved"] + + word6 = self.read_efuse(6) + coding_scheme = word6 & 0x3 + features += ["Coding Scheme %s" % { + 0: "None", + 1: "3/4", + 2: "Repeat (UNSUPPORTED)", + 3: "Invalid"}[coding_scheme]] + + return features + + def read_efuse(self, n): + """ Read the nth word of the ESP3x EFUSE region. """ + return self.read_reg(self.EFUSE_RD_REG_BASE + (4 * n)) + def chip_id(self): - id0 = self.read_reg(self.ESP_OTP_MAC0) - id1 = self.read_reg(self.ESP_OTP_MAC1) - return (id0 >> 24) | ((id1 & 0xffffff) << 8) + raise NotSupportedError(self, "chip_id") - """ Read SPI flash manufacturer and device id """ - def flash_id(self): - self.flash_begin(0, 0) - self.write_reg(0x60000240, 0x0, 0xffffffff) - self.write_reg(0x60000200, 0x10000000, 0xffffffff) - flash_id = self.read_reg(0x60000240) - self.flash_finish(False) - return flash_id + def read_mac(self): + """ Read MAC from EFUSE region """ + words = [self.read_efuse(2), self.read_efuse(1)] + bitstring = struct.pack(">II", *words) + bitstring = bitstring[2:8] # trim the 2 byte CRC + try: + return tuple(ord(b) for b in bitstring) + except TypeError: # Python 3, bitstring elements are already bytes + return tuple(bitstring) - """ Abuse the loader protocol to force flash to be left in write mode """ - def flash_unlock_dio(self): - # Enable flash write mode - self.flash_begin(0, 0) - # Reset the chip rather than call flash_finish(), which would have - # write protected the chip again (why oh why does it do that?!) - self.mem_begin(0,0,0,0x40100000) - self.mem_finish(0x40000080) + def get_erase_size(self, offset, size): + return size - """ Perform a chip erase of SPI flash """ - def flash_erase(self): - # Trick ROM to initialize SFlash - self.flash_begin(0, 0) + def override_vddsdio(self, new_voltage): + new_voltage = new_voltage.upper() + if new_voltage not in self.OVERRIDE_VDDSDIO_CHOICES: + raise FatalError("The only accepted VDDSDIO overrides are '1.8V', '1.9V' and 'OFF'") + RTC_CNTL_SDIO_CONF_REG = 0x3ff48074 + RTC_CNTL_XPD_SDIO_REG = (1 << 31) + RTC_CNTL_DREFH_SDIO_M = (3 << 29) + RTC_CNTL_DREFM_SDIO_M = (3 << 27) + RTC_CNTL_DREFL_SDIO_M = (3 << 25) + # RTC_CNTL_SDIO_TIEH = (1 << 23) # not used here, setting TIEH=1 would set 3.3V output, not safe for esptool.py to do + RTC_CNTL_SDIO_FORCE = (1 << 22) + RTC_CNTL_SDIO_PD_EN = (1 << 21) - # This is hacky: we don't have a custom stub, instead we trick - # the bootloader to jump to the SPIEraseChip() routine and then halt/crash - # when it tries to boot an unconfigured system. - self.mem_begin(0,0,0,0x40100000) - self.mem_finish(0x40004984) + reg_val = RTC_CNTL_SDIO_FORCE # override efuse setting + reg_val |= RTC_CNTL_SDIO_PD_EN + if new_voltage != "OFF": + reg_val |= RTC_CNTL_XPD_SDIO_REG # enable internal LDO + if new_voltage == "1.9V": + reg_val |= (RTC_CNTL_DREFH_SDIO_M | RTC_CNTL_DREFM_SDIO_M | RTC_CNTL_DREFL_SDIO_M) # boost voltage + self.write_reg(RTC_CNTL_SDIO_CONF_REG, reg_val) + print("VDDSDIO regulator set to %s" % new_voltage) - # Yup - there's no good way to detect if we succeeded. - # It it on the other hand unlikely to fail. + def read_flash_slow(self, offset, length, progress_fn): + BLOCK_LEN = 64 # ROM read limit per command (this limit is why it's so slow) - def run_stub(self, stub, params, read_output=True): - stub = dict(stub) - stub['code'] = unhexify(stub['code']) - if 'data' in stub: - stub['data'] = unhexify(stub['data']) + data = b'' + while len(data) < length: + block_len = min(BLOCK_LEN, length - len(data)) + r = self.check_command("read flash block", self.ESP_READ_FLASH_SLOW, + struct.pack('> 21) & 0x0F + return pkg_version + + def get_chip_description(self): + chip_name = { + 0: "ESP32-S2", + 1: "ESP32-S2FH16", + 2: "ESP32-S2FH32", + }.get(self.get_pkg_version(), "unknown ESP32-S2") + + return "%s" % (chip_name) + + def get_chip_features(self): + features = ["WiFi"] + + if self.secure_download_mode: + features += ["Secure Download Mode Enabled"] + + pkg_version = self.get_pkg_version() + + if pkg_version in [1, 2]: + if pkg_version == 1: + features += ["Embedded 2MB Flash"] + elif pkg_version == 2: + features += ["Embedded 4MB Flash"] + features += ["105C temp rating"] + + num_word = 4 + block2_addr = self.EFUSE_BASE + 0x05C + word4 = self.read_reg(block2_addr + (4 * num_word)) + block2_version = (word4 >> 4) & 0x07 + + if block2_version == 1: + features += ["ADC and temperature sensor calibration in BLK2 of efuse"] + return features + + def get_crystal_freq(self): + # ESP32-S2 XTAL is fixed to 40MHz + return 40 + + def override_vddsdio(self, new_voltage): + raise NotImplementedInROMError("VDD_SDIO overrides are not supported for ESP32-S2") + + def read_mac(self): + mac0 = self.read_reg(self.MAC_EFUSE_REG) + mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC + bitstring = struct.pack(">II", mac1, mac0)[2:] + try: + return tuple(ord(b) for b in bitstring) + except TypeError: # Python 3, bitstring elements are already bytes + return tuple(bitstring) + + def get_flash_crypt_config(self): + return None # doesn't exist on ESP32-S2 + + def get_key_block_purpose(self, key_block): + if key_block < 0 or key_block > 5: + raise FatalError("Valid key block numbers must be in range 0-5") + + reg, shift = [(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), + (self.EFUSE_PURPOSE_KEY1_REG, self.EFUSE_PURPOSE_KEY1_SHIFT), + (self.EFUSE_PURPOSE_KEY2_REG, self.EFUSE_PURPOSE_KEY2_SHIFT), + (self.EFUSE_PURPOSE_KEY3_REG, self.EFUSE_PURPOSE_KEY3_SHIFT), + (self.EFUSE_PURPOSE_KEY4_REG, self.EFUSE_PURPOSE_KEY4_SHIFT), + (self.EFUSE_PURPOSE_KEY5_REG, self.EFUSE_PURPOSE_KEY5_SHIFT)][key_block] + return (self.read_reg(reg) >> shift) & 0xF + + def is_flash_encryption_key_valid(self): + # Need to see either an AES-128 key or two AES-256 keys + purposes = [self.get_key_block_purpose(b) for b in range(6)] + + if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): + return True + + return any(p == self.PURPOSE_VAL_XTS_AES256_KEY_1 for p in purposes) \ + and any(p == self.PURPOSE_VAL_XTS_AES256_KEY_2 for p in purposes) + + def uses_usb(self, _cache=[]): + if self.secure_download_mode: + return False # can't detect native USB in secure download mode + if not _cache: + buf_no = self.read_reg(self.UARTDEV_BUF_NO) & 0xff + _cache.append(buf_no == self.UARTDEV_BUF_NO_USB) + return _cache[0] + + def _post_connect(self): + if self.uses_usb(): + self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK + + def _check_if_can_reset(self): + """ + Check the strapping register to see if we can reset out of download mode. + """ + if os.getenv("ESPTOOL_TESTING") is not None: + print("ESPTOOL_TESTING is set, ignoring strapping mode check") + # Esptool tests over USB CDC run with GPIO0 strapped low, don't complain in this case. + return + strap_reg = self.read_reg(self.GPIO_STRAP_REG) + force_dl_reg = self.read_reg(self.RTC_CNTL_OPTION1_REG) + if strap_reg & self.GPIO_STRAP_SPI_BOOT_MASK == 0 and force_dl_reg & self.RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK == 0: + print("ERROR: {} chip was placed into download mode using GPIO0.\n" + "esptool.py can not exit the download mode over USB. " + "To run the app, reset the chip manually.\n" + "To suppress this error, set --after option to 'no_reset'.".format(self.get_chip_description())) + raise SystemExit(1) + + def hard_reset(self): + if self.uses_usb(): + self._check_if_can_reset() + + self._setRTS(True) # EN->LOW + if self.uses_usb(): + # Give the chip some time to come out of reset, to be able to handle further DTR/RTS transitions + time.sleep(0.2) + self._setRTS(False) + time.sleep(0.2) + else: + self._setRTS(False) + + +class ESP32S3BETA2ROM(ESP32ROM): + CHIP_NAME = "ESP32-S3(beta2)" + IMAGE_CHIP_ID = 4 + + IROM_MAP_START = 0x42000000 + IROM_MAP_END = 0x44000000 + DROM_MAP_START = 0x3c000000 + DROM_MAP_END = 0x3e000000 + + UART_DATE_REG_ADDR = 0x60000080 + + CHIP_DETECT_MAGIC_VALUE = 0xeb004136 + + SPI_REG_BASE = 0x60002000 + SPI_USR_OFFS = 0x18 + SPI_USR1_OFFS = 0x1c + SPI_USR2_OFFS = 0x20 + SPI_MOSI_DLEN_OFFS = 0x24 + SPI_MISO_DLEN_OFFS = 0x28 + SPI_W0_OFFS = 0x58 + + EFUSE_REG_BASE = 0x6001A030 # BLOCK0 read base address + + MAC_EFUSE_REG = 0x6001A000 # ESP32S3 has special block for MAC efuses + + UART_CLKDIV_REG = 0x60000014 + + GPIO_STRAP_REG = 0x60004038 + + MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], + [0x3C000000, 0x3D000000, "DROM"], + [0x3D000000, 0x3E000000, "EXTRAM_DATA"], + [0x600FE000, 0x60100000, "RTC_DRAM"], + [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"], + [0x3FC88000, 0x403E2000, "MEM_INTERNAL"], + [0x3FC88000, 0x3FD00000, "DRAM"], + [0x40000000, 0x4001A100, "IROM_MASK"], + [0x40370000, 0x403E0000, "IRAM"], + [0x600FE000, 0x60100000, "RTC_IRAM"], + [0x42000000, 0x42800000, "IROM"], + [0x50000000, 0x50002000, "RTC_DATA"]] + + def get_chip_description(self): + return "ESP32-S3(beta2)" + + def get_chip_features(self): + return ["WiFi", "BLE"] + + def get_crystal_freq(self): + # ESP32S3 XTAL is fixed to 40MHz + return 40 + + def override_vddsdio(self, new_voltage): + raise NotImplementedInROMError("VDD_SDIO overrides are not supported for ESP32-S3") + + def read_mac(self): + mac0 = self.read_reg(self.MAC_EFUSE_REG) + mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC + bitstring = struct.pack(">II", mac1, mac0)[2:] + try: + return tuple(ord(b) for b in bitstring) + except TypeError: # Python 3, bitstring elements are already bytes + return tuple(bitstring) + + +class ESP32C3ROM(ESP32ROM): + CHIP_NAME = "ESP32-C3" + IMAGE_CHIP_ID = 5 + + IROM_MAP_START = 0x42000000 + IROM_MAP_END = 0x42800000 + DROM_MAP_START = 0x3c000000 + DROM_MAP_END = 0x3c800000 + + SPI_REG_BASE = 0x3f402000 + SPI_USR_OFFS = 0x18 + SPI_USR1_OFFS = 0x1c + SPI_USR2_OFFS = 0x20 + SPI_MOSI_DLEN_OFFS = 0x24 + SPI_MISO_DLEN_OFFS = 0x28 + SPI_W0_OFFS = 0xA8 + + BOOTLOADER_FLASH_OFFSET = 0x0 + + CHIP_DETECT_MAGIC_VALUE = 0x6921506f + + UART_DATE_REG_ADDR = 0x60000000 + 0x7c + + EFUSE_BASE = 0x60008800 + MAC_EFUSE_REG = EFUSE_BASE + 0x044 + + GPIO_STRAP_REG = 0x3f404038 + + FLASH_ENCRYPTED_WRITE_ALIGN = 16 + + MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], + [0x3C000000, 0x3C800000, "DROM"], + [0x3FC80000, 0x3FCE0000, "DRAM"], + [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"], + [0x3FF00000, 0x3FF20000, "DROM_MASK"], + [0x40000000, 0x40060000, "IROM_MASK"], + [0x42000000, 0x42800000, "IROM"], + [0x4037C000, 0x403E0000, "IRAM"], + [0x50000000, 0x50002000, "RTC_IRAM"], + [0x50000000, 0x50002000, "RTC_DRAM"], + [0x600FE000, 0x60100000, "MEM_INTERNAL2"]] + + def get_pkg_version(self): + num_word = 3 + block1_addr = self.EFUSE_BASE + 0x044 + word3 = self.read_reg(block1_addr + (4 * num_word)) + pkg_version = (word3 >> 21) & 0x0F + return pkg_version + + def get_chip_description(self): + chip_name = { + 0: "ESP32-C3", + }.get(self.get_pkg_version(), "unknown ESP32-C3") + + return "%s" % (chip_name) + + def get_chip_features(self): + return ["Wi-Fi"] + + def get_crystal_freq(self): + # ESP32C3 XTAL is fixed to 40MHz + return 40 + + def override_vddsdio(self, new_voltage): + raise NotImplementedInROMError("VDD_SDIO overrides are not supported for ESP32-C3") + + def read_mac(self): + mac0 = self.read_reg(self.MAC_EFUSE_REG) + mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC + bitstring = struct.pack(">II", mac1, mac0)[2:] + try: + return tuple(ord(b) for b in bitstring) + except TypeError: # Python 3, bitstring elements are already bytes + return tuple(bitstring) + + +class ESP32StubLoader(ESP32ROM): + """ Access class for ESP32 stub loader, runs on top of ROM. + """ + FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c + STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM + IS_STUB = True + + def __init__(self, rom_loader): + self.secure_download_mode = rom_loader.secure_download_mode + self._port = rom_loader._port + self._trace_enabled = rom_loader._trace_enabled + self.flush_input() # resets _slip_reader + + +ESP32ROM.STUB_CLASS = ESP32StubLoader + + +class ESP32S2StubLoader(ESP32S2ROM): + """ Access class for ESP32-S2 stub loader, runs on top of ROM. + + (Basically the same as ESP32StubLoader, but different base class. + Can possibly be made into a mixin.) + """ + FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c + STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM + IS_STUB = True + + def __init__(self, rom_loader): + self.secure_download_mode = rom_loader.secure_download_mode + self._port = rom_loader._port + self._trace_enabled = rom_loader._trace_enabled + self.flush_input() # resets _slip_reader + + if rom_loader.uses_usb(): + self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK + self.FLASH_WRITE_SIZE = self.USB_RAM_BLOCK + + +ESP32S2ROM.STUB_CLASS = ESP32S2StubLoader + + +class ESP32S3BETA2StubLoader(ESP32S3BETA2ROM): + """ Access class for ESP32S3 stub loader, runs on top of ROM. + + (Basically the same as ESP32StubLoader, but different base class. + Can possibly be made into a mixin.) + """ + FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c + STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM + IS_STUB = True + + def __init__(self, rom_loader): + self.secure_download_mode = rom_loader.secure_download_mode + self._port = rom_loader._port + self._trace_enabled = rom_loader._trace_enabled + self.flush_input() # resets _slip_reader + + +ESP32S3BETA2ROM.STUB_CLASS = ESP32S3BETA2StubLoader + + +class ESP32C3StubLoader(ESP32C3ROM): + """ Access class for ESP32C3 stub loader, runs on top of ROM. + + (Basically the same as ESP32StubLoader, but different base class. + Can possibly be made into a mixin.) + """ + FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c + STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM + IS_STUB = True + + def __init__(self, rom_loader): + self.secure_download_mode = rom_loader.secure_download_mode + self._port = rom_loader._port + self._trace_enabled = rom_loader._trace_enabled + self.flush_input() # resets _slip_reader + + +ESP32C3ROM.STUB_CLASS = ESP32C3StubLoader class ESPBOOTLOADER(object): @@ -327,125 +1922,274 @@ class ESPBOOTLOADER(object): IMAGE_V2_SEGMENT = 4 -def LoadFirmwareImage(filename): - """ Load a firmware image, without knowing what kind of file (v1 or v2) it is. +def LoadFirmwareImage(chip, filename): + """ Load a firmware image. Can be for any supported SoC. - Returns a BaseFirmwareImage subclass, either ESPFirmwareImage (v1) or OTAFirmwareImage (v2). + ESP8266 images will be examined to determine if they are original ROM firmware images (ESP8266ROMFirmwareImage) + or "v2" OTA bootloader images. + + Returns a BaseFirmwareImage subclass, either ESP8266ROMFirmwareImage (v1) or ESP8266V2FirmwareImage (v2). """ + chip = chip.lower().replace("-", "") with open(filename, 'rb') as f: - magic = ord(f.read(1)) - f.seek(0) - if magic == ESPROM.ESP_IMAGE_MAGIC: - return ESPFirmwareImage(f) - elif magic == ESPBOOTLOADER.IMAGE_V2_MAGIC: - return OTAFirmwareImage(f) - else: - raise FatalError("Invalid image magic number: %d" % magic) + if chip == 'esp32': + return ESP32FirmwareImage(f) + elif chip == "esp32s2": + return ESP32S2FirmwareImage(f) + elif chip == "esp32s3beta2": + return ESP32S3BETA2FirmwareImage(f) + elif chip == 'esp32c3': + return ESP32C3FirmwareImage(f) + else: # Otherwise, ESP8266 so look at magic to determine the image type + magic = ord(f.read(1)) + f.seek(0) + if magic == ESPLoader.ESP_IMAGE_MAGIC: + return ESP8266ROMFirmwareImage(f) + elif magic == ESPBOOTLOADER.IMAGE_V2_MAGIC: + return ESP8266V2FirmwareImage(f) + else: + raise FatalError("Invalid image magic number: %d" % magic) + + +class ImageSegment(object): + """ Wrapper class for a segment in an ESP image + (very similar to a section in an ELFImage also) """ + def __init__(self, addr, data, file_offs=None): + self.addr = addr + self.data = data + self.file_offs = file_offs + self.include_in_checksum = True + if self.addr != 0: + self.pad_to_alignment(4) # pad all "real" ImageSegments 4 byte aligned length + + def copy_with_new_addr(self, new_addr): + """ Return a new ImageSegment with same data, but mapped at + a new address. """ + return ImageSegment(new_addr, self.data, 0) + + def split_image(self, split_len): + """ Return a new ImageSegment which splits "split_len" bytes + from the beginning of the data. Remaining bytes are kept in + this segment object (and the start address is adjusted to match.) """ + result = copy.copy(self) + result.data = self.data[:split_len] + self.data = self.data[split_len:] + self.addr += split_len + self.file_offs = None + result.file_offs = None + return result + + def __repr__(self): + r = "len 0x%05x load 0x%08x" % (len(self.data), self.addr) + if self.file_offs is not None: + r += " file_offs 0x%08x" % (self.file_offs) + return r + + def pad_to_alignment(self, alignment): + self.data = pad_to(self.data, alignment, b'\x00') + + +class ELFSection(ImageSegment): + """ Wrapper class for a section in an ELF image, has a section + name as well as the common properties of an ImageSegment. """ + def __init__(self, name, addr, data): + super(ELFSection, self).__init__(addr, data) + self.name = name.decode("utf-8") + + def __repr__(self): + return "%s %s" % (self.name, super(ELFSection, self).__repr__()) class BaseFirmwareImage(object): + SEG_HEADER_LEN = 8 + SHA256_DIGEST_LEN = 32 + """ Base class with common firmware image functions """ def __init__(self): self.segments = [] self.entrypoint = 0 + self.elf_sha256 = None + self.elf_sha256_offset = 0 - def add_segment(self, addr, data, pad_to=4): - """ Add a segment to the image, with specified address & data - (padded to a boundary of pad_to size) """ - # Data should be aligned on word boundary - l = len(data) - if l % pad_to: - data += b"\x00" * (pad_to - l % pad_to) - if l > 0: - self.segments.append((addr, len(data), data)) + def load_common_header(self, load_file, expected_magic): + (magic, segments, self.flash_mode, self.flash_size_freq, self.entrypoint) = struct.unpack(' 16: + raise FatalError('Invalid segment count %d (max 16). Usually this indicates a linker script problem.' % len(self.segments)) def load_segment(self, f, is_irom_segment=False): """ Load the next segment from the image file """ + file_offs = f.tell() (offset, size) = struct.unpack(' 0x40200000 or offset < 0x3ffe0000 or size > 65536: - raise FatalError('Suspicious segment 0x%x, length %d' % (offset, size)) + self.warn_if_unusual_segment(offset, size, is_irom_segment) segment_data = f.read(size) if len(segment_data) < size: raise FatalError('End of file reading segment 0x%x, length %d (actual length %d)' % (offset, size, len(segment_data))) - segment = (offset, size, segment_data) + segment = ImageSegment(offset, segment_data, file_offs) self.segments.append(segment) return segment + def warn_if_unusual_segment(self, offset, size, is_irom_segment): + if not is_irom_segment: + if offset > 0x40200000 or offset < 0x3ffe0000 or size > 65536: + print('WARNING: Suspicious segment 0x%x, length %d' % (offset, size)) + + def maybe_patch_segment_data(self, f, segment_data): + """If SHA256 digest of the ELF file needs to be inserted into this segment, do so. Returns segment data.""" + segment_len = len(segment_data) + file_pos = f.tell() # file_pos is position in the .bin file + if self.elf_sha256_offset >= file_pos and self.elf_sha256_offset < file_pos + segment_len: + # SHA256 digest needs to be patched into this binary segment, + # calculate offset of the digest inside the binary segment. + patch_offset = self.elf_sha256_offset - file_pos + # Sanity checks + if patch_offset < self.SEG_HEADER_LEN or patch_offset + self.SHA256_DIGEST_LEN > segment_len: + raise FatalError('Cannot place SHA256 digest on segment boundary' + '(elf_sha256_offset=%d, file_pos=%d, segment_size=%d)' % + (self.elf_sha256_offset, file_pos, segment_len)) + # offset relative to the data part + patch_offset -= self.SEG_HEADER_LEN + if segment_data[patch_offset:patch_offset + self.SHA256_DIGEST_LEN] != b'\x00' * self.SHA256_DIGEST_LEN: + raise FatalError('Contents of segment at SHA256 digest offset 0x%x are not all zero. Refusing to overwrite.' % + self.elf_sha256_offset) + assert(len(self.elf_sha256) == self.SHA256_DIGEST_LEN) + segment_data = segment_data[0:patch_offset] + self.elf_sha256 + \ + segment_data[patch_offset + self.SHA256_DIGEST_LEN:] + return segment_data + def save_segment(self, f, segment, checksum=None): """ Save the next segment to the image file, return next checksum value if provided """ - (offset, size, data) = segment - f.write(struct.pack(' 0: + if len(irom_segments) != 1: + raise FatalError('Found %d segments that could be irom0. Bad ELF file?' % len(irom_segments)) + return irom_segments[0] + return None + + def get_non_irom_segments(self): + irom_segment = self.get_irom_segment() + return [s for s in self.segments if s != irom_segment] + + +class ESP8266ROMFirmwareImage(BaseFirmwareImage): """ 'Version 1' firmware image, segments loaded directly by the ROM bootloader. """ + + ROM_LOADER = ESP8266ROM + def __init__(self, load_file=None): - super(ESPFirmwareImage, self).__init__() + super(ESP8266ROMFirmwareImage, self).__init__() self.flash_mode = 0 self.flash_size_freq = 0 self.version = 1 if load_file is not None: - (magic, segments, self.flash_mode, self.flash_size_freq, self.entrypoint) = struct.unpack(' 16: - raise FatalError('Invalid firmware image magic=%d segments=%d' % (magic, segments)) - - for i in xrange(segments): + for _ in range(segments): self.load_segment(load_file) self.checksum = self.read_checksum(load_file) - def save(self, filename): - with open(filename, 'wb') as f: - self.write_v1_header(f, self.segments) - checksum = ESPROM.ESP_CHECKSUM_MAGIC - for segment in self.segments: + self.verify() + + def default_output_name(self, input_file): + """ Derive a default output name from the ELF name. """ + return input_file + '-' + + def save(self, basename): + """ Save a set of V1 images for flashing. Parameter is a base filename. """ + # IROM data goes in its own plain binary file + irom_segment = self.get_irom_segment() + if irom_segment is not None: + with open("%s0x%05x.bin" % (basename, irom_segment.addr - ESP8266ROM.IROM_MAP_START), "wb") as f: + f.write(irom_segment.data) + + # everything but IROM goes at 0x00000 in an image file + normal_segments = self.get_non_irom_segments() + with open("%s0x00000.bin" % basename, 'wb') as f: + self.write_common_header(f, normal_segments) + checksum = ESPLoader.ESP_CHECKSUM_MAGIC + for segment in normal_segments: checksum = self.save_segment(f, segment, checksum) self.append_checksum(f, checksum) -class OTAFirmwareImage(BaseFirmwareImage): +ESP8266ROM.BOOTLOADER_IMAGE = ESP8266ROMFirmwareImage + + +class ESP8266V2FirmwareImage(BaseFirmwareImage): """ 'Version 2' firmware image, segments loaded by software bootloader stub (ie Espressif bootloader or rboot) """ + + ROM_LOADER = ESP8266ROM + def __init__(self, load_file=None): - super(OTAFirmwareImage, self).__init__() + super(ESP8266V2FirmwareImage, self).__init__() self.version = 2 if load_file is not None: - (magic, segments, first_flash_mode, first_flash_size_freq, first_entrypoint) = struct.unpack(' 16: - raise FatalError('Invalid V2 second header magic=%d segments=%d' % (magic, segments)) - # load all the usual segments - for _ in xrange(segments): + for _ in range(segments): self.load_segment(load_file) self.checksum = self.read_checksum(load_file) + self.verify() + + def default_output_name(self, input_file): + """ Derive a default output name from the ELF name. """ + irom_segment = self.get_irom_segment() + if irom_segment is not None: + irom_offs = irom_segment.addr - ESP8266ROM.IROM_MAP_START + else: + irom_offs = 0 + return "%s-0x%05x.bin" % (os.path.splitext(input_file)[0], + irom_offs & ~(ESPLoader.FLASH_SECTOR_SIZE - 1)) + def save(self, filename): with open(filename, 'wb') as f: # Save first header for irom0 segment - f.write(struct.pack(' 0: + last_addr = flash_segments[0].addr + for segment in flash_segments[1:]: + if segment.addr // self.IROM_ALIGN == last_addr // self.IROM_ALIGN: + raise FatalError(("Segment loaded at 0x%08x lands in same 64KB flash mapping as segment loaded at 0x%08x. " + "Can't generate binary. Suggest changing linker script or ELF to merge sections.") % + (segment.addr, last_addr)) + last_addr = segment.addr + + def get_alignment_data_needed(segment): + # Actual alignment (in data bytes) required for a segment header: positioned so that + # after we write the next 8 byte header, file_offs % IROM_ALIGN == segment.addr % IROM_ALIGN + # + # (this is because the segment's vaddr may not be IROM_ALIGNed, more likely is aligned + # IROM_ALIGN+0x18 to account for the binary file header + align_past = (segment.addr % self.IROM_ALIGN) - self.SEG_HEADER_LEN + pad_len = (self.IROM_ALIGN - (f.tell() % self.IROM_ALIGN)) + align_past + if pad_len == 0 or pad_len == self.IROM_ALIGN: + return 0 # already aligned + + # subtract SEG_HEADER_LEN a second time, as the padding block has a header as well + pad_len -= self.SEG_HEADER_LEN + if pad_len < 0: + pad_len += self.IROM_ALIGN + return pad_len + + # try to fit each flash segment on a 64kB aligned boundary + # by padding with parts of the non-flash segments... + while len(flash_segments) > 0: + segment = flash_segments[0] + pad_len = get_alignment_data_needed(segment) + if pad_len > 0: # need to pad + if len(ram_segments) > 0 and pad_len > self.SEG_HEADER_LEN: + pad_segment = ram_segments[0].split_image(pad_len) + if len(ram_segments[0].data) == 0: + ram_segments.pop(0) + else: + pad_segment = ImageSegment(0, b'\x00' * pad_len, f.tell()) + checksum = self.save_segment(f, pad_segment, checksum) + total_segments += 1 + else: + # write the flash segment + assert (f.tell() + 8) % self.IROM_ALIGN == segment.addr % self.IROM_ALIGN + checksum = self.save_flash_segment(f, segment, checksum) + flash_segments.pop(0) + total_segments += 1 + + # flash segments all written, so write any remaining RAM segments + for segment in ram_segments: + checksum = self.save_segment(f, segment, checksum) + total_segments += 1 + + if self.secure_pad: + # pad the image so that after signing it will end on a a 64KB boundary. + # This ensures all mapped flash content will be verified. + if not self.append_digest: + raise FatalError("secure_pad only applies if a SHA-256 digest is also appended to the image") + align_past = (f.tell() + self.SEG_HEADER_LEN) % self.IROM_ALIGN + # 16 byte aligned checksum (force the alignment to simplify calculations) + checksum_space = 16 + if self.secure_pad == '1': + # after checksum: SHA-256 digest + (to be added by signing process) version, signature + 12 trailing bytes due to alignment + space_after_checksum = 32 + 4 + 64 + 12 + elif self.secure_pad == '2': # Secure Boot V2 + # after checksum: SHA-256 digest + signature sector, but we place signature sector after the 64KB boundary + space_after_checksum = 32 + pad_len = (self.IROM_ALIGN - align_past - checksum_space - space_after_checksum) % self.IROM_ALIGN + pad_segment = ImageSegment(0, b'\x00' * pad_len, f.tell()) + + checksum = self.save_segment(f, pad_segment, checksum) + total_segments += 1 + + # done writing segments + self.append_checksum(f, checksum) + image_length = f.tell() + + if self.secure_pad: + assert ((image_length + space_after_checksum) % self.IROM_ALIGN) == 0 + + # kinda hacky: go back to the initial header and write the new segment count + # that includes padding segments. This header is not checksummed + f.seek(1) + try: + f.write(chr(total_segments)) + except TypeError: # Python 3 + f.write(bytes([total_segments])) + + if self.append_digest: + # calculate the SHA256 of the whole file and append it + f.seek(0) + digest = hashlib.sha256() + digest.update(f.read(image_length)) + f.write(digest.digest()) + + with open(filename, 'wb') as real_file: + real_file.write(f.getvalue()) + + def save_flash_segment(self, f, segment, checksum=None): + """ Save the next segment to the image file, return next checksum value if provided """ + segment_end_pos = f.tell() + len(segment.data) + self.SEG_HEADER_LEN + segment_len_remainder = segment_end_pos % self.IROM_ALIGN + if segment_len_remainder < 0x24: + # Work around a bug in ESP-IDF 2nd stage bootloader, that it didn't map the + # last MMU page, if an IROM/DROM segment was < 0x24 bytes over the page boundary. + segment.data += b'\x00' * (0x24 - segment_len_remainder) + return self.save_segment(f, segment, checksum) + + def load_extended_header(self, load_file): + def split_byte(n): + return (n & 0x0F, (n >> 4) & 0x0F) + + fields = list(struct.unpack(self.EXTENDED_HEADER_STRUCT_FMT, load_file.read(16))) + + self.wp_pin = fields[0] + + # SPI pin drive stengths are two per byte + self.clk_drv, self.q_drv = split_byte(fields[1]) + self.d_drv, self.cs_drv = split_byte(fields[2]) + self.hd_drv, self.wp_drv = split_byte(fields[3]) + + chip_id = fields[4] + if chip_id != self.ROM_LOADER.IMAGE_CHIP_ID: + print(("Unexpected chip id in image. Expected %d but value was %d. " + "Is this image for a different chip model?") % (self.ROM_LOADER.IMAGE_CHIP_ID, chip_id)) + + # reserved fields in the middle should all be zero + if any(f for f in fields[6:-1] if f != 0): + print("Warning: some reserved header fields have non-zero values. This image may be from a newer esptool.py?") + + append_digest = fields[-1] # last byte is append_digest + if append_digest in [0, 1]: + self.append_digest = (append_digest == 1) + else: + raise RuntimeError("Invalid value for append_digest field (0x%02x). Should be 0 or 1.", append_digest) + + def save_extended_header(self, save_file): + def join_byte(ln, hn): + return (ln & 0x0F) + ((hn & 0x0F) << 4) + + append_digest = 1 if self.append_digest else 0 + + fields = [self.wp_pin, + join_byte(self.clk_drv, self.q_drv), + join_byte(self.d_drv, self.cs_drv), + join_byte(self.hd_drv, self.wp_drv), + self.ROM_LOADER.IMAGE_CHIP_ID, + self.min_rev] + fields += [0] * 8 # padding + fields += [append_digest] + + packed = struct.pack(self.EXTENDED_HEADER_STRUCT_FMT, *fields) + save_file.write(packed) + + +ESP32ROM.BOOTLOADER_IMAGE = ESP32FirmwareImage + + +class ESP32S2FirmwareImage(ESP32FirmwareImage): + """ ESP32S2 Firmware Image almost exactly the same as ESP32FirmwareImage """ + ROM_LOADER = ESP32S2ROM + + +ESP32S2ROM.BOOTLOADER_IMAGE = ESP32S2FirmwareImage + + +class ESP32S3BETA2FirmwareImage(ESP32FirmwareImage): + """ ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage """ + ROM_LOADER = ESP32S3BETA2ROM + + +ESP32S3BETA2ROM.BOOTLOADER_IMAGE = ESP32S3BETA2FirmwareImage + + +class ESP32C3FirmwareImage(ESP32FirmwareImage): + """ ESP32C3 Firmware Image almost exactly the same as ESP32FirmwareImage """ + ROM_LOADER = ESP32C3ROM + + +ESP32C3ROM.BOOTLOADER_IMAGE = ESP32C3FirmwareImage + class ELFFile(object): + SEC_TYPE_PROGBITS = 0x01 + SEC_TYPE_STRTAB = 0x03 + + LEN_SEC_HEADER = 0x28 + def __init__(self, name): - self.name = binutils_safe_path(name) - self.symbols = None + # Load sections from the ELF file + self.name = name + with open(self.name, 'rb') as f: + self._read_elf_file(f) - def _fetch_symbols(self): - if self.symbols is not None: - return - self.symbols = {} + def get_section(self, section_name): + for s in self.sections: + if s.name == section_name: + return s + raise ValueError("No section %s in ELF file" % section_name) + + def _read_elf_file(self, f): + # read the ELF file header + LEN_FILE_HEADER = 0x34 try: - tool_nm = "xtensa-lx106-elf-nm" - if os.getenv('XTENSA_CORE') == 'lx106': - tool_nm = "xt-nm" - proc = subprocess.Popen([tool_nm, self.name], stdout=subprocess.PIPE) - except OSError: - print "Error calling %s, do you have Xtensa toolchain in PATH?" % tool_nm - sys.exit(1) - for l in proc.stdout: - fields = l.strip().split() - try: - if fields[0] == "U": - print "Warning: ELF binary has undefined symbol %s" % fields[1] - continue - if fields[0] == "w": - continue # can skip weak symbols - self.symbols[fields[2]] = int(fields[0], 16) - except ValueError: - raise FatalError("Failed to strip symbol output from nm: %s" % fields) + (ident, _type, machine, _version, + self.entrypoint, _phoff, shoff, _flags, + _ehsize, _phentsize, _phnum, shentsize, + shnum, shstrndx) = struct.unpack("<16sHHLLLLLHHHHHH", f.read(LEN_FILE_HEADER)) + except struct.error as e: + raise FatalError("Failed to read a valid ELF header from %s: %s" % (self.name, e)) - def get_symbol_addr(self, sym): - self._fetch_symbols() - return self.symbols[sym] + if byte(ident, 0) != 0x7f or ident[1:4] != b'ELF': + raise FatalError("%s has invalid ELF magic header" % self.name) + if machine not in [0x5e, 0xf3]: + raise FatalError("%s does not appear to be an Xtensa or an RISCV ELF file. e_machine=%04x" % (self.name, machine)) + if shentsize != self.LEN_SEC_HEADER: + raise FatalError("%s has unexpected section header entry size 0x%x (not 0x%x)" % (self.name, shentsize, self.LEN_SEC_HEADER)) + if shnum == 0: + raise FatalError("%s has 0 section headers" % (self.name)) + self._read_sections(f, shoff, shnum, shstrndx) - def get_entry_point(self): - tool_readelf = "xtensa-lx106-elf-readelf" - if os.getenv('XTENSA_CORE') == 'lx106': - tool_readelf = "xt-readelf" - try: - proc = subprocess.Popen([tool_readelf, "-h", self.name], stdout=subprocess.PIPE) - except OSError: - print "Error calling %s, do you have Xtensa toolchain in PATH?" % tool_readelf - sys.exit(1) - for l in proc.stdout: - fields = l.strip().split() - if fields[0] == "Entry": - return int(fields[3], 0) + def _read_sections(self, f, section_header_offs, section_header_count, shstrndx): + f.seek(section_header_offs) + len_bytes = section_header_count * self.LEN_SEC_HEADER + section_header = f.read(len_bytes) + if len(section_header) == 0: + raise FatalError("No section header found at offset %04x in ELF file." % section_header_offs) + if len(section_header) != (len_bytes): + raise FatalError("Only read 0x%x bytes from section header (expected 0x%x.) Truncated ELF file?" % (len(section_header), len_bytes)) - def load_section(self, section): - tool_objcopy = "xtensa-lx106-elf-objcopy" - if os.getenv('XTENSA_CORE') == 'lx106': - tool_objcopy = "xt-objcopy" - tmpsection = binutils_safe_path(tempfile.mktemp(suffix=".section")) - try: - subprocess.check_call([tool_objcopy, "--only-section", section, "-Obinary", self.name, tmpsection]) - with open(tmpsection, "rb") as f: - data = f.read() - finally: - os.remove(tmpsection) - return data + # walk through the section header and extract all sections + section_header_offsets = range(0, len(section_header), self.LEN_SEC_HEADER) + + def read_section_header(offs): + name_offs, sec_type, _flags, lma, sec_offs, size = struct.unpack_from(" 0] + self.sections = prog_sections + + def sha256(self): + # return SHA256 hash of the input ELF file + sha256 = hashlib.sha256() + with open(self.name, 'rb') as f: + sha256.update(f.read()) + return sha256.digest() -class CesantaFlasher(object): - - # From stub_flasher.h - CMD_FLASH_WRITE = 1 - CMD_FLASH_READ = 2 - CMD_FLASH_DIGEST = 3 - CMD_BOOT_FW = 6 - - def __init__(self, esp, baud_rate=0): - print 'Running Cesanta flasher stub...' - if baud_rate <= ESPROM.ESP_ROM_BAUD: # don't change baud rates if we already synced at that rate - baud_rate = 0 - self._esp = esp - esp.run_stub(json.loads(_CESANTA_FLASHER_STUB), [baud_rate], read_output=False) - if baud_rate > 0: - esp._port.baudrate = baud_rate - # Read the greeting. - p = esp.read() - if p != 'OHAI': - raise FatalError('Failed to connect to the flasher (got %s)' % hexify(p)) - - def flash_write(self, addr, data, show_progress=False): - assert addr % self._esp.ESP_FLASH_SECTOR == 0, 'Address must be sector-aligned' - assert len(data) % self._esp.ESP_FLASH_SECTOR == 0, 'Length must be sector-aligned' - sys.stdout.write('Writing %d @ 0x%x... ' % (len(data), addr)) - sys.stdout.flush() - self._esp.write(struct.pack(' length: - raise FatalError('Read more than expected') - p = self._esp.read() - if len(p) != 16: - raise FatalError('Expected digest, got: %s' % hexify(p)) - expected_digest = hexify(p).upper() - digest = hashlib.md5(data).hexdigest().upper() - print - if digest != expected_digest: - raise FatalError('Digest mismatch: expected %s, got %s' % (expected_digest, digest)) - p = self._esp.read() - if len(p) != 1: - raise FatalError('Expected status, got: %s' % hexify(p)) - status_code = struct.unpack(' 16 bytes) will be + printed as separately indented lines, with ASCII decoding at the end + of each line. + """ + def __init__(self, binary_string, auto_split=True): + self._s = binary_string + self._auto_split = auto_split + + def __str__(self): + if self._auto_split and len(self._s) > 16: + result = "" + s = self._s + while len(s) > 0: + line = s[:16] + ascii_line = "".join(c if (c == ' ' or (c in string.printable and c not in string.whitespace)) + else '.' for c in line.decode('ascii', 'replace')) + s = s[16:] + result += "\n %-16s %-16s | %s" % (hexify(line[:8], False), hexify(line[8:], False), ascii_line) + return result + else: + return hexify(self._s, False) + + +def pad_to(data, alignment, pad_character=b'\xFF'): + """ Pad to the next alignment boundary """ + pad_mod = len(data) % alignment + if pad_mod != 0: + data += pad_character * (alignment - pad_mod) + return data class FatalError(RuntimeError): @@ -770,170 +2759,439 @@ class FatalError(RuntimeError): @staticmethod def WithResult(message, result): """ - Return a fatal error object that includes the hex values of + Return a fatal error object that appends the hex values of 'result' as a string formatted argument. """ - return FatalError(message % ", ".join(hex(ord(x)) for x in result)) + message += " (result was %s)" % hexify(result) + return FatalError(message) +class NotImplementedInROMError(FatalError): + """ + Wrapper class for the error thrown when a particular ESP bootloader function + is not implemented in the ROM bootloader. + """ + def __init__(self, bootloader, func): + FatalError.__init__(self, "%s ROM does not support function %s." % (bootloader.CHIP_NAME, func.__name__)) + + +class NotSupportedError(FatalError): + def __init__(self, esp, function_name): + FatalError.__init__(self, "Function %s is not supported for %s." % (function_name, esp.CHIP_NAME)) + # "Operation" commands, executable at command line. One function each # -# Each function takes either two args (, ) or a single +# Each function takes either two args (, ) or a single # argument. -def load_ram(esp, args): - image = LoadFirmwareImage(args.filename) - print 'RAM boot...' - for (offset, size, data) in image.segments: - print 'Downloading %d bytes at %08x...' % (size, offset), +class UnsupportedCommandError(RuntimeError): + """ + Wrapper class for when ROM loader returns an invalid command response. + + Usually this indicates the loader is running in Secure Download Mode. + """ + def __init__(self, esp, op): + if esp.secure_download_mode: + msg = "This command (0x%x) is not supported in Secure Download Mode" % op + else: + msg = "Invalid (unsupported) command 0x%x" % op + RuntimeError.__init__(self, msg) + + +def load_ram(esp, args): + image = LoadFirmwareImage(esp.CHIP_NAME, args.filename) + + print('RAM boot...') + for seg in image.segments: + size = len(seg.data) + print('Downloading %d bytes at %08x...' % (size, seg.addr), end=' ') sys.stdout.flush() - esp.mem_begin(size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, offset) + esp.mem_begin(size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, seg.addr) seq = 0 - while len(data) > 0: - esp.mem_block(data[0:esp.ESP_RAM_BLOCK], seq) - data = data[esp.ESP_RAM_BLOCK:] + while len(seg.data) > 0: + esp.mem_block(seg.data[0:esp.ESP_RAM_BLOCK], seq) + seg.data = seg.data[esp.ESP_RAM_BLOCK:] seq += 1 - print 'done!' + print('done!') - print 'All segments done, executing at %08x' % image.entrypoint + print('All segments done, executing at %08x' % image.entrypoint) esp.mem_finish(image.entrypoint) def read_mem(esp, args): - print '0x%08x = 0x%08x' % (args.address, esp.read_reg(args.address)) + print('0x%08x = 0x%08x' % (args.address, esp.read_reg(args.address))) def write_mem(esp, args): esp.write_reg(args.address, args.value, args.mask, 0) - print 'Wrote %08x, mask %08x to %08x' % (args.value, args.mask, args.address) + print('Wrote %08x, mask %08x to %08x' % (args.value, args.mask, args.address)) def dump_mem(esp, args): - f = file(args.filename, 'wb') - for i in xrange(args.size / 4): - d = esp.read_reg(args.address + (i * 4)) - f.write(struct.pack('> 16 + args.flash_size = DETECTED_FLASH_SIZES.get(size_id) + if args.flash_size is None: + print('Warning: Could not auto-detect Flash size (FlashID=0x%x, SizeID=0x%x), defaulting to 4MB' % (flash_id, size_id)) + args.flash_size = '4MB' + else: + print('Auto-detected Flash size:', args.flash_size) + + +def _update_image_flash_params(esp, address, args, image): + """ Modify the flash mode & size bytes if this looks like an executable bootloader image """ + if len(image) < 8: + return image # not long enough to be a bootloader image + + # unpack the (potential) image header + magic, _, flash_mode, flash_size_freq = struct.unpack("BBBB", image[:4]) + if address != esp.BOOTLOADER_FLASH_OFFSET: + return image # not flashing bootloader offset, so don't modify this + + if (args.flash_mode, args.flash_freq, args.flash_size) == ('keep',) * 3: + return image # all settings are 'keep', not modifying anything + + # easy check if this is an image: does it start with a magic byte? + if magic != esp.ESP_IMAGE_MAGIC: + print("Warning: Image file at 0x%x doesn't look like an image file, so not changing any flash settings." % address) + return image + + # make sure this really is an image, and not just data that + # starts with esp.ESP_IMAGE_MAGIC (mostly a problem for encrypted + # images that happen to start with a magic byte + try: + test_image = esp.BOOTLOADER_IMAGE(io.BytesIO(image)) + test_image.verify() + except Exception: + print("Warning: Image file at 0x%x is not a valid %s image, so not changing any flash settings." % (address, esp.CHIP_NAME)) + return image + + if args.flash_mode != 'keep': + flash_mode = {'qio': 0, 'qout': 1, 'dio': 2, 'dout': 3}[args.flash_mode] + + flash_freq = flash_size_freq & 0x0F + if args.flash_freq != 'keep': + flash_freq = {'40m': 0, '26m': 1, '20m': 2, '80m': 0xf}[args.flash_freq] + + flash_size = flash_size_freq & 0xF0 + if args.flash_size != 'keep': + flash_size = esp.parse_flash_size_arg(args.flash_size) + + flash_params = struct.pack(b'BB', flash_mode, flash_size + flash_freq) + if flash_params != image[2:4]: + print('Flash params set to 0x%04x' % struct.unpack(">H", flash_params)) + image = image[0:2] + flash_params + image[4:] + return image def write_flash(esp, args): - flash_mode = {'qio':0, 'qout':1, 'dio':2, 'dout': 3}[args.flash_mode] - flash_size_freq = {'4m':0x00, '2m':0x10, '8m':0x20, '16m':0x30, '32m':0x40, '16m-c1': 0x50, '32m-c1':0x60, '32m-c2':0x70, '64m':0x80, '128m':0x90}[args.flash_size] - flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq] - flash_params = struct.pack('BB', flash_mode, flash_size_freq) + # set args.compress based on default behaviour: + # -> if either --compress or --no-compress is set, honour that + # -> otherwise, set --compress unless --no-stub is set + if args.compress is None and not args.no_compress: + args.compress = not args.no_stub - flasher = CesantaFlasher(esp, args.baud) + # In case we have encrypted files to write, we first do few sanity checks before actual flash + if args.encrypt or args.encrypt_files is not None: + do_write = True - for address, argfile in args.addr_filename: - image = argfile.read() - argfile.seek(0) # rewind in case we need it again - # Fix sflash config data. - if address == 0 and image[0] == '\xe9': - print 'Flash params set to 0x%02x%02x' % (flash_mode, flash_size_freq) - image = image[0:2] + flash_params + image[4:] - # Pad to sector size, which is the minimum unit of writing (erasing really). - if len(image) % esp.ESP_FLASH_SECTOR != 0: - image += '\xff' * (esp.ESP_FLASH_SECTOR - (len(image) % esp.ESP_FLASH_SECTOR)) + if not esp.secure_download_mode: + if esp.get_encrypted_download_disabled(): + raise FatalError("This chip has encrypt functionality in UART download mode disabled. " + "This is the Flash Encryption configuration for Production mode instead of Development mode.") + + crypt_cfg_efuse = esp.get_flash_crypt_config() + + if crypt_cfg_efuse is not None and crypt_cfg_efuse != 0xF: + print('Unexpected FLASH_CRYPT_CONFIG value: 0x%x' % (crypt_cfg_efuse)) + do_write = False + + enc_key_valid = esp.is_flash_encryption_key_valid() + + if not enc_key_valid: + print('Flash encryption key is not programmed') + do_write = False + + # Determine which files list contain the ones to encrypt + files_to_encrypt = args.addr_filename if args.encrypt else args.encrypt_files + + for address, argfile in files_to_encrypt: + if address % esp.FLASH_ENCRYPTED_WRITE_ALIGN: + print("File %s address 0x%x is not %d byte aligned, can't flash encrypted" % + (argfile.name, address, esp.FLASH_ENCRYPTED_WRITE_ALIGN)) + do_write = False + + if not do_write and not args.ignore_flash_encryption_efuse_setting: + raise FatalError("Can't perform encrypted flash write, consult Flash Encryption documentation for more information") + + # verify file sizes fit in flash + if args.flash_size != 'keep': # TODO: check this even with 'keep' + flash_end = flash_size_bytes(args.flash_size) + for address, argfile in args.addr_filename: + argfile.seek(0, 2) # seek to end + if address + argfile.tell() > flash_end: + raise FatalError(("File %s (length %d) at offset %d will not fit in %d bytes of flash. " + "Use --flash-size argument, or change flashing address.") + % (argfile.name, argfile.tell(), address, flash_end)) + argfile.seek(0) + + if args.erase_all: + erase_flash(esp, args) + + """ Create a list describing all the files we have to flash. Each entry holds an "encrypt" flag + marking whether the file needs encryption or not. This list needs to be sorted. + + First, append to each entry of our addr_filename list the flag args.encrypt + For example, if addr_filename is [(0x1000, "partition.bin"), (0x8000, "bootloader")], + all_files will be [(0x1000, "partition.bin", args.encrypt), (0x8000, "bootloader", args.encrypt)], + where, of course, args.encrypt is either True or False + """ + all_files = [(offs, filename, args.encrypt) for (offs, filename) in args.addr_filename] + + """Now do the same with encrypt_files list, if defined. + In this case, the flag is True + """ + if args.encrypt_files is not None: + encrypted_files_flag = [(offs, filename, True) for (offs, filename) in args.encrypt_files] + + # Concatenate both lists and sort them. + # As both list are already sorted, we could simply do a merge instead, + # but for the sake of simplicity and because the lists are very small, + # let's use sorted. + all_files = sorted(all_files + encrypted_files_flag, key=lambda x: x[0]) + + for address, argfile, encrypted in all_files: + compress = args.compress + + # Check whether we can compress the current file before flashing + if compress and encrypted: + print('\nWARNING: - compress and encrypt options are mutually exclusive ') + print('Will flash %s uncompressed' % argfile.name) + compress = False + + if args.no_stub: + print('Erasing flash...') + image = pad_to(argfile.read(), esp.FLASH_ENCRYPTED_WRITE_ALIGN if encrypted else 4) + if len(image) == 0: + print('WARNING: File %s is empty' % argfile.name) + continue + image = _update_image_flash_params(esp, address, args, image) + calcmd5 = hashlib.md5(image).hexdigest() + uncsize = len(image) + if compress: + uncimage = image + image = zlib.compress(uncimage, 9) + blocks = esp.flash_defl_begin(uncsize, len(image), address) + else: + blocks = esp.flash_begin(uncsize, address, begin_rom_encrypted=encrypted) + argfile.seek(0) # in case we need it again + seq = 0 + written = 0 t = time.time() - flasher.flash_write(address, image, not args.no_progress) + while len(image) > 0: + print_overwrite('Writing at 0x%08x... (%d %%)' % (address + seq * esp.FLASH_WRITE_SIZE, 100 * (seq + 1) // blocks)) + sys.stdout.flush() + block = image[0:esp.FLASH_WRITE_SIZE] + if compress: + esp.flash_defl_block(block, seq, timeout=timeout_per_mb(COMP_BLOCK_WRITE_TIMEOUT_PER_MB, uncsize)) + else: + # Pad the last block + block = block + b'\xff' * (esp.FLASH_WRITE_SIZE - len(block)) + if encrypted: + esp.flash_encrypt_block(block, seq) + else: + esp.flash_block(block, seq) + image = image[esp.FLASH_WRITE_SIZE:] + seq += 1 + written += len(block) t = time.time() - t - print ('\rWrote %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' - % (len(image), address, t, len(image) / t * 8 / 1000)) - print 'Leaving...' + speed_msg = "" + if compress: + if t > 0.0: + speed_msg = " (effective %.1f kbit/s)" % (uncsize / t * 8 / 1000) + print_overwrite('Wrote %d bytes (%d compressed) at 0x%08x in %.1f seconds%s...' % (uncsize, written, address, t, speed_msg), last_line=True) + else: + if t > 0.0: + speed_msg = " (%.1f kbit/s)" % (written / t * 8 / 1000) + print_overwrite('Wrote %d bytes at 0x%08x in %.1f seconds%s...' % (written, address, t, speed_msg), last_line=True) + + if not encrypted and not esp.secure_download_mode: + try: + res = esp.flash_md5sum(address, uncsize) + if res != calcmd5: + print('File md5: %s' % calcmd5) + print('Flash md5: %s' % res) + print('MD5 of 0xFF is %s' % (hashlib.md5(b'\xFF' * uncsize).hexdigest())) + raise FatalError("MD5 of file does not match data in flash!") + else: + print('Hash of data verified.') + except NotImplementedInROMError: + pass + + print('\nLeaving...') + + if esp.IS_STUB: + # skip sending flash_finish to ROM loader here, + # as it causes the loader to exit and run user code + esp.flash_begin(0, 0) + + # Get the "encrypted" flag for the last file flashed + # Note: all_files list contains triplets like: + # (address: Integer, filename: String, encrypted: Boolean) + last_file_encrypted = all_files[-1][2] + + # Check whether the last file flashed was compressed or not + if args.compress and not last_file_encrypted: + esp.flash_defl_finish(False) + else: + esp.flash_finish(False) + if args.verify: - print 'Verifying just-written flash...' - _verify_flash(flasher, args, flash_params) - flasher.boot_fw() + print('Verifying just-written flash...') + print('(This option is deprecated, flash contents are now always read back after flashing.)') + # If some encrypted files have been flashed print a warning saying that we won't check them + if args.encrypt or args.encrypt_files is not None: + print('WARNING: - cannot verify encrypted files, they will be ignored') + # Call verify_flash function only if there at least one non-encrypted file flashed + if not args.encrypt: + verify_flash(esp, args) def image_info(args): - image = LoadFirmwareImage(args.filename) + image = LoadFirmwareImage(args.chip, args.filename) print('Image version: %d' % image.version) - print('Entry point: %08x' % image.entrypoint) if image.entrypoint != 0 else 'Entry point not set' - print '%d segments' % len(image.segments) - print - checksum = ESPROM.ESP_CHECKSUM_MAGIC - for (idx, (offset, size, data)) in enumerate(image.segments): - if image.version == 2 and idx == 0: - print 'Segment 1: %d bytes IROM0 (no load address)' % size - else: - print 'Segment %d: %5d bytes at %08x' % (idx + 1, size, offset) - checksum = ESPROM.checksum(data, checksum) - print - print 'Checksum: %02x (%s)' % (image.checksum, 'valid' if image.checksum == checksum else 'invalid!') + print('Entry point: %08x' % image.entrypoint if image.entrypoint != 0 else 'Entry point not set') + print('%d segments' % len(image.segments)) + print() + idx = 0 + for seg in image.segments: + idx += 1 + seg_name = ", ".join([seg_range[2] for seg_range in image.ROM_LOADER.MEMORY_MAP if seg_range[0] <= seg.addr < seg_range[1]]) + print('Segment %d: %r [%s]' % (idx, seg, seg_name)) + calc_checksum = image.calculate_checksum() + print('Checksum: %02x (%s)' % (image.checksum, + 'valid' if image.checksum == calc_checksum else 'invalid - calculated %02x' % calc_checksum)) + try: + digest_msg = 'Not appended' + if image.append_digest: + is_valid = image.stored_digest == image.calc_digest + digest_msg = "%s (%s)" % (hexify(image.calc_digest).lower(), + "valid" if is_valid else "invalid") + print('Validation Hash: %s' % digest_msg) + except AttributeError: + pass # ESP8266 image has no append_digest field def make_image(args): - image = ESPFirmwareImage() + image = ESP8266ROMFirmwareImage() if len(args.segfile) == 0: raise FatalError('No segments specified') if len(args.segfile) != len(args.segaddr): raise FatalError('Number of specified files does not match number of specified addresses') for (seg, addr) in zip(args.segfile, args.segaddr): - data = file(seg, 'rb').read() - image.add_segment(addr, data) + with open(seg, 'rb') as f: + data = f.read() + image.segments.append(ImageSegment(addr, data)) image.entrypoint = args.entrypoint image.save(args.output) def elf2image(args): e = ELFFile(args.input) - if args.version == '1': - image = ESPFirmwareImage() + if args.chip == 'auto': # Default to ESP8266 for backwards compatibility + print("Creating image for ESP8266...") + args.chip = 'esp8266' + + if args.chip == 'esp32': + image = ESP32FirmwareImage() + if args.secure_pad: + image.secure_pad = '1' + elif args.secure_pad_v2: + image.secure_pad = '2' + image.min_rev = int(args.min_rev) + elif args.chip == 'esp32s2': + image = ESP32S2FirmwareImage() + if args.secure_pad_v2: + image.secure_pad = '2' + image.min_rev = 0 + elif args.chip == 'esp32s3beta2': + image = ESP32S3BETA2FirmwareImage() + if args.secure_pad_v2: + image.secure_pad = '2' + image.min_rev = 0 + elif args.chip == 'esp32c3': + image = ESP32C3FirmwareImage() + if args.secure_pad_v2: + image.secure_pad = '2' + image.min_rev = 0 + elif args.version == '1': # ESP8266 + image = ESP8266ROMFirmwareImage() else: - image = OTAFirmwareImage() - irom_data = e.load_section('.irom0.text') - if len(irom_data) == 0: - raise FatalError(".irom0.text section not found in ELF file - can't create V2 image.") - image.add_segment(0, irom_data, 16) - image.entrypoint = e.get_entry_point() - for section, start in ((".text", "_text_start"), (".data", "_data_start"), (".rodata", "_rodata_start")): - data = e.load_section(section) - image.add_segment(e.get_symbol_addr(start), data) + image = ESP8266V2FirmwareImage() + image.entrypoint = e.entrypoint + image.segments = e.sections # ELFSection is a subclass of ImageSegment + image.flash_mode = {'qio': 0, 'qout': 1, 'dio': 2, 'dout': 3}[args.flash_mode] + image.flash_size_freq = image.ROM_LOADER.FLASH_SIZES[args.flash_size] + image.flash_size_freq += {'40m': 0, '26m': 1, '20m': 2, '80m': 0xf}[args.flash_freq] - image.flash_mode = {'qio':0, 'qout':1, 'dio':2, 'dout': 3}[args.flash_mode] - image.flash_size_freq = {'4m':0x00, '2m':0x10, '8m':0x20, '16m':0x30, '32m':0x40, '16m-c1': 0x50, '32m-c1':0x60, '32m-c2':0x70, '64m':0x80, '128m':0x90}[args.flash_size] - image.flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq] + if args.elf_sha256_offset: + image.elf_sha256 = e.sha256() + image.elf_sha256_offset = args.elf_sha256_offset - irom_offs = e.get_symbol_addr("_irom0_text_start") - 0x40200000 + image.verify() - if args.version == '1': - if args.output is None: - args.output = args.input + '-' - image.save(args.output + "0x00000.bin") - data = e.load_section(".irom0.text") - if irom_offs < 0: - raise FatalError('Address of symbol _irom0_text_start in ELF is located before flash mapping address. Bad linker script?') - if (irom_offs & 0xFFF) != 0: # irom0 isn't flash sector aligned - print "WARNING: irom0 section offset is 0x%08x. ELF is probably linked for 'elf2image --version=2'" % irom_offs - with open(args.output + "0x%05x.bin" % irom_offs, "wb") as f: - f.write(data) - f.close() - else: # V2 OTA image - if args.output is None: - args.output = "%s-0x%05x.bin" % (os.path.splitext(args.input)[0], irom_offs & ~(ESPROM.ESP_FLASH_SECTOR - 1)) - image.save(args.output) + if args.output is None: + args.output = image.default_output_name(args.input) + image.save(args.output) def read_mac(esp, args): mac = esp.read_mac() - print 'MAC: %s' % ':'.join(map(lambda x: '%02x' % x, mac)) + + def print_mac(label, mac): + print('%s: %s' % (label, ':'.join(map(lambda x: '%02x' % x, mac)))) + print_mac("MAC", mac) def chip_id(esp, args): - chipid = esp.chip_id() - print 'Chip ID: 0x%08x' % chipid + try: + chipid = esp.chip_id() + print('Chip ID: 0x%08x' % chipid) + except NotSupportedError: + print('Warning: %s has no Chip ID. Reading MAC instead.' % esp.CHIP_NAME) + read_mac(esp, args) def erase_flash(esp, args): - print 'Erasing flash (this may take a while)...' - esp.flash_erase() + print('Erasing flash (this may take a while)...') + t = time.time() + esp.erase_flash() + print('Chip erase completed successfully in %.1fs' % (time.time() - t)) + + +def erase_region(esp, args): + print('Erasing region (may be slow depending on size)...') + t = time.time() + esp.erase_region(args.address, args.size) + print('Erase completed successfully in %.1f seconds.' % (time.time() - t)) def run(esp, args): @@ -942,83 +3200,170 @@ def run(esp, args): def flash_id(esp, args): flash_id = esp.flash_id() - print 'Manufacturer: %02x' % (flash_id & 0xff) - print 'Device: %02x%02x' % ((flash_id >> 8) & 0xff, (flash_id >> 16) & 0xff) + print('Manufacturer: %02x' % (flash_id & 0xff)) + flid_lowbyte = (flash_id >> 16) & 0xFF + print('Device: %02x%02x' % ((flash_id >> 8) & 0xff, flid_lowbyte)) + print('Detected flash size: %s' % (DETECTED_FLASH_SIZES.get(flid_lowbyte, "Unknown"))) def read_flash(esp, args): - flasher = CesantaFlasher(esp, args.baud) + if args.no_progress: + flash_progress = None + else: + def flash_progress(progress, length): + msg = '%d (%d %%)' % (progress, progress * 100.0 / length) + padding = '\b' * len(msg) + if progress == length: + padding = '\n' + sys.stdout.write(msg + padding) + sys.stdout.flush() t = time.time() - data = flasher.flash_read(args.address, args.size, not args.no_progress) + data = esp.read_flash(args.address, args.size, flash_progress) t = time.time() - t - print ('\rRead %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' - % (len(data), args.address, t, len(data) / t * 8 / 1000)) - file(args.filename, 'wb').write(data) + print_overwrite('Read %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' + % (len(data), args.address, t, len(data) / t * 8 / 1000), last_line=True) + with open(args.filename, 'wb') as f: + f.write(data) -def _verify_flash(flasher, args, flash_params=None): +def verify_flash(esp, args): differences = False + for address, argfile in args.addr_filename: - image = argfile.read() + image = pad_to(argfile.read(), 4) argfile.seek(0) # rewind in case we need it again - if address == 0 and image[0] == '\xe9' and flash_params is not None: - image = image[0:2] + flash_params + image[4:] + + image = _update_image_flash_params(esp, address, args, image) + image_size = len(image) - print 'Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s...' % (image_size, image_size, address, argfile.name) + print('Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s...' % (image_size, image_size, address, argfile.name)) # Try digest first, only read if there are differences. - digest, _ = flasher.flash_digest(address, image_size) - digest = hexify(digest).upper() - expected_digest = hashlib.md5(image).hexdigest().upper() + digest = esp.flash_md5sum(address, image_size) + expected_digest = hashlib.md5(image).hexdigest() if digest == expected_digest: - print '-- verify OK (digest matched)' + print('-- verify OK (digest matched)') continue else: differences = True if getattr(args, 'diff', 'no') != 'yes': - print '-- verify FAILED (digest mismatch)' + print('-- verify FAILED (digest mismatch)') continue - flash = flasher.flash_read(address, image_size) + flash = esp.read_flash(address, image_size) assert flash != image - diff = [i for i in xrange(image_size) if flash[i] != image[i]] - print '-- verify FAILED: %d differences, first @ 0x%08x' % (len(diff), address + diff[0]) + diff = [i for i in range(image_size) if flash[i] != image[i]] + print('-- verify FAILED: %d differences, first @ 0x%08x' % (len(diff), address + diff[0])) for d in diff: - print ' %08x %02x %02x' % (address + d, ord(flash[d]), ord(image[d])) + flash_byte = flash[d] + image_byte = image[d] + if PYTHON2: + flash_byte = ord(flash_byte) + image_byte = ord(image_byte) + print(' %08x %02x %02x' % (address + d, flash_byte, image_byte)) if differences: raise FatalError("Verify failed.") -def verify_flash(esp, args, flash_params=None): - flasher = CesantaFlasher(esp) - _verify_flash(flasher, args, flash_params) +def read_flash_status(esp, args): + print('Status value: 0x%04x' % esp.read_status(args.bytes)) + + +def write_flash_status(esp, args): + fmt = "0x%%0%dx" % (args.bytes * 2) + args.value = args.value & ((1 << (args.bytes * 8)) - 1) + print(('Initial flash status: ' + fmt) % esp.read_status(args.bytes)) + print(('Setting flash status: ' + fmt) % args.value) + esp.write_status(args.value, args.bytes, args.non_volatile) + print(('After flash status: ' + fmt) % esp.read_status(args.bytes)) + + +def get_security_info(esp, args): + (flags, flash_crypt_cnt, key_purposes) = esp.get_security_info() + # TODO: better display + print('Flags: 0x%08x (%s)' % (flags, bin(flags))) + print('Flash_Crypt_Cnt: 0x%x' % flash_crypt_cnt) + print('Key_Purposes: %s' % (key_purposes,)) def version(args): - print __version__ + print(__version__) # # End of operations functions # -def main(): +def main(custom_commandline=None): + """ + Main function for esptool + + custom_commandline - Optional override for default arguments parsing (that uses sys.argv), can be a list of custom arguments + as strings. Arguments and their values need to be added as individual items to the list e.g. "-b 115200" thus + becomes ['-b', '115200']. + """ parser = argparse.ArgumentParser(description='esptool.py v%s - ESP8266 ROM Bootloader Utility' % __version__, prog='esptool') + parser.add_argument('--chip', '-c', + help='Target chip type', + type=lambda c: c.lower().replace('-', ''), # support ESP32-S2, etc. + choices=['auto', 'esp8266', 'esp32', 'esp32s2', 'esp32s3beta2', 'esp32c3'], + default=os.environ.get('ESPTOOL_CHIP', 'auto')) + parser.add_argument( '--port', '-p', help='Serial port device', - default=os.environ.get('ESPTOOL_PORT', '/dev/ttyUSB0')) + default=os.environ.get('ESPTOOL_PORT', None)) parser.add_argument( '--baud', '-b', help='Serial port baud rate used when flashing/reading', type=arg_auto_int, - default=os.environ.get('ESPTOOL_BAUD', ESPROM.ESP_ROM_BAUD)) + default=os.environ.get('ESPTOOL_BAUD', ESPLoader.ESP_ROM_BAUD)) + + parser.add_argument( + '--before', + help='What to do before connecting to the chip', + choices=['default_reset', 'no_reset', 'no_reset_no_sync'], + default=os.environ.get('ESPTOOL_BEFORE', 'default_reset')) + + parser.add_argument( + '--after', '-a', + help='What to do after esptool.py is finished', + choices=['hard_reset', 'soft_reset', 'no_reset'], + default=os.environ.get('ESPTOOL_AFTER', 'hard_reset')) + + parser.add_argument( + '--no-stub', + help="Disable launching the flasher stub, only talk to ROM bootloader. Some features will not be available.", + action='store_true') + + parser.add_argument( + '--trace', '-t', + help="Enable trace-level output of esptool.py interactions.", + action='store_true') + + parser.add_argument( + '--override-vddsdio', + help="Override ESP32 VDDSDIO internal voltage regulator (use with care)", + choices=ESP32ROM.OVERRIDE_VDDSDIO_CHOICES, + nargs='?') + + parser.add_argument( + '--connect-attempts', + help=('Number of attempts to connect, negative or 0 for infinite. ' + 'Default: %d.' % DEFAULT_CONNECT_ATTEMPTS), + type=int, + default=os.environ.get('ESPTOOL_CONNECT_ATTEMPTS', DEFAULT_CONNECT_ATTEMPTS)) subparsers = parser.add_subparsers( dest='operation', help='Run esptool {command} -h for additional help') + def add_spi_connection_arg(parent): + parent.add_argument('--spi-connection', '-sc', help='ESP32-only argument. Override default SPI Flash connection. ' + 'Value can be SPI, HSPI or a comma-separated list of 5 I/O numbers to use for SPI flash (CLK,Q,D,HD,CS).', + action=SpiConnectionAction) + parser_load_ram = subparsers.add_parser( 'load_ram', help='Download an image to RAM and execute') @@ -1043,26 +3388,56 @@ def main(): parser_write_mem.add_argument('value', help='Value', type=arg_auto_int) parser_write_mem.add_argument('mask', help='Mask of bits to write', type=arg_auto_int) - def add_spi_flash_subparsers(parent): + def add_spi_flash_subparsers(parent, is_elf2image): """ Add common parser arguments for SPI flash properties """ + extra_keep_args = [] if is_elf2image else ['keep'] + auto_detect = not is_elf2image + + if auto_detect: + extra_fs_message = ", detect, or keep" + else: + extra_fs_message = "" + parent.add_argument('--flash_freq', '-ff', help='SPI Flash frequency', - choices=['40m', '26m', '20m', '80m'], - default=os.environ.get('ESPTOOL_FF', '40m')) + choices=extra_keep_args + ['40m', '26m', '20m', '80m'], + default=os.environ.get('ESPTOOL_FF', '40m' if is_elf2image else 'keep')) parent.add_argument('--flash_mode', '-fm', help='SPI Flash mode', - choices=['qio', 'qout', 'dio', 'dout'], - default=os.environ.get('ESPTOOL_FM', 'qio')) - parent.add_argument('--flash_size', '-fs', help='SPI Flash size in Mbit', type=str.lower, - choices=['4m', '2m', '8m', '16m', '32m', '16m-c1', '32m-c1', '32m-c2', '64m', '128m'], - default=os.environ.get('ESPTOOL_FS', '4m')) + choices=extra_keep_args + ['qio', 'qout', 'dio', 'dout'], + default=os.environ.get('ESPTOOL_FM', 'qio' if is_elf2image else 'keep')) + parent.add_argument('--flash_size', '-fs', help='SPI Flash size in MegaBytes (1MB, 2MB, 4MB, 8MB, 16M)' + ' plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1)' + extra_fs_message, + action=FlashSizeAction, auto_detect=auto_detect, + default=os.environ.get('ESPTOOL_FS', '1MB' if is_elf2image else 'keep')) + add_spi_connection_arg(parent) parser_write_flash = subparsers.add_parser( 'write_flash', help='Write a binary blob to flash') + parser_write_flash.add_argument('addr_filename', metavar='
', help='Address followed by binary filename, separated by space', action=AddrFilenamePairAction) - add_spi_flash_subparsers(parser_write_flash) + parser_write_flash.add_argument('--erase-all', '-e', + help='Erase all regions of flash (not just write areas) before programming', + action="store_true") + + add_spi_flash_subparsers(parser_write_flash, is_elf2image=False) parser_write_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true") - parser_write_flash.add_argument('--verify', help='Verify just-written data (only necessary if very cautious, data is already CRCed', action='store_true') + parser_write_flash.add_argument('--verify', help='Verify just-written data on flash ' + '(mostly superfluous, data is read back during flashing)', action='store_true') + parser_write_flash.add_argument('--encrypt', help='Apply flash encryption when writing data (required correct efuse settings)', + action='store_true') + # In order to not break backward compatibility, our list of encrypted files to flash is a new parameter + parser_write_flash.add_argument('--encrypt-files', metavar='
', + help='Files to be encrypted on the flash. Address followed by binary filename, separated by space.', + action=AddrFilenamePairAction) + parser_write_flash.add_argument('--ignore-flash-encryption-efuse-setting', help='Ignore flash encryption efuse settings ', + action='store_true') + + compress_args = parser_write_flash.add_mutually_exclusive_group(required=False) + compress_args.add_argument('--compress', '-z', help='Compress data in transfer (default unless --no-stub is specified)', + action="store_true", default=None) + compress_args.add_argument('--no-compress', '-u', help='Disable data compression during transfer (default if --no-stub is specified)', + action="store_true") subparsers.add_parser( 'run', @@ -1086,8 +3461,17 @@ def main(): help='Create an application image from ELF file') parser_elf2image.add_argument('input', help='Input ELF file') parser_elf2image.add_argument('--output', '-o', help='Output filename prefix (for version 1 image), or filename (for version 2 single image)', type=str) - parser_elf2image.add_argument('--version', '-e', help='Output image version', choices=['1','2'], default='1') - add_spi_flash_subparsers(parser_elf2image) + parser_elf2image.add_argument('--version', '-e', help='Output image version', choices=['1', '2'], default='1') + parser_elf2image.add_argument('--min-rev', '-r', help='Minimum chip revision', choices=['0', '1', '2', '3'], default='0') + parser_elf2image.add_argument('--secure-pad', action='store_true', + help='Pad image so once signed it will end on a 64KB boundary. For Secure Boot v1 images only.') + parser_elf2image.add_argument('--secure-pad-v2', action='store_true', + help='Pad image to 64KB, so once signed its signature sector will start at the next 64K block. ' + 'For Secure Boot v2 images only.') + parser_elf2image.add_argument('--elf-sha256-offset', help='If set, insert SHA256 hash (32 bytes) of the input ELF file at specified offset in the binary.', + type=arg_auto_int, default=None) + + add_spi_flash_subparsers(parser_elf2image, is_elf2image=True) subparsers.add_parser( 'read_mac', @@ -1097,13 +3481,31 @@ def main(): 'chip_id', help='Read Chip ID from OTP ROM') - subparsers.add_parser( + parser_flash_id = subparsers.add_parser( 'flash_id', help='Read SPI flash manufacturer and device ID') + add_spi_connection_arg(parser_flash_id) + + parser_read_status = subparsers.add_parser( + 'read_flash_status', + help='Read SPI flash status register') + + add_spi_connection_arg(parser_read_status) + parser_read_status.add_argument('--bytes', help='Number of bytes to read (1-3)', type=int, choices=[1, 2, 3], default=2) + + parser_write_status = subparsers.add_parser( + 'write_flash_status', + help='Write SPI flash status register') + + add_spi_connection_arg(parser_write_status) + parser_write_status.add_argument('--non-volatile', help='Write non-volatile bits (use with caution)', action='store_true') + parser_write_status.add_argument('--bytes', help='Number of status bytes to write (1-3)', type=int, choices=[1, 2, 3], default=2) + parser_write_status.add_argument('value', help='New value', type=arg_auto_int) parser_read_flash = subparsers.add_parser( 'read_flash', help='Read SPI flash content') + add_spi_connection_arg(parser_read_flash) parser_read_flash.add_argument('address', help='Start address', type=arg_auto_int) parser_read_flash.add_argument('size', help='Size of region to dump', type=arg_auto_int) parser_read_flash.add_argument('filename', help='Name of binary dump') @@ -1116,36 +3518,252 @@ def main(): action=AddrFilenamePairAction) parser_verify_flash.add_argument('--diff', '-d', help='Show differences', choices=['no', 'yes'], default='no') + add_spi_flash_subparsers(parser_verify_flash, is_elf2image=False) - subparsers.add_parser( + parser_erase_flash = subparsers.add_parser( 'erase_flash', help='Perform Chip Erase on SPI flash') + add_spi_connection_arg(parser_erase_flash) + + parser_erase_region = subparsers.add_parser( + 'erase_region', + help='Erase a region of the flash') + add_spi_connection_arg(parser_erase_region) + parser_erase_region.add_argument('address', help='Start address (must be multiple of 4096)', type=arg_auto_int) + parser_erase_region.add_argument('size', help='Size of region to erase (must be multiple of 4096)', type=arg_auto_int) subparsers.add_parser( 'version', help='Print esptool version') + subparsers.add_parser('get_security_info', help='Get some security-related data') + # internal sanity check - every operation matches a module function of the same name for operation in subparsers.choices.keys(): assert operation in globals(), "%s should be a module function" % operation - args = parser.parse_args() + expand_file_arguments() - print 'esptool.py v%s' % __version__ + args = parser.parse_args(custom_commandline) + print('esptool.py v%s' % __version__) # operation function can take 1 arg (args), 2 args (esp, arg) - # or be a member function of the ESPROM class. + # or be a member function of the ESPLoader class. + + if args.operation is None: + parser.print_help() + sys.exit(1) + + # Forbid the usage of both --encrypt, which means encrypt all the given files, + # and --encrypt-files, which represents the list of files to encrypt. + # The reason is that allowing both at the same time increases the chances of + # having contradictory lists (e.g. one file not available in one of list). + if args.operation == "write_flash" and args.encrypt and args.encrypt_files is not None: + raise FatalError("Options --encrypt and --encrypt-files must not be specified at the same time.") operation_func = globals()[args.operation] - operation_args,_,_,_ = inspect.getargspec(operation_func) - if operation_args[0] == 'esp': # operation function takes an ESPROM connection object - initial_baud = min(ESPROM.ESP_ROM_BAUD, args.baud) # don't sync faster than the default baud rate - esp = ESPROM(args.port, initial_baud) - esp.connect() - operation_func(esp, args) + + if PYTHON2: + # This function is depreciated in Python3 + operation_args = inspect.getargspec(operation_func).args + else: + operation_args = inspect.getfullargspec(operation_func).args + + if operation_args[0] == 'esp': # operation function takes an ESPLoader connection object + if args.before != "no_reset_no_sync": + initial_baud = min(ESPLoader.ESP_ROM_BAUD, args.baud) # don't sync faster than the default baud rate + else: + initial_baud = args.baud + + if args.port is None: + if list_ports is None: + raise FatalError("Listing all serial ports is currently not available on this operating system version. " + "Specify the port when running esptool.py") + ser_list = sorted(ports.device for ports in list_ports.comports()) + print("Found %d serial ports" % len(ser_list)) + else: + ser_list = [args.port] + esp = None + for each_port in reversed(ser_list): + print("Serial port %s" % each_port) + try: + if args.chip == 'auto': + esp = ESPLoader.detect_chip(each_port, initial_baud, args.before, args.trace, + args.connect_attempts) + else: + chip_class = { + 'esp8266': ESP8266ROM, + 'esp32': ESP32ROM, + 'esp32s2': ESP32S2ROM, + 'esp32s3beta2': ESP32S3BETA2ROM, + 'esp32c3': ESP32C3ROM, + }[args.chip] + esp = chip_class(each_port, initial_baud, args.trace) + esp.connect(args.before, args.connect_attempts) + break + except (FatalError, OSError) as err: + if args.port is not None: + raise + print("%s failed to connect: %s" % (each_port, err)) + esp = None + if esp is None: + raise FatalError("Could not connect to an Espressif device on any of the %d available serial ports." % len(ser_list)) + + if esp.secure_download_mode: + print("Chip is %s in Secure Download Mode" % esp.CHIP_NAME) + else: + print("Chip is %s" % (esp.get_chip_description())) + print("Features: %s" % ", ".join(esp.get_chip_features())) + print("Crystal is %dMHz" % esp.get_crystal_freq()) + read_mac(esp, args) + + if not args.no_stub: + if esp.secure_download_mode: + print("WARNING: Stub loader is not supported in Secure Download Mode, setting --no-stub") + args.no_stub = True + else: + esp = esp.run_stub() + + if args.override_vddsdio: + esp.override_vddsdio(args.override_vddsdio) + + if args.baud > initial_baud: + try: + esp.change_baud(args.baud) + except NotImplementedInROMError: + print("WARNING: ROM doesn't support changing baud rate. Keeping initial baud rate %d" % initial_baud) + + # override common SPI flash parameter stuff if configured to do so + if hasattr(args, "spi_connection") and args.spi_connection is not None: + if esp.CHIP_NAME != "ESP32": + raise FatalError("Chip %s does not support --spi-connection option." % esp.CHIP_NAME) + print("Configuring SPI flash mode...") + esp.flash_spi_attach(args.spi_connection) + elif args.no_stub: + print("Enabling default SPI flash mode...") + # ROM loader doesn't enable flash unless we explicitly do it + esp.flash_spi_attach(0) + + if hasattr(args, "flash_size"): + print("Configuring flash size...") + detect_flash_size(esp, args) + if args.flash_size != 'keep': # TODO: should set this even with 'keep' + esp.flash_set_parameters(flash_size_bytes(args.flash_size)) + + try: + operation_func(esp, args) + finally: + try: # Clean up AddrFilenamePairAction files + for address, argfile in args.addr_filename: + argfile.close() + except AttributeError: + pass + + # Handle post-operation behaviour (reset or other) + if operation_func == load_ram: + # the ESP is now running the loaded image, so let it run + print('Exiting immediately.') + elif args.after == 'hard_reset': + print('Hard resetting via RTS pin...') + esp.hard_reset() + elif args.after == 'soft_reset': + print('Soft resetting...') + # flash_finish will trigger a soft reset + esp.soft_reset(False) + else: + print('Staying in bootloader.') + if esp.IS_STUB: + esp.soft_reset(True) # exit stub back to ROM loader + + esp._port.close() + else: operation_func(args) +def expand_file_arguments(): + """ Any argument starting with "@" gets replaced with all values read from a text file. + Text file arguments can be split by newline or by space. + Values are added "as-is", as if they were specified in this order on the command line. + """ + new_args = [] + expanded = False + for arg in sys.argv: + if arg.startswith("@"): + expanded = True + with open(arg[1:], "r") as f: + for line in f.readlines(): + new_args += shlex.split(line) + else: + new_args.append(arg) + if expanded: + print("esptool.py %s" % (" ".join(new_args[1:]))) + sys.argv = new_args + + +class FlashSizeAction(argparse.Action): + """ Custom flash size parser class to support backwards compatibility with megabit size arguments. + + (At next major relase, remove deprecated sizes and this can become a 'normal' choices= argument again.) + """ + def __init__(self, option_strings, dest, nargs=1, auto_detect=False, **kwargs): + super(FlashSizeAction, self).__init__(option_strings, dest, nargs, **kwargs) + self._auto_detect = auto_detect + + def __call__(self, parser, namespace, values, option_string=None): + try: + value = { + '2m': '256KB', + '4m': '512KB', + '8m': '1MB', + '16m': '2MB', + '32m': '4MB', + '16m-c1': '2MB-c1', + '32m-c1': '4MB-c1', + }[values[0]] + print("WARNING: Flash size arguments in megabits like '%s' are deprecated." % (values[0])) + print("Please use the equivalent size '%s'." % (value)) + print("Megabit arguments may be removed in a future release.") + except KeyError: + value = values[0] + + known_sizes = dict(ESP8266ROM.FLASH_SIZES) + known_sizes.update(ESP32ROM.FLASH_SIZES) + if self._auto_detect: + known_sizes['detect'] = 'detect' + known_sizes['keep'] = 'keep' + if value not in known_sizes: + raise argparse.ArgumentError(self, '%s is not a known flash size. Known sizes: %s' % (value, ", ".join(known_sizes.keys()))) + setattr(namespace, self.dest, value) + + +class SpiConnectionAction(argparse.Action): + """ Custom action to parse 'spi connection' override. Values are SPI, HSPI, or a sequence of 5 pin numbers separated by commas. + """ + def __call__(self, parser, namespace, value, option_string=None): + if value.upper() == "SPI": + value = 0 + elif value.upper() == "HSPI": + value = 1 + elif "," in value: + values = value.split(",") + if len(values) != 5: + raise argparse.ArgumentError(self, '%s is not a valid list of comma-separate pin numbers. Must be 5 numbers - CLK,Q,D,HD,CS.' % value) + try: + values = tuple(int(v, 0) for v in values) + except ValueError: + raise argparse.ArgumentError(self, '%s is not a valid argument. All pins must be numeric values' % values) + if any([v for v in values if v > 33 or v < 0]): + raise argparse.ArgumentError(self, 'Pin numbers must be in the range 0-33.') + # encode the pin numbers as a 32-bit integer with packed 6-bit values, the same way ESP32 ROM takes them + # TODO: make this less ESP32 ROM specific somehow... + clk, q, d, hd, cs = values + value = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk + else: + raise argparse.ArgumentError(self, '%s is not a valid spi-connection value. ' + 'Values are SPI, HSPI, or a sequence of 5 pin numbers CLK,Q,D,HD,CS).' % value) + setattr(namespace, self.dest, value) + + class AddrFilenamePairAction(argparse.Action): """ Custom parser class for the address/filename pairs passed as arguments """ def __init__(self, option_strings, dest, nargs='+', **kwargs): @@ -1154,83 +3772,247 @@ class AddrFilenamePairAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): # validate pair arguments pairs = [] - for i in range(0,len(values),2): + for i in range(0, len(values), 2): try: - address = int(values[i],0) - except ValueError as e: - raise argparse.ArgumentError(self,'Address "%s" must be a number' % values[i]) + address = int(values[i], 0) + except ValueError: + raise argparse.ArgumentError(self, 'Address "%s" must be a number' % values[i]) try: argfile = open(values[i + 1], 'rb') except IOError as e: raise argparse.ArgumentError(self, e) except IndexError: - raise argparse.ArgumentError(self,'Must be pairs of an address and the binary filename to write there') + raise argparse.ArgumentError(self, 'Must be pairs of an address and the binary filename to write there') pairs.append((address, argfile)) + + # Sort the addresses and check for overlapping + end = 0 + for address, argfile in sorted(pairs, key=lambda x: x[0]): + argfile.seek(0, 2) # seek to end + size = argfile.tell() + argfile.seek(0) + sector_start = address & ~(ESPLoader.FLASH_SECTOR_SIZE - 1) + sector_end = ((address + size + ESPLoader.FLASH_SECTOR_SIZE - 1) & ~(ESPLoader.FLASH_SECTOR_SIZE - 1)) - 1 + if sector_start < end: + message = 'Detected overlap at address: 0x%x for file: %s' % (address, argfile.name) + raise argparse.ArgumentError(self, message) + end = sector_end setattr(namespace, self.dest, pairs) -# This is "wrapped" stub_flasher.c, to be loaded using run_stub. -_CESANTA_FLASHER_STUB = """\ -{"code_start": 1074790404, "code": "080000601C000060000000601000006031FCFF71FCFF\ -81FCFFC02000680332D218C020004807404074DCC48608005823C0200098081BA5A9239245005803\ -1B555903582337350129230B446604DFC6F3FF21EEFFC0200069020DF0000000010078480040004A\ -0040B449004012C1F0C921D911E901DD0209312020B4ED033C2C56C2073020B43C3C56420701F5FF\ -C000003C4C569206CD0EEADD860300202C4101F1FFC0000056A204C2DCF0C02DC0CC6CCAE2D1EAFF\ -0606002030F456D3FD86FBFF00002020F501E8FFC00000EC82D0CCC0C02EC0C73DEB2ADC46030020\ -2C4101E1FFC00000DC42C2DCF0C02DC056BCFEC602003C5C8601003C6C4600003C7C08312D0CD811\ -C821E80112C1100DF0000C180000140010400C0000607418000064180000801800008C1800008418\ -0000881800009018000018980040880F0040A80F0040349800404C4A0040740F0040800F0040980F\ -00400099004012C1E091F5FFC961CD0221EFFFE941F9310971D9519011C01A223902E2D1180C0222\ -6E1D21E4FF31E9FF2AF11A332D0F42630001EAFFC00000C030B43C2256A31621E1FF1A2228022030\ -B43C3256B31501ADFFC00000DD023C4256ED1431D6FF4D010C52D90E192E126E0101DDFFC0000021\ -D2FF32A101C020004802303420C0200039022C0201D7FFC00000463300000031CDFF1A333803D023\ -C03199FF27B31ADC7F31CBFF1A3328030198FFC0000056C20E2193FF2ADD060E000031C6FF1A3328\ -030191FFC0000056820DD2DD10460800000021BEFF1A2228029CE231BCFFC020F51A33290331BBFF\ -C02C411A332903C0F0F4222E1D22D204273D9332A3FFC02000280E27B3F721ABFF381E1A2242A400\ -01B5FFC00000381E2D0C42A40001B3FFC0000056120801B2FFC00000C02000280EC2DC0422D2FCC0\ -2000290E01ADFFC00000222E1D22D204226E1D281E22D204E7B204291E860000126E012198FF32A0\ -042A21C54C003198FF222E1D1A33380337B202C6D6FF2C02019FFFC000002191FF318CFF1A223A31\ -019CFFC00000218DFF1C031A22C549000C02060300003C528601003C624600003C72918BFF9A1108\ -71C861D851E841F83112C1200DF00010000068100000581000007010000074100000781000007C10\ -0000801000001C4B0040803C004091FDFF12C1E061F7FFC961E941F9310971D9519011C01A662906\ -21F3FFC2D1101A22390231F2FF0C0F1A33590331EAFFF26C1AED045C2247B3028636002D0C016DFF\ -C0000021E5FF41EAFF2A611A4469040622000021E4FF1A222802F0D2C0D7BE01DD0E31E0FF4D0D1A\ -3328033D0101E2FFC00000561209D03D2010212001DFFFC000004D0D2D0C3D01015DFFC0000041D5\ -FFDAFF1A444804D0648041D2FF1A4462640061D1FF106680622600673F1331D0FF10338028030C43\ -853A002642164613000041CAFF222C1A1A444804202FC047328006F6FF222C1A273F3861C2FF222C\ -1A1A6668066732B921BDFF3D0C1022800148FFC0000021BAFF1C031A2201BFFFC000000C02460300\ -5C3206020000005C424600005C5291B7FF9A110871C861D851E841F83112C1200DF0B0100000C010\ -0000D010000012C1E091FEFFC961D951E9410971F931CD039011C0ED02DD0431A1FF9C1422A06247\ -B302062D0021F4FF1A22490286010021F1FF1A223902219CFF2AF12D0F011FFFC00000461C0022D1\ -10011CFFC0000021E9FFFD0C1A222802C7B20621E6FF1A22F8022D0E3D014D0F0195FFC000008C52\ -22A063C6180000218BFF3D01102280F04F200111FFC00000AC7D22D1103D014D0F010DFFC0000021\ -D6FF32D110102280010EFFC0000021D3FF1C031A220185FFC00000FAEEF0CCC056ACF821CDFF317A\ -FF1A223A310105FFC0000021C9FF1C031A22017CFFC000002D0C91C8FF9A110871C861D851E841F8\ -3112C1200DF0000200600000001040020060FFFFFF0012C1E00C02290131FAFF21FAFF026107C961\ -C02000226300C02000C80320CC10564CFF21F5FFC02000380221F4FF20231029010C432D010163FF\ -C0000008712D0CC86112C1200DF00080FE3F8449004012C1D0C9A109B17CFC22C1110C13C51C0026\ -1202463000220111C24110B68202462B0031F5FF3022A02802A002002D011C03851A0066820A2801\ -32210105A6FF0607003C12C60500000010212032A01085180066A20F2221003811482105B3FF2241\ -10861A004C1206FDFF2D011C03C5160066B20E280138114821583185CFFF06F7FF005C1286F5FF00\ -10212032A01085140066A20D2221003811482105E1FF06EFFF0022A06146EDFF45F0FFC6EBFF0000\ -01D2FFC0000006E9FF000C022241100C1322C110C50F00220111060600000022C1100C13C50E0022\ -011132C2FA303074B6230206C8FF08B1C8A112C1300DF0000000000010404F484149007519031027\ -000000110040A8100040BC0F0040583F0040CC2E00401CE20040D83900408000004021F4FF12C1E0\ -C961C80221F2FF097129010C02D951C91101F4FFC0000001F3FFC00000AC2C22A3E801F2FFC00000\ -21EAFFC031412A233D0C01EFFFC000003D0222A00001EDFFC00000C1E4FF2D0C01E8FFC000002D01\ -32A004450400C5E7FFDD022D0C01E3FFC00000666D1F4B2131DCFF4600004B22C0200048023794F5\ -31D9FFC0200039023DF08601000001DCFFC000000871C861D85112C1200DF000000012C1F0026103\ -01EAFEC00000083112C1100DF000643B004012C1D0E98109B1C9A1D991F97129013911E2A0C001FA\ -FFC00000CD02E792F40C0DE2A0C0F2A0DB860D00000001F4FFC00000204220E71240F7921C226102\ -01EFFFC0000052A0DC482157120952A0DD571205460500004D0C3801DA234242001BDD3811379DC5\ -C6000000000C0DC2A0C001E3FFC00000C792F608B12D0DC8A1D891E881F87112C1300DF00000", "\ -entry": 1074792180, "num_params": 1, "params_start": 1074790400, "data": "FE0510\ -401A0610403B0610405A0610407A061040820610408C0610408C061040", "data_start": 10736\ -43520} -""" -if __name__ == '__main__': +# Binary stub code (see flasher_stub dir for source & details) +ESP8266ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" +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\ +"""))) +ESP32ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" +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\ +"""))) +ESP32S2ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" +eNqNW/9X3DYS/1d2nQBLSO8kr9eW095jSdp9pOn1Ak0pzeNdsWUb0pdysN3Akkv+99N8s2SvSe8HB68sjUaj+fKZkfLfnVW9Xu08G5U7Z2tl3KPgOT9baxv8oBf+Udi9s3VT77s+vjk9gD9j96FwT3O2tmoELUAy\ +dt+avNM8cf8kI/eaJ+5xU9Wxa0ndMwtng4EzGmi0+5t2iDhWgLyjYAxxX0CbWjlyKlhOGTXAhWvNXFegkQAdYFZ3CObUTVeuteXhzWi+/0bN92mFjlsYU/UYcQy4WQ28qccnh/QVexb/T8/ujPA8dbPCX/4TPEYY\ +qUEyVlZSEiVlaeF+Pl4UMlMGssx7jOXxJb34FpTqyf3mChzFT641hkVECvYRdmFzFfDMid9amHX93BbkhWelrgJ52T5beW9BXa6G5+RH+3ejgtGK9RcIyIMdk5Hs81hYiSNeXPoCtBOWYfwy6oK+FjORrnlOmwC9\ +4K9OjkThMlbY0kTA0JQMyNrpEckSiVrR6Gju+mq95dqnwbYpfoc1IYWgsbvpU/elijtfjm1ni0+h18kHYns+hfb8uYm+f/Ey6ko2V4HUYDdg+qbaF0UO5JyEv+dzeTsE4jwGbJ6piS6XWuQ6Qgt2Yq54p3IR86zr\ +BPLgvbX7nLfYhHpcxruB6bIwc9bkTs8crN/4NcMDe6fd1tqclmC5rR1k41Me4bjMy9A9xS/7JhVMgKpfeG5kMhEpvmdgAQvunPiV1+wWC3hnhcT5Q1Ox6GvKYCjSA60EmuAWlPpEBOCLdgRqvYBBoR2FanUVyjU/\ +W7Vkuu1X3VErYroKGDVkH6uOcFiQfaNGzUBrBI1LYD49551AG3c/yiT4kSvqQ+oVuOHcRmyE064bDANGEdMjmyQG3wkqKdnpYP90gGY452zze7jkRkmALds3Y3WworF3lKEWWUO7UXA4LIOVm8D/dxbCAcP0gp9O\ +JMztz/eCqZkSu2wTC6VmgnFN+6AqQdlY0vli5rl2s149vAHEw6Q7bVEBg2Ox4EgUr4k4ukF053lXYLKTXdG7Og2CIwStguJKa5+wDBAeChnNA0xwF1zsCN5ASy06ZTeomT9x/xbkdUBs4IdhkaDeaJfMCOpIvBmX\ +cMvqL+sAPa3IY5rNtnJgU47Plqx/7ktV1n6/20a7IM3rcNCOaOlwbMt7oytekhkKt8Tes3hzqWgO/FuXURv8ea4mGSblJ8aVzrwthb0LI1ZRJPKmlHiFmi0F1+zUp2AnB/vbkd30K9exYJOwPewp9ora4J6yIjyB\ +Kptt7p3RkZecAA+xgAcdwXSTEOgq+GGQvGPqKtw40KnpNusxhGtmStm9uPiybiHuYf4pXmBkQfVBLhuaVpnAXoJA9qKLxmQ7rL0JjPQA4exp8npqGR6BBKen4E3e/vT67OyA8DetBmJ86yq+dZOkHBsR/jymXUId\ +iEkJbb6JH4F5nQAnU4ChZTxi0cYDe2SfRaxdye6bCQx8Fu3Cn0kCWuHQT0cvryktaQoEPQESnwvWKVnnCn5LCw/NLXIQeDiNOGcE4pwKl0Wfy3/ijoP4YNGgeBIrNZmOBBrBL1rgHiBFmwXYKPYIoYkHsxB0YGa0\ +EatLng/NhXW1bgaCmnrMKLQfsEFTmw0vpglJIYds57SsQ+gAi7IHkojEYf6ELXrXILqAjLGInkzVNwfi0ndP88MWmX+FoQVEWMh2z4YTBZ+/noY/3h/zJhu75A02VtqU/YmymvGYNgN0WKuH9hMVvsVTR96hkUN5\ +/cKyGSeBd3oAQzT2ie8sDmmDhQ2f8n1E0P7EUtxGyMhxuAxGg/lDWHvIheC4PEhTSj8GFL5WJH3ym2k3/1IK98IObcT7UPiX4Y/r8Mcq/LEOfzBkQj80Lnp5binWh1nTc9TKgx+8SVISUHo5ADZZCrr7lQsLMfrH\ +5gzKJOkWwYHNGP+UUM3TvvCOxH6ct7QsWl38DHB39ovbhYyI2PTrAOuktACZqRtt3O+SCYq31ugpPh6xUSTI+mIrGIFJwPxPiq6aHYsEKVKo67UoZNZVSDsdcqjgn24oWLUAa3aMPvrjDTt7K84endM1LHfEtDU0\ +Sybj/lYSeJgB4glqTil7zHIDLn6MPn6bkVuoeKEV8vp6NbxQk0kinvrUmaHwFWz14j0vuQ4FC18mXpi26jNywkC8JuBdBFBKpe+JTFmSrZia9TbDQUsw+O/Ort6SLhTxK4FOP3PFaurZBJstGp4oo1Bos+Y74ON4\ +G+YBcQCWiX8huUADWG9eB74n7Vp8ofrrAS1vfAyRiNuavuLBEu9QT2sRmwavRzB9SjCdthRdQOFolwMWROhvFCh4/VcQmeVY7f/r8OAlIEtChJ+Ihornh9+gZ6goUrmGIPcx55ToYMUCv/iqp5nP93vloYHakpPC\ +jrROYM5+vc6wnZhO3Jl3KmSD6/H5Jf7QSVCCFa0VzhqPg00wpgzKNmeEAnC2KkycizBxrji5PhU0DWpRJ8Jlcs3NSn2QyGikVAM/1EtB4WbW4vGvpWsrO2wmWu9vhKSVN5Ps4tv6VvqqO37Lk9uWA5LdZUsz5fwN\ +smMBlmDSEcLa54w3xBduxNexqHBg3D6KPQeAp15FGSCpDNS3lhlekd5aPWq1uiYbc7Q+g/TH+O8BAZGmefKoW3EeP4LPLzm9hTUggTaFavZKwBpTardS8KvZi8VsVLMA+dabSX5uvyHD9bm3SCnsWgZO1sZeaJyY\ +rbqu8Utlk7zYZASpJx66t9GleKBkwt8BmPdpdcZvpGQH7CR7Zw6vIw93d9nEOllWGSSF6A3wecvRpxqaBlHnMXlJ0JZwPocIBqYEWmZgSTiHGdDMQm8sJSZ9hfwAXLJN5lC0BZiFmUdbfh6RiRtOZkEDcJqBvW8C\ +N49oiHfZBu2lnjDfMa9YhSpV2AHuaezBNgx8Mj0GN7O3oDxuqDZSsuPnxZZC6fwcIGB6y2g5UDfuGR0Kkd8H1AVkHgDDvBnGVZvtN+TlmoZLpTzbJYMkTZkqVeUZVHKXd9QFyeYPTLex3bBhksbmA6WGQAemLMSY\ +Uo/uF9xtibhp+/UevpYHwGfJ3gNLCBNsg8XER2er+6NtKr0DBW2zO6KhKy6VZLIzMH665JdYRKCvm1EDW6wuo47A0ndH3eRA2+3SzVezg2Org40ipwo0am8ARrzitAzn5FwYoKJLaIsL6Hx+7mvoZUoZdVheAtCS\ +2269C/KeImyfeWQEXFdt0O3IDsDtHcsrJsRWYDHpIvsRu8cL8ploZentqGl7fpDGBVZhtiUTOJU68zaGgAUTwVRfNSfBRFhzWESBpw95gd3KK+IFZ7gNhiLaWdC2YnkpXEHuYbHDmS3JBUlUiuA6l30MZ1V4Wuam\ +3GtI+MTKkfQFDbrIvIdt5L3piJHngTVItgdjdXeBb9svOx0WbtoEnOIeUlhyYTPuTDRtBdRIB4Uq/0h+avyZMLmkT27aIQeL1/Ip8aL7Iai5y0QN7G2R+y86g0zCQPUZq3o1uIKDAe8BlUVE7mtw7wuyIGJrm9Od\ +REjSZpG/LrF2vkRofg3sjvyhU5mccAgCUyBfeM3njXhwVHDeZDz6xNM3qNwYvXGycfIMsOiSsz9I6IuUz9EsIGeD7lx5QnTydUKlwKZeBMcs/DQIdP62MdMTSvYR9tfij+9oMte45OyT5r8zhGvRmU27LPBatgbX\ +km+u5YQyLMdsE6iEbTeB7cnE4e4vTsPAt81CB6eR/hrqAn8hTf/EGAXr9yYqPTyrA0dVqFuK9zZdBwwpHdBq5W7k0L0u+aS7aVGfrCS+CAcuhYljZEICTO1jnEQeZCRHRv7w55/EC/gFo2TO9tyo/vL8C4T769hP\ +f31LkoW5KwAsOSL74gMVu+R4C8IsQBqTg45U6d79NhHH0+LpZzyITP8d7knxn4AElywxcrV8peS48lxEg55ofQIxT46UGsUx0QbLt+r8HiTDGwi1IdM7QYF4Dt3dsyJjaEunCmlmfydR5RIRZ0F05JwWOMOQju+j\ +oEPq16Xa6Cnn52HHzIdXpaXsPArW1J5N6fM17bbBWKaKEzZ9kZVpBciCNQxMpIzdlovEN6IAMz4WQAvYlwOsBYl68Q8fFky4KDSei3DoMzlMXoJ7BS0AFbKQGYpBBRW3Hnp0/F4Jzm3UR7Gv3rkam+yhTNkeJkVd\ +8G2nA9g/DWvmfUGowHZVuodwKlrHHVSXfiYKjhLWJJpDjtchsgpIwpDHG8y3pjbGTeT8BoKQOV5HjEDgoAOcX1PfB8rE16v81TECcJK5yt7Uxgd+iEzeVP7gBagL0iSQTwYqP71GYN03vPSEEhmEa7V8zbkigYeb\ +/3jF6o9n2sHayXL5to5ugosMeVFeNq/g67uzK2YJUpgCvIv6zGqf5XRzCTQY6pY11/yUvee5QeVnXvI640NxjWUz8HT1mkEU71ig9lyMFGGD1DHjz728dcohKHf+60rke81XYRoEDxaQKGetDZQXEG3RdZktbN+6\ +hH9PACQ3AagVs1Z8a0SnLy7wrE0kZVDdVAtvMcFU24IR8ZIDaE36aBCe2fSuxVzlIKybe5BZc7mzC990+tsmxoIBI4a1Uo7tJZhQCqvarFIgN2wXVoVQ1TG5Ra0iZ94Csdu+5Y4vqCXXl520lXN0QmlwNJlAkRTy\ +c3K0mK2P9tCVcrzAmnh2TrUfi6WN1UAiG5NJ4a2doUwXzKOadZde4T02PJbkkFvGXJt13qn+HKQ42o8sH8q2IEXHbKssR8xuyXrFrGuzVfmjdazv1F/OF2E1G573hqv5QN5yvd4YDEoN57WQXpQSwzK63YG2h5VX\ +OXLW/mZcjfenpv6WSk1nqztcWJCsJkF0sENZOHjButp6OnAETSNBGjYd+c3TuD9vBorY6fftgRieRf8CZ9HZ73gWnU2yc7xD9g4LBz8OFPNSX/9HgyCZBjE7ZuRLof9uVApDS66UKX/NRaXj0DiwsDjmi4N4LxfP\ +PJYFufca60sKS6rpZKsls8OHWJgN517MhMro3NBqkR6BsTGMwsXxzRuXnXCLHFAgsuKaJpYCDJ01KRYxtkHk12ZTTjmG7NJswebdhPkS6a/Fq2rwVbKEUq4RF1ie5NMR6AsuClwvpgcApMo8uHEMljMbeaoAIPBU\ +JuYrNiLvyl/hMVy7wYRKtzUfcTR5jKdCxeynnpqi6KCMaCYJnSxA7oGwrNH+WgBMU6UTPpcClWw4TlEFgZGnzd69Ce9kyLneSz7cY8SWNd4naEZyeRP5aOUpSGO+i4Q/wsBJdHJMp0/F7OvgVsKMcKBzyVfDtVA9\ +G1L/Vd+rT+KALVDaWXiNqXWVXCjr0cN3KVtDntKPGMMXlXI5G20hPZfdjGQE4Pps7G9zmLZu1l5bgBGfqJSKX2vOBTUi7+2Il5X+xQ0utftI5sXbQZEQbhAmZ8G+VJh1yzUeYg17f8WHo8Fc7RyVXPaWpaWdoZFn\ +pSurnacj/P8Fv/25Kpbwvwy0yqa5mqVp4r7UV6vlfduYzXTqGqtiVfT+O0JT7e/wlw6hNI6VSj7/D3TrM/g=\ +"""))) +ESP32S3BETA2ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" +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\ +"""))) +ESP32C3ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" +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\ +"""))) + + +def _main(): try: main() except FatalError as e: - print '\nA fatal error occurred: %s' % e + print('\nA fatal error occurred: %s' % e) sys.exit(2) + + +if __name__ == '__main__': + _main() diff --git a/os/flash.sh b/os/flash.sh index 552208d..beb0894 100755 --- a/os/flash.sh +++ b/os/flash.sh @@ -4,7 +4,7 @@ if [ $# -ne 1 ]; then echo "One parameter required: the device of the serial interface" echo "$0 " echo "e.g.:" - echo "$0 ttyUSB0" + echo "$0 /dev/ttyUSB0" exit 1 fi @@ -14,8 +14,8 @@ DEVICE=$1 # check the serial connection -if [ ! -c /dev/$DEVICE ]; then - echo "/dev/$DEVICE does not exist" +if [ ! -c $DEVICE ]; then + echo "$DEVICE does not exist" exit 1 fi @@ -24,13 +24,12 @@ if [ ! -f esptool.py ]; then echo "esptool.py" exit 1 fi - -./esptool.py --port /dev/$DEVICE $BAUD read_mac +python3 esptool.py --port $DEVICE $BAUD read_mac if [ $? -ne 0 ]; then echo "Error reading the MAC -> set the device into the bootloader!" exit 1 fi echo "Flashing the new" -#./esptool.py --port /dev/$DEVICE $BAUD write_flash -fm dio 0x00000 nodemcu2.bin -./esptool.py --port /dev/$DEVICE $BAUD write_flash -fm dio 0x00000 0x00000.bin 0x10000 0x10000.bin 0x3fc000 esp_init_data_default.bin 0x07e000 blank.bin 0x3fe000 blank.bin +#python3 esptool.py --port $DEVICE $BAUD write_flash -fm dio 0x00000 nodemcu2.bin +python3 esptool.py --port $DEVICE write_flash -fm dio 0x00000 0x00000.bin 0x10000 0x10000.bin 0x3fc000 esp_init_data_default.bin From fe8817bfe65d3c7d1333a304a59cfa9ca7da45ac Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 7 Dec 2020 20:54:46 +0100 Subject: [PATCH 026/204] Ignore locally stored configuration files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0ac4a73..40db714 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ wlancfg.lua +config.lua *.swp unit/testTimesMarchOctoberWithAllSeconds.lua From a2021fcb4808928f4a55a14fd8142a6f0dcab172 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 7 Dec 2020 21:12:48 +0100 Subject: [PATCH 027/204] Sync the time every 5 minutes from the internet --- main.lua | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/main.lua b/main.lua index 59aca40..51e3e0e 100644 --- a/main.lua +++ b/main.lua @@ -154,20 +154,26 @@ function normalOperation() tmr.alarm(2, 500, 0 ,function() syncTimeFromInternet() + displayTime() end) tmr.alarm(3, 2000, 0 ,function() - if (startTelnetServer ~= nil) then - startTelnetServer() - else - print("NO Telent found") - end + if (startTelnetServer ~= nil) then + startTelnetServer() + else + print("NO Telent found") + end end) - displayTime() -- Start the time Thread tmr.alarm(1, 10000, 1 ,function() displayTime() collectgarbage() end) + + -- sync the time every 5 minutes + tmr.alarm(4, 300000, 1 ,function() + syncTimeFromInternet() + displayTime() + end) end -- when no wifi available, open an accesspoint and ask the user From 8858fa19bd971738709ce411d641bdf49c511ab2 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 7 Dec 2020 21:26:02 +0100 Subject: [PATCH 028/204] Added MQTT module --- main.lua | 4 ++-- mqtt.lua | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 mqtt.lua diff --git a/main.lua b/main.lua index 51e3e0e..1260ff7 100644 --- a/main.lua +++ b/main.lua @@ -42,6 +42,7 @@ function syncTimeFromInternet() end ) end + briPercent = 50 function displayTime() local sec, usec = rtctime.get() @@ -146,7 +147,7 @@ function normalOperation() print('IP: ',wifi.sta.getip()) -- Here the WLAN is found, and something is done print("Solving dependencies") - local dependModules = { "timecore" , "wordclock", "telnet" } + local dependModules = { "timecore" , "wordclock", "telnet", "mqtt" } for _,mod in pairs(dependModules) do print("Loading " .. mod) mydofile(mod) @@ -154,7 +155,6 @@ function normalOperation() tmr.alarm(2, 500, 0 ,function() syncTimeFromInternet() - displayTime() end) tmr.alarm(3, 2000, 0 ,function() if (startTelnetServer ~= nil) then diff --git a/mqtt.lua b/mqtt.lua new file mode 100644 index 0000000..845a6eb --- /dev/null +++ b/mqtt.lua @@ -0,0 +1,44 @@ +-- MQTT extension +function startMqtt() + m = mqtt.Client("wordclock", 120) + -- on publish message receive event + m:on("message", function(client, topic, data) + print(topic .. ":" ) + if data ~= nil then + print(data) + if (data == "ON") then + mqttBrightness=100 + m:publish(mqttPrefix .. "/clock", "ON", 0, 0) + elseif (data == "OFF") then + mqttBrightness=0 + m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) + else + if (tonumber(data) >= 0 and tonumber(data) <= 100) then + mqttBrightness=tonumber(data) + m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) + end + end + end + end) + + m:connect(mqttServer, 1883, 0, function(client) + print("[MQTT] connected") + mqttConnected = true + -- subscribe topic with qos = 0 + client:subscribe(mqttPrefix .. "/command", 0) + -- publish a message with data = hello, QoS = 0, retain = 0 + client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) + end, + function(client, reason) + print("failed reason: " .. reason) + end) +end + +if (mqttServer ~= nil and mqttPrefix ~= nil) then + startMqtt() + print "Started MQTT client" + + tmr.alarm(5, 60000, 1 ,function() + m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) + end) +end \ No newline at end of file From df7f33bbf05af4587ebb832f906df071200994e8 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 7 Dec 2020 21:37:04 +0100 Subject: [PATCH 029/204] Brightness is controllable via MQTT --- mqtt.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 845a6eb..67e0356 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -7,14 +7,14 @@ function startMqtt() if data ~= nil then print(data) if (data == "ON") then - mqttBrightness=100 + briPercent=100 m:publish(mqttPrefix .. "/clock", "ON", 0, 0) elseif (data == "OFF") then - mqttBrightness=0 + briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) else if (tonumber(data) >= 0 and tonumber(data) <= 100) then - mqttBrightness=tonumber(data) + briPercent=tonumber(data) m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) end end @@ -22,7 +22,7 @@ function startMqtt() end) m:connect(mqttServer, 1883, 0, function(client) - print("[MQTT] connected") + print("MQTT is connected") mqttConnected = true -- subscribe topic with qos = 0 client:subscribe(mqttPrefix .. "/command", 0) @@ -38,7 +38,7 @@ if (mqttServer ~= nil and mqttPrefix ~= nil) then startMqtt() print "Started MQTT client" - tmr.alarm(5, 60000, 1 ,function() + tmr.alarm(5, 30000, 1 ,function() m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) end) end \ No newline at end of file From de47de1e6fff0936d4a831a2675ed0668c631f6e Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 8 Dec 2020 20:30:43 +0100 Subject: [PATCH 030/204] Always keep the LEDs at a minimum --- main.lua | 5 ++++- mqtt.lua | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/main.lua b/main.lua index 1260ff7..6d10fd7 100644 --- a/main.lua +++ b/main.lua @@ -54,6 +54,9 @@ function displayTime() local words = display_timestat(time.hour, time.minute) if ((dim ~= nil) and (dim == "on")) then words.briPercent=briPercent + if (words.briPercent ~= nil and words.briPercent < 3) then + words.briPercent=3 + end else words.briPercent=nil end @@ -164,7 +167,7 @@ function normalOperation() end end) -- Start the time Thread - tmr.alarm(1, 10000, 1 ,function() + tmr.alarm(1, 5000, 1 ,function() displayTime() collectgarbage() end) diff --git a/mqtt.lua b/mqtt.lua index 67e0356..8f51f35 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -9,13 +9,16 @@ function startMqtt() if (data == "ON") then briPercent=100 m:publish(mqttPrefix .. "/clock", "ON", 0, 0) + displayTime() elseif (data == "OFF") then briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) + displayTime() else if (tonumber(data) >= 0 and tonumber(data) <= 100) then briPercent=tonumber(data) m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) + displayTime() end end end @@ -37,8 +40,11 @@ end if (mqttServer ~= nil and mqttPrefix ~= nil) then startMqtt() print "Started MQTT client" - - tmr.alarm(5, 30000, 1 ,function() + oldBrightness=0 + tmr.alarm(5, 10000, 1 ,function() + if (oldBrightness <> briPercent) then m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) + end + oldBrightness = briPercent end) -end \ No newline at end of file +end From b95f59ee7f08996575966afdd41f9e5345dbeb02 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 8 Dec 2020 20:45:18 +0100 Subject: [PATCH 031/204] Fix LUA syntax --- mqtt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 8f51f35..7fca973 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -42,7 +42,7 @@ if (mqttServer ~= nil and mqttPrefix ~= nil) then print "Started MQTT client" oldBrightness=0 tmr.alarm(5, 10000, 1 ,function() - if (oldBrightness <> briPercent) then + if (oldBrightness ~= briPercent) then m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) end oldBrightness = briPercent From 1eaf05a1ad95219dc3e10e571c28f61ea6633909 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 8 Dec 2020 20:45:28 +0100 Subject: [PATCH 032/204] Add stop functionality --- main.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.lua b/main.lua index 6d10fd7..63718f3 100644 --- a/main.lua +++ b/main.lua @@ -188,6 +188,10 @@ function normalOperation() end +function stopWordclock() + for i=0,5,1 do tmr.stop(i) end +end + -------------------main program ----------------------------- ws2812.init() -- WS2812 LEDs initialized on GPIO2 From 10104b5d0e88b0a278b6dcaf20eff7654cd346c4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 8 Dec 2020 21:11:53 +0100 Subject: [PATCH 033/204] Don call display function in MQTT module --- mqtt.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 7fca973..2c5d832 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -9,16 +9,13 @@ function startMqtt() if (data == "ON") then briPercent=100 m:publish(mqttPrefix .. "/clock", "ON", 0, 0) - displayTime() elseif (data == "OFF") then briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) - displayTime() else if (tonumber(data) >= 0 and tonumber(data) <= 100) then briPercent=tonumber(data) m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) - displayTime() end end end From 7e7a87f90aaa3688d9d9139df5815ce2679c6395 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 8 Dec 2020 21:51:14 +0100 Subject: [PATCH 034/204] Move startup procedure into one loop --- main.lua | 50 ++++++++++++++++++++++++++++++++------------------ mqtt.lua | 25 ++++++++++++++----------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/main.lua b/main.lua index 63718f3..a7c96ba 100644 --- a/main.lua +++ b/main.lua @@ -31,16 +31,20 @@ end function syncTimeFromInternet() ---ptbtime1.ptb.de + if (syncRunning == nil) then + syncRunning=true sntp.sync(sntpserverhostname, function(sec,usec,server) print('sync', sec, usec, server) displayTime() + syncRunning=nil end, function() print('failed!') + syncRunning=nil end ) + end end briPercent = 50 @@ -155,25 +159,34 @@ function normalOperation() print("Loading " .. mod) mydofile(mod) end - - tmr.alarm(2, 500, 0 ,function() - syncTimeFromInternet() - end) - tmr.alarm(3, 2000, 0 ,function() - if (startTelnetServer ~= nil) then - startTelnetServer() - else - print("NO Telent found") - end - end) - -- Start the time Thread + + setupCounter=5 tmr.alarm(1, 5000, 1 ,function() - displayTime() - collectgarbage() - end) + if (setupCounter > 4) then + syncTimeFromInternet() + setupCounter=setupCounter-1 + elseif (setupCounter > 3) then + if (startTelnetServer ~= nil) then + startTelnetServer() + else + print("NO Telent found") + end + setupCounter=setupCounter-1 + elseif (setupCounter > 2) then + if (startMqttClient ~= nil) then + startMqttClient() + else + print("NO Mqtt found") + end + setupCounter=setupCounter-1 + else + displayTime() + end + collectgarbage() + end) -- sync the time every 5 minutes - tmr.alarm(4, 300000, 1 ,function() + tmr.alarm(2, 300000, 1 ,function() syncTimeFromInternet() displayTime() end) @@ -198,7 +211,7 @@ ws2812.init() -- WS2812 LEDs initialized on GPIO2 if ( file.open("config.lua") ) then --- Normal operation wifi.setmode(wifi.STATION) - dofile("config.lua") + mydofile("config") normalOperation() else -- Logic for inital setup @@ -217,6 +230,7 @@ tmr.alarm(4, 500, 1 ,function() ws2812.write(ledBuf) if (btnCounter >= 110) then file.remove("config.lua") + file.remove("config.lc") node.restart() end end diff --git a/mqtt.lua b/mqtt.lua index 2c5d832..23c3ec1 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -34,14 +34,17 @@ function startMqtt() end) end -if (mqttServer ~= nil and mqttPrefix ~= nil) then - startMqtt() - print "Started MQTT client" - oldBrightness=0 - tmr.alarm(5, 10000, 1 ,function() - if (oldBrightness ~= briPercent) then - m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) - end - oldBrightness = briPercent - end) -end +function startMqttClient() + if (mqttServer ~= nil and mqttPrefix ~= nil) then + startMqtt() + print "Started MQTT client" + oldBrightness=0 + tmr.alarm(5, 10000, 1 ,function() + if (oldBrightness ~= briPercent) then + m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) + m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) + end + oldBrightness = briPercent + end) + end +end \ No newline at end of file From efe5b38e587b95a7f7fa168f1f4a9ac0a0f8fe90 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 10 Dec 2020 21:11:35 +0100 Subject: [PATCH 035/204] Different loop cycles --- main.lua | 2 +- mqtt.lua | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/main.lua b/main.lua index a7c96ba..bc1de9a 100644 --- a/main.lua +++ b/main.lua @@ -186,7 +186,7 @@ function normalOperation() end) -- sync the time every 5 minutes - tmr.alarm(2, 300000, 1 ,function() + tmr.alarm(2, 300003, 1 ,function() syncTimeFromInternet() displayTime() end) diff --git a/mqtt.lua b/mqtt.lua index 23c3ec1..14e9bb9 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -39,12 +39,13 @@ function startMqttClient() startMqtt() print "Started MQTT client" oldBrightness=0 - tmr.alarm(5, 10000, 1 ,function() + tmr.alarm(5, 5001, 1 ,function() if (oldBrightness ~= briPercent) then m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) + else m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) end oldBrightness = briPercent end) end -end \ No newline at end of file +end From 6746d62567c748eff0314dc13d820a3dc8de0134 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 10 Dec 2020 22:15:27 +0100 Subject: [PATCH 036/204] Formating added --- displayword.lua | 28 ++++++++++++++-------------- main.lua | 4 ++-- wordclock.lua | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/displayword.lua b/displayword.lua index 58752c9..04bfde2 100644 --- a/displayword.lua +++ b/displayword.lua @@ -3,20 +3,20 @@ local M do local updateColor = function (data) if (data.amountOfChars > 0) then - local div = tonumber(data.drawnCharacters/data.amountOfChars) - if (div < 1) then - return data.colorFg - elseif (div < 2) then - return data.colorMin1 - elseif (div < 3) then - return data.colorMin2 - elseif (div < 4) then - return data.colorMin3 - elseif (div < 5) then - return data.colorMin4 - else - return data.colorFg - end + local div = tonumber(data.drawnCharacters/data.amountOfChars) + if (div < 1) then + return data.colorFg + elseif (div < 2) then + return data.colorMin1 + elseif (div < 3) then + return data.colorMin2 + elseif (div < 4) then + return data.colorMin3 + elseif (div < 5) then + return data.colorMin4 + else + return data.colorFg + end else return data.colorFg end diff --git a/main.lua b/main.lua index bc1de9a..81ce2c4 100644 --- a/main.lua +++ b/main.lua @@ -72,9 +72,9 @@ function displayTime() invertRows=true end displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows) - if (displayword.data.drawnCharacters ~= nil) then + if (displayword.data.drawnCharacters ~= nil) then ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, displayword.data.drawnCharacters) - end + end end displayword = nil if (ledBuf ~= nil) then diff --git a/wordclock.lua b/wordclock.lua index ef3136e..0228c51 100755 --- a/wordclock.lua +++ b/wordclock.lua @@ -64,7 +64,7 @@ function display_timestat(hours, minutes, longmode) ret.before=1 elseif (minutes==9) then -- Hande if three quater or quater before is displayed - if (threequater ~= nil) then + if ((threequater ~= nil) and (threequater==true or threequater=="on")) then ret.threequater=1 else ret.quater = 1 From 7b02f1a447782e34b133db2798cea0134eb6bf27 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 13 Dec 2020 16:37:40 +0100 Subject: [PATCH 037/204] Seperate function to calculate the amount of characters to draw --- displayword.lua | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ main.lua | 10 +++----- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/displayword.lua b/displayword.lua index 04bfde2..a87c43d 100644 --- a/displayword.lua +++ b/displayword.lua @@ -305,12 +305,77 @@ if (words.fiveMin== 1) then collectgarbage() return buf end + +-- Count amount of characters to display +local countChars = function(words) + local characters = 0 + for key,value in pairs(words) do + if (value > 0) then + if (key == "it") then + characters = characters + 2 + elseif (key == "is") then + characters = characters + 3 + elseif (key == "fiveMin") then + characters = characters + 4 + elseif (key == "tenMin") then + characters = characters + 4 + elseif (key == "after") then + characters = characters + 4 + elseif (key == "before") then + characters = characters + 3 + elseif (key == "threeHour") then + characters = characters + 4 + elseif (key == "quater") then + characters = characters + 7 + elseif (key == "threequater") then + characters = characters + 11 + elseif (key == "half") then + characters = characters + 4 + elseif (key == "one") then + characters = characters + 3 + elseif (key == "oneLong") then + characters = characters + 4 + elseif (key == "two") then + characters = characters + 4 + elseif (key == "three") then + characters = characters + 4 + elseif (key == "four") then + characters = characters + 4 + elseif (key == "five") then + characters = characters + 4 + elseif (key == "six") then + characters = characters + 4 + elseif (key == "seven") then + characters = characters + 6 + elseif (key == "eight") then + characters = characters + 4 + elseif (key == "nine") then + characters = characters + 4 + elseif (key == "ten") then + characters = characters + 4 + elseif (key == "eleven") then + characters = characters + 3 + elseif (key == "twelve") then + characters = characters + 5 + elseif (key == "twenty") then + characters = characters + 7 + elseif (key == "clock") then + characters = characters + 3 + elseif (key == "sr_nc") then + characters = characters + 3 + end + end + end + return characters +end + M = { generateLEDs = generateLEDs, round = round, drawLEDs = drawLEDs, updateColor = updateColor, data = data, + countChars = countChars } end displayword = M diff --git a/main.lua b/main.lua index 81ce2c4..cd85dc3 100644 --- a/main.lua +++ b/main.lua @@ -70,16 +70,14 @@ function displayTime() local invertRows=false if ((inv46 ~= nil) and (inv46 == "on")) then invertRows=true - end - displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows) - if (displayword.data.drawnCharacters ~= nil) then - ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, displayword.data.drawnCharacters) - end + end + local characters = displayword.countChars(words) + ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, characters) end displayword = nil if (ledBuf ~= nil) then ws2812.write(ledBuf) - else + else if ((colorBg ~= nil) and (color ~= nil)) then ws2812.write(colorBg:rep(107) .. color:rep(3)) else From 9d764a3b8eb05aa47f093e05e0b2396719681faf Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 14 Dec 2020 19:45:09 +0100 Subject: [PATCH 038/204] Added temperature measurement; but ESP is resetting due to RAM usage --- ds18b20.lua | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mqtt.lua | 46 ++++++++++++++++-- 2 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 ds18b20.lua diff --git a/ds18b20.lua b/ds18b20.lua new file mode 100644 index 0000000..fac19b4 --- /dev/null +++ b/ds18b20.lua @@ -0,0 +1,138 @@ +-------------------------------------------------------------------------------- +-- DS18B20 one wire module for NODEMCU +-- NODEMCU TEAM +-- LICENCE: http://opensource.org/licenses/MIT +-- Vowstar +-- 2015/02/14 sza2 Fix for negative values +-------------------------------------------------------------------------------- + +-- Set module name as parameter of require +local modname = ... +local M = {} +_G[modname] = M +-------------------------------------------------------------------------------- +-- Local used variables +-------------------------------------------------------------------------------- +-- DS18B20 dq pin +local pin = nil +-- DS18B20 default pin +local defaultPin = 9 +-------------------------------------------------------------------------------- +-- Local used modules +-------------------------------------------------------------------------------- +-- Table module +local table = table +-- String module +local string = string +-- One wire module +local ow = ow +-- Timer module +local tmr = tmr +-- Limited to local environment +setfenv(1,M) +-------------------------------------------------------------------------------- +-- Implementation +-------------------------------------------------------------------------------- +C = 0 +F = 1 +K = 2 +function setup(dq) + pin = dq + if(pin == nil) then + pin = defaultPin + end + ow.setup(pin) +end + +function addrs() + setup(pin) + tbl = {} + ow.reset_search(pin) + repeat + addr = ow.search(pin) + if(addr ~= nil) then + table.insert(tbl, addr) + end + tmr.wdclr() + until (addr == nil) + ow.reset_search(pin) + return tbl +end + +function readNumber(addr, unit) + result = nil + setup(pin) + flag = false + if(addr == nil) then + ow.reset_search(pin) + count = 0 + repeat + count = count + 1 + addr = ow.search(pin) + tmr.wdclr() + until((addr ~= nil) or (count > 100)) + ow.reset_search(pin) + end + if(addr == nil) then + return result + end + crc = ow.crc8(string.sub(addr,1,7)) + if (crc == addr:byte(8)) then + if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then + -- print("Device is a DS18S20 family device.") + ow.reset(pin) + ow.select(pin, addr) + ow.write(pin, 0x44, 1) + -- tmr.delay(1000000) + present = ow.reset(pin) + ow.select(pin, addr) + ow.write(pin,0xBE,1) + -- print("P="..present) + data = nil + data = string.char(ow.read(pin)) + for i = 1, 8 do + data = data .. string.char(ow.read(pin)) + end + -- print(data:byte(1,9)) + crc = ow.crc8(string.sub(data,1,8)) + -- print("CRC="..crc) + if (crc == data:byte(9)) then + t = (data:byte(1) + data:byte(2) * 256) + if (t > 32767) then + t = t - 65536 + end + if(unit == nil or unit == C) then + t = t * 625 + elseif(unit == F) then + t = t * 1125 + 320000 + elseif(unit == K) then + t = t * 625 + 2731500 + else + return nil + end + t = t / 100 + -- print("Temperature="..t1.."."..t2.." Centigrade") + -- result = t1.."."..t2 + return t + end + tmr.wdclr() + else + -- print("Device family is not recognized.") + end + else + -- print("CRC is not valid!") + end + return result +end + +function read(addr, unit) + t = readNumber(addr, unit) + if (t == nil) then + return nil + else + return t + end +end + +-- Return module table +return M diff --git a/mqtt.lua b/mqtt.lua index 14e9bb9..4d054c2 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -1,3 +1,7 @@ +-- Global variable +t=nil +mqttConnected = false + -- MQTT extension function startMqtt() m = mqtt.Client("wordclock", 120) @@ -34,18 +38,50 @@ function startMqtt() end) end +function readTemp() + if (t ~= nil) then + addrs=t.addrs() + -- Total DS18B20 numbers + sensors=table.getn(addrs) + local temp1=0 + if (sensors >= 1) then + temp1=t.read(addrs[1]) + end + return temp1 + else + return nil + end +end + function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then startMqtt() print "Started MQTT client" + if (file.open("ds18b20.lc")) then + t=require("ds18b20") + t.setup(2) -- GPIO4 + readTemp() -- read once, to setup chip + print "Setup temperature" + end + oldBrightness=0 + oldTemp=0 tmr.alarm(5, 5001, 1 ,function() - if (oldBrightness ~= briPercent) then - m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) - else - m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) + if (mqttConnected) then + local temp = nil + if (t ~= nil) then + temp=readTemp() + end + if (oldBrightness ~= briPercent) then + m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) + elseif (temp ~= nil and temp ~= oldTemp) then + oldTemp = temp + m:publish(mqttPrefix .. "/temp", tostring(temp), 0, 0) + else + m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) + end + oldBrightness = briPercent end - oldBrightness = briPercent end) end end From d1b5e67ce6d70f3958b20b87975dc006ae0be826 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 14 Jan 2021 21:16:12 +0100 Subject: [PATCH 039/204] Removed temperature reading --- ds18b20.lua | 138 ---------------------------------------------------- mqtt.lua | 25 ---------- 2 files changed, 163 deletions(-) delete mode 100644 ds18b20.lua diff --git a/ds18b20.lua b/ds18b20.lua deleted file mode 100644 index fac19b4..0000000 --- a/ds18b20.lua +++ /dev/null @@ -1,138 +0,0 @@ --------------------------------------------------------------------------------- --- DS18B20 one wire module for NODEMCU --- NODEMCU TEAM --- LICENCE: http://opensource.org/licenses/MIT --- Vowstar --- 2015/02/14 sza2 Fix for negative values --------------------------------------------------------------------------------- - --- Set module name as parameter of require -local modname = ... -local M = {} -_G[modname] = M --------------------------------------------------------------------------------- --- Local used variables --------------------------------------------------------------------------------- --- DS18B20 dq pin -local pin = nil --- DS18B20 default pin -local defaultPin = 9 --------------------------------------------------------------------------------- --- Local used modules --------------------------------------------------------------------------------- --- Table module -local table = table --- String module -local string = string --- One wire module -local ow = ow --- Timer module -local tmr = tmr --- Limited to local environment -setfenv(1,M) --------------------------------------------------------------------------------- --- Implementation --------------------------------------------------------------------------------- -C = 0 -F = 1 -K = 2 -function setup(dq) - pin = dq - if(pin == nil) then - pin = defaultPin - end - ow.setup(pin) -end - -function addrs() - setup(pin) - tbl = {} - ow.reset_search(pin) - repeat - addr = ow.search(pin) - if(addr ~= nil) then - table.insert(tbl, addr) - end - tmr.wdclr() - until (addr == nil) - ow.reset_search(pin) - return tbl -end - -function readNumber(addr, unit) - result = nil - setup(pin) - flag = false - if(addr == nil) then - ow.reset_search(pin) - count = 0 - repeat - count = count + 1 - addr = ow.search(pin) - tmr.wdclr() - until((addr ~= nil) or (count > 100)) - ow.reset_search(pin) - end - if(addr == nil) then - return result - end - crc = ow.crc8(string.sub(addr,1,7)) - if (crc == addr:byte(8)) then - if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then - -- print("Device is a DS18S20 family device.") - ow.reset(pin) - ow.select(pin, addr) - ow.write(pin, 0x44, 1) - -- tmr.delay(1000000) - present = ow.reset(pin) - ow.select(pin, addr) - ow.write(pin,0xBE,1) - -- print("P="..present) - data = nil - data = string.char(ow.read(pin)) - for i = 1, 8 do - data = data .. string.char(ow.read(pin)) - end - -- print(data:byte(1,9)) - crc = ow.crc8(string.sub(data,1,8)) - -- print("CRC="..crc) - if (crc == data:byte(9)) then - t = (data:byte(1) + data:byte(2) * 256) - if (t > 32767) then - t = t - 65536 - end - if(unit == nil or unit == C) then - t = t * 625 - elseif(unit == F) then - t = t * 1125 + 320000 - elseif(unit == K) then - t = t * 625 + 2731500 - else - return nil - end - t = t / 100 - -- print("Temperature="..t1.."."..t2.." Centigrade") - -- result = t1.."."..t2 - return t - end - tmr.wdclr() - else - -- print("Device family is not recognized.") - end - else - -- print("CRC is not valid!") - end - return result -end - -function read(addr, unit) - t = readNumber(addr, unit) - if (t == nil) then - return nil - else - return t - end -end - --- Return module table -return M diff --git a/mqtt.lua b/mqtt.lua index 4d054c2..ae95c87 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -38,32 +38,10 @@ function startMqtt() end) end -function readTemp() - if (t ~= nil) then - addrs=t.addrs() - -- Total DS18B20 numbers - sensors=table.getn(addrs) - local temp1=0 - if (sensors >= 1) then - temp1=t.read(addrs[1]) - end - return temp1 - else - return nil - end -end - function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then startMqtt() print "Started MQTT client" - if (file.open("ds18b20.lc")) then - t=require("ds18b20") - t.setup(2) -- GPIO4 - readTemp() -- read once, to setup chip - print "Setup temperature" - end - oldBrightness=0 oldTemp=0 tmr.alarm(5, 5001, 1 ,function() @@ -74,9 +52,6 @@ function startMqttClient() end if (oldBrightness ~= briPercent) then m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) - elseif (temp ~= nil and temp ~= oldTemp) then - oldTemp = temp - m:publish(mqttPrefix .. "/temp", tostring(temp), 0, 0) else m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) end From fb2556c62c6c6cd18e846640cdbaee3863bdace1 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 14 Jan 2021 21:27:13 +0100 Subject: [PATCH 040/204] Refactor MQTT function names --- mqtt.lua | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index ae95c87..1df27b8 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -1,9 +1,9 @@ -- Global variable -t=nil +m=nil mqttConnected = false -- MQTT extension -function startMqtt() +function registerMqtt() m = mqtt.Client("wordclock", 120) -- on publish message receive event m:on("message", function(client, topic, data) @@ -30,17 +30,20 @@ function startMqtt() mqttConnected = true -- subscribe topic with qos = 0 client:subscribe(mqttPrefix .. "/command", 0) - -- publish a message with data = hello, QoS = 0, retain = 0 - client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) + tmr.alarm(3, 500, 0, function() + -- publish a message with data = hello, QoS = 0, retain = 0 + client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) + end) end, function(client, reason) print("failed reason: " .. reason) + m=nil end) end -function startMqttClient() +function registerMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then - startMqtt() + registerMqtt() print "Started MQTT client" oldBrightness=0 oldTemp=0 From 8d6fc180a33ba1c8252e7681412d7779d59a327c Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 14 Jan 2021 21:32:12 +0100 Subject: [PATCH 041/204] Background color is adjustable --- mqtt.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 1df27b8..eacea11 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -16,6 +16,11 @@ function registerMqtt() elseif (data == "OFF") then briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) + elseif (data:sub(1,1) == "#" and data:len() == 7) then + red = tonumber(data:sub(2,3), 16) + green = tonumber(data:sub(4,5), 16) + blue = tonumber(data:sub(6,7), 16) + colorBg=string.char(red, green, blue) else if (tonumber(data) >= 0 and tonumber(data) <= 100) then briPercent=tonumber(data) @@ -37,7 +42,7 @@ function registerMqtt() end, function(client, reason) print("failed reason: " .. reason) - m=nil + mqttConnected = false end) end From 7195c0899221cd895176ee39cc4efd53eac95bc1 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 14 Jan 2021 21:51:29 +0100 Subject: [PATCH 042/204] Fixed Mqtt function names --- mqtt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index eacea11..2959cdd 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -46,7 +46,7 @@ function registerMqtt() end) end -function registerMqttClient() +function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then registerMqtt() print "Started MQTT client" From 30343fe638bd99f533bd46e050027db69e337ba9 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 14 Jan 2021 21:55:51 +0100 Subject: [PATCH 043/204] Made Telnetserver optional --- init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/init.lua b/init.lua index 1b60740..3023999 100644 --- a/init.lua +++ b/init.lua @@ -36,8 +36,10 @@ end function mydofile(mod) if (file.open(mod .. ".lua")) then dofile( mod .. ".lua") - else + elseif (file.open(mod .. ".lc")) then dofile(mod .. ".lc") + else + print("Error: " .. mod) end end From b44eb6f13eb81db5053036c9d3055c71cad957a4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 14 Jan 2021 22:14:59 +0100 Subject: [PATCH 044/204] Background can be changed via MQTT --- displayword.lua | 7 ++++++- main.lua | 2 +- mqtt.lua | 16 +++++++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/displayword.lua b/displayword.lua index a87c43d..d725b84 100644 --- a/displayword.lua +++ b/displayword.lua @@ -54,7 +54,7 @@ end local data={} -- Module displaying of the words -local generateLEDs = function(words, colorFg, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars) +local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil @@ -103,9 +103,14 @@ local generateLEDs = function(words, colorFg, colorMin1, colorMin2, colorMin3, c end data.drawnCharacters=0 local charsPerLine=11 + -- Space / background has no color by default local space=string.char(0,0,0) + if (colorBg ~= nil) then + space = colorBg + end + -- Set the foreground color as the default color local buf=data.colorFg local line=space diff --git a/main.lua b/main.lua index cd85dc3..2497c2b 100644 --- a/main.lua +++ b/main.lua @@ -72,7 +72,7 @@ function displayTime() invertRows=true end local characters = displayword.countChars(words) - ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, characters) + ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters) end displayword = nil if (ledBuf ~= nil) then diff --git a/mqtt.lua b/mqtt.lua index 2959cdd..a1141ee 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -16,15 +16,21 @@ function registerMqtt() elseif (data == "OFF") then briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) - elseif (data:sub(1,1) == "#" and data:len() == 7) then - red = tonumber(data:sub(2,3), 16) - green = tonumber(data:sub(4,5), 16) - blue = tonumber(data:sub(6,7), 16) - colorBg=string.char(red, green, blue) + elseif (data:sub(1,1) == "#" and data:len() == 7) then + red = tonumber(data:sub(2,3), 16) + green = tonumber(data:sub(4,5), 16) + blue = tonumber(data:sub(6,7), 16) + colorBg=string.char(red, green, blue) + print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) + if (displayTime~= nil) then + displayTime() + end else if (tonumber(data) >= 0 and tonumber(data) <= 100) then briPercent=tonumber(data) m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) + else + print "Unknown MQTT command" end end end From 8c18722dededf34736cc55df732770920d886aeb Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 14 Jan 2021 22:39:56 +0100 Subject: [PATCH 045/204] Added configurable background color --- main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.lua b/main.lua index 2497c2b..cd85dc3 100644 --- a/main.lua +++ b/main.lua @@ -72,7 +72,7 @@ function displayTime() invertRows=true end local characters = displayword.countChars(words) - ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters) + ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, characters) end displayword = nil if (ledBuf ~= nil) then From 8c454f0a9ae100e458d14d881b88f08930f925c5 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 17:45:37 +0100 Subject: [PATCH 046/204] More documentation added for the tools --- tools/Readme.md | 4 +++- tools/initialFlash.sh | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/Readme.md b/tools/Readme.md index 2b6725d..57da26a 100644 --- a/tools/Readme.md +++ b/tools/Readme.md @@ -1,2 +1,4 @@ -# Source: +# luatool.py +**Not** supported with python 3.x +## Source: https://github.com/4refr0nt/luatool/tree/master/luatool diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index a6270ad..b1d5efc 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -5,6 +5,13 @@ LUATOOL=./tools/luatool.py DEVICE=$1 BAUD=115200 +# check environment +if [ ! -f $LUATOOL ]; then + echo "$LUATOOL not found" + echo "is the command prompt at the same level as the tools folder ?" + exit 1 +fi + # check the serial connection if [ ! -c $DEVICE ]; then @@ -12,7 +19,6 @@ if [ ! -c $DEVICE ]; then exit 1 fi - if [ $# -eq 0 ]; then echo "" echo "e.g. usage $0 []" From 86a9503de9a20c4404f89902a123b39d8a05b47f Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 18:01:19 +0100 Subject: [PATCH 047/204] Fixed merging --- main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.lua b/main.lua index cd85dc3..c64084c 100644 --- a/main.lua +++ b/main.lua @@ -72,7 +72,7 @@ function displayTime() invertRows=true end local characters = displayword.countChars(words) - ledBuf = displayword.generateLEDs(words, color, color1, color2, color3, color4, invertRows, characters) + ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters) end displayword = nil if (ledBuf ~= nil) then From 34e47c9a398d3a10c395a150d593cf4d5ebd0314 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 18:02:17 +0100 Subject: [PATCH 048/204] Start MQTT without Telent Server --- main.lua | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/main.lua b/main.lua index c64084c..578de3e 100644 --- a/main.lua +++ b/main.lua @@ -72,7 +72,7 @@ function displayTime() invertRows=true end local characters = displayword.countChars(words) - ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters) + ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters) end displayword = nil if (ledBuf ~= nil) then @@ -152,7 +152,7 @@ function normalOperation() print('IP: ',wifi.sta.getip()) -- Here the WLAN is found, and something is done print("Solving dependencies") - local dependModules = { "timecore" , "wordclock", "telnet", "mqtt" } + local dependModules = { "timecore" , "wordclock", "mqtt" } for _,mod in pairs(dependModules) do print("Loading " .. mod) mydofile(mod) @@ -164,17 +164,18 @@ function normalOperation() syncTimeFromInternet() setupCounter=setupCounter-1 elseif (setupCounter > 3) then - if (startTelnetServer ~= nil) then - startTelnetServer() - else - print("NO Telent found") - end - setupCounter=setupCounter-1 - elseif (setupCounter > 2) then if (startMqttClient ~= nil) then startMqttClient() else print("NO Mqtt found") + mydofile("telnet") + end + setupCounter=setupCounter-1 + elseif (setupCounter > 2) then + if (startTelnetServer ~= nil) then + startTelnetServer() + else + print("NO Telent found") end setupCounter=setupCounter-1 else From 9534368b01114aca10248e2678fed5882fb30011 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 18:08:56 +0100 Subject: [PATCH 049/204] Added cmd MQTT sublevel and refactored function --- mqtt.lua | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index a1141ee..65acfa8 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -2,6 +2,33 @@ m=nil mqttConnected = false +function handleSingleCommand(client, topic, data) + if (data == "ON") then + briPercent=100 + m:publish(mqttPrefix .. "/clock", "ON", 0, 0) + elseif (data == "OFF") then + briPercent=0 + m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) + elseif (data:sub(1,1) == "#" and data:len() == 7) then + red = tonumber(data:sub(2,3), 16) + green = tonumber(data:sub(4,5), 16) + blue = tonumber(data:sub(6,7), 16) + colorBg=string.char(red, green, blue) + print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) + if (displayTime~= nil) then + displayTime() + end + else + if (tonumber(data) >= 0 and tonumber(data) <= 100) then + briPercent=tonumber(data) + m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) + else + print "Unknown MQTT command" + end + end + +end + -- MQTT extension function registerMqtt() m = mqtt.Client("wordclock", 120) @@ -10,29 +37,7 @@ function registerMqtt() print(topic .. ":" ) if data ~= nil then print(data) - if (data == "ON") then - briPercent=100 - m:publish(mqttPrefix .. "/clock", "ON", 0, 0) - elseif (data == "OFF") then - briPercent=0 - m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) - elseif (data:sub(1,1) == "#" and data:len() == 7) then - red = tonumber(data:sub(2,3), 16) - green = tonumber(data:sub(4,5), 16) - blue = tonumber(data:sub(6,7), 16) - colorBg=string.char(red, green, blue) - print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) - if (displayTime~= nil) then - displayTime() - end - else - if (tonumber(data) >= 0 and tonumber(data) <= 100) then - briPercent=tonumber(data) - m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) - else - print "Unknown MQTT command" - end - end + handleSingleCommand(client, topic, data) end end) @@ -44,6 +49,7 @@ function registerMqtt() tmr.alarm(3, 500, 0, function() -- publish a message with data = hello, QoS = 0, retain = 0 client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) + client:subscribe(mqttPrefix .. "/cmd/#", 0) end) end, function(client, reason) From 8789f75e2756aadad1f28231c7c71422dd46ede9 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 18:10:17 +0100 Subject: [PATCH 050/204] Fixed color convertion from MQTT --- mqtt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 65acfa8..3d45af7 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -13,7 +13,7 @@ function handleSingleCommand(client, topic, data) red = tonumber(data:sub(2,3), 16) green = tonumber(data:sub(4,5), 16) blue = tonumber(data:sub(6,7), 16) - colorBg=string.char(red, green, blue) + colorBg=string.char(green, red, blue) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) if (displayTime~= nil) then displayTime() From 62f40d202cc0fe516cec217b6a6db1e2a5cf6ccb Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 18:14:39 +0100 Subject: [PATCH 051/204] Addition color format supported --- main.lua | 1 + mqtt.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/main.lua b/main.lua index 578de3e..18abe65 100644 --- a/main.lua +++ b/main.lua @@ -175,6 +175,7 @@ function normalOperation() if (startTelnetServer ~= nil) then startTelnetServer() else + displayTime() print("NO Telent found") end setupCounter=setupCounter-1 diff --git a/mqtt.lua b/mqtt.lua index 3d45af7..c2141b8 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -9,7 +9,7 @@ function handleSingleCommand(client, topic, data) elseif (data == "OFF") then briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) - elseif (data:sub(1,1) == "#" and data:len() == 7) then + elseif ((data:sub(1,1) == "#" and data:len() == 7) or (string.match(data, "%d+,%d+,%d+"))) then red = tonumber(data:sub(2,3), 16) green = tonumber(data:sub(4,5), 16) blue = tonumber(data:sub(6,7), 16) From b5658b048afa95967128596e4dd83baa238b45bd Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 18:33:49 +0100 Subject: [PATCH 052/204] Start telnetserver via mqtt command --- mqtt.lua | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index c2141b8..c672b15 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -10,9 +10,13 @@ function handleSingleCommand(client, topic, data) briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) elseif ((data:sub(1,1) == "#" and data:len() == 7) or (string.match(data, "%d+,%d+,%d+"))) then - red = tonumber(data:sub(2,3), 16) - green = tonumber(data:sub(4,5), 16) - blue = tonumber(data:sub(6,7), 16) + if (data:sub(1,1) == "#") then + red = tonumber(data:sub(2,3), 16) + green = tonumber(data:sub(4,5), 16) + blue = tonumber(data:sub(6,7), 16) + else + red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") + end colorBg=string.char(green, red, blue) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) if (displayTime~= nil) then @@ -37,7 +41,21 @@ function registerMqtt() print(topic .. ":" ) if data ~= nil then print(data) - handleSingleCommand(client, topic, data) + if (topic == (mqttPrefix .. "/command")) then + handleSingleCommand(client, topic, data) + else + -- Handle here the /cmd/# sublevel + if (string.match(topic, "telnet$")) then + client:publish(mqttPrefix .. "/telnet", tostring(wifi.sta.getip()), 0, 0) + print("Stop Mqtt") + m=nil + mqttConnected = false + stopWordclock() + collectgarbage() + mydofile("telnet") + startTelnetServer() + end + end end end) From a68313e55f96cad416dba17db02e77e0186e8cad Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 18:39:23 +0100 Subject: [PATCH 053/204] Updated the documentation --- Readme.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 813d863..943b796 100644 --- a/Readme.md +++ b/Readme.md @@ -29,5 +29,17 @@ Determine the IP address of your clock and execute the following script: ./tools/remoteFlash.sh IP-Address -## Internal Setup +## Hardware Setup * GPIO2 LEDs +* GPIO0 Bootloader (at start) +* GPIO0 factory reset (long during operation) + +## MQTT Interface +* **basetopic**/command +** ON Set brightness to 100% +** OFF Set brightness to 0% +** 0-100 Set brightness to given value +** #rrggbb Bacground color is set to hex representation of red, green and blue +** 0-255,0-255,0-255 Background color is set to decimal representation of red, green an blue +* **basetopic**/cmd/telnet +** ignored Stop MQTT server and start telnetserver at port 23 From 9eabc733f46e9ae3af5c2fbf41d5c90a5d4f9911 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 19:03:20 +0100 Subject: [PATCH 054/204] Support only one single command --- Readme.md | 2 +- mqtt.lua | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Readme.md b/Readme.md index 943b796..08e6c33 100644 --- a/Readme.md +++ b/Readme.md @@ -35,7 +35,7 @@ Determine the IP address of your clock and execute the following script: * GPIO0 factory reset (long during operation) ## MQTT Interface -* **basetopic**/command +* **basetopic**/cmd/single ** ON Set brightness to 100% ** OFF Set brightness to 0% ** 0-100 Set brightness to given value diff --git a/mqtt.lua b/mqtt.lua index c672b15..2504766 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -41,7 +41,7 @@ function registerMqtt() print(topic .. ":" ) if data ~= nil then print(data) - if (topic == (mqttPrefix .. "/command")) then + if (topic == (mqttPrefix .. "/cmd/single")) then handleSingleCommand(client, topic, data) else -- Handle here the /cmd/# sublevel @@ -63,11 +63,10 @@ function registerMqtt() print("MQTT is connected") mqttConnected = true -- subscribe topic with qos = 0 - client:subscribe(mqttPrefix .. "/command", 0) - tmr.alarm(3, 500, 0, function() + client:subscribe(mqttPrefix .. "/cmd/#", 0) + tmr.alarm(3, 1000, 0, function() -- publish a message with data = hello, QoS = 0, retain = 0 client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) - client:subscribe(mqttPrefix .. "/cmd/#", 0) end) end, function(client, reason) From 4e9d78c86ad71cded5800c9c1822353b4ad70c2b Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 19:06:49 +0100 Subject: [PATCH 055/204] Dim background to same level as foreground --- mqtt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 2504766..8b6ce5c 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -17,7 +17,7 @@ function handleSingleCommand(client, topic, data) else red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") end - colorBg=string.char(green, red, blue) + colorBg=string.char(green* briPercent / 100, red * briPercent / 100, blue * briPercent / 100) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) if (displayTime~= nil) then displayTime() From 9763f4b5739ce7051c21ddd3cf97f835e1169f7a Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 19:28:20 +0100 Subject: [PATCH 056/204] Publish current background color --- mqtt.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 8b6ce5c..350551f 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -10,6 +10,9 @@ function handleSingleCommand(client, topic, data) briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) elseif ((data:sub(1,1) == "#" and data:len() == 7) or (string.match(data, "%d+,%d+,%d+"))) then + local red=0 + local green=0 + local blue=0 if (data:sub(1,1) == "#") then red = tonumber(data:sub(2,3), 16) green = tonumber(data:sub(4,5), 16) @@ -17,8 +20,9 @@ function handleSingleCommand(client, topic, data) else red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") end - colorBg=string.char(green* briPercent / 100, red * briPercent / 100, blue * briPercent / 100) + colorBg=string.char(red* briPercent / 100, green * briPercent / 100, blue * briPercent / 100) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) + m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) if (displayTime~= nil) then displayTime() end @@ -67,6 +71,10 @@ function registerMqtt() tmr.alarm(3, 1000, 0, function() -- publish a message with data = hello, QoS = 0, retain = 0 client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) + local red = string.byte(colorBg,1) + local green = string.byte(colorBg,2) + local blue = string.byte(colorBg,3) + client:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) end) end, function(client, reason) From 84edd69c96cfdeadaa4051156996f28aded561f9 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 20:21:57 +0100 Subject: [PATCH 057/204] Describe OpenHAB2 --- Readme.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Readme.md b/Readme.md index 08e6c33..c84c38f 100644 --- a/Readme.md +++ b/Readme.md @@ -43,3 +43,16 @@ Determine the IP address of your clock and execute the following script: ** 0-255,0-255,0-255 Background color is set to decimal representation of red, green an blue * **basetopic**/cmd/telnet ** ignored Stop MQTT server and start telnetserver at port 23 + +## OpenHAB2 +Tested MQTT with binding-mqtt 2.5.x +### Configuration +``` +Thing mqtt:topic:wordclock "Wordclock" (mqtt:broker) @ "MQTT" { + Channels: + Type dimmer : dim "Dimming" [ stateTopic="basetopic/brightness", commandTopic="basetopic/cmd/single" ] + Type string : cmd "Command" [ commandTopic="basetopic/cmd/single" ] + Type switch : active "Active" [ commandTopic="basetopic/cmd/single" ] + Type colorRGB : background "Background" [ stateTopic="basetopic/background", commandTopic="basetopic/cmd/single", on="28,0,0", off="0,0,0" ] +} +``` From 95aad4f254c934e1150fc119c900550f28f76272 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 20:32:39 +0100 Subject: [PATCH 058/204] Fix color --- mqtt.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 350551f..3b8e5f6 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -20,7 +20,7 @@ function handleSingleCommand(client, topic, data) else red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") end - colorBg=string.char(red* briPercent / 100, green * briPercent / 100, blue * briPercent / 100) + colorBg=string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) if (displayTime~= nil) then @@ -71,8 +71,8 @@ function registerMqtt() tmr.alarm(3, 1000, 0, function() -- publish a message with data = hello, QoS = 0, retain = 0 client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) - local red = string.byte(colorBg,1) - local green = string.byte(colorBg,2) + local red = string.byte(colorBg,2) + local green = string.byte(colorBg,1) local blue = string.byte(colorBg,3) client:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) end) From b5178d5f5b399e8e61a7ce18beefbee5a9ac25f7 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 15 Jan 2021 20:36:48 +0100 Subject: [PATCH 059/204] Documentation formating --- Readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Readme.md b/Readme.md index c84c38f..e5b5d4c 100644 --- a/Readme.md +++ b/Readme.md @@ -36,13 +36,13 @@ Determine the IP address of your clock and execute the following script: ## MQTT Interface * **basetopic**/cmd/single -** ON Set brightness to 100% -** OFF Set brightness to 0% -** 0-100 Set brightness to given value -** #rrggbb Bacground color is set to hex representation of red, green and blue -** 0-255,0-255,0-255 Background color is set to decimal representation of red, green an blue + * ON Set brightness to 100% + * OFF Set brightness to 0% + * 0-100 Set brightness to given value + * #rrggbb Bacground color is set to hex representation of red, green and blue + * 0-255,0-255,0-255 Background color is set to decimal representation of red, green an blue * **basetopic**/cmd/telnet -** ignored Stop MQTT server and start telnetserver at port 23 + * ignored Stop MQTT server and start telnetserver at port 23 ## OpenHAB2 Tested MQTT with binding-mqtt 2.5.x From 1cea6b377e763e6fb5d337a3bf0caa74c4db6c5d Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 23 Jan 2021 09:44:15 +0100 Subject: [PATCH 060/204] Background of first row changeable --- displayword.lua | 13 ++++++++++++- main.lua | 3 ++- mqtt.lua | 20 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/displayword.lua b/displayword.lua index d725b84..395ac6c 100644 --- a/displayword.lua +++ b/displayword.lua @@ -54,7 +54,7 @@ end local data={} -- Module displaying of the words -local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars) +local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars, row1bgColor) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil @@ -107,14 +107,20 @@ local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, col -- Space / background has no color by default local space=string.char(0,0,0) + -- Background color must always be set if (colorBg ~= nil) then space = colorBg + else + colorBg = space end -- Set the foreground color as the default color local buf=data.colorFg local line=space -- line 1---------------------------------------------- + if (row1bgColor ~= nil) then + space = row1bgColor + end if (words.it==1) then buf=drawLEDs(data,2) -- ES else @@ -135,6 +141,11 @@ if (words.fiveMin== 1) then buf= buf .. space:rep(4) end -- line 2-- even row (so inverted) -------------------- + if (row2bgColor ~= nil) then + space = row2bgColor + else + space = colorBg + end if (words.tenMin == 1) then line= drawLEDs(data,4) -- ZEHN else diff --git a/main.lua b/main.lua index 18abe65..014bf44 100644 --- a/main.lua +++ b/main.lua @@ -72,7 +72,8 @@ function displayTime() invertRows=true end local characters = displayword.countChars(words) - ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters) + ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters, + row1bgColor) end displayword = nil if (ledBuf ~= nil) then diff --git a/mqtt.lua b/mqtt.lua index 3b8e5f6..32b6ae4 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -37,6 +37,24 @@ function handleSingleCommand(client, topic, data) end +function parseBgColor(data) + local red=nil + local green=nil + local blue=nil + if (data:sub(1,1) == "#") then + red = tonumber(data:sub(2,3), 16) + green = tonumber(data:sub(4,5), 16) + blue = tonumber(data:sub(6,7), 16) + else + red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") + end + if ((red ~= nil) and (green ~= nil) and (blue ~= nil) ) then + return string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) + else + return nil + end +end + -- MQTT extension function registerMqtt() m = mqtt.Client("wordclock", 120) @@ -58,6 +76,8 @@ function registerMqtt() collectgarbage() mydofile("telnet") startTelnetServer() + elseif (string.match(topic, "row1$")) then + row1bgColor = parseBgColor(data) end end end From f1baf8b916232c0b296dfbbc247455f75d7f2c99 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 23 Jan 2021 09:55:13 +0100 Subject: [PATCH 061/204] Formating corrected --- Readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Readme.md b/Readme.md index c84c38f..b286f1f 100644 --- a/Readme.md +++ b/Readme.md @@ -36,13 +36,13 @@ Determine the IP address of your clock and execute the following script: ## MQTT Interface * **basetopic**/cmd/single -** ON Set brightness to 100% -** OFF Set brightness to 0% -** 0-100 Set brightness to given value -** #rrggbb Bacground color is set to hex representation of red, green and blue -** 0-255,0-255,0-255 Background color is set to decimal representation of red, green an blue + * ON **Set brightness to 100%** + * OFF **Set brightness to 0%** + * 0-100 **Set brightness to given value** + * #rrggbb **Background color is set to hex representation of red, green and blue** + * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** * **basetopic**/cmd/telnet -** ignored Stop MQTT server and start telnetserver at port 23 + * ignored **Stop MQTT server and start telnetserver at port 23** ## OpenHAB2 Tested MQTT with binding-mqtt 2.5.x From 5b96bcc7bbe8780fe5f1ffec8486076c9bd299ac Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 23 Jan 2021 10:00:15 +0100 Subject: [PATCH 062/204] Documentation improved --- Readme.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Readme.md b/Readme.md index b286f1f..e06bd90 100644 --- a/Readme.md +++ b/Readme.md @@ -30,11 +30,19 @@ Determine the IP address of your clock and execute the following script: ## Hardware Setup +Mandatory: * GPIO2 LEDs * GPIO0 Bootloader (at start) * GPIO0 factory reset (long during operation) +Optinal: +* ADC VT93N2, 48k light resistor ## MQTT Interface +### Status +* **basetopic**/brightness **Current brightness in percent** +* **basetopic**/background **Current background color** + +### Commands * **basetopic**/cmd/single * ON **Set brightness to 100%** * OFF **Set brightness to 0%** From f79195e9a575fc97bd2c892ae9f8b707254d4641 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 23 Jan 2021 10:05:18 +0100 Subject: [PATCH 063/204] Status of first row color added to MQTT --- Readme.md | 3 +++ mqtt.lua | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index e06bd90..4bce2b1 100644 --- a/Readme.md +++ b/Readme.md @@ -41,6 +41,7 @@ Optinal: ### Status * **basetopic**/brightness **Current brightness in percent** * **basetopic**/background **Current background color** +* **basetopic**/row1 **Current background color** ### Commands * **basetopic**/cmd/single @@ -51,6 +52,8 @@ Optinal: * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** * **basetopic**/cmd/telnet * ignored **Stop MQTT server and start telnetserver at port 23** +* **basetopic**/cmd/row1 + * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** ## OpenHAB2 Tested MQTT with binding-mqtt 2.5.x diff --git a/mqtt.lua b/mqtt.lua index 32b6ae4..ad82d94 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -37,7 +37,10 @@ function handleSingleCommand(client, topic, data) end -function parseBgColor(data) +-- Parse MQTT data and extract color +-- @param data MQTT information +-- @param row string of the row e.g. "row1" used to publish current state +function parseBgColor(data, row) local red=nil local green=nil local blue=nil @@ -49,6 +52,7 @@ function parseBgColor(data) red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") end if ((red ~= nil) and (green ~= nil) and (blue ~= nil) ) then + m:publish(mqttPrefix .. "/"..row, tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) return string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) else return nil @@ -77,7 +81,7 @@ function registerMqtt() mydofile("telnet") startTelnetServer() elseif (string.match(topic, "row1$")) then - row1bgColor = parseBgColor(data) + row1bgColor = parseBgColor(data, "row1") end end end From c73478d86e1cb61f5156aab098d753842e272387 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 23 Jan 2021 16:44:16 +0100 Subject: [PATCH 064/204] Telnet server can be activated via MQTT --- main.lua | 1 - mqtt.lua | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/main.lua b/main.lua index 014bf44..d08dfed 100644 --- a/main.lua +++ b/main.lua @@ -177,7 +177,6 @@ function normalOperation() startTelnetServer() else displayTime() - print("NO Telent found") end setupCounter=setupCounter-1 else diff --git a/mqtt.lua b/mqtt.lua index ad82d94..016215e 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -79,7 +79,9 @@ function registerMqtt() stopWordclock() collectgarbage() mydofile("telnet") - startTelnetServer() + if (startTelnetServer ~= nil) then + startTelnetServer() + end elseif (string.match(topic, "row1$")) then row1bgColor = parseBgColor(data, "row1") end From 999c8ae3ac5e29287bedc287c978d1c5b597927c Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 23 Jan 2021 18:10:53 +0100 Subject: [PATCH 065/204] Temperatur measurement via DS18B20 added --- Readme.md | 2 + ds18b20.lua | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++ init.lua | 2 + mqtt.lua | 27 ++++++++++ 4 files changed, 169 insertions(+) create mode 100644 ds18b20.lua diff --git a/Readme.md b/Readme.md index 4bce2b1..1948b7b 100644 --- a/Readme.md +++ b/Readme.md @@ -36,12 +36,14 @@ Mandatory: * GPIO0 factory reset (long during operation) Optinal: * ADC VT93N2, 48k light resistor +* GPIO4 DS18B20 Temperatur sensor ## MQTT Interface ### Status * **basetopic**/brightness **Current brightness in percent** * **basetopic**/background **Current background color** * **basetopic**/row1 **Current background color** +* **basetopic**/temp **Temperatur** ### Commands * **basetopic**/cmd/single diff --git a/ds18b20.lua b/ds18b20.lua new file mode 100644 index 0000000..fac19b4 --- /dev/null +++ b/ds18b20.lua @@ -0,0 +1,138 @@ +-------------------------------------------------------------------------------- +-- DS18B20 one wire module for NODEMCU +-- NODEMCU TEAM +-- LICENCE: http://opensource.org/licenses/MIT +-- Vowstar +-- 2015/02/14 sza2 Fix for negative values +-------------------------------------------------------------------------------- + +-- Set module name as parameter of require +local modname = ... +local M = {} +_G[modname] = M +-------------------------------------------------------------------------------- +-- Local used variables +-------------------------------------------------------------------------------- +-- DS18B20 dq pin +local pin = nil +-- DS18B20 default pin +local defaultPin = 9 +-------------------------------------------------------------------------------- +-- Local used modules +-------------------------------------------------------------------------------- +-- Table module +local table = table +-- String module +local string = string +-- One wire module +local ow = ow +-- Timer module +local tmr = tmr +-- Limited to local environment +setfenv(1,M) +-------------------------------------------------------------------------------- +-- Implementation +-------------------------------------------------------------------------------- +C = 0 +F = 1 +K = 2 +function setup(dq) + pin = dq + if(pin == nil) then + pin = defaultPin + end + ow.setup(pin) +end + +function addrs() + setup(pin) + tbl = {} + ow.reset_search(pin) + repeat + addr = ow.search(pin) + if(addr ~= nil) then + table.insert(tbl, addr) + end + tmr.wdclr() + until (addr == nil) + ow.reset_search(pin) + return tbl +end + +function readNumber(addr, unit) + result = nil + setup(pin) + flag = false + if(addr == nil) then + ow.reset_search(pin) + count = 0 + repeat + count = count + 1 + addr = ow.search(pin) + tmr.wdclr() + until((addr ~= nil) or (count > 100)) + ow.reset_search(pin) + end + if(addr == nil) then + return result + end + crc = ow.crc8(string.sub(addr,1,7)) + if (crc == addr:byte(8)) then + if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then + -- print("Device is a DS18S20 family device.") + ow.reset(pin) + ow.select(pin, addr) + ow.write(pin, 0x44, 1) + -- tmr.delay(1000000) + present = ow.reset(pin) + ow.select(pin, addr) + ow.write(pin,0xBE,1) + -- print("P="..present) + data = nil + data = string.char(ow.read(pin)) + for i = 1, 8 do + data = data .. string.char(ow.read(pin)) + end + -- print(data:byte(1,9)) + crc = ow.crc8(string.sub(data,1,8)) + -- print("CRC="..crc) + if (crc == data:byte(9)) then + t = (data:byte(1) + data:byte(2) * 256) + if (t > 32767) then + t = t - 65536 + end + if(unit == nil or unit == C) then + t = t * 625 + elseif(unit == F) then + t = t * 1125 + 320000 + elseif(unit == K) then + t = t * 625 + 2731500 + else + return nil + end + t = t / 100 + -- print("Temperature="..t1.."."..t2.." Centigrade") + -- result = t1.."."..t2 + return t + end + tmr.wdclr() + else + -- print("Device family is not recognized.") + end + else + -- print("CRC is not valid!") + end + return result +end + +function read(addr, unit) + t = readNumber(addr, unit) + if (t == nil) then + return nil + else + return t + end +end + +-- Return module table +return M diff --git a/init.lua b/init.lua index 3023999..0d0f1f8 100644 --- a/init.lua +++ b/init.lua @@ -51,6 +51,8 @@ tmr.alarm(1, 5000, 0, function() (file.open("timecore.lua")) or (file.open("wordclock.lua")) or (file.open("displayword.lua")) or + (file.open("mqtt.lua")) or + (file.open("ds18b20.lua")) or (file.open("telnet.lua")) ) then c = string.char(0,128,0) diff --git a/mqtt.lua b/mqtt.lua index 016215e..f239cb4 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -1,6 +1,8 @@ -- Global variable m=nil mqttConnected = false +-- Temp: +t=nil function handleSingleCommand(client, topic, data) if (data == "ON") then @@ -59,6 +61,21 @@ function parseBgColor(data, row) end end +function readTemp() + if (t ~= nil) then + addrs=t.addrs() + -- Total DS18B20 numbers + sensors=table.getn(addrs) + local temp1=0 + if (sensors >= 1) then + temp1=t.read(addrs[0]) + end + return temp1 + else + return nil + end +end + -- MQTT extension function registerMqtt() m = mqtt.Client("wordclock", 120) @@ -113,6 +130,12 @@ function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then registerMqtt() print "Started MQTT client" + if (file.open("ds18b20.lc")) then + t=require("ds18b20") + t.setup(2) -- GPIO4 + readTemp() -- read once, to setup chip + print "Setup temperature" + end oldBrightness=0 oldTemp=0 tmr.alarm(5, 5001, 1 ,function() @@ -120,9 +143,13 @@ function startMqttClient() local temp = nil if (t ~= nil) then temp=readTemp() + print(tostring(temp) .. "°C") end if (oldBrightness ~= briPercent) then m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) + elseif (temp ~= nil and temp ~= oldTemp) then + oldTemp = temp + m:publish(mqttPrefix .. "/temp", tostring(temp/100).."."..tostring(temp%100), 0, 0) else m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) end From 93b889f706929015254b0e0701f6f33ff4615f36 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 23 Jan 2021 19:17:30 +0100 Subject: [PATCH 066/204] Each rows background can be set --- Readme.md | 10 +++ commands.lua | 186 +++++++++++++++++++++++++++++++++++++++++++++++ displayword.lua | 50 +++++++++++-- main.lua | 3 +- mqtt.lua | 19 +++-- telnet.lua | 190 +----------------------------------------------- 6 files changed, 258 insertions(+), 200 deletions(-) create mode 100644 commands.lua diff --git a/Readme.md b/Readme.md index 1948b7b..4b0038d 100644 --- a/Readme.md +++ b/Readme.md @@ -56,6 +56,16 @@ Optinal: * ignored **Stop MQTT server and start telnetserver at port 23** * **basetopic**/cmd/row1 * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** +* **basetopic**/cmd/row1 + * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** +* **basetopic**/cmd/row2 + * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** +* **basetopic**/cmd/row3 + * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** +* For all rows... +* **basetopic**/cmd/row10 + * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** + ## OpenHAB2 Tested MQTT with binding-mqtt 2.5.x diff --git a/commands.lua b/commands.lua new file mode 100644 index 0000000..4f9ede5 --- /dev/null +++ b/commands.lua @@ -0,0 +1,186 @@ +function storeConfig(_ssid, _password, _timezoneoffset, _sntpserver, _inv46, _dim, _fcolor, _colorMin1, _colorMin2, _colorMin3, _colorMin4, _bcolor, _threequater) + +if ( (_ssid == nil) and + (_password == nil) and + (_timezoneoffset == nil) and + (_sntpserver == nil) and + (_inv46 == nil) and + (_dim == nil) and + (_fcolor == nil) and + (_colorMin1 == nil) and + (_colorMin2 == nil) and + (_colorMin3 == nil) and + (_colorMin4 == nil) and + (_bcolor == nil) and + (_threequater == nil) ) then + print("one parameter is mandatory:") + print("storeConfig(ssid, ") + print(" password,") + print(" timezoneoffset,") + print(" sntpserver,") + print(" inv46,") + print(" dim,") + print(" fcolor,") + print(" colorMin1,") + print(" colorMin2,") + print(" colorMin3,") + print(" colorMin4,") + print(" bcolor,") + print(" threequater)") + print(" ") + print("e.g.:") + print('storeConfig(nil, nil, 1, nil, "on", true, "00FF00", "00FF88", "008888", "00FF44", "004488", "000000", true)') + return +end + +if (_password==nil) then + _, password, _, _ = wifi.sta.getconfig() + print("Restore password") +else + password = _password +end +if (_ssid==nil) then + ssid, _, _, _ = wifi.sta.getconfig() +else + ssid = _ssid +end + +if (_sntpserver == nil) then + sntpserver = sntpserverhostname + print("Restore SNTP: " .. tostring(sntpserver)) +else + sntpserver = _sntpserver +end + +if (_timezoneoffset ~= nil) then +timezoneoffset = _timezoneoffset +end +if (_inv46 ~= nil) then +if ((_inv46 == true) or (_inv == "on")) then + inv46 = "on" +elseif ((_inv46 == false) or (_inv == "off")) then + inv46 = "off" +else + inv46 = "off" +end +end +if ( _dim ~= nil) then + dim = _dim +end +if (_fcolor ~= nil) then + fcolor = _fcolor +end +if (_bcolor ~= nil) then + bcolor = _bcolor +end +if (_colorMin1 ~= nil) then + colorMin1 = _colorMin1 +end +if (_colorMin2 ~= nil) then + colorMin2 = _colorMin2 +end +if (_colorMin3 ~= nil) then + colorMin3 = _colorMin3 +end +if (_colorMin4 ~= nil) then + colorMin4 = _colorMin4 +end +if (_threequater ~= nil) then + threequater = _threequater +end + +print("SSID = " .. tostring(ssid)) +print("TZNE = " .. tostring(timezoneoffset)) +print("NTP = " .. tostring(sntpserver)) +print("INVT = " .. tostring(inv46)) +print("DIM = " .. tostring(dim)) +print("FCOL = " .. tostring(fcolor)) +print("BCOL = " .. tostring(bcolor)) +print("MIN1 = " .. tostring(colorMin1)) +print("MIN2 = " .. tostring(colorMin2)) +print("MIN3 = " .. tostring(colorMin3)) +print("MIN4 = " .. tostring(colorMin4)) +print("3QRT = " .. tostring(threequater)) + +local configFile="config.lua" +-- Safe configuration: +file.remove(configFile .. ".new") +sec, _ = rtctime.get() +file.open(configFile.. ".new", "w+") +file.write("-- Config\n" .. "station_cfg={}\nstation_cfg.ssid=\"" .. ssid .. "\"\nstation_cfg.pwd=\"" .. password .. "\"\nstation_cfg.save=false\nwifi.sta.config(station_cfg)\n") +file.write("sntpserverhostname=\"" .. sntpserver .. "\"\n" .. "timezoneoffset=\"" .. timezoneoffset .. "\"\n".. "inv46=\"" .. tostring(inv46) .. "\"\n" .. "dim=\"" .. tostring(dim) .. "\"\n") + +if (fcolor ~= nil) then + local hexColor=string.sub(fcolor, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + -- fill the current values + color=string.char(green, red, blue) +end +if (colorMin1 ~= nil) then + local hexColor=string.sub(colorMin1, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color1=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + color1=string.char(green, red, blue) +end +if ( colorMin2 ~= nil) then + local hexColor=string.sub(colorMin2, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color2=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + color2=string.char(green, red, blue) +end +if ( colorMin3 ~= nil) then + local hexColor=string.sub(colorMin3, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color3=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + color3=string.char(green, red, blue) +end +if ( colorMin4 ~= nil) then + local hexColor=string.sub(colorMin4, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("color4=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + color4=string.char(green, red, blue) +end +if ( bcolor ~= nil) then + local hexColor=string.sub(bcolor, 1) + local red = tonumber(string.sub(hexColor, 1, 2), 16) + local green = tonumber(string.sub(hexColor, 3, 4), 16) + local blue = tonumber(string.sub(hexColor, 5, 6), 16) + file.write("colorBg=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") + -- fill the current values + colorBg=string.char(green, red, blue) +end +if (getTime ~= nil) then + time = getTime(sec, timezoneoffset) + file.write("print(\"Config from " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. "\")\n") +end +if ( threequater ~= nil) then + file.write("threequater=true\n") + -- fill the current values + threequater=true +else + file.write("threequater=nil\n") -- unset threequater + -- fill the current values + threequater=nil +end +file.close() +collectgarbage() +sec=nil +file.remove(configFile) +if (file.rename(configFile .. ".new", configFile)) then + print("Rename Successfully") +else + print("Cannot rename " .. configFile .. ".new") +end + +end diff --git a/displayword.lua b/displayword.lua index 395ac6c..b860ce4 100644 --- a/displayword.lua +++ b/displayword.lua @@ -54,7 +54,7 @@ end local data={} -- Module displaying of the words -local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars, row1bgColor) +local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil @@ -118,8 +118,8 @@ local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, col local buf=data.colorFg local line=space -- line 1---------------------------------------------- - if (row1bgColor ~= nil) then - space = row1bgColor + if (rowbgColor[1] ~= nil) then + space = rowbgColor[1] end if (words.it==1) then buf=drawLEDs(data,2) -- ES @@ -141,8 +141,8 @@ if (words.fiveMin== 1) then buf= buf .. space:rep(4) end -- line 2-- even row (so inverted) -------------------- - if (row2bgColor ~= nil) then - space = row2bgColor + if (rowbgColor[2] ~= nil) then + space = rowbgColor[2] else space = colorBg end @@ -162,6 +162,11 @@ if (words.fiveMin== 1) then end -- line3---------------------------------------------- + if (rowbgColor[3] ~= nil) then + space = rowbgColor[3] + else + space = colorBg + end if (words.threequater == 1) then line= drawLEDs(data,11) -- Dreiviertel elseif (words.quater == 1) then @@ -173,6 +178,11 @@ if (words.fiveMin== 1) then -- fill, the buffer buf = buf .. line --line 4-------- even row (so inverted) ------------- + if (rowbgColor[4] ~= nil) then + space = rowbgColor[4] + else + space = colorBg + end if (words.after == 1) then line= space:rep(2) -- TG line= line .. drawLEDs(data,4) -- NACH @@ -193,6 +203,11 @@ if (words.fiveMin== 1) then end end ------------------------------------------------ + if (rowbgColor[5] ~= nil) then + space = rowbgColor[5] + else + space = colorBg + end if (words.half == 1) then line= drawLEDs(data,4) -- HALB line= line .. space:rep(1) -- X @@ -213,6 +228,11 @@ if (words.fiveMin== 1) then buf=buf .. line end ------------even row (so inverted) --------------------- + if (rowbgColor[6] ~= nil) then + space = rowbgColor[6] + else + space = colorBg + end if (words.seven == 1) then line= space:rep(5) line= line .. drawLEDs(data,6) -- SIEBEN @@ -238,6 +258,11 @@ if (words.fiveMin== 1) then end end ------------------------------------------------ + if (rowbgColor[7] ~= nil) then + space = rowbgColor[7] + else + space = colorBg + end if (words.three == 1) then line= space:rep(1) line= line .. drawLEDs(data,4) -- DREI @@ -250,6 +275,11 @@ if (words.fiveMin== 1) then end buf = buf .. line ------------even row (so inverted) --------------------- + if (rowbgColor[8] ~= nil) then + space = rowbgColor[8] + else + space = colorBg + end if (words.four == 1) then line= space:rep(7) line= line .. drawLEDs(data,4) -- VIER @@ -268,6 +298,11 @@ if (words.fiveMin== 1) then buf = buf .. line:sub((11-i)*3-2,(11-i)*3) end ------------------------------------------------ + if (rowbgColor[9] ~= nil) then + space = rowbgColor[9] + else + space = colorBg + end if (words.eight == 1) then line= space:rep(1) line= line .. drawLEDs(data,4) -- ACHT @@ -281,6 +316,11 @@ if (words.fiveMin== 1) then end buf = buf .. line ------------even row (so inverted) --------------------- + if (rowbgColor[10] ~= nil) then + space = rowbgColor[10] + else + space = colorBg + end if (words.six == 1) then line= space:rep(1) line= line .. drawLEDs(data,5) -- SECHS diff --git a/main.lua b/main.lua index d08dfed..c624ff0 100644 --- a/main.lua +++ b/main.lua @@ -72,8 +72,7 @@ function displayTime() invertRows=true end local characters = displayword.countChars(words) - ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters, - row1bgColor) + ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters) end displayword = nil if (ledBuf ~= nil) then diff --git a/mqtt.lua b/mqtt.lua index f239cb4..6247e08 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -3,6 +3,7 @@ m=nil mqttConnected = false -- Temp: t=nil +rowbgColor= {} function handleSingleCommand(client, topic, data) if (data == "ON") then @@ -90,18 +91,26 @@ function registerMqtt() -- Handle here the /cmd/# sublevel if (string.match(topic, "telnet$")) then client:publish(mqttPrefix .. "/telnet", tostring(wifi.sta.getip()), 0, 0) - print("Stop Mqtt") + ws2812.write(string.char(0,0,0):rep(114)) + print("Stop Mqtt and Temp") m=nil + t=nil mqttConnected = false - stopWordclock() + for i=0,6,1 do tmr.stop(i) end collectgarbage() mydofile("telnet") if (startTelnetServer ~= nil) then startTelnetServer() end - elseif (string.match(topic, "row1$")) then - row1bgColor = parseBgColor(data, "row1") - end + else + for i=1,10,1 do + if (string.match(topic, "row".. tostring(i) .."$")) then + rowbgColor[i] = parseBgColor(data, "row" .. tostring(i)) + print("Updated row" .. tostring(i) ) + return + end + end + end end end end) diff --git a/telnet.lua b/telnet.lua index a2ad090..9bac3bc 100644 --- a/telnet.lua +++ b/telnet.lua @@ -28,195 +28,9 @@ function startTelnetServer() end end) print("Welcome to the Wordclock.") + print("- mydofile(\"commands\")") print("- storeConfig()") print("Visite https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en for further commands") end) print("Telnetserver is up") -end - -function storeConfig(_ssid, _password, _timezoneoffset, _sntpserver, _inv46, _dim, _fcolor, _colorMin1, _colorMin2, _colorMin3, _colorMin4, _bcolor, _threequater) - -if ( (_ssid == nil) and - (_password == nil) and - (_timezoneoffset == nil) and - (_sntpserver == nil) and - (_inv46 == nil) and - (_dim == nil) and - (_fcolor == nil) and - (_colorMin1 == nil) and - (_colorMin2 == nil) and - (_colorMin3 == nil) and - (_colorMin4 == nil) and - (_bcolor == nil) and - (_threequater == nil) ) then - print("one parameter is mandatory:") - print("storeConfig(ssid, ") - print(" password,") - print(" timezoneoffset,") - print(" sntpserver,") - print(" inv46,") - print(" dim,") - print(" fcolor,") - print(" colorMin1,") - print(" colorMin2,") - print(" colorMin3,") - print(" colorMin4,") - print(" bcolor,") - print(" threequater)") - print(" ") - print("e.g.:") - print('storeConfig(nil, nil, 1, nil, "on", true, "00FF00", "00FF88", "008888", "00FF44", "004488", "000000", true)') - return -end - -if (_password==nil) then - _, password, _, _ = wifi.sta.getconfig() - print("Restore password") -else - password = _password -end -if (_ssid==nil) then - ssid, _, _, _ = wifi.sta.getconfig() -else - ssid = _ssid -end - -if (_sntpserver == nil) then - sntpserver = sntpserverhostname - print("Restore SNTP: " .. tostring(sntpserver)) -else - sntpserver = _sntpserver -end - -if (_timezoneoffset ~= nil) then -timezoneoffset = _timezoneoffset -end -if (_inv46 ~= nil) then -if ((_inv46 == true) or (_inv == "on")) then - inv46 = "on" -elseif ((_inv46 == false) or (_inv == "off")) then - inv46 = "off" -else - inv46 = "off" -end -end -if ( _dim ~= nil) then - dim = _dim -end -if (_fcolor ~= nil) then - fcolor = _fcolor -end -if (_bcolor ~= nil) then - bcolor = _bcolor -end -if (_colorMin1 ~= nil) then - colorMin1 = _colorMin1 -end -if (_colorMin2 ~= nil) then - colorMin2 = _colorMin2 -end -if (_colorMin3 ~= nil) then - colorMin3 = _colorMin3 -end -if (_colorMin4 ~= nil) then - colorMin4 = _colorMin4 -end -if (_threequater ~= nil) then - threequater = _threequater -end - -print("SSID = " .. tostring(ssid)) -print("TZNE = " .. tostring(timezoneoffset)) -print("NTP = " .. tostring(sntpserver)) -print("INVT = " .. tostring(inv46)) -print("DIM = " .. tostring(dim)) -print("FCOL = " .. tostring(fcolor)) -print("BCOL = " .. tostring(bcolor)) -print("MIN1 = " .. tostring(colorMin1)) -print("MIN2 = " .. tostring(colorMin2)) -print("MIN3 = " .. tostring(colorMin3)) -print("MIN4 = " .. tostring(colorMin4)) -print("3QRT = " .. tostring(threequater)) - -local configFile="config.lua" --- Safe configuration: -file.remove(configFile .. ".new") -sec, _ = rtctime.get() -file.open(configFile.. ".new", "w+") -file.write("-- Config\n" .. "station_cfg={}\nstation_cfg.ssid=\"" .. ssid .. "\"\nstation_cfg.pwd=\"" .. password .. "\"\nstation_cfg.save=false\nwifi.sta.config(station_cfg)\n") -file.write("sntpserverhostname=\"" .. sntpserver .. "\"\n" .. "timezoneoffset=\"" .. timezoneoffset .. "\"\n".. "inv46=\"" .. tostring(inv46) .. "\"\n" .. "dim=\"" .. tostring(dim) .. "\"\n") - -if (fcolor ~= nil) then - local hexColor=string.sub(fcolor, 1) - local red = tonumber(string.sub(hexColor, 1, 2), 16) - local green = tonumber(string.sub(hexColor, 3, 4), 16) - local blue = tonumber(string.sub(hexColor, 5, 6), 16) - file.write("color=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") - -- fill the current values - color=string.char(green, red, blue) -end -if (colorMin1 ~= nil) then - local hexColor=string.sub(colorMin1, 1) - local red = tonumber(string.sub(hexColor, 1, 2), 16) - local green = tonumber(string.sub(hexColor, 3, 4), 16) - local blue = tonumber(string.sub(hexColor, 5, 6), 16) - file.write("color1=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") - color1=string.char(green, red, blue) -end -if ( colorMin2 ~= nil) then - local hexColor=string.sub(colorMin2, 1) - local red = tonumber(string.sub(hexColor, 1, 2), 16) - local green = tonumber(string.sub(hexColor, 3, 4), 16) - local blue = tonumber(string.sub(hexColor, 5, 6), 16) - file.write("color2=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") - color2=string.char(green, red, blue) -end -if ( colorMin3 ~= nil) then - local hexColor=string.sub(colorMin3, 1) - local red = tonumber(string.sub(hexColor, 1, 2), 16) - local green = tonumber(string.sub(hexColor, 3, 4), 16) - local blue = tonumber(string.sub(hexColor, 5, 6), 16) - file.write("color3=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") - color3=string.char(green, red, blue) -end -if ( colorMin4 ~= nil) then - local hexColor=string.sub(colorMin4, 1) - local red = tonumber(string.sub(hexColor, 1, 2), 16) - local green = tonumber(string.sub(hexColor, 3, 4), 16) - local blue = tonumber(string.sub(hexColor, 5, 6), 16) - file.write("color4=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") - color4=string.char(green, red, blue) -end -if ( bcolor ~= nil) then - local hexColor=string.sub(bcolor, 1) - local red = tonumber(string.sub(hexColor, 1, 2), 16) - local green = tonumber(string.sub(hexColor, 3, 4), 16) - local blue = tonumber(string.sub(hexColor, 5, 6), 16) - file.write("colorBg=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n") - -- fill the current values - colorBg=string.char(green, red, blue) -end -if (getTime ~= nil) then - time = getTime(sec, timezoneoffset) - file.write("print(\"Config from " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. "\")\n") -end -if ( threequater ~= nil) then - file.write("threequater=true\n") - -- fill the current values - threequater=true -else - file.write("threequater=nil\n") -- unset threequater - -- fill the current values - threequater=nil -end -file.close() -collectgarbage() -sec=nil -file.remove(configFile) -if (file.rename(configFile .. ".new", configFile)) then - print("Rename Successfully") -else - print("Cannot rename " .. configFile .. ".new") -end - -end +end \ No newline at end of file From c2b40f692dcb7cba8ec213c505ff79d7344018ba Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 31 Jan 2021 16:06:28 +0100 Subject: [PATCH 067/204] Upgraded to Nodemcu-firmware 3.0 release --- os/0x00000.bin | Bin 29776 -> 31376 bytes os/0x10000.bin | Bin 397312 -> 421888 bytes os/Readme.md | 41 +++++++++++++++++++++-------------------- os/flash.sh | 1 - os/nodemcu2.bin | Bin 458752 -> 0 bytes 5 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 os/nodemcu2.bin diff --git a/os/0x00000.bin b/os/0x00000.bin index 47bcfd4d9caa72ea6b69dff11a7ca77813d635c7..764056047df0324b7743c651e6430847875080ba 100644 GIT binary patch delta 18365 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 delta 16641 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 diff --git a/os/0x10000.bin b/os/0x10000.bin index ac44e0eda90a0f883bfec6c349c5dba04b7c9062..9d65139bdea05967f8c3e3a1ba6898676b6dc2ac 100644 GIT binary patch delta 259244 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

KE zNyYC!n-U6`Uby8faLndPUi*Wwg3!&OOmc)w%QH;lEk?> z(@6|FVGE-ya~mMD+fG-PQ>LRhe{N^u4WBubii@FTk5Oh?l9)KrJd3HNnQ~fgqvZD~Auc<4ZQiG$RVuP;aDcz5!Ba1$ctVmW@thZJq>8K=iVxoy?`U|PAoorH0x_K7$ zqO8!@P^*|v)qmLF`-dtjdEOhrJk8dA*ihwbkg2F0eY>R8KdkRscPY?kuLlRewsGUi zdtQ5eJ($O(4;JlKXXQ{(p;kh9-?$Q$6qWg$aJ5PTpK;Qzzx|>l>jI{{BOd{moJ-q# z3$Cv@px<&|LtnvVMM<*`&H;jL@X4W#W>r*XR4dT2Rzpp1h2o;ZKvX~6i9zhP)s?jl zISTv&%bbip5-_ipuBv>s>@(p(^EPTq?R>r3+WCua{husmRYf^ku}TM?6tb)~Rc}G! z6df!td>YW5GGRG;-rC}rvI`j|6n?8RGM`UoGv}9~^Q7a_2aC&Up46x3Jf6lh$SD1U z9ZeA3LRC14TSn*7m6UV`zx2MV;zai&-xj^pO}^6A;;8-%lNPK5T7Wd3MgBd`5DVro z4WBVOl%}(7U5XBq{%LR5yGSET1hm?5-aGSAG<>|hc9t&x27CaHrOjJZI-3qIeRzJR zFVk8lTMSpgjSRbgz7_q8G&kjXg-6lqDX)BgHK0M>H8;+Vy+i-Fi zgs;O@H)PHQn^*$T_Qeb8e$c1d5@etjH82$536-2$2;Z>soW(L3z@N}6+RresVL>yZ zURe&tYw2I$*fQhzaj>_W9CYLJ04W@CfjgtfEcG0g8CdNu3G=5}CWukI?;0!u-=S&` z=>;R1%-X&k?zPmISt(osgjS}@*nda{87+_weEsrCIPn>@AqQ1Nm{AWOVJ*Ws(wgsU zK2Da@JmI!3#}?iPx+GB{#R@@ic$Ucf^l(_jb>AdE6!#E0yVb*IFzReP1bSQ`0fYYY z7;a9$KePQjzI*F}dKb337{2fbCe4ve$7rqyUjR*}uZ&nX)6jtAG6Qjiwk#{Tbw+o( zW7dIoTy!*WXy3Y`H32XMw3+}I|7iMIm@I^($HzdFjpu$kj+PtXmU?v(C=ciGCSRZ) zzStPFkR4!oAi7zJ>vVf*mpKGHmb!5b@!OfsZ*{u-m6pzx=6%twSwCgPPz^Pm8`t}I z1r=vz)^ufY5Mat0-O3GWlt{+1`2yxGRFe;{SI5UH!Co0hO4oxYD$1-+wpIoTxB8&& zS6D1HBx~z$oBWv77D^~*4i)v6!W?Na%46pj7c}4trL}fYjiCC8<6?Dv@>fkjB)On} zcz(cZcFAa}Czo#i2}jG0;s3J1Fg~q@Z?{77`W{D7-uTDSayt5q_m#&{t@|d?WQG>I z?p@IZ0B8f~asdUw1%NimWogPNqXaO}pDbzp7q}T#NeE?0;bI6YO#@FIlOi#)ti(R$ z_aEkUNi)$Z0cXH?pCqY<$XP&FCA&C91D?nyqU+HSGH$iZO#!`J6#>AwPDkEfL3 zo|Ce{t1Izu5yi-K4ydBkw%v(h$fjSW#pXIm>mv9#(!H>t@bNf+lzCm&m4JP((3 zGWnS-&oW=%$In#qtc;%-!n5+OnK}H-P`&YM9#N#NIa;kZvJ+EieF$8}9mPB+Gkr-M zjQ-&g_*fTgqgGqFq}11HIh@%-`;MYRFhXjo>d?+fiEsW}1Jq8X@bFB)G|jv(VdH3yIv zkZA6FO|kjHsG||!e}j$9_M(+2QN?@-GXpXJQ#K?IysKX8N;EuH3RpA9nt{g1G5#^h zQH@aozQ`G(FA^MIJ>E4d5l7qic;8-$lJv}{fPdsl(4Dh=YTK9?OC6+sAZZ1B`>`92 z_J#+<+tXNSEo5b7c`LKB0u02&MAC%PLc3w9A)+F;dB10|p6dU;pO=s0&YU@O z?&o)Y_uonqMT(>mkCIU5?Tq=*js4N2;Sf4x;j^tPCqTn@JYz6t*7O!9VD0=YTi8s6 zrcTMEeq~Lmnm10d5M+sEY~~OBu4#&b@8vEZ-78ArJDFEo*ku7mb!v+3^PcNbeyLwu zCs)OeQ#_+GD)Vm3%e^~zv+c8Fw>Fn3#_GRCuUmmMpD%b}r@&r>; zzs-|pRFT27th9i;&;Bx;Ev}Nm_@qVLTYRow(pT4QI;0K|MySod#`!J8ujZ@9s$ zH1bWO6}5f}(>qYBw|U+o?Pt)eOPV^czS{1D6UPDAE4}>~8ACQm-#$hJ@`Tj)7)czu z4BR(e2go|@gy)p0LGwbwF&Q2GLasD(6%;Z6bz$A=1-!>tT@5FSSh_yK@_sB0t4ie4 zPb}-t4T`t$TZ0XeB~273^88NTq1Bt?ne!gz{35E$0y^2#LEfOr7kDv#Xo*d1SnSe{ zHuBytZW0fD^*4aV08r0!f|t^ms%R;r$0}tRHi<+R5;k=kTYMj5iweygCl}`-r$M9J zI~4ot5#8jW*u}+*kR}>~r=C|QL{db}HC|PFR2GecZJHR1CJvgCB|nr@qQyl9tt&>A z0_$3>cx*`5vN%$m*xzuUMSC$)WoJaEz<}FvevGnqyox$jwpENEkI|;;zU=GsFTNqC zY7J4k8voP`-AaE^U<=Je6i9-_1QkcD>%TX`Zd8G9XEP4AXr^g(ulkg9(jhZMftReb zN2rRCJy8py^DGn#bbGlPV{nzTN~xQ!6#DxutnO7MhBGHP&^97)s*Y7fGpZPLd~DpE z^<#0)8pbAHgV}T(c8kfk-&V1NOsDNk;xk|E^`3fQ)VOxAu))I2y~+O3+5Wx;Clvi7 zFR~z~V6_v_Hq#!9u2Qy6#S`SNJO1n}rBicC#u~I3Ux2vpWR)LaQm&1y^T@d?*pym1 zHz=&G5?YIvu_@`C2j*!DaBVp<0 z(yC&D{Dqrxji-~ue!fFA3pRODd`EY@a?Ol z`<@_E74~CB>CGp|XeUMKF03;uE-ApXsi2$j7zFvQCs~lfU9zr3BWkii>ow#U{kdf< zgreeb)5u71p{XvO$?;Hz``j&oT+x|?LxRj8h zZ!tr8aCfou{x}rAFw#@-Ac35v1fno-^x7A=(W;%%7kPRD z*r3#Wn+&|fpux7cb;3-B-Z?WXuNK2VRShZY-x=prChA3a|L^G3K8VqQ;~3razl@Ik zUu^N{|BcQltZ~@i2BmTBw)G$ktD@KII|JuobOi6{$i248?l93gpO8Cff4oDJMUo&^ z+N`a;Oww37GPS$@e@2EMYtA92i@mm22N~653@s_`?;}%tfR2p)?f;ETNc(g*TC_6? zBO?q9jeYc=LsR+3&}6cmbY!H?C&`=6XE}3(N{oQ!$;^(1A)tf?9&bO}*x1>0uPQdl z0@xg2Kfz^0a7_^^(<^Av9HW26f?>1HR*}|k&@NyH<1DsmLHNRpfVAZ|Ef|)0Z_hti z?9iq)NB)yZwIjK_~@C5(R+NydQg} zV*ivq#-7PA1^~IUZ4V(k=(kNCIYrOlPsr|dCI#3(qCEEiZW0SV2hgrbAT`B@2e$-( zlRo^&2!qiy@2V{bbLjGC4FP$z z^#TUF_H$x*peqL)dv62AlTEY%DuT+<3iTe)IR9L#Q7_Zpx0(`rTheW>y>pgD&nYN4 z?@)F)6l4W00H@k{wQDyET`nw{(Y;s|w%7KP0{Tw$$g1HeAMK9wwmX1Ru*Lw8Yn%pz z{6SIpxi^XD-sS|~z9dby7fCyxKUkbTi?58^*~0T;+;F46eKZSps?pyy2BQH4!890t z{f<+^*eqI!DX5paCT}EjZ&itN02Tjp{+ap+>2e`B#Ht|}E7w&{)P!V;oKW3c&+2%k zg+J{c51`Gx$~DCg7TRS?nr(O>DQTwN7#>)gM$yv6tf`~t5|Hle5G{_Q)fHp-YT`pP zFZN`P?l$^+M^p6tx%j-&odeqi>tf(?g4d7t5G=y*SNUtug!qN-t6N0cdu`J5>&O9i zj8U3ZL>Bv>Xu-RrfCuBj{Qt5=swpBd@wX&^1F}DQp!Y$m;*zpqEa>DYxZh@UHW_Di zhJ)C@kpkC~VNP%q21t+Rn>fS@(2J!BIlIA!O$kZze;RUyj=I35TJk2XD^F`aHrAj@ zBsDX+K9$$w$soqU)(0g9KyYhAWQ#Xwwp17oFZ2f#Z>Q^X8ZiW97WF~3=pV!>pd18p zZ1o!HjrC-L!Zp|^om)>#n=bjdzi8tbLU9po<8s+%G-rBB?{{{|BYq4GzW15z=KB88+c9 zCbJ{N03@s(Y%{Z`6=-+yOh}x9VcHXH-!JR4R~FWhs(OHr=i@^QPWHE#Xuq&5mnIbh zYggGo&nIb?5}?w8>qj|_%_FO|n*`lc!Bv*R^ySR3CaiRH9^L@>H2RxfsY2mBrC2YNvXOFDWtx z)P|5^Cp|Ra(AC7qh76vAw25XSJL&3M$a))+!+l{`F79rIe}_cw=HLm#hgmebuYCBB zHbvN!k{L<;Suh>7%fCWDv$5hG)L>yqMHWe;ky<0SrL?639F}1;L$+rDzvX^ce zqdzPO(4<;^4m@iV2cr#8JSf(Bhr)hRhVNUm4xm(lBXos>Y!>Xnq|e)$%oSI`ckyAE z`5L1lg=478bL1#;uv`M^^QR52J1TA6NaFqAVK=j!H{i6XmA=|YGL_3@#~jJH2`GuH zNt(HdM8vupGvAA}e%u@r%57_7|91US$vKcl}#=3-Z7@Er9 zlkvW_nM`J7Kd0@H5}ziKgR;C>VSDnK4k`C(Vz55y*BH8d~4g5?4Yd_$^drcJv^?ia+$9rk0R- zx@S5jln)ctiGX5X7Y&BVgHi43=cM;a083ob&n0leV3*>aA*n2H+^ zNEcv|+VwiC3c7XAy~1J5B^S{-SG#`aU^0Ne4|4a_>dD{S79#8HdUPdEYL6{N!2a3r&W;?UrW25C1V0= zH!+(kGSA=48nVS@Kmul0Ir~LH#N3n_>k6e-r6I zaFJZ_z2qq)HbrfBy7W^SsbHTzC2cAv!`V^I(i`Q(!R|aI4RVubbVE;~58!)-l>mOd zI=`&2aV1&%i}a40xb-_OcnxpqF{Si1aiD#nqyWtU%J|*cWO`A`evTw0^kVXmWq_#& z3Kx7a1yF(Y%GHXzpe3P`g&SZAZ{3^4F8Qx-o7p}?s(OyBWDi`BZu>8pKX?X$cO<5= zg=5Jy{s{ZE8~hb}wzU1fP?2HJO2_|8VuNch^ozWA-dEr)^+j>N3I?z z$lb#sgHI0SRrbiHp;GSiWCVNijI{B2GC8vLc#rq(uz5MYM*i-Ju5bTQoPC~j>3I@P z9MT|(L~A}|&gbikRiGf1t^?9UiPSp>j@v)=TyBD^quZFtl)!8;(6mJ!8MP2Rf`@V(aF9Xw*;zJE3-3?e9UaF* zv&RI+(FUJi$Q>D`K?jbc75g%R+--VVHWb+^He^7}r0r|z}EO2)I3zmkf!lDh&Az@5IX96X)cR;&W(DI)69 z6GK#Cqp&tK?O|_uc6ZLZqn7u|NS2(E9^OV0*n3V%72C*2cIGMR*ft^zPdNp##URF} zV5+B_(uK$%=?@3}239yB!@iOHUIwmm@Pah@WinPZxu+!0VU?D=OrFrV*2_B~c>+nO z;GUO$f0;xMcNNOen^#?z83dRaqp#iHpV`FxGMvLX%59d$yh4N!HSF3>M+^a^E0(DM z3g`4*Y4Iy$oDW^~5L-#dn@L=XH@cmjtZKqk+yVnka{f*4c>yVszHy~NiBY#z%pc%$ zk#q|9kFi_Jz41VD>3610QvWNk`%qq!B0MD4kDETqLcn1yyWT0y@{pOVeS}ouAz?;Z zGXuWonafns4Tet8sIv{IEtcc}^QY_}h}_h%Ibp&{>70jz=)VDD^Q(R#;^w(avH^#t ztrDs+L`55c3EA5t`Be~e$ieeq9$MJLZk1(XA`RG*+$>9Xj8jHPXU8c6$5V2sQUu*X z7}{Rp^TC2{ zZH6Fd1Cs4~@4@KnnH60O3D(hLhw5gH|H@{0A#e!*QdP0UOvj|UL zK-)5@5+`v}hyfI#DM=GPg}h43GK9Mxk&aiA45vMXI!VYE#CZJ~;Bw}Cy%-+>Rf`3~ z&*Z2SOf$>DjmJWuX~l3OA3x$ujW@COvaIVHNTgp!i1{PL1$PYOza;Cn4ZIo{1MgAr zo)-rI8{@=?PE$muL33dpB}Z;L3&J3BXj6#G7@GrL9kuDYPM+`L;-5V{f>o6>b=$#w ziGhWR{|uRyxq}Z!auzrBziizo#^%5C;P#r) zBZYs#M55-Qk$&U2i0iQjeGD^rUKIsYN+J61G(RMb*iM~1*GtCjWRjvb^t$x$c4A^( zFH4o%ae}{gT>5Q0iSd8wI0h|Mn7WrD8hfM>uYtkdC{1~dB+fjeL{hVyMGSYA*yF~h zVAq>oxf-WP)ou+DM~7P8&4~zH5ur`<&-hYVyN0!mjwzXAcxdf#b?>R*GAhJnRc;?M9!_SL zy|)-nbN`{IN!d-(y{{9H0n#I{ld;3?wK7%X8yr&}B=S){IXoW;?gT_R09(VPL$3oM z{Wwzk{dE!%&AkIy=2BrrrNH)qZ?JPI^IA%Cq_yUJIE+!!Vmh~@}a_S9l&($t+I*l z$GKT?Ke5ryf=8PZADSAzG(B%;7QfVy6CNm>>zJlpT3`#;=H(~x^U1VzP4O`~4yEf1 zUDFLYSn_9ziWN*3Ykxu3$rwDWc0dm73F?fmi>;OZOy22VJb}(l7wdXn)&+p}LS93< z#gSLAdR<_${_b?Uoh^A1b^+#HT~!*!^iv;gToDOtlrHZex&`Ywdy3C<0x)`BBtuH&5`FC`)-<&{9*B9+x{`|FAjt<6gYmSzz6!-9X`VL z4hV5x4V2Q~gdPNFT*^(`UIWP1aw|`zQrLn#JAX))I*j}#;~)NTe<;+xQ>qLA=qS_Sp2sd3Rmd}Litoj*9M5*``~>{5ae6cj_>PLQY54AMzR1 zC*Z#r`DQ4A{6)#NeL83h*M&b2N(@u7M>fsrFeojG+eKX^tWSYtVmOZo`YP#_w+N?j z-RP6vc#F(3xH|eQM8^ghg5vyZA_5zBB9KSz3nR^7d)^x;`r}YYTsNvCIZhh!Hn~lk z4qxo?x1!(H!^%o-KAN;3}b6#9ED>@PSH?i@H0qNJv`Nxb&j z6+r&;IZWc6t{muw)YeD=JAsv+ydd4alPo0nNLzLSqHuGhqdUo6iM9P5`7rhO`I|QH z&q3c5-;^7$70%#l#PtQPR$OwGEPsyQ`U@Y-c!vxkY;CY~&%0!ep@S~ zN5;XrGvkhZ>0CKHR)`aW?Gvt-*(qF63O%G*y)^351N9!LU37NjX3 z5dFw&KxL+J$pw8&m9DFO*#6I2W7ju3g(-2%2!3qyawhxIo#E&&3CBJw%?)DaCVp5$Cp5DW_%u0o7PDuK7=M7_Y+gM2>4E>`R2OS*Egv*3k^exuMwWx5pY(W#y!J< zVY#GykU{fCkWRmFy?(=bLsFVX7xctgwiv35XSp=B?nj9C6ctOai;EQop=D59Qn=E3 zci>hfEPjohcil-Vt{p{GcgalXZ){4cyj5YCoNH6k0C=|{C}pNXrg*(V$h-{TVPIn+ zhNgCdA+EOmOE9=Up8jU956WUh#NBstH~YnVBf=vg7y1x>`LV*y&{6raUp0hsfKMe8J+Bg!mkn&(Szt|R?}*1HCMM5McfBip^)X2rmewl{V(M0t z@F?r#z;H1(goSptXdJP}CXGA@Tz=G1DeWMMRgUhhxGb$ch;?t5b{-@t)6@Gij8U26 z399AAJ=$J6Ed7!lNNkJM$8#Uzvh+rxTM@WW+_*glw+W3I);zpdiurTmJ+j{C@!>^ zheza&;M%D&WM}eEJ?4d@L?tutJi=8GI1B>T_DzrD+a6mqQ?W%ljtZQ%t7!q*OZ8AK zermXG$> z(CJ8+5t-AX_(u}c>MqhRYJcxv_el>lvS^+trfgr2*_WBR=+TOOJvL*gd1Ndz;kl(4 zF45yvOG%3|YFtzL_sqVO>Ua7%A45`{A0&5-X@yk&DGb?cmuzrHDl)cZ*mEsx?Ra9^ z)&oqXxc+aouTM-Si;~`Q3YAIS6#-`pYC%hl^f_J=j~*SRPz}+dHv$wJ1G)JI&ER`T8w$^SN-c! zdcs+=nu%S{s#eKmc5lag(Xrx3CH&-++}MY0s1PmUQE)s z7WSJyqRPY-_mSJaz~NOq5%Ucu)dY4lwuXeLN7^}GA*21Ce$zYNj1Q1FZ^kh+qiwjQ zVZ$CnPpaRU#jw52Fp9cs{d9faTG~I z1qaP6S&{7DgCPMRNY~IcHSav6OLXwe`3zUUV5}L_Ov$erXl8deuQ5cl@GYv-K}!3* zeJv5Lul)CmY+V%i1NOAOI?A3a5}5Rb9i?&l!aEBA0Y6|=kM}X>e(m03s`#~g&u`tJ z!;Hdw|MGiPM0T4wygJnMJ2uq4ogecFZU?7Dd!6|&+7|$YL#|#&zj^HOukq8RE6I- zJ>;c^Dyna`I(dufaJiq+mz&XN^sgI@My{~=i$j%WPe`L!CEly5d5C!-!suI@+y@zg zzx@VINT^Fdm>yvcfjhCnN3;p4$=0cQ%MdC_onhUSY@5s!O(sQynS%cu$xhQ|3AU57 zW}Va*zCxDo3T!{{Xz9mJePOD$af?7Tt>4nN=Oq`Og&wwk`D1~er}d33`sI0g6b31- z^+0m=j+NP^k7jRrv~hK^I2j%QgKd-9y^|F=la-Z|x$?=XqRBo@llc{sHAeq`3==v7 z4?gBYAsCz{heltcKMN=K0Ay0cA)*efo!X~s;?3cqSvwPnY4MQ{ZaYM_5f;qfQ=b#T zx4RxA1lx~PN&cLKX-4#^k{Bk(81_JZ?NKSVmaJwQ>!pfX_%=yBA;I}zH0%0AimM~b zLTdy2(%7v*Iq_kTPMI5El->H29?BZ;)RFnDD^^k;CV75y>yJ2&v7#8-k}fqKCnKa6 z50jC?N z`qfJ>)syGhfTPmbBjg#vO4Ub55?Lb2N66hIUAp@V*!bFKe6ZvTG9QR$wp4SJY+y$m zmQowYz5v%-y=U3g!X~Zmd_eN=b<&_?B#}&%rW_+4VF+H(7EOn3sCJnT2#EmDyD&^# zQX4`WR3>p>l6~y@x(`13k^~X<&N}JK<8X*`jY$5DMCW7gfaSF7A!$@2d7b!6O^sw+ zy#1A4D#>B8NFKRo3cSejA+zQrXV3N2ZtK1KV$N`-x6k+EyC1xzggRSMhXfw`IA7D5^TPdY1~#(@^iCTLEp+D@6Cz5%)#Q`Baw!LYV1Mw*@Byfu^gdz!t^ApP zIy8772?){`5etnY1za$29m%}QKRDki%Nje*h)wmOOi z7T{|F(+xqB(np=+c_H|7(^aZ4cZ5shxr;KQDppO`ixr(<(Lz0z-g_3iew86WrT4G4 z)n1TIM`%Nk{elcf=V}wawy@A3tQQhlFP}&Hu8F9fH@gwL)$|Pln80=4pWQ2Xo;D-Z z$Jcc5M_!c`75iUf*0>4(HNYw^CC*0$94Ss^fLn;HAWO*YSvF#F9wrahVrGh2 zCQG?YSu#G2OKJbJ%n9M{arn;ia$E;Enid1VvS3`0ll%_eCk~1y=70&QLaQlME^)lHcY%yil z{0d>^dYV$J>Gh^mUfBBZYNu|(1;c;Rr(UA_wsfh!%7=jm04B5f7gMsd?GzE!zP)fB zJk}m19X>_=%~lzU0)Mnu-&is88A=%#o1(o0Q!D&@*(NVW->C7GLm22 zM!M+y{INlVOTS`e8fd^c+p9al2BGZDlXb{J*_*r~ehRs8NQ!PDsXsz`>aPNJp-yh4vX8vPGN$%$hqUus5*O^cgv7$j zT1-zIiH+dx%~z$iZ;6q1I`j+~Ir-d=FvZ%sK2=fjW0o?vc2JfGE7rlOAyWs3nj=Fq zXZO2aU~t@n=7y3=C*3Caz4FJ9cpYI#g=a|EZI=|*#?DMTpAhZNJnyIb#1BF+wD?;Y zE(-X`20k%7X0JN8hOLWasG&1xtW;f&uXN%JELkELLx>o3`}Lv~2(~SHLTnW!#ie5XNM!xSyK zTFDr8ZjH3R6-Q@kjdY=vBqSaTvaq@PjHdn{{yJCh|G&)DWp9TuSKjUwOBv_LB(42b z%mG|I8~K)3Ay-PSkSfoSsiC#oWL*&)x0}Vm4U?fk7_*3)Pi%btJhjdEi43{Revy_2 zwk=hm+#>75ek?w2I<-uoa=sw1LxNd{P}hJm`4Qm)sqT}{^~lt_M$@Zu?XXnHD#)p? zq|HB(5lSx$)` zo=J!%aiAI_1%0*%C8$Cw^M1A`jlCHT9=1ct&Fo1{E_u$tXPHaJdy#U;vMIKoO7_st z{x8zi`;7F~&txv^nkkWA$P)kc*WwD`M4{+f+&cU04(YL9$ixS@&%0AAV8Tx<>!wxM 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%0DVD-Z+qw(>+^`O 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 diff --git a/os/Readme.md b/os/Readme.md index c8a60f3..dbc574a 100644 --- a/os/Readme.md +++ b/os/Readme.md @@ -1,22 +1,23 @@ -# Firmware was compiled with the following modules: +# Nodemcu-firmware - * LUA_USE_MODULES_ADC - * LUA_USE_MODULES_BIT - * LUA_USE_MODULES_DHT - * LUA_USE_MODULES_FILE - * LUA_USE_MODULES_GPIO - * LUA_USE_MODULES_I2C - * LUA_USE_MODULES_MQTT - * LUA_USE_MODULES_NET - * LUA_USE_MODULES_NODE - * LUA_USE_MODULES_OW - * LUA_USE_MODULES_RTCFIFO - * LUA_USE_MODULES_RTCMEM - * LUA_USE_MODULES_RTCTIME - * LUA_USE_MODULES_SNTP - * LUA_USE_MODULES_SPI - * LUA_USE_MODULES_TMR - * LUA_USE_MODULES_UART - * LUA_USE_MODULES_WIFI - * LUA_USE_MODULES_WS2812 +## Release +* 3.0-release_20201107 + +## Modules +Firmware was compiled with the following modules: + * LUA_USE_MODULES_ADC + * LUA_USE_MODULES_FILE + * LUA_USE_MODULES_GPIO + * LUA_USE_MODULES_MQTT + * LUA_USE_MODULES_NET + * LUA_USE_MODULES_NODE + * LUA_USE_MODULES_OW + * LUA_USE_MODULES_RTCFIFO + * LUA_USE_MODULES_RTCMEM + * LUA_USE_MODULES_RTCTIME + * LUA_USE_MODULES_SNTP + * LUA_USE_MODULES_TMR + * LUA_USE_MODULES_UART + * LUA_USE_MODULES_WIFI + * LUA_USE_MODULES_WS2812 diff --git a/os/flash.sh b/os/flash.sh index beb0894..876ca98 100755 --- a/os/flash.sh +++ b/os/flash.sh @@ -31,5 +31,4 @@ if [ $? -ne 0 ]; then exit 1 fi echo "Flashing the new" -#python3 esptool.py --port $DEVICE $BAUD write_flash -fm dio 0x00000 nodemcu2.bin python3 esptool.py --port $DEVICE write_flash -fm dio 0x00000 0x00000.bin 0x10000 0x10000.bin 0x3fc000 esp_init_data_default.bin diff --git a/os/nodemcu2.bin b/os/nodemcu2.bin deleted file mode 100644 index 1644bdf71aa9352b5a19930393d26500cd36044e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 458752 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 From 0e8fc8864666f919682e3749b44cb70299ddec5b Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 31 Jan 2021 16:13:44 +0100 Subject: [PATCH 068/204] Flash script improved --- os/flash.sh | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/os/flash.sh b/os/flash.sh index 876ca98..a4f1f0b 100755 --- a/os/flash.sh +++ b/os/flash.sh @@ -1,34 +1,33 @@ #!/bin/bash if [ $# -ne 1 ]; then - echo "One parameter required: the device of the serial interface" - echo "$0 " - echo "e.g.:" - echo "$0 /dev/ttyUSB0" - exit 1 -fi - -DEVICE=$1 -#BAUD="--baud 57600" -#BAUD="--baud 921600" - + DEVICE=$1 # check the serial connection - if [ ! -c $DEVICE ]; then echo "$DEVICE does not exist" exit 1 fi +else + print "Autodetect serial port" +fi + if [ ! -f esptool.py ]; then echo "Cannot found the required tool:" echo "esptool.py" exit 1 fi -python3 esptool.py --port $DEVICE $BAUD read_mac + +CMD="python3 esptool.py " +if [ $# -eq 1 ]; then +CMD="python3 esptool.py --port $DEVICE " +fi + +$CMD read_mac if [ $? -ne 0 ]; then echo "Error reading the MAC -> set the device into the bootloader!" exit 1 fi -echo "Flashing the new" -python3 esptool.py --port $DEVICE write_flash -fm dio 0x00000 0x00000.bin 0x10000 0x10000.bin 0x3fc000 esp_init_data_default.bin +echo "Flashing the new firmware" +$CMD write_flash -fm dio 0x00000 0x00000.bin 0x10000 0x10000.bin 0x3fc000 esp_init_data_default.bin From 768ff42c1a6a66991f8691ad7e61448af8f235c6 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 31 Jan 2021 16:51:31 +0100 Subject: [PATCH 069/204] Initial flash is working again --- tools/initialFlash.sh | 4 ++-- tools/luatool.py | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index b1d5efc..67240a8 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -34,7 +34,7 @@ fi # Format filesystem first echo "Format the complete ESP" -$LUATOOL -p $DEVICE -w -b $BAUD +python3 $LUATOOL -p $DEVICE -w -b $BAUD if [ $? -ne 0 ]; then echo "STOOOOP" exit 1 @@ -59,7 +59,7 @@ for f in $FILES; do exit 1 fi echo "------------- $f ------------" - $LUATOOL -p $DEVICE -f $f -b $BAUD -t $f + python3 $LUATOOL -p $DEVICE -f $f -b $BAUD -t $f if [ $? -ne 0 ]; then echo "STOOOOP" exit 1 diff --git a/tools/luatool.py b/tools/luatool.py index 6358855..5bfb296 100755 --- a/tools/luatool.py +++ b/tools/luatool.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301 USA. +# version 0.6.4 based version +# Version 0.8.0 upgraded to python3 + import sys import serial @@ -25,7 +28,7 @@ import argparse from os.path import basename -version = "0.6.4" +version = "0.8.0" class TransportError(Exception): @@ -55,11 +58,12 @@ class AbstractTransport: line = '' char = '' i = -1 - while char != chr(62): # '>' + while (len(char) == 0) or (ord(char) != 62): # '>' char = self.read(1) + #print(ord(char)) if char == '': raise Exception('No proper answer from MCU') - if char == chr(13) or char == chr(10): # LF or CR + if ord(char) == 13 or ord(char) == 10: # LF or CR if line != '': line = line.strip() if line+'\r' == expected: @@ -78,8 +82,8 @@ class AbstractTransport: raise Exception('Error sending data to MCU\r\n\r\n') line = '' else: - line += char - if char == chr(62) and expected[i] == char: + line += char.decode("utf-8") + if ord(char) == 62 and expected[i] == char: char = '' i += 1 @@ -105,7 +109,7 @@ class SerialTransport(AbstractTransport): if len(data) > 0: sys.stdout.write("\r\n->") sys.stdout.write(data.split("\r")[0]) - self.serial.write(data) + self.serial.write(str.encode(data)) sleep(self.delay) if check > 0: self.performcheck(data) @@ -142,7 +146,7 @@ class TcpSocketTransport(AbstractTransport): if len(data) > 0: sys.stdout.write("\r\n->") sys.stdout.write(data.split("\r")[0]) - self.socket.sendall(data) + self.socket.sendall(str.encode(data)) if check > 0: self.performcheck(data) else: @@ -218,10 +222,10 @@ if __name__ == '__main__': fn = "" while True: char = transport.read(1) - if char == '' or char == chr(62): + if char == '' or ord(char) == 62: break if char not in ['\r', '\n']: - fn += char + fn += char.decode("utf-8") else: if fn: file_list.append(fn.strip()) From fc97df71eaab41157975b7328bd0276b4e9e4fef Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 31 Jan 2021 16:58:17 +0100 Subject: [PATCH 070/204] Nodemcu-firmware has only integer support --- os/0x00000.bin | Bin 31376 -> 31360 bytes os/0x10000.bin | Bin 421888 -> 413696 bytes os/Readme.md | 4 ++++ 3 files changed, 4 insertions(+) diff --git a/os/0x00000.bin b/os/0x00000.bin index 764056047df0324b7743c651e6430847875080ba..4fdaaf9ea508cdc817052a11050a213102f90272 100644 GIT binary patch delta 352 zcmbR6m9gO~;|3lkrXTk=^D(VrW4rJ|&Edw2&HFg)n1v)>syRFW@);Ny9142=*_*uF z%*T_($o2s!X7h4$9q%SaCWe=rjrgtjm?j8s&XWydVKmr$P?4FL>4E3wV=84#VB_9+ zZgx@^6J}g6Inru5(*d>3Ox9v7U>OFl&2sjiIGHwRZWi)f#SRwZ@Y;MRz=@mbh300q z7$t52gLV~%h87iv8~4>50@xTFCQnS0*&LE?!OXa2b8pslRz{Y|sRhP@K5EJiZxR?B zE&%a|Y$XSm%_|GqS>zfXsW~9y79byn3%n-#mD;fsdaFB3RxB&nRCa*btP;qnA_D(M c0h51KmWi-*{j=u)29*Gie(?35J&?%+0N$R5K>z>% delta 368 zcmZqp$~fUG;|3lkrXAll^D(VrW1I3{&0)^}&HFg)n1yZt*$aS}fq}uHpy!|cm;amj zc(NGTHUP!`{NG&1yNQwM!2iug{8oHS4r-h8WP?~38#W(QWM*dCkg@rgN*NQ_xIG!0 zoz%sI89z*pv|7$2puU;OT8srOb0K51oc$+GCI+p|LY}MG!D2TuHXjOb;%2hY+RPTC z#4XS_0%O5BYRV385*QpV z0P%-xC5I`SR~EFh$T|E}b3n!}Kt2pRWKQ-gwPSJ2Qg@iFSXQv9>;SWsCy?Vs1pbc# h7#J8CCV#6eQ{d?OXU_o)E&(9@;OjqoAQKs!2LJ)viKzep diff --git a/os/0x10000.bin b/os/0x10000.bin index 9d65139bdea05967f8c3e3a1ba6898676b6dc2ac..71067ff9fd08e5d0bea2e52b95449de4e9b6d480 100644 GIT binary patch delta 118851 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 delta 126392 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

fq_j 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 diff --git a/os/Readme.md b/os/Readme.md index dbc574a..d258434 100644 --- a/os/Readme.md +++ b/os/Readme.md @@ -21,3 +21,7 @@ Firmware was compiled with the following modules: * LUA_USE_MODULES_WIFI * LUA_USE_MODULES_WS2812 +## Numbers +Floating point calcuation was disabled: + * LUA_NUMBER_INTEGRAL + From f72295e709598e5a9513a666b09df93e859699b4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 31 Jan 2021 20:22:32 +0100 Subject: [PATCH 071/204] Timer calls replaced --- init.lua | 8 ++++---- main.lua | 44 +++++++++++++++++++++++--------------------- mqtt.lua | 13 ++++++++++--- webserver.lua | 23 ++++++++--------------- 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/init.lua b/init.lua index 0d0f1f8..2b7ce4e 100644 --- a/init.lua +++ b/init.lua @@ -13,7 +13,6 @@ end) local blacklistfile="init.lua config.lua config.lua.new webpage.html" function recompileAll() - for i=0,5 do tmr.stop(i) end -- compile all files l = file.list(); for k,_ in pairs(l) do @@ -43,9 +42,8 @@ function mydofile(mod) end end - -tmr.alarm(1, 5000, 0, function() - tmr.stop(2) +local initTimer = tmr.create() +initTimer:register(5000, tmr.ALARM_SINGLE, function (t) if ( (file.open("main.lua")) or (file.open("timecore.lua")) or @@ -68,5 +66,7 @@ tmr.alarm(1, 5000, 0, function() else print("No Main file found") end + t:unregister() end) +initTimer:start() print("Init file end reached") diff --git a/main.lua b/main.lua index c624ff0..2b97d2d 100644 --- a/main.lua +++ b/main.lua @@ -1,10 +1,9 @@ -- Main Module +local looptimer = tmr.create() displayword = {} function startSetupMode() - tmr.stop(0) - tmr.stop(1) -- start the webserver module mydofile("webserver") @@ -112,7 +111,8 @@ function normalOperation() connect_counter=0 -- Wait to be connect to the WiFi access point. - tmr.alarm(0, 500, 1, function() + local wifitimer = tmr.create() + wifitimer:register(5000, tmr.ALARM_SINGLE, function (t) connect_counter=connect_counter+1 if wifi.sta.status() ~= 5 then print(connect_counter .. "/60 Connecting to AP...") @@ -148,7 +148,7 @@ function normalOperation() ws2812.write(string.char(0,0,0):rep(114)) end else - tmr.stop(0) + t:unregister() print('IP: ',wifi.sta.getip()) -- Here the WLAN is found, and something is done print("Solving dependencies") @@ -158,8 +158,9 @@ function normalOperation() mydofile(mod) end - setupCounter=5 - tmr.alarm(1, 5000, 1 ,function() + local setupCounter=5 + local alive=0 + looptimer:register(5000, tmr.ALARM_AUTO, function (lt) if (setupCounter > 4) then syncTimeFromInternet() setupCounter=setupCounter-1 @@ -178,17 +179,20 @@ function normalOperation() displayTime() end setupCounter=setupCounter-1 + elseif ((alive % 60) == 0) then + -- sync the time every 5 minutes + syncTimeFromInternet() + displayTime() + alive = alive + 1 else displayTime() + alive = alive + 1 end collectgarbage() + -- Feed the system watchdog. + tmr.wdclr() end) - - -- sync the time every 5 minutes - tmr.alarm(2, 300003, 1 ,function() - syncTimeFromInternet() - displayTime() - end) + looptimer:start() end -- when no wifi available, open an accesspoint and ask the user @@ -196,12 +200,8 @@ function normalOperation() startSetupMode() end end) + wifitimer:start() - -end - -function stopWordclock() - for i=0,5,1 do tmr.stop(i) end end -------------------main program ----------------------------- @@ -218,11 +218,12 @@ else end ----------- button --------- gpio.mode(3, gpio.INPUT) -btnCounter=0 --- Start the time Thread -tmr.alarm(4, 500, 1 ,function() +local btnCounter=0 +-- Start the time Thread handling the button +local btntimer = tmr.create() +btntimer:register(5000, tmr.ALARM_AUTO, function (t) if (gpio.read(3) == 0) then - tmr.stop(1) -- stop the LED thread + looptimer:unregister() print("Button pressed " .. tostring(btnCounter)) btnCounter = btnCounter + 5 local ledBuf= string.char(128,0,0):rep(btnCounter) .. string.char(0,0,0):rep(110 - btnCounter) @@ -234,3 +235,4 @@ tmr.alarm(4, 500, 1 ,function() end end end) +btntimer:start() diff --git a/mqtt.lua b/mqtt.lua index 6247e08..9784fe2 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -96,7 +96,9 @@ function registerMqtt() m=nil t=nil mqttConnected = false - for i=0,6,1 do tmr.stop(i) end + if (looptimer ~= nil) then + looptimer:unregister() + end collectgarbage() mydofile("telnet") if (startTelnetServer ~= nil) then @@ -120,14 +122,17 @@ function registerMqtt() mqttConnected = true -- subscribe topic with qos = 0 client:subscribe(mqttPrefix .. "/cmd/#", 0) - tmr.alarm(3, 1000, 0, function() + local mytimer = tmr.create() + mytimer:register(1000, tmr.ALARM_SINGLE, function (t) -- publish a message with data = hello, QoS = 0, retain = 0 client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) local red = string.byte(colorBg,2) local green = string.byte(colorBg,1) local blue = string.byte(colorBg,3) client:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) + t:unregister() end) + mytimer:start() end, function(client, reason) print("failed reason: " .. reason) @@ -147,7 +152,8 @@ function startMqttClient() end oldBrightness=0 oldTemp=0 - tmr.alarm(5, 5001, 1 ,function() + local mqtttimer = tmr.create() + mqtttimer:register(5001, tmr.ALARM_AUTO, function (t) if (mqttConnected) then local temp = nil if (t ~= nil) then @@ -165,5 +171,6 @@ function startMqttClient() oldBrightness = briPercent end end) + mqtttimer:start() end end diff --git a/webserver.lua b/webserver.lua index d0e2d60..b61d2d3 100644 --- a/webserver.lua +++ b/webserver.lua @@ -130,7 +130,6 @@ end function stopWordclock() print("Stop all Wordclock") -- Stop all - for i=0,5 do tmr.stop(i) end -- unload all other functions -- grep function *.lua | grep -v webserver | grep -v init.lua | grep -v main.lua | cut -f 2 -d ':' | grep "^function" | sed "s/function //g" | grep -o "^[a-zA-Z0-9\_]*" updateColor = nil @@ -159,18 +158,6 @@ function startWebServer() color=string.char(0,128,0) end ws2812.write(string.char(0,0,0):rep(56) .. color:rep(2) .. string.char(0,0,0):rep(4) .. color:rep(2) .. string.char(0,0,0):rep(48)) - -- Start Time after 3 minute - tmr.alarm(5, 180000, 0 ,function() - dependModules = { "timecore" , "wordclock", "displayword" } - for _,mod in pairs(dependModules) do - print("Loading " .. mod) - mydofile(mod) - end - -- Start the time Thread again - tmr.alarm(1, 20000, 1 ,function() - displayTime() - end) - end) if (sendPage ~= nil) then print("Sending webpage.html (" .. tostring(node.heap()) .. "B free) ...") -- Load the sendPagewebcontent @@ -285,18 +272,24 @@ function startWebServer() print("Rename config") if (file.rename(configFile .. ".new", configFile)) then print("Successfully") - tmr.alarm(3, 20, 0 ,function() + local mytimer = tmr.create() + mytimer:register(50, tmr.ALARM_SINGLE, function (t) replaceMap=fillDynamicMap() replaceMap["$ADDITIONAL_LINE"]="

New configuration saved

" print("Send success to client") sendPage(conn, "webpage.html", replaceMap) + t:unregister() end) + mytimer:start() else - tmr.alarm(3, 20, 0 ,function() + local mytimer = tmr.create() + mytimer:register(50, tmr.ALARM_SINGLE, function (t) replaceMap=fillDynamicMap() replaceMap["$ADDITIONAL_LINE"]="

ERROR

" sendPage(conn, "webpage.html", replaceMap) + t:unregister() end) + mytimer:start() end else replaceMap=fillDynamicMap() From f93d0df461fa5fafea4f51d4053358e3ea773dcd Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 31 Jan 2021 20:41:03 +0100 Subject: [PATCH 072/204] Only format ESP if no file is specified --- init.lua | 6 ++++-- tools/initialFlash.sh | 14 ++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/init.lua b/init.lua index 2b7ce4e..015e8ca 100644 --- a/init.lua +++ b/init.lua @@ -5,11 +5,13 @@ ws2812.init() -- WS2812 LEDs initialized on GPIO2 MAXLEDS=110 counter1=0 ws2812.write(string.char(0,0,0):rep(114)) -tmr.alarm(2, 85, 1, function() +local bootledtimer = tmr.create() +bootledtimer:register(5000, tmr.ALARM_AUTO, function (t) counter1=counter1+1 spaceLeds = math.max(MAXLEDS - (counter1*2), 0) ws2812.write(string.char(128,0,0):rep(counter1) .. string.char(0,0,0):rep(spaceLeds) .. string.char(0,0,64):rep(counter1)) end) +bootledtimer:start() local blacklistfile="init.lua config.lua config.lua.new webpage.html" function recompileAll() @@ -44,6 +46,7 @@ end local initTimer = tmr.create() initTimer:register(5000, tmr.ALARM_SINGLE, function (t) + bootledtimer:unregister() if ( (file.open("main.lua")) or (file.open("timecore.lua")) or @@ -69,4 +72,3 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) t:unregister() end) initTimer:start() -print("Init file end reached") diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index 67240a8..858bfe7 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -32,12 +32,14 @@ else fi -# Format filesystem first -echo "Format the complete ESP" -python3 $LUATOOL -p $DEVICE -w -b $BAUD -if [ $? -ne 0 ]; then - echo "STOOOOP" - exit 1 +if [ $# -eq 1 ]; then + # Format filesystem first + echo "Format the complete ESP" + python3 $LUATOOL -p $DEVICE -w -b $BAUD + if [ $? -ne 0 ]; then + echo "STOOOOP" + exit 1 + fi fi #stty -F $DEVICE $BAUD From 6193618d1b66c2002031c53cfb9eda04f22dcd62 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 31 Jan 2021 20:45:59 +0100 Subject: [PATCH 073/204] enhanced mydofile --- init.lua | 2 ++ main.lua | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/init.lua b/init.lua index 015e8ca..164e15b 100644 --- a/init.lua +++ b/init.lua @@ -39,6 +39,8 @@ function mydofile(mod) dofile( mod .. ".lua") elseif (file.open(mod .. ".lc")) then dofile(mod .. ".lc") + elseif (file.open(mod)) then + dofile(mod) else print("Error: " .. mod) end diff --git a/main.lua b/main.lua index 2b97d2d..a31399c 100644 --- a/main.lua +++ b/main.lua @@ -6,7 +6,7 @@ displayword = {} function startSetupMode() -- start the webserver module mydofile("webserver") - + collectgarbage() wifi.setmode(wifi.SOFTAP) cfg={} cfg.ssid="wordclock" From 54095e7c20f0a0af95659d3dffd2ac14f7d99edf Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 5 Feb 2021 20:38:31 +0100 Subject: [PATCH 074/204] Lonely webserver is running --- init.lua | 19 +++++++++++++++---- main.lua | 35 ----------------------------------- webserver.lua | 26 +++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/init.lua b/init.lua index 164e15b..2f14baa 100644 --- a/init.lua +++ b/init.lua @@ -27,6 +27,7 @@ function recompileAll() node.compile(k) -- remove the lua file file.remove(k) + node.restart() else print("No code: " .. k) end @@ -46,14 +47,14 @@ function mydofile(mod) end end -local initTimer = tmr.create() +initTimer = tmr.create() initTimer:register(5000, tmr.ALARM_SINGLE, function (t) bootledtimer:unregister() if ( (file.open("main.lua")) or (file.open("timecore.lua")) or (file.open("wordclock.lua")) or - (file.open("displayword.lua")) or + (file.open("displayword.lua")) or (file.open("mqtt.lua")) or (file.open("ds18b20.lua")) or (file.open("telnet.lua")) @@ -66,8 +67,18 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) -- reboot repairs everything node.restart() elseif (file.open("main.lc")) then - print("Starting main") - dofile("main.lc") + if ( file.open("config.lua") ) then + --- Normal operation + print("Starting main") + dofile("main.lc") + wifi.setmode(wifi.STATION) + dofile("config.lua") + normalOperation() + else + mydofile("webserver") + -- Logic for inital setup + startSetupMode() + end else print("No Main file found") end diff --git a/main.lua b/main.lua index a31399c..63afaf1 100644 --- a/main.lua +++ b/main.lua @@ -3,32 +3,6 @@ local looptimer = tmr.create() displayword = {} -function startSetupMode() - -- start the webserver module - mydofile("webserver") - collectgarbage() - wifi.setmode(wifi.SOFTAP) - cfg={} - cfg.ssid="wordclock" - cfg.pwd="wordclock" - wifi.ap.config(cfg) - - -- Write the buffer to the LEDs - local color=string.char(0,128,0) - local white=string.char(0,0,0) - local ledBuf= white:rep(6) .. color .. white:rep(7) .. color:rep(3) .. white:rep(44) .. color:rep(3) .. white:rep(50) - ws2812.write(ledBuf) - color=nil - white=nil - ledBuf=nil - - print("Waiting in access point >wordclock< for Clients") - print("Please visit 192.168.4.1") - startWebServer() - collectgarbage() -end - - function syncTimeFromInternet() if (syncRunning == nil) then syncRunning=true @@ -207,15 +181,6 @@ end -------------------main program ----------------------------- ws2812.init() -- WS2812 LEDs initialized on GPIO2 -if ( file.open("config.lua") ) then - --- Normal operation - wifi.setmode(wifi.STATION) - mydofile("config") - normalOperation() -else - -- Logic for inital setup - startSetupMode() -end ----------- button --------- gpio.mode(3, gpio.INPUT) local btnCounter=0 diff --git a/webserver.lua b/webserver.lua index b61d2d3..ac3b237 100644 --- a/webserver.lua +++ b/webserver.lua @@ -327,4 +327,28 @@ function startWebServer() end) end ---FileView done. + + +function startSetupMode() + -- start the webserver module + collectgarbage() + wifi.setmode(wifi.SOFTAP) + cfg={} + cfg.ssid="wordclock" + cfg.pwd="wordclock" + wifi.ap.config(cfg) + + -- Write the buffer to the LEDs + local color=string.char(0,128,0) + local white=string.char(0,0,0) + local ledBuf= white:rep(6) .. color .. white:rep(7) .. color:rep(3) .. white:rep(44) .. color:rep(3) .. white:rep(50) + ws2812.write(ledBuf) + color=nil + white=nil + ledBuf=nil + + print("Waiting in access point >wordclock< for Clients") + print("Please visit 192.168.4.1") + startWebServer() + collectgarbage() +end \ No newline at end of file From da139e3412965149524153a2c38a88145af3719a Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 5 Feb 2021 20:41:49 +0100 Subject: [PATCH 075/204] Webserver memory optimization with local variables --- webserver.lua | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/webserver.lua b/webserver.lua index ac3b237..edf6346 100644 --- a/webserver.lua +++ b/webserver.lua @@ -1,8 +1,7 @@ ---TODO: -configFile="config.lua" - -httpSending=false -sentBytes=0 +-- Webserver +local configFile="config.lua" +local httpSending=false +local sentBytes=0 function sendPage(conn, nameOfFile, replaceMap) collectgarbage() print("Sending " .. nameOfFile .. " " .. sentBytes .. "B already; " .. node.heap() .. "B in heap") @@ -127,22 +126,6 @@ function fillDynamicMap() return replaceMap end -function stopWordclock() - print("Stop all Wordclock") - -- Stop all - -- unload all other functions - -- grep function *.lua | grep -v webserver | grep -v init.lua | grep -v main.lua | cut -f 2 -d ':' | grep "^function" | sed "s/function //g" | grep -o "^[a-zA-Z0-9\_]*" - updateColor = nil - drawLEDs = nil - round = nil - generateLEDs = nil - isSummerTime = nil - getUTCtime = nil - getTime = nil - display_timestat = nil - collectgarbage() -end - function startWebServer() srv=net.createServer(net.TCP) srv:listen(80,function(conn) @@ -153,7 +136,6 @@ function startWebServer() end if (payload:find("GET /") ~= nil) then httpSending=true - stopWordclock() if (color == nil) then color=string.char(0,128,0) end From a3aa7018d162bab33a864d5008e8f6168069c371 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 5 Feb 2021 20:58:15 +0100 Subject: [PATCH 076/204] Further optimisation in webserver --- init.lua | 9 ++++----- webserver.lua | 37 +++++++++---------------------------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/init.lua b/init.lua index 2f14baa..f92b063 100644 --- a/init.lua +++ b/init.lua @@ -6,7 +6,7 @@ MAXLEDS=110 counter1=0 ws2812.write(string.char(0,0,0):rep(114)) local bootledtimer = tmr.create() -bootledtimer:register(5000, tmr.ALARM_AUTO, function (t) +bootledtimer:register(500, tmr.ALARM_AUTO, function (t) counter1=counter1+1 spaceLeds = math.max(MAXLEDS - (counter1*2), 0) ws2812.write(string.char(128,0,0):rep(counter1) .. string.char(0,0,0):rep(spaceLeds) .. string.char(0,0,64):rep(counter1)) @@ -50,6 +50,8 @@ end initTimer = tmr.create() initTimer:register(5000, tmr.ALARM_SINGLE, function (t) bootledtimer:unregister() + t:unregister() + collectgarbage() if ( (file.open("main.lua")) or (file.open("timecore.lua")) or @@ -66,7 +68,7 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) print("Rebooting ...") -- reboot repairs everything node.restart() - elseif (file.open("main.lc")) then + else if ( file.open("config.lua") ) then --- Normal operation print("Starting main") @@ -79,9 +81,6 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) -- Logic for inital setup startSetupMode() end - else - print("No Main file found") end - t:unregister() end) initTimer:start() diff --git a/webserver.lua b/webserver.lua index edf6346..f8b6f2f 100644 --- a/webserver.lua +++ b/webserver.lua @@ -74,35 +74,16 @@ end function fillDynamicMap() replaceMap = {} ssid, _ = wifi.sta.getconfig() - - if (ssid == nil) then - ssid="Not set" - end - if (sntpserverhostname == nil) then - sntpserverhostname="ptbtime1.ptb.de" - end - if (timezoneoffset == nil) then - timezoneoffset=1 - end + if (ssid == nil) then return replaceMap end + if (sntpserverhostname == nil) then sntpserverhostname="ptbtime1.ptb.de" end + if (timezoneoffset == nil) then timezoneoffset=1 end -- Set the default color, if nothing is set - if (color == nil) then - color=string.char(0,0,250) - end - if (color1 == nil) then - color1=color - end - if (color2 == nil) then - color2=color - end - if (color3 == nil) then - color3=color - end - if (color4 == nil) then - color4=color - end - if (colorBg == nil) then - colorBg=string.char(0,0,0) -- black is the default background color - end + if (color == nil) then color=string.char(0,0,250) end + if (color1 == nil) then color1=color end + if (color2 == nil) then color2=color end + if (color3 == nil) then color3=color end + if (color4 == nil) then color4=color end + if (colorBg == nil) then colorBg=string.char(0,0,0) end local hexColor = "#" .. string.format("%02x",string.byte(color,2)) .. string.format("%02x",string.byte(color,1)) .. string.format("%02x",string.byte(color,3)) local hexColor1 = "#" .. string.format("%02x",string.byte(color1,2)) .. string.format("%02x",string.byte(color1,1)) .. string.format("%02x",string.byte(color1,3)) local hexColor2 = "#" .. string.format("%02x",string.byte(color2,2)) .. string.format("%02x",string.byte(color2,1)) .. string.format("%02x",string.byte(color2,3)) From 89e215a609abaacff6aaa7641f82028285ce43ab Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 5 Feb 2021 21:32:46 +0100 Subject: [PATCH 077/204] Compressing Luafiles added --- init.lua | 4 +- tools/Readme.md | 9 + tools/bin/luasrcdiet | 653 ++++++++++++++ tools/luasrcdiet/equiv.lua | 465 ++++++++++ tools/luasrcdiet/fs.lua | 74 ++ tools/luasrcdiet/init.lua | 117 +++ tools/luasrcdiet/llex.lua | 350 ++++++++ tools/luasrcdiet/lparser.lua | 1286 +++++++++++++++++++++++++++ tools/luasrcdiet/optlex.lua | 852 ++++++++++++++++++ tools/luasrcdiet/optparser.lua | 644 ++++++++++++++ tools/luasrcdiet/plugin/example.lua | 90 ++ tools/luasrcdiet/plugin/html.lua | 177 ++++ tools/luasrcdiet/plugin/sloc.lua | 89 ++ tools/luasrcdiet/utils.lua | 30 + websrv_diet.lua | 270 ++++++ 15 files changed, 5109 insertions(+), 1 deletion(-) create mode 100755 tools/bin/luasrcdiet create mode 100644 tools/luasrcdiet/equiv.lua create mode 100644 tools/luasrcdiet/fs.lua create mode 100644 tools/luasrcdiet/init.lua create mode 100644 tools/luasrcdiet/llex.lua create mode 100644 tools/luasrcdiet/lparser.lua create mode 100644 tools/luasrcdiet/optlex.lua create mode 100644 tools/luasrcdiet/optparser.lua create mode 100644 tools/luasrcdiet/plugin/example.lua create mode 100644 tools/luasrcdiet/plugin/html.lua create mode 100644 tools/luasrcdiet/plugin/sloc.lua create mode 100644 tools/luasrcdiet/utils.lua create mode 100644 websrv_diet.lua diff --git a/init.lua b/init.lua index f92b063..7a0e284 100644 --- a/init.lua +++ b/init.lua @@ -15,6 +15,8 @@ bootledtimer:start() local blacklistfile="init.lua config.lua config.lua.new webpage.html" function recompileAll() + -- 3, discard Local, Upvalue and line-number debug info + node.stripdebug(3) -- compile all files l = file.list(); for k,_ in pairs(l) do @@ -77,7 +79,7 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) dofile("config.lua") normalOperation() else - mydofile("webserver") + mydofile("websrv_diet") -- Logic for inital setup startSetupMode() end diff --git a/tools/Readme.md b/tools/Readme.md index 57da26a..e9f1bb9 100644 --- a/tools/Readme.md +++ b/tools/Readme.md @@ -2,3 +2,12 @@ **Not** supported with python 3.x ## Source: https://github.com/4refr0nt/luatool/tree/master/luatool +# LuaSrcDiet +LuaSrcDiet reduces the size of Lua 5.1+ source files by aggressively removing all unnecessary whitespace and comments, optimizing constant tokens, and renaming local variables to shorter names. +* https://github.com/jirutka/luasrcdiet + +## Source: +https://raw.githubusercontent.com/jirutka/luasrcdiet/master/bin/luasrcdiet + +## Example: + bin/luasrcdiet ../webserver.lua -o ../websrv_diet.lua diff --git a/tools/bin/luasrcdiet b/tools/bin/luasrcdiet new file mode 100755 index 0000000..28e6289 --- /dev/null +++ b/tools/bin/luasrcdiet @@ -0,0 +1,653 @@ +#!/usr/bin/env lua +--------- +-- LuaSrcDiet +-- +-- Compresses Lua source code by removing unnecessary characters. +-- For Lua 5.1+ source code. +-- +-- **Notes:** +-- +-- * Remember to update version and date information below (MSG_TITLE). +-- * TODO: passing data tables around is a horrific mess. +-- * TODO: to implement pcall() to properly handle lexer etc. errors. +-- * TODO: need some automatic testing for a semblance of sanity. +-- * TODO: the plugin module is highly experimental and unstable. +---- +local equiv = require "luasrcdiet.equiv" +local fs = require "luasrcdiet.fs" +local llex = require "luasrcdiet.llex" +local lparser = require "luasrcdiet.lparser" +local luasrcdiet = require "luasrcdiet.init" +local optlex = require "luasrcdiet.optlex" +local optparser = require "luasrcdiet.optparser" + +local byte = string.byte +local concat = table.concat +local find = string.find +local fmt = string.format +local gmatch = string.gmatch +local match = string.match +local print = print +local rep = string.rep +local sub = string.sub + +local plugin + +local LUA_VERSION = match(_VERSION, " (5%.[123])$") or "5.1" + +-- Is --opt-binequiv available for this Lua version? +local BIN_EQUIV_AVAIL = LUA_VERSION == "5.1" and not package.loaded.jit + + +---------------------- Messages and textual data ---------------------- + +local MSG_TITLE = fmt([[ +LuaSrcDiet: Puts your Lua 5.1+ source code on a diet +Version %s <%s> +]], luasrcdiet._VERSION, luasrcdiet._HOMEPAGE) + +local MSG_USAGE = [[ +usage: luasrcdiet [options] [filenames] + +example: + >luasrcdiet myscript.lua -o myscript_.lua + +options: + -v, --version prints version information + -h, --help prints usage information + -o specify file name to write output + -s suffix for output files (default '_') + --keep keep block comment with inside + --plugin run in plugin/ directory + - stop handling arguments + + (optimization levels) + --none all optimizations off (normalizes EOLs only) + --basic lexer-based optimizations only + --maximum maximize reduction of source + + (informational) + --quiet process files quietly + --read-only read file and print token stats only + --dump-lexer dump raw tokens from lexer to stdout + --dump-parser dump variable tracking tables from parser + --details extra info (strings, numbers, locals) + +features (to disable, insert 'no' prefix like --noopt-comments): +%s +default settings: +%s]] + +-- Optimization options, for ease of switching on and off. +-- +-- * Positive to enable optimization, negative (no) to disable. +-- * These options should follow --opt-* and --noopt-* style for now. +local OPTION = [[ +--opt-comments,'remove comments and block comments' +--opt-whitespace,'remove whitespace excluding EOLs' +--opt-emptylines,'remove empty lines' +--opt-eols,'all above, plus remove unnecessary EOLs' +--opt-strings,'optimize strings and long strings' +--opt-numbers,'optimize numbers' +--opt-locals,'optimize local variable names' +--opt-entropy,'tries to reduce symbol entropy of locals' +--opt-srcequiv,'insist on source (lexer stream) equivalence' +--opt-binequiv,'insist on binary chunk equivalence (only for PUC Lua 5.1)' +--opt-experimental,'apply experimental optimizations' +]] + +-- Preset configuration. +local DEFAULT_CONFIG = [[ + --opt-comments --opt-whitespace --opt-emptylines + --opt-numbers --opt-locals + --opt-srcequiv --noopt-binequiv +]] +-- Override configurations: MUST explicitly enable/disable everything. +local BASIC_CONFIG = [[ + --opt-comments --opt-whitespace --opt-emptylines + --noopt-eols --noopt-strings --noopt-numbers + --noopt-locals --noopt-entropy + --opt-srcequiv --noopt-binequiv +]] +local MAXIMUM_CONFIG = [[ + --opt-comments --opt-whitespace --opt-emptylines + --opt-eols --opt-strings --opt-numbers + --opt-locals --opt-entropy + --opt-srcequiv +]] .. (BIN_EQUIV_AVAIL and ' --opt-binequiv' or ' --noopt-binequiv') + +local NONE_CONFIG = [[ + --noopt-comments --noopt-whitespace --noopt-emptylines + --noopt-eols --noopt-strings --noopt-numbers + --noopt-locals --noopt-entropy + --opt-srcequiv --noopt-binequiv +]] + +local DEFAULT_SUFFIX = "_" -- default suffix for file renaming +local PLUGIN_SUFFIX = "luasrcdiet.plugin." -- relative location of plugins + + +------------- Startup and initialize option list handling ------------- + +--- Simple error message handler; change to error if traceback wanted. +-- +-- @tparam string msg The message to print. +local function die(msg) + print("LuaSrcDiet (error): "..msg); os.exit(1) +end +--die = error--DEBUG + +-- Prepare text for list of optimizations, prepare lookup table. +local MSG_OPTIONS = "" +do + local WIDTH = 24 + local o = {} + for op, desc in gmatch(OPTION, "%s*([^,]+),'([^']+)'") do + local msg = " "..op + msg = msg..rep(" ", WIDTH - #msg)..desc.."\n" + MSG_OPTIONS = MSG_OPTIONS..msg + o[op] = true + o["--no"..sub(op, 3)] = true + end + OPTION = o -- replace OPTION with lookup table +end + +MSG_USAGE = fmt(MSG_USAGE, MSG_OPTIONS, DEFAULT_CONFIG) + + +--------- Global variable initialization, option set handling --------- + +local suffix = DEFAULT_SUFFIX -- file suffix +local option = {} -- program options +local stat_c, stat_l -- statistics tables + +--- Sets option lookup table based on a text list of options. +-- +-- Note: additional forced settings for --opt-eols is done in optlex.lua. +-- +-- @tparam string CONFIG +local function set_options(CONFIG) + for op in gmatch(CONFIG, "(%-%-%S+)") do + if sub(op, 3, 4) == "no" and -- handle negative options + OPTION["--"..sub(op, 5)] then + option[sub(op, 5)] = false + else + option[sub(op, 3)] = true + end + end +end + + +-------------------------- Support functions -------------------------- + +-- List of token types, parser-significant types are up to TTYPE_GRAMMAR +-- while the rest are not used by parsers; arranged for stats display. +local TTYPES = { + "TK_KEYWORD", "TK_NAME", "TK_NUMBER", -- grammar + "TK_STRING", "TK_LSTRING", "TK_OP", + "TK_EOS", + "TK_COMMENT", "TK_LCOMMENT", -- non-grammar + "TK_EOL", "TK_SPACE", +} +local TTYPE_GRAMMAR = 7 + +local EOLTYPES = { -- EOL names for token dump + ["\n"] = "LF", ["\r"] = "CR", + ["\n\r"] = "LFCR", ["\r\n"] = "CRLF", +} + +--- Reads source code from the file. +-- +-- @tparam string fname Path of the file to read. +-- @treturn string Content of the file. +local function load_file(fname) + local data, err = fs.read_file(fname, "rb") + if not data then die(err) end + return data +end + +--- Saves source code to the file. +-- +-- @tparam string fname Path of the destination file. +-- @tparam string dat The data to write into the file. +local function save_file(fname, dat) + local ok, err = fs.write_file(fname, dat, "wb") + if not ok then die(err) end +end + + +------------------ Functions to deal with statistics ------------------ + +--- Initializes the statistics table. +local function stat_init() + stat_c, stat_l = {}, {} + for i = 1, #TTYPES do + local ttype = TTYPES[i] + stat_c[ttype], stat_l[ttype] = 0, 0 + end +end + +--- Adds a token to the statistics table. +-- +-- @tparam string tok The token. +-- @param seminfo +local function stat_add(tok, seminfo) + stat_c[tok] = stat_c[tok] + 1 + stat_l[tok] = stat_l[tok] + #seminfo +end + +--- Computes totals for the statistics table, returns average table. +-- +-- @treturn table +local function stat_calc() + local function avg(c, l) -- safe average function + if c == 0 then return 0 end + return l / c + end + local stat_a = {} + local c, l = 0, 0 + for i = 1, TTYPE_GRAMMAR do -- total grammar tokens + local ttype = TTYPES[i] + c = c + stat_c[ttype]; l = l + stat_l[ttype] + end + stat_c.TOTAL_TOK, stat_l.TOTAL_TOK = c, l + stat_a.TOTAL_TOK = avg(c, l) + c, l = 0, 0 + for i = 1, #TTYPES do -- total all tokens + local ttype = TTYPES[i] + c = c + stat_c[ttype]; l = l + stat_l[ttype] + stat_a[ttype] = avg(stat_c[ttype], stat_l[ttype]) + end + stat_c.TOTAL_ALL, stat_l.TOTAL_ALL = c, l + stat_a.TOTAL_ALL = avg(c, l) + return stat_a +end + + +----------------------------- Main tasks ----------------------------- + +--- A simple token dumper, minimal translation of seminfo data. +-- +-- @tparam string srcfl Path of the source file. +local function dump_tokens(srcfl) + -- Load file and process source input into tokens. + local z = load_file(srcfl) + local toklist, seminfolist = llex.lex(z) + + -- Display output. + for i = 1, #toklist do + local tok, seminfo = toklist[i], seminfolist[i] + if tok == "TK_OP" and byte(seminfo) < 32 then + seminfo = "("..byte(seminfo)..")" + elseif tok == "TK_EOL" then + seminfo = EOLTYPES[seminfo] + else + seminfo = "'"..seminfo.."'" + end + print(tok.." "..seminfo) + end--for +end + +--- Dumps globalinfo and localinfo tables. +-- +-- @tparam string srcfl Path of the source file. +local function dump_parser(srcfl) + -- Load file and process source input into tokens, + local z = load_file(srcfl) + local toklist, seminfolist, toklnlist = llex.lex(z) + + -- Do parser optimization here. + local xinfo = lparser.parse(toklist, seminfolist, toklnlist) + local globalinfo, localinfo = xinfo.globalinfo, xinfo.localinfo + + -- Display output. + local hl = rep("-", 72) + print("*** Local/Global Variable Tracker Tables ***") + print(hl.."\n GLOBALS\n"..hl) + -- global tables have a list of xref numbers only + for i = 1, #globalinfo do + local obj = globalinfo[i] + local msg = "("..i..") '"..obj.name.."' -> " + local xref = obj.xref + for j = 1, #xref do msg = msg..xref[j].." " end + print(msg) + end + -- Local tables have xref numbers and a few other special + -- numbers that are specially named: decl (declaration xref), + -- act (activation xref), rem (removal xref). + print(hl.."\n LOCALS (decl=declared act=activated rem=removed)\n"..hl) + for i = 1, #localinfo do + local obj = localinfo[i] + local msg = "("..i..") '"..obj.name.."' decl:"..obj.decl.. + " act:"..obj.act.." rem:"..obj.rem + if obj.is_special then + msg = msg.." is_special" + end + msg = msg.." -> " + local xref = obj.xref + for j = 1, #xref do msg = msg..xref[j].." " end + print(msg) + end + print(hl.."\n") +end + +--- Reads source file(s) and reports some statistics. +-- +-- @tparam string srcfl Path of the source file. +local function read_only(srcfl) + -- Load file and process source input into tokens. + local z = load_file(srcfl) + local toklist, seminfolist = llex.lex(z) + print(MSG_TITLE) + print("Statistics for: "..srcfl.."\n") + + -- Collect statistics. + stat_init() + for i = 1, #toklist do + local tok, seminfo = toklist[i], seminfolist[i] + stat_add(tok, seminfo) + end--for + local stat_a = stat_calc() + + -- Display output. + local function figures(tt) + return stat_c[tt], stat_l[tt], stat_a[tt] + end + local tabf1, tabf2 = "%-16s%8s%8s%10s", "%-16s%8d%8d%10.2f" + local hl = rep("-", 42) + print(fmt(tabf1, "Lexical", "Input", "Input", "Input")) + print(fmt(tabf1, "Elements", "Count", "Bytes", "Average")) + print(hl) + for i = 1, #TTYPES do + local ttype = TTYPES[i] + print(fmt(tabf2, ttype, figures(ttype))) + if ttype == "TK_EOS" then print(hl) end + end + print(hl) + print(fmt(tabf2, "Total Elements", figures("TOTAL_ALL"))) + print(hl) + print(fmt(tabf2, "Total Tokens", figures("TOTAL_TOK"))) + print(hl.."\n") +end + +--- Processes source file(s), writes output and reports some statistics. +-- +-- @tparam string srcfl Path of the source file. +-- @tparam string destfl Path of the destination file where to write optimized source. +local function process_file(srcfl, destfl) + -- handle quiet option + local function print(...) --luacheck: ignore 431 + if option.QUIET then return end + _G.print(...) + end + if plugin and plugin.init then -- plugin init + option.EXIT = false + plugin.init(option, srcfl, destfl) + if option.EXIT then return end + end + print(MSG_TITLE) -- title message + + -- Load file and process source input into tokens. + local z = load_file(srcfl) + if plugin and plugin.post_load then -- plugin post-load + z = plugin.post_load(z) or z + if option.EXIT then return end + end + local toklist, seminfolist, toklnlist = llex.lex(z) + if plugin and plugin.post_lex then -- plugin post-lex + plugin.post_lex(toklist, seminfolist, toklnlist) + if option.EXIT then return end + end + + -- Collect 'before' statistics. + stat_init() + for i = 1, #toklist do + local tok, seminfo = toklist[i], seminfolist[i] + stat_add(tok, seminfo) + end--for + local stat1_a = stat_calc() + local stat1_c, stat1_l = stat_c, stat_l + + -- Do parser optimization here. + optparser.print = print -- hack + local xinfo = lparser.parse(toklist, seminfolist, toklnlist) + if plugin and plugin.post_parse then -- plugin post-parse + plugin.post_parse(xinfo.globalinfo, xinfo.localinfo) + if option.EXIT then return end + end + optparser.optimize(option, toklist, seminfolist, xinfo) + if plugin and plugin.post_optparse then -- plugin post-optparse + plugin.post_optparse() + if option.EXIT then return end + end + + -- Do lexer optimization here, save output file. + local warn = optlex.warn -- use this as a general warning lookup + optlex.print = print -- hack + toklist, seminfolist, toklnlist + = optlex.optimize(option, toklist, seminfolist, toklnlist) + if plugin and plugin.post_optlex then -- plugin post-optlex + plugin.post_optlex(toklist, seminfolist, toklnlist) + if option.EXIT then return end + end + local dat = concat(seminfolist) + -- Depending on options selected, embedded EOLs in long strings and + -- long comments may not have been translated to \n, tack a warning. + if find(dat, "\r\n", 1, 1) or + find(dat, "\n\r", 1, 1) then + warn.MIXEDEOL = true + end + + -- Test source and binary chunk equivalence. + equiv.init(option, llex, warn) + equiv.source(z, dat) + if BIN_EQUIV_AVAIL then + equiv.binary(z, dat) + end + local smsg = "before and after lexer streams are NOT equivalent!" + local bmsg = "before and after binary chunks are NOT equivalent!" + -- for reporting, die if option was selected, else just warn + if warn.SRC_EQUIV then + if option["opt-srcequiv"] then die(smsg) end + else + print("*** SRCEQUIV: token streams are sort of equivalent") + if option["opt-locals"] then + print("(but no identifier comparisons since --opt-locals enabled)") + end + print() + end + if warn.BIN_EQUIV then + if option["opt-binequiv"] then die(bmsg) end + elseif BIN_EQUIV_AVAIL then + print("*** BINEQUIV: binary chunks are sort of equivalent") + print() + end + + -- Save optimized source stream to output file. + save_file(destfl, dat) + + -- Collect 'after' statistics. + stat_init() + for i = 1, #toklist do + local tok, seminfo = toklist[i], seminfolist[i] + stat_add(tok, seminfo) + end--for + local stat_a = stat_calc() + + -- Display output. + print("Statistics for: "..srcfl.." -> "..destfl.."\n") + local function figures(tt) + return stat1_c[tt], stat1_l[tt], stat1_a[tt], + stat_c[tt], stat_l[tt], stat_a[tt] + end + local tabf1, tabf2 = "%-16s%8s%8s%10s%8s%8s%10s", + "%-16s%8d%8d%10.2f%8d%8d%10.2f" + local hl = rep("-", 68) + print("*** lexer-based optimizations summary ***\n"..hl) + print(fmt(tabf1, "Lexical", + "Input", "Input", "Input", + "Output", "Output", "Output")) + print(fmt(tabf1, "Elements", + "Count", "Bytes", "Average", + "Count", "Bytes", "Average")) + print(hl) + for i = 1, #TTYPES do + local ttype = TTYPES[i] + print(fmt(tabf2, ttype, figures(ttype))) + if ttype == "TK_EOS" then print(hl) end + end + print(hl) + print(fmt(tabf2, "Total Elements", figures("TOTAL_ALL"))) + print(hl) + print(fmt(tabf2, "Total Tokens", figures("TOTAL_TOK"))) + print(hl) + + -- Report warning flags from optimizing process. + if warn.LSTRING then + print("* WARNING: "..warn.LSTRING) + elseif warn.MIXEDEOL then + print("* WARNING: ".."output still contains some CRLF or LFCR line endings") + elseif warn.SRC_EQUIV then + print("* WARNING: "..smsg) + elseif warn.BIN_EQUIV then + print("* WARNING: "..bmsg) + end + print() +end + + +---------------------------- Main functions --------------------------- + +local arg = {...} -- program arguments +set_options(DEFAULT_CONFIG) -- set to default options at beginning + +--- Does per-file handling, ship off to tasks. +-- +-- @tparam {string,...} fspec List of source files. +local function do_files(fspec) + for i = 1, #fspec do + local srcfl = fspec[i] + local destfl + + -- Find and replace extension for filenames. + local extb, exte = find(srcfl, "%.[^%.%\\%/]*$") + local basename, extension = srcfl, "" + if extb and extb > 1 then + basename = sub(srcfl, 1, extb - 1) + extension = sub(srcfl, extb, exte) + end + destfl = basename..suffix..extension + if #fspec == 1 and option.OUTPUT_FILE then + destfl = option.OUTPUT_FILE + end + if srcfl == destfl then + die("output filename identical to input filename") + end + + -- Perform requested operations. + if option.DUMP_LEXER then + dump_tokens(srcfl) + elseif option.DUMP_PARSER then + dump_parser(srcfl) + elseif option.READ_ONLY then + read_only(srcfl) + else + process_file(srcfl, destfl) + end + end--for +end + +--- The main function. +local function main() + local fspec = {} + local argn, i = #arg, 1 + if argn == 0 then + option.HELP = true + end + + -- Handle arguments. + while i <= argn do + local o, p = arg[i], arg[i + 1] + local dash = match(o, "^%-%-?") + if dash == "-" then -- single-dash options + if o == "-h" then + option.HELP = true; break + elseif o == "-v" then + option.VERSION = true; break + elseif o == "-s" then + if not p then die("-s option needs suffix specification") end + suffix = p + i = i + 1 + elseif o == "-o" then + if not p then die("-o option needs a file name") end + option.OUTPUT_FILE = p + i = i + 1 + elseif o == "-" then + break -- ignore rest of args + else + die("unrecognized option "..o) + end + elseif dash == "--" then -- double-dash options + if o == "--help" then + option.HELP = true; break + elseif o == "--version" then + option.VERSION = true; break + elseif o == "--keep" then + if not p then die("--keep option needs a string to match for") end + option.KEEP = p + i = i + 1 + elseif o == "--plugin" then + if not p then die("--plugin option needs a module name") end + if option.PLUGIN then die("only one plugin can be specified") end + option.PLUGIN = p + plugin = require(PLUGIN_SUFFIX..p) + i = i + 1 + elseif o == "--quiet" then + option.QUIET = true + elseif o == "--read-only" then + option.READ_ONLY = true + elseif o == "--basic" then + set_options(BASIC_CONFIG) + elseif o == "--maximum" then + set_options(MAXIMUM_CONFIG) + elseif o == "--none" then + set_options(NONE_CONFIG) + elseif o == "--dump-lexer" then + option.DUMP_LEXER = true + elseif o == "--dump-parser" then + option.DUMP_PARSER = true + elseif o == "--details" then + option.DETAILS = true + elseif OPTION[o] then -- lookup optimization options + set_options(o) + else + die("unrecognized option "..o) + end + else + fspec[#fspec + 1] = o -- potential filename + end + i = i + 1 + end--while + if option.HELP then + print(MSG_TITLE..MSG_USAGE); return true + elseif option.VERSION then + print(MSG_TITLE); return true + end + if option["opt-binequiv"] and not BIN_EQUIV_AVAIL then + die("--opt-binequiv is available only for PUC Lua 5.1!") + end + if #fspec > 0 then + if #fspec > 1 and option.OUTPUT_FILE then + die("with -o, only one source file can be specified") + end + do_files(fspec) + return true + else + die("nothing to do!") + end +end + +-- entry point -> main() -> do_files() +if not main() then + die("Please run with option -h or --help for usage information") +end diff --git a/tools/luasrcdiet/equiv.lua b/tools/luasrcdiet/equiv.lua new file mode 100644 index 0000000..3efa4ef --- /dev/null +++ b/tools/luasrcdiet/equiv.lua @@ -0,0 +1,465 @@ +--------- +-- Source and binary equivalency comparisons +-- +-- **Notes:** +-- +-- * Intended as an extra safety check for mission-critical code, +-- should give affirmative results if everything works. +-- * Heavy on load() and string.dump(), which may be slowish, +-- and may cause problems for cross-compiled applications. +-- * Optional detailed information dump is mainly for debugging, +-- reason being, if the two are not equivalent when they should be, +-- then some form of optimization has failed. +-- * source: IMPORTANT: TK_NAME not compared if opt-locals enabled. +-- * binary: IMPORTANT: Some shortcuts are taken with int and size_t +-- value reading -- if the functions break, then the binary chunk +-- is very large indeed. +-- * binary: There is a lack of diagnostic information when a compare +-- fails; you can use ChunkSpy and compare using visual diff. +---- +local byte = string.byte +local dump = string.dump +local load = loadstring or load --luacheck: ignore 113 +local sub = string.sub + +local M = {} + +local is_realtoken = { -- significant (grammar) tokens + TK_KEYWORD = true, + TK_NAME = true, + TK_NUMBER = true, + TK_STRING = true, + TK_LSTRING = true, + TK_OP = true, + TK_EOS = true, +} + +local option, llex, warn + + +--- The initialization function. +-- +-- @tparam {[string]=bool,...} _option +-- @tparam luasrcdiet.llex _llex +-- @tparam table _warn +function M.init(_option, _llex, _warn) + option = _option + llex = _llex + warn = _warn +end + +--- Builds lists containing a 'normal' lexer stream. +-- +-- @tparam string s The source code. +-- @treturn table +-- @treturn table +local function build_stream(s) + local stok, sseminfo = llex.lex(s) -- source list (with whitespace elements) + local tok, seminfo -- processed list (real elements only) + = {}, {} + for i = 1, #stok do + local t = stok[i] + if is_realtoken[t] then + tok[#tok + 1] = t + seminfo[#seminfo + 1] = sseminfo[i] + end + end--for + return tok, seminfo +end + +-- Tests source (lexer stream) equivalence. +-- +-- @tparam string z +-- @tparam string dat +function M.source(z, dat) + + -- Returns a dumped string for seminfo compares. + local function dumpsem(s) + local sf = load("return "..s, "z") + if sf then + return dump(sf) + end + end + + -- Marks and optionally reports non-equivalence. + local function bork(msg) + if option.DETAILS then print("SRCEQUIV: "..msg) end + warn.SRC_EQUIV = true + end + + -- Get lexer streams for both source strings, compare. + local tok1, seminfo1 = build_stream(z) -- original + local tok2, seminfo2 = build_stream(dat) -- compressed + + -- Compare shbang lines ignoring EOL. + local sh1 = z:match("^(#[^\r\n]*)") + local sh2 = dat:match("^(#[^\r\n]*)") + if sh1 or sh2 then + if not sh1 or not sh2 or sh1 ~= sh2 then + bork("shbang lines different") + end + end + + -- Compare by simple count. + if #tok1 ~= #tok2 then + bork("count "..#tok1.." "..#tok2) + return + end + + -- Compare each element the best we can. + for i = 1, #tok1 do + local t1, t2 = tok1[i], tok2[i] + local s1, s2 = seminfo1[i], seminfo2[i] + if t1 ~= t2 then -- by type + bork("type ["..i.."] "..t1.." "..t2) + break + end + if t1 == "TK_KEYWORD" or t1 == "TK_NAME" or t1 == "TK_OP" then + if t1 == "TK_NAME" and option["opt-locals"] then + -- can't compare identifiers of locals that are optimized + elseif s1 ~= s2 then -- by semantic info (simple) + bork("seminfo ["..i.."] "..t1.." "..s1.." "..s2) + break + end + elseif t1 == "TK_EOS" then + -- no seminfo to compare + else-- "TK_NUMBER" or "TK_STRING" or "TK_LSTRING" + -- compare 'binary' form, so dump a function + local s1b,s2b = dumpsem(s1), dumpsem(s2) + if not s1b or not s2b or s1b ~= s2b then + bork("seminfo ["..i.."] "..t1.." "..s1.." "..s2) + break + end + end + end--for + + -- Successful comparison if end is reached with no borks. +end + +--- Tests binary chunk equivalence (only for PUC Lua 5.1). +-- +-- @tparam string z +-- @tparam string dat +function M.binary(z, dat) + local TNIL = 0 --luacheck: ignore 211 + local TBOOLEAN = 1 + local TNUMBER = 3 + local TSTRING = 4 + + -- sizes of data types + local endian + local sz_int + local sz_sizet + local sz_inst + local sz_number + local getint + local getsizet + + -- Marks and optionally reports non-equivalence. + local function bork(msg) + if option.DETAILS then print("BINEQUIV: "..msg) end + warn.BIN_EQUIV = true + end + + -- Checks if bytes exist. + local function ensure(c, sz) + if c.i + sz - 1 > c.len then return end + return true + end + + -- Skips some bytes. + local function skip(c, sz) + if not sz then sz = 1 end + c.i = c.i + sz + end + + -- Returns a byte value. + local function getbyte(c) + local i = c.i + if i > c.len then return end + local d = sub(c.dat, i, i) + c.i = i + 1 + return byte(d) + end + + -- Return an int value (little-endian). + local function getint_l(c) + local n, scale = 0, 1 + if not ensure(c, sz_int) then return end + for _ = 1, sz_int do + n = n + scale * getbyte(c) + scale = scale * 256 + end + return n + end + + -- Returns an int value (big-endian). + local function getint_b(c) + local n = 0 + if not ensure(c, sz_int) then return end + for _ = 1, sz_int do + n = n * 256 + getbyte(c) + end + return n + end + + -- Returns a size_t value (little-endian). + local function getsizet_l(c) + local n, scale = 0, 1 + if not ensure(c, sz_sizet) then return end + for _ = 1, sz_sizet do + n = n + scale * getbyte(c) + scale = scale * 256 + end + return n + end + + -- Returns a size_t value (big-endian). + local function getsizet_b(c) + local n = 0 + if not ensure(c, sz_sizet) then return end + for _ = 1, sz_sizet do + n = n * 256 + getbyte(c) + end + return n + end + + -- Returns a block (as a string). + local function getblock(c, sz) + local i = c.i + local j = i + sz - 1 + if j > c.len then return end + local d = sub(c.dat, i, j) + c.i = i + sz + return d + end + + -- Returns a string. + local function getstring(c) + local n = getsizet(c) + if not n then return end + if n == 0 then return "" end + return getblock(c, n) + end + + -- Compares byte value. + local function goodbyte(c1, c2) + local b1, b2 = getbyte(c1), getbyte(c2) + if not b1 or not b2 or b1 ~= b2 then + return + end + return b1 + end + + -- Compares byte value. + local function badbyte(c1, c2) + local b = goodbyte(c1, c2) + if not b then return true end + end + + -- Compares int value. + local function goodint(c1, c2) + local i1, i2 = getint(c1), getint(c2) + if not i1 or not i2 or i1 ~= i2 then + return + end + return i1 + end + + -- Recursively-called function to compare function prototypes. + local function getfunc(c1, c2) + -- source name (ignored) + if not getstring(c1) or not getstring(c2) then + bork("bad source name"); return + end + -- linedefined (ignored) + if not getint(c1) or not getint(c2) then + bork("bad linedefined"); return + end + -- lastlinedefined (ignored) + if not getint(c1) or not getint(c2) then + bork("bad lastlinedefined"); return + end + if not (ensure(c1, 4) and ensure(c2, 4)) then + bork("prototype header broken") + end + -- nups (compared) + if badbyte(c1, c2) then + bork("bad nups"); return + end + -- numparams (compared) + if badbyte(c1, c2) then + bork("bad numparams"); return + end + -- is_vararg (compared) + if badbyte(c1, c2) then + bork("bad is_vararg"); return + end + -- maxstacksize (compared) + if badbyte(c1, c2) then + bork("bad maxstacksize"); return + end + -- code (compared) + local ncode = goodint(c1, c2) + if not ncode then + bork("bad ncode"); return + end + local code1 = getblock(c1, ncode * sz_inst) + local code2 = getblock(c2, ncode * sz_inst) + if not code1 or not code2 or code1 ~= code2 then + bork("bad code block"); return + end + -- constants (compared) + local nconst = goodint(c1, c2) + if not nconst then + bork("bad nconst"); return + end + for _ = 1, nconst do + local ctype = goodbyte(c1, c2) + if not ctype then + bork("bad const type"); return + end + if ctype == TBOOLEAN then + if badbyte(c1, c2) then + bork("bad boolean value"); return + end + elseif ctype == TNUMBER then + local num1 = getblock(c1, sz_number) + local num2 = getblock(c2, sz_number) + if not num1 or not num2 or num1 ~= num2 then + bork("bad number value"); return + end + elseif ctype == TSTRING then + local str1 = getstring(c1) + local str2 = getstring(c2) + if not str1 or not str2 or str1 ~= str2 then + bork("bad string value"); return + end + end + end + -- prototypes (compared recursively) + local nproto = goodint(c1, c2) + if not nproto then + bork("bad nproto"); return + end + for _ = 1, nproto do + if not getfunc(c1, c2) then + bork("bad function prototype"); return + end + end + -- debug information (ignored) + -- lineinfo (ignored) + local sizelineinfo1 = getint(c1) + if not sizelineinfo1 then + bork("bad sizelineinfo1"); return + end + local sizelineinfo2 = getint(c2) + if not sizelineinfo2 then + bork("bad sizelineinfo2"); return + end + if not getblock(c1, sizelineinfo1 * sz_int) then + bork("bad lineinfo1"); return + end + if not getblock(c2, sizelineinfo2 * sz_int) then + bork("bad lineinfo2"); return + end + -- locvars (ignored) + local sizelocvars1 = getint(c1) + if not sizelocvars1 then + bork("bad sizelocvars1"); return + end + local sizelocvars2 = getint(c2) + if not sizelocvars2 then + bork("bad sizelocvars2"); return + end + for _ = 1, sizelocvars1 do + if not getstring(c1) or not getint(c1) or not getint(c1) then + bork("bad locvars1"); return + end + end + for _ = 1, sizelocvars2 do + if not getstring(c2) or not getint(c2) or not getint(c2) then + bork("bad locvars2"); return + end + end + -- upvalues (ignored) + local sizeupvalues1 = getint(c1) + if not sizeupvalues1 then + bork("bad sizeupvalues1"); return + end + local sizeupvalues2 = getint(c2) + if not sizeupvalues2 then + bork("bad sizeupvalues2"); return + end + for _ = 1, sizeupvalues1 do + if not getstring(c1) then bork("bad upvalues1"); return end + end + for _ = 1, sizeupvalues2 do + if not getstring(c2) then bork("bad upvalues2"); return end + end + return true + end + + -- Removes shbang line so that load runs. + local function zap_shbang(s) + local shbang = s:match("^(#[^\r\n]*\r?\n?)") + if shbang then -- cut out shbang + s = sub(s, #shbang + 1) + end + return s + end + + -- Attempt to compile, then dump to get binary chunk string. + local cz = load(zap_shbang(z), "z") + if not cz then + bork("failed to compile original sources for binary chunk comparison") + return + end + + local cdat = load(zap_shbang(dat), "z") + if not cdat then + bork("failed to compile compressed result for binary chunk comparison") + end + + -- if load() works, dump assuming string.dump() is error-free + local c1 = { i = 1, dat = dump(cz) } + c1.len = #c1.dat + + local c2 = { i = 1, dat = dump(cdat) } + c2.len = #c2.dat + + -- Parse binary chunks to verify equivalence. + -- * For headers, handle sizes to allow a degree of flexibility. + -- * Assume a valid binary chunk is generated, since it was not + -- generated via external means. + if not (ensure(c1, 12) and ensure(c2, 12)) then + bork("header broken") + end + skip(c1, 6) -- skip signature(4), version, format + endian = getbyte(c1) -- 1 = little endian + sz_int = getbyte(c1) -- get data type sizes + sz_sizet = getbyte(c1) + sz_inst = getbyte(c1) + sz_number = getbyte(c1) + skip(c1) -- skip integral flag + skip(c2, 12) -- skip other header (assume similar) + + if endian == 1 then -- set for endian sensitive data we need + getint = getint_l + getsizet = getsizet_l + else + getint = getint_b + getsizet = getsizet_b + end + getfunc(c1, c2) -- get prototype at root + + if c1.i ~= c1.len + 1 then + bork("inconsistent binary chunk1"); return + elseif c2.i ~= c2.len + 1 then + bork("inconsistent binary chunk2"); return + end + + -- Successful comparison if end is reached with no borks. +end + +return M diff --git a/tools/luasrcdiet/fs.lua b/tools/luasrcdiet/fs.lua new file mode 100644 index 0000000..00baa11 --- /dev/null +++ b/tools/luasrcdiet/fs.lua @@ -0,0 +1,74 @@ +--------- +-- Utility functions for operations on a file system. +-- +-- **Note: This module is not part of public API!** +---- +local fmt = string.format +local open = io.open + +local UTF8_BOM = '\239\187\191' + +local function normalize_io_error (name, err) + if err:sub(1, #name + 2) == name..': ' then + err = err:sub(#name + 3) + end + return err +end + +local M = {} + +--- Reads the specified file and returns its content as string. +-- +-- @tparam string filename Path of the file to read. +-- @tparam string mode The mode in which to open the file, see @{io.open} (default: "r"). +-- @treturn[1] string A content of the file. +-- @treturn[2] nil +-- @treturn[2] string An error message. +function M.read_file (filename, mode) + local handler, err = open(filename, mode or 'r') + if not handler then + return nil, fmt('Could not open %s for reading: %s', + filename, normalize_io_error(filename, err)) + end + + local content, err = handler:read('*a') --luacheck: ignore 411 + if not content then + return nil, fmt('Could not read %s: %s', filename, normalize_io_error(filename, err)) + end + + handler:close() + + if content:sub(1, #UTF8_BOM) == UTF8_BOM then + content = content:sub(#UTF8_BOM + 1) + end + + return content +end + +--- Writes the given data to the specified file. +-- +-- @tparam string filename Path of the file to write. +-- @tparam string data The data to write. +-- @tparam ?string mode The mode in which to open the file, see @{io.open} (default: "w"). +-- @treturn[1] true +-- @treturn[2] nil +-- @treturn[2] string An error message. +function M.write_file (filename, data, mode) + local handler, err = open(filename, mode or 'w') + if not handler then + return nil, fmt('Could not open %s for writing: %s', + filename, normalize_io_error(filename, err)) + end + + local _, err = handler:write(data) --luacheck: ignore 411 + if err then + return nil, fmt('Could not write %s: %s', filename, normalize_io_error(filename, err)) + end + + handler:flush() + handler:close() + + return true +end + +return M diff --git a/tools/luasrcdiet/init.lua b/tools/luasrcdiet/init.lua new file mode 100644 index 0000000..348a979 --- /dev/null +++ b/tools/luasrcdiet/init.lua @@ -0,0 +1,117 @@ +--------- +-- LuaSrcDiet API +---- +local equiv = require 'luasrcdiet.equiv' +local llex = require 'luasrcdiet.llex' +local lparser = require 'luasrcdiet.lparser' +local optlex = require 'luasrcdiet.optlex' +local optparser = require 'luasrcdiet.optparser' +local utils = require 'luasrcdiet.utils' + +local concat = table.concat +local merge = utils.merge + +local _ -- placeholder + + +local function noop () + return +end + +local function opts_to_legacy (opts) + local res = {} + for key, val in pairs(opts) do + res['opt-'..key] = val + end + return res +end + + +local M = {} + +--- The module's name. +M._NAME = 'luasrcdiet' + +--- The module's version number. +M._VERSION = '1.0.0' + +--- The module's homepage. +M._HOMEPAGE = 'https://github.com/jirutka/luasrcdiet' + +--- All optimizations disabled. +M.NONE_OPTS = { + binequiv = false, + comments = false, + emptylines = false, + entropy = false, + eols = false, + experimental = false, + locals = false, + numbers = false, + srcequiv = false, + strings = false, + whitespace = false, +} + +--- Basic optimizations enabled. +-- @table BASIC_OPTS +M.BASIC_OPTS = merge(M.NONE_OPTS, { + comments = true, + emptylines = true, + srcequiv = true, + whitespace = true, +}) + +--- Defaults. +-- @table DEFAULT_OPTS +M.DEFAULT_OPTS = merge(M.BASIC_OPTS, { + locals = true, + numbers = true, +}) + +--- Maximum optimizations enabled (all except experimental). +-- @table MAXIMUM_OPTS +M.MAXIMUM_OPTS = merge(M.DEFAULT_OPTS, { + entropy = true, + eols = true, + strings = true, +}) + +--- Optimizes the given Lua source code. +-- +-- @tparam ?{[string]=bool,...} opts Optimizations to do (default is @{DEFAULT_OPTS}). +-- @tparam string source The Lua source code to optimize. +-- @treturn string Optimized source. +-- @raise if the source is malformed, source equivalence test failed, or some +-- other error occured. +function M.optimize (opts, source) + assert(source and type(source) == 'string', + 'bad argument #2: expected string, got a '..type(source)) + + opts = opts and merge(M.NONE_OPTS, opts) or M.DEFAULT_OPTS + local legacy_opts = opts_to_legacy(opts) + + local toklist, seminfolist, toklnlist = llex.lex(source) + local xinfo = lparser.parse(toklist, seminfolist, toklnlist) + + optparser.print = noop + optparser.optimize(legacy_opts, toklist, seminfolist, xinfo) + + local warn = optlex.warn -- use this as a general warning lookup + optlex.print = noop + _, seminfolist = optlex.optimize(legacy_opts, toklist, seminfolist, toklnlist) + local optim_source = concat(seminfolist) + + if opts.srcequiv and not opts.experimental then + equiv.init(legacy_opts, llex, warn) + equiv.source(source, optim_source) + + if warn.SRC_EQUIV then + error('Source equivalence test failed!') + end + end + + return optim_source +end + +return M diff --git a/tools/luasrcdiet/llex.lua b/tools/luasrcdiet/llex.lua new file mode 100644 index 0000000..c9d5a0e --- /dev/null +++ b/tools/luasrcdiet/llex.lua @@ -0,0 +1,350 @@ +--------- +-- Lua 5.1+ lexical analyzer written in Lua. +-- +-- This file is part of LuaSrcDiet, based on Yueliang material. +-- +-- **Notes:** +-- +-- * This is a version of the native 5.1.x lexer from Yueliang 0.4.0, +-- with significant modifications to handle LuaSrcDiet's needs: +-- (1) llex.error is an optional error function handler, +-- (2) seminfo for strings include their delimiters and no +-- translation operations are performed on them. +-- * ADDED shbang handling has been added to support executable scripts. +-- * NO localized decimal point replacement magic. +-- * NO limit to number of lines. +-- * NO support for compatible long strings (LUA\_COMPAT_LSTR). +-- * Added goto keyword and double-colon operator (Lua 5.2+). +---- +local find = string.find +local fmt = string.format +local match = string.match +local sub = string.sub +local tonumber = tonumber + +local M = {} + +local kw = {} +for v in ([[ +and break do else elseif end false for function goto if in +local nil not or repeat return then true until while]]):gmatch("%S+") do + kw[v] = true +end + +local z, -- source stream + sourceid, -- name of source + I, -- position of lexer + buff, -- buffer for strings + ln, -- line number + tok, -- lexed token list + seminfo, -- lexed semantic information list + tokln -- line numbers for messages + + +--- Adds information to token listing. +-- +-- @tparam string token +-- @tparam string info +local function addtoken(token, info) + local i = #tok + 1 + tok[i] = token + seminfo[i] = info + tokln[i] = ln +end + +--- Handles line number incrementation and end-of-line characters. +-- +-- @tparam int i Position of lexer in the source stream. +-- @tparam bool is_tok +-- @treturn int +local function inclinenumber(i, is_tok) + local old = sub(z, i, i) + i = i + 1 -- skip '\n' or '\r' + local c = sub(z, i, i) + if (c == "\n" or c == "\r") and (c ~= old) then + i = i + 1 -- skip '\n\r' or '\r\n' + old = old..c + end + if is_tok then addtoken("TK_EOL", old) end + ln = ln + 1 + I = i + return i +end + +--- Returns a chunk name or id, no truncation for long names. +-- +-- @treturn string +local function chunkid() + if sourceid and match(sourceid, "^[=@]") then + return sub(sourceid, 2) -- remove first char + end + return "[string]" +end + +--- Formats error message and throws error. +-- +-- A simplified version, does not report what token was responsible. +-- +-- @tparam string s +-- @tparam int line The line number. +-- @raise +local function errorline(s, line) + local e = M.error or error + e(fmt("%s:%d: %s", chunkid(), line or ln, s)) +end + +--- Counts separators (`="` in a long string delimiter. +-- +-- @tparam int i Position of lexer in the source stream. +-- @treturn int +local function skip_sep(i) + local s = sub(z, i, i) + i = i + 1 + local count = #match(z, "=*", i) + i = i + count + I = i + return (sub(z, i, i) == s) and count or (-count) - 1 +end + +--- Reads a long string or long comment. +-- +-- @tparam bool is_str +-- @tparam string sep +-- @treturn string +-- @raise if unfinished long string or comment. +local function read_long_string(is_str, sep) + local i = I + 1 -- skip 2nd '[' + local c = sub(z, i, i) + if c == "\r" or c == "\n" then -- string starts with a newline? + i = inclinenumber(i) -- skip it + end + while true do + local p, _, r = find(z, "([\r\n%]])", i) -- (long range match) + if not p then + errorline(is_str and "unfinished long string" or + "unfinished long comment") + end + i = p + if r == "]" then -- delimiter test + if skip_sep(i) == sep then + buff = sub(z, buff, I) + I = I + 1 -- skip 2nd ']' + return buff + end + i = I + else -- newline + buff = buff.."\n" + i = inclinenumber(i) + end + end--while +end + +--- Reads a string. +-- +-- @tparam string del The delimiter. +-- @treturn string +-- @raise if unfinished string or too large escape sequence. +local function read_string(del) + local i = I + while true do + local p, _, r = find(z, "([\n\r\\\"\'])", i) -- (long range match) + if p then + if r == "\n" or r == "\r" then + errorline("unfinished string") + end + i = p + if r == "\\" then -- handle escapes + i = i + 1 + r = sub(z, i, i) + if r == "" then break end -- (EOZ error) + p = find("abfnrtv\n\r", r, 1, true) + + if p then -- special escapes + if p > 7 then + i = inclinenumber(i) + else + i = i + 1 + end + + elseif find(r, "%D") then -- other non-digits + i = i + 1 + + else -- \xxx sequence + local _, q, s = find(z, "^(%d%d?%d?)", i) + i = q + 1 + if s + 1 > 256 then -- UCHAR_MAX + errorline("escape sequence too large") + end + + end--if p + else + i = i + 1 + if r == del then -- ending delimiter + I = i + return sub(z, buff, i - 1) -- return string + end + end--if r + else + break -- (error) + end--if p + end--while + errorline("unfinished string") +end + + +--- Initializes lexer for given source _z and source name _sourceid. +-- +-- @tparam string _z The source code. +-- @tparam string _sourceid Name of the source. +local function init(_z, _sourceid) + z = _z -- source + sourceid = _sourceid -- name of source + I = 1 -- lexer's position in source + ln = 1 -- line number + tok = {} -- lexed token list* + seminfo = {} -- lexed semantic information list* + tokln = {} -- line numbers for messages* + + -- Initial processing (shbang handling). + local p, _, q, r = find(z, "^(#[^\r\n]*)(\r?\n?)") + if p then -- skip first line + I = I + #q + addtoken("TK_COMMENT", q) + if #r > 0 then inclinenumber(I, true) end + end +end + +--- Runs lexer on the given source code. +-- +-- @tparam string source The Lua source to scan. +-- @tparam ?string source_name Name of the source (optional). +-- @treturn {string,...} A list of lexed tokens. +-- @treturn {string,...} A list of semantic information (lexed strings). +-- @treturn {int,...} A list of line numbers. +function M.lex(source, source_name) + init(source, source_name) + + while true do--outer + local i = I + -- inner loop allows break to be used to nicely section tests + while true do --luacheck: ignore 512 + + local p, _, r = find(z, "^([_%a][_%w]*)", i) + if p then + I = i + #r + if kw[r] then + addtoken("TK_KEYWORD", r) -- reserved word (keyword) + else + addtoken("TK_NAME", r) -- identifier + end + break -- (continue) + end + + local p, _, r = find(z, "^(%.?)%d", i) + if p then -- numeral + if r == "." then i = i + 1 end + local _, q, r = find(z, "^%d*[%.%d]*([eE]?)", i) --luacheck: ignore 421 + i = q + 1 + if #r == 1 then -- optional exponent + if match(z, "^[%+%-]", i) then -- optional sign + i = i + 1 + end + end + local _, q = find(z, "^[_%w]*", i) + I = q + 1 + local v = sub(z, p, q) -- string equivalent + if not tonumber(v) then -- handles hex test also + errorline("malformed number") + end + addtoken("TK_NUMBER", v) + break -- (continue) + end + + local p, q, r, t = find(z, "^((%s)[ \t\v\f]*)", i) + if p then + if t == "\n" or t == "\r" then -- newline + inclinenumber(i, true) + else + I = q + 1 -- whitespace + addtoken("TK_SPACE", r) + end + break -- (continue) + end + + local _, q = find(z, "^::", i) + if q then + I = q + 1 + addtoken("TK_OP", "::") + break -- (continue) + end + + local r = match(z, "^%p", i) + if r then + buff = i + local p = find("-[\"\'.=<>~", r, 1, true) --luacheck: ignore 421 + if p then + + -- two-level if block for punctuation/symbols + if p <= 2 then + if p == 1 then -- minus + local c = match(z, "^%-%-(%[?)", i) + if c then + i = i + 2 + local sep = -1 + if c == "[" then + sep = skip_sep(i) + end + if sep >= 0 then -- long comment + addtoken("TK_LCOMMENT", read_long_string(false, sep)) + else -- short comment + I = find(z, "[\n\r]", i) or (#z + 1) + addtoken("TK_COMMENT", sub(z, buff, I - 1)) + end + break -- (continue) + end + -- (fall through for "-") + else -- [ or long string + local sep = skip_sep(i) + if sep >= 0 then + addtoken("TK_LSTRING", read_long_string(true, sep)) + elseif sep == -1 then + addtoken("TK_OP", "[") + else + errorline("invalid long string delimiter") + end + break -- (continue) + end + + elseif p <= 5 then + if p < 5 then -- strings + I = i + 1 + addtoken("TK_STRING", read_string(r)) + break -- (continue) + end + r = match(z, "^%.%.?%.?", i) -- .|..|... dots + -- (fall through) + + else -- relational + r = match(z, "^%p=?", i) + -- (fall through) + end + end + I = i + #r + addtoken("TK_OP", r) -- for other symbols, fall through + break -- (continue) + end + + local r = sub(z, i, i) + if r ~= "" then + I = i + 1 + addtoken("TK_OP", r) -- other single-char tokens + break + end + addtoken("TK_EOS", "") -- end of stream, + return tok, seminfo, tokln -- exit here + + end--while inner + end--while outer +end + +return M diff --git a/tools/luasrcdiet/lparser.lua b/tools/luasrcdiet/lparser.lua new file mode 100644 index 0000000..334243e --- /dev/null +++ b/tools/luasrcdiet/lparser.lua @@ -0,0 +1,1286 @@ +--------- +-- Lua 5.1+ parser written in Lua. +-- +-- This file is part of LuaSrcDiet, based on Yueliang material. +-- +-- **Notes:** +-- +-- * This is a version of the native 5.1.x parser from Yueliang 0.4.0, +-- with significant modifications to handle LuaSrcDiet's needs: +-- (1) needs pre-built token tables instead of a module.method, +-- (2) lparser.error is an optional error handler (from llex), +-- (3) not full parsing, currently fakes raw/unlexed constants, +-- (4) parser() returns globalinfo, localinfo tables. +-- * NO support for 'arg' vararg functions (LUA_COMPAT_VARARG). +-- * A lot of the parser is unused, but might later be useful for +-- full-on parsing and analysis. +-- * Relaxed parsing of statement to not require "break" to be the +-- last statement of block (Lua 5.2+). +-- * Added basic support for goto and label statements, i.e. parser +-- does not crash on them (Lua 5.2+). +---- +local fmt = string.format +local gmatch = string.gmatch +local pairs = pairs + +local M = {} + +--[[-------------------------------------------------------------------- +-- variable and data structure initialization +----------------------------------------------------------------------]] + +---------------------------------------------------------------------- +-- initialization: main variables +---------------------------------------------------------------------- + +local toklist, -- grammar-only token tables (token table, + seminfolist, -- semantic information table, line number + toklnlist, -- table, cross-reference table) + xreflist, + tpos, -- token position + + line, -- start line # for error messages + lastln, -- last line # for ambiguous syntax chk + tok, seminfo, ln, xref, -- token, semantic info, line + nameref, -- proper position of token + fs, -- current function state + top_fs, -- top-level function state + + globalinfo, -- global variable information table + globallookup, -- global variable name lookup table + localinfo, -- local variable information table + ilocalinfo, -- inactive locals (prior to activation) + ilocalrefs, -- corresponding references to activate + statinfo -- statements labeled by type + +-- forward references for local functions +local explist1, expr, block, exp1, body, chunk + +---------------------------------------------------------------------- +-- initialization: data structures +---------------------------------------------------------------------- + +local block_follow = {} -- lookahead check in chunk(), returnstat() +for v in gmatch("else elseif end until ", "%S+") do + block_follow[v] = true +end + +local binopr_left = {} -- binary operators, left priority +local binopr_right = {} -- binary operators, right priority +for op, lt, rt in gmatch([[ +{+ 6 6}{- 6 6}{* 7 7}{/ 7 7}{% 7 7} +{^ 10 9}{.. 5 4} +{~= 3 3}{== 3 3} +{< 3 3}{<= 3 3}{> 3 3}{>= 3 3} +{and 2 2}{or 1 1} +]], "{(%S+)%s(%d+)%s(%d+)}") do + binopr_left[op] = lt + 0 + binopr_right[op] = rt + 0 +end + +local unopr = { ["not"] = true, ["-"] = true, + ["#"] = true, } -- unary operators +local UNARY_PRIORITY = 8 -- priority for unary operators + +--[[-------------------------------------------------------------------- +-- support functions +----------------------------------------------------------------------]] + +---------------------------------------------------------------------- +-- formats error message and throws error (duplicated from llex) +-- * a simplified version, does not report what token was responsible +---------------------------------------------------------------------- + +local function errorline(s, line) + local e = M.error or error + e(fmt("(source):%d: %s", line or ln, s)) +end + +---------------------------------------------------------------------- +-- handles incoming token, semantic information pairs +-- * NOTE: 'nextt' is named 'next' originally +---------------------------------------------------------------------- + +-- reads in next token +local function nextt() + lastln = toklnlist[tpos] + tok, seminfo, ln, xref + = toklist[tpos], seminfolist[tpos], toklnlist[tpos], xreflist[tpos] + tpos = tpos + 1 +end + +-- peek at next token (single lookahead for table constructor) +local function lookahead() + return toklist[tpos] +end + +---------------------------------------------------------------------- +-- throws a syntax error, or if token expected is not there +---------------------------------------------------------------------- + +local function syntaxerror(msg) + if tok ~= "" and tok ~= "" then + if tok == "" then tok = seminfo end + tok = "'"..tok.."'" + end + errorline(msg.." near "..tok) +end + +local function error_expected(token) + syntaxerror("'"..token.."' expected") +end + +---------------------------------------------------------------------- +-- tests for a token, returns outcome +-- * return value changed to boolean +---------------------------------------------------------------------- + +local function testnext(c) + if tok == c then nextt(); return true end +end + +---------------------------------------------------------------------- +-- check for existence of a token, throws error if not found +---------------------------------------------------------------------- + +local function check(c) + if tok ~= c then error_expected(c) end +end + +---------------------------------------------------------------------- +-- verify existence of a token, then skip it +---------------------------------------------------------------------- + +local function checknext(c) + check(c); nextt() +end + +---------------------------------------------------------------------- +-- throws error if condition not matched +---------------------------------------------------------------------- + +local function check_condition(c, msg) + if not c then syntaxerror(msg) end +end + +---------------------------------------------------------------------- +-- verifies token conditions are met or else throw error +---------------------------------------------------------------------- + +local function check_match(what, who, where) + if not testnext(what) then + if where == ln then + error_expected(what) + else + syntaxerror("'"..what.."' expected (to close '"..who.."' at line "..where..")") + end + end +end + +---------------------------------------------------------------------- +-- expect that token is a name, consume it and return the name +---------------------------------------------------------------------- + +local function str_checkname() + check("") + local ts = seminfo + nameref = xref + nextt() + return ts +end + +--[[-------------------------------------------------------------------- +-- variable (global|local|upvalue) handling +-- * to track locals and globals, variable management code needed +-- * entry point is singlevar() for variable lookups +-- * lookup tables (bl.locallist) are maintained awkwardly in the basic +-- block data structures, PLUS the function data structure (this is +-- an inelegant hack, since bl is nil for the top level of a function) +----------------------------------------------------------------------]] + +---------------------------------------------------------------------- +-- register a local variable, create local variable object, set in +-- to-activate variable list +-- * used in new_localvarliteral(), parlist(), fornum(), forlist(), +-- localfunc(), localstat() +---------------------------------------------------------------------- + +local function new_localvar(name, special) + local bl = fs.bl + local locallist + -- locate locallist in current block object or function root object + if bl then + locallist = bl.locallist + else + locallist = fs.locallist + end + -- build local variable information object and set localinfo + local id = #localinfo + 1 + localinfo[id] = { -- new local variable object + name = name, -- local variable name + xref = { nameref }, -- xref, first value is declaration + decl = nameref, -- location of declaration, = xref[1] + } + if special or name == "_ENV" then -- "self" and "_ENV" must be not be changed + localinfo[id].is_special = true + end + -- this can override a local with the same name in the same scope + -- but first, keep it inactive until it gets activated + local i = #ilocalinfo + 1 + ilocalinfo[i] = id + ilocalrefs[i] = locallist +end + +---------------------------------------------------------------------- +-- actually activate the variables so that they are visible +-- * remember Lua semantics, e.g. RHS is evaluated first, then LHS +-- * used in parlist(), forbody(), localfunc(), localstat(), body() +---------------------------------------------------------------------- + +local function adjustlocalvars(nvars) + local sz = #ilocalinfo + -- i goes from left to right, in order of local allocation, because + -- of something like: local a,a,a = 1,2,3 which gives a = 3 + while nvars > 0 do + nvars = nvars - 1 + local i = sz - nvars + local id = ilocalinfo[i] -- local's id + local obj = localinfo[id] + local name = obj.name -- name of local + obj.act = xref -- set activation location + ilocalinfo[i] = nil + local locallist = ilocalrefs[i] -- ref to lookup table to update + ilocalrefs[i] = nil + local existing = locallist[name] -- if existing, remove old first! + if existing then -- do not overlap, set special + obj = localinfo[existing] -- form of rem, as -id + obj.rem = -id + end + locallist[name] = id -- activate, now visible to Lua + end +end + +---------------------------------------------------------------------- +-- remove (deactivate) variables in current scope (before scope exits) +-- * zap entire locallist tables since we are not allocating registers +-- * used in leaveblock(), close_func() +---------------------------------------------------------------------- + +local function removevars() + local bl = fs.bl + local locallist + -- locate locallist in current block object or function root object + if bl then + locallist = bl.locallist + else + locallist = fs.locallist + end + -- enumerate the local list at current scope and deactivate 'em + for _, id in pairs(locallist) do + local obj = localinfo[id] + obj.rem = xref -- set deactivation location + end +end + +---------------------------------------------------------------------- +-- creates a new local variable given a name +-- * skips internal locals (those starting with '('), so internal +-- locals never needs a corresponding adjustlocalvars() call +-- * special is true for "self" which must not be optimized +-- * used in fornum(), forlist(), parlist(), body() +---------------------------------------------------------------------- + +local function new_localvarliteral(name, special) + if name:sub(1, 1) == "(" then -- can skip internal locals + return + end + new_localvar(name, special) +end + +---------------------------------------------------------------------- +-- search the local variable namespace of the given fs for a match +-- * returns localinfo index +-- * used only in singlevaraux() +---------------------------------------------------------------------- + +local function searchvar(fs, n) + local bl = fs.bl + local locallist + if bl then + locallist = bl.locallist + while locallist do + if locallist[n] then return locallist[n] end -- found + bl = bl.prev + locallist = bl and bl.locallist + end + end + locallist = fs.locallist + return locallist[n] or -1 -- found or not found (-1) +end + +---------------------------------------------------------------------- +-- handle locals, globals and upvalues and related processing +-- * search mechanism is recursive, calls itself to search parents +-- * used only in singlevar() +---------------------------------------------------------------------- + +local function singlevaraux(fs, n, var) + if fs == nil then -- no more levels? + var.k = "VGLOBAL" -- default is global variable + return "VGLOBAL" + else + local v = searchvar(fs, n) -- look up at current level + if v >= 0 then + var.k = "VLOCAL" + var.id = v + -- codegen may need to deal with upvalue here + return "VLOCAL" + else -- not found at current level; try upper one + if singlevaraux(fs.prev, n, var) == "VGLOBAL" then + return "VGLOBAL" + end + -- else was LOCAL or UPVAL, handle here + var.k = "VUPVAL" -- upvalue in this level + return "VUPVAL" + end--if v + end--if fs +end + +---------------------------------------------------------------------- +-- consume a name token, creates a variable (global|local|upvalue) +-- * used in prefixexp(), funcname() +---------------------------------------------------------------------- + +local function singlevar(v) + local name = str_checkname() + singlevaraux(fs, name, v) + ------------------------------------------------------------------ + -- variable tracking + ------------------------------------------------------------------ + if v.k == "VGLOBAL" then + -- if global being accessed, keep track of it by creating an object + local id = globallookup[name] + if not id then + id = #globalinfo + 1 + globalinfo[id] = { -- new global variable object + name = name, -- global variable name + xref = { nameref }, -- xref, first value is declaration + } + globallookup[name] = id -- remember it + else + local obj = globalinfo[id].xref + obj[#obj + 1] = nameref -- add xref + end + else + -- local/upvalue is being accessed, keep track of it + local obj = localinfo[v.id].xref + obj[#obj + 1] = nameref -- add xref + end +end + +--[[-------------------------------------------------------------------- +-- state management functions with open/close pairs +----------------------------------------------------------------------]] + +---------------------------------------------------------------------- +-- enters a code unit, initializes elements +---------------------------------------------------------------------- + +local function enterblock(isbreakable) + local bl = {} -- per-block state + bl.isbreakable = isbreakable + bl.prev = fs.bl + bl.locallist = {} + fs.bl = bl +end + +---------------------------------------------------------------------- +-- leaves a code unit, close any upvalues +---------------------------------------------------------------------- + +local function leaveblock() + local bl = fs.bl + removevars() + fs.bl = bl.prev +end + +---------------------------------------------------------------------- +-- opening of a function +-- * top_fs is only for anchoring the top fs, so that parser() can +-- return it to the caller function along with useful output +-- * used in parser() and body() +---------------------------------------------------------------------- + +local function open_func() + local new_fs -- per-function state + if not fs then -- top_fs is created early + new_fs = top_fs + else + new_fs = {} + end + new_fs.prev = fs -- linked list of function states + new_fs.bl = nil + new_fs.locallist = {} + fs = new_fs +end + +---------------------------------------------------------------------- +-- closing of a function +-- * used in parser() and body() +---------------------------------------------------------------------- + +local function close_func() + removevars() + fs = fs.prev +end + +--[[-------------------------------------------------------------------- +-- other parsing functions +-- * for table constructor, parameter list, argument list +----------------------------------------------------------------------]] + +---------------------------------------------------------------------- +-- parse a function name suffix, for function call specifications +-- * used in primaryexp(), funcname() +---------------------------------------------------------------------- + +local function field(v) + -- field -> ['.' | ':'] NAME + nextt() -- skip the dot or colon + str_checkname() + v.k = "VINDEXED" +end + +---------------------------------------------------------------------- +-- parse a table indexing suffix, for constructors, expressions +-- * used in recfield(), primaryexp() +---------------------------------------------------------------------- + +local function yindex() + -- index -> '[' expr ']' + nextt() -- skip the '[' + expr({}) + checknext("]") +end + +---------------------------------------------------------------------- +-- parse a table record (hash) field +-- * used in constructor() +---------------------------------------------------------------------- + +local function recfield() + -- recfield -> (NAME | '['exp1']') = exp1 + if tok == "" then + str_checkname() + else-- tok == '[' + yindex() + end + checknext("=") + expr({}) +end + +---------------------------------------------------------------------- +-- parse a table list (array) field +-- * used in constructor() +---------------------------------------------------------------------- + +local function listfield(cc) + expr(cc.v) +end + +---------------------------------------------------------------------- +-- parse a table constructor +-- * used in funcargs(), simpleexp() +---------------------------------------------------------------------- + +local function constructor(t) + -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}' + -- field -> recfield | listfield + -- fieldsep -> ',' | ';' + local line = ln + local cc = { + v = { k = "VVOID" }, + } + t.k = "VRELOCABLE" + checknext("{") + repeat + if tok == "}" then break end + -- closelistfield(cc) here + local c = tok + if c == "" then -- may be listfields or recfields + if lookahead() ~= "=" then -- look ahead: expression? + listfield(cc) + else + recfield() + end + elseif c == "[" then -- constructor_item -> recfield + recfield() + else -- constructor_part -> listfield + listfield(cc) + end + until not testnext(",") and not testnext(";") + check_match("}", "{", line) + -- lastlistfield(cc) here +end + +---------------------------------------------------------------------- +-- parse the arguments (parameters) of a function declaration +-- * used in body() +---------------------------------------------------------------------- + +local function parlist() + -- parlist -> [ param { ',' param } ] + local nparams = 0 + if tok ~= ")" then -- is 'parlist' not empty? + repeat + local c = tok + if c == "" then -- param -> NAME + new_localvar(str_checkname()) + nparams = nparams + 1 + elseif c == "..." then + nextt() + fs.is_vararg = true + else + syntaxerror(" or '...' expected") + end + until fs.is_vararg or not testnext(",") + end--if + adjustlocalvars(nparams) +end + +---------------------------------------------------------------------- +-- parse the parameters of a function call +-- * contrast with parlist(), used in function declarations +-- * used in primaryexp() +---------------------------------------------------------------------- + +local function funcargs(f) + local line = ln + local c = tok + if c == "(" then -- funcargs -> '(' [ explist1 ] ')' + if line ~= lastln then + syntaxerror("ambiguous syntax (function call x new statement)") + end + nextt() + if tok ~= ")" then -- arg list is not empty? + explist1() + end + check_match(")", "(", line) + elseif c == "{" then -- funcargs -> constructor + constructor({}) + elseif c == "" then -- funcargs -> STRING + nextt() -- must use 'seminfo' before 'next' + else + syntaxerror("function arguments expected") + return + end--if c + f.k = "VCALL" +end + +--[[-------------------------------------------------------------------- +-- mostly expression functions +----------------------------------------------------------------------]] + +---------------------------------------------------------------------- +-- parses an expression in parentheses or a single variable +-- * used in primaryexp() +---------------------------------------------------------------------- + +local function prefixexp(v) + -- prefixexp -> NAME | '(' expr ')' + local c = tok + if c == "(" then + local line = ln + nextt() + expr(v) + check_match(")", "(", line) + elseif c == "" then + singlevar(v) + else + syntaxerror("unexpected symbol") + end--if c +end + +---------------------------------------------------------------------- +-- parses a prefixexp (an expression in parentheses or a single +-- variable) or a function call specification +-- * used in simpleexp(), assignment(), expr_stat() +---------------------------------------------------------------------- + +local function primaryexp(v) + -- primaryexp -> + -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } + prefixexp(v) + while true do + local c = tok + if c == "." then -- field + field(v) + elseif c == "[" then -- '[' exp1 ']' + yindex() + elseif c == ":" then -- ':' NAME funcargs + nextt() + str_checkname() + funcargs(v) + elseif c == "(" or c == "" or c == "{" then -- funcargs + funcargs(v) + else + return + end--if c + end--while +end + +---------------------------------------------------------------------- +-- parses general expression types, constants handled here +-- * used in subexpr() +---------------------------------------------------------------------- + +local function simpleexp(v) + -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | + -- constructor | FUNCTION body | primaryexp + local c = tok + if c == "" then + v.k = "VKNUM" + elseif c == "" then + v.k = "VK" + elseif c == "nil" then + v.k = "VNIL" + elseif c == "true" then + v.k = "VTRUE" + elseif c == "false" then + v.k = "VFALSE" + elseif c == "..." then -- vararg + check_condition(fs.is_vararg == true, + "cannot use '...' outside a vararg function"); + v.k = "VVARARG" + elseif c == "{" then -- constructor + constructor(v) + return + elseif c == "function" then + nextt() + body(false, ln) + return + else + primaryexp(v) + return + end--if c + nextt() +end + +------------------------------------------------------------------------ +-- Parse subexpressions. Includes handling of unary operators and binary +-- operators. A subexpr is given the rhs priority level of the operator +-- immediately left of it, if any (limit is -1 if none,) and if a binop +-- is found, limit is compared with the lhs priority level of the binop +-- in order to determine which executes first. +-- * recursively called +-- * used in expr() +------------------------------------------------------------------------ + +local function subexpr(v, limit) + -- subexpr -> (simpleexp | unop subexpr) { binop subexpr } + -- * where 'binop' is any binary operator with a priority + -- higher than 'limit' + local op = tok + local uop = unopr[op] + if uop then + nextt() + subexpr(v, UNARY_PRIORITY) + else + simpleexp(v) + end + -- expand while operators have priorities higher than 'limit' + op = tok + local binop = binopr_left[op] + while binop and binop > limit do + nextt() + -- read sub-expression with higher priority + op = subexpr({}, binopr_right[op]) -- next operator + binop = binopr_left[op] + end + return op -- return first untreated operator +end + +---------------------------------------------------------------------- +-- Expression parsing starts here. Function subexpr is entered with the +-- left operator (which is non-existent) priority of -1, which is lower +-- than all actual operators. Expr information is returned in parm v. +-- * used in cond(), explist1(), index(), recfield(), listfield(), +-- prefixexp(), while_stat(), exp1() +---------------------------------------------------------------------- + +-- this is a forward-referenced local +function expr(v) + -- expr -> subexpr + subexpr(v, 0) +end + +--[[-------------------------------------------------------------------- +-- third level parsing functions +----------------------------------------------------------------------]] + +------------------------------------------------------------------------ +-- parse a variable assignment sequence +-- * recursively called +-- * used in expr_stat() +------------------------------------------------------------------------ + +local function assignment(v) + local c = v.v.k + check_condition(c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL" + or c == "VINDEXED", "syntax error") + if testnext(",") then -- assignment -> ',' primaryexp assignment + local nv = {} -- expdesc + nv.v = {} + primaryexp(nv.v) + -- lparser.c deals with some register usage conflict here + assignment(nv) + else -- assignment -> '=' explist1 + checknext("=") + explist1() + return -- avoid default + end +end + +---------------------------------------------------------------------- +-- parse a for loop body for both versions of the for loop +-- * used in fornum(), forlist() +---------------------------------------------------------------------- + +local function forbody(nvars) + -- forbody -> DO block + checknext("do") + enterblock(false) -- scope for declared variables + adjustlocalvars(nvars) + block() + leaveblock() -- end of scope for declared variables +end + +---------------------------------------------------------------------- +-- parse a numerical for loop, calls forbody() +-- * used in for_stat() +---------------------------------------------------------------------- + +local function fornum(varname) + -- fornum -> NAME = exp1, exp1 [, exp1] DO body + new_localvarliteral("(for index)") + new_localvarliteral("(for limit)") + new_localvarliteral("(for step)") + new_localvar(varname) + checknext("=") + exp1() -- initial value + checknext(",") + exp1() -- limit + if testnext(",") then + exp1() -- optional step + else + -- default step = 1 + end + forbody(1) +end + +---------------------------------------------------------------------- +-- parse a generic for loop, calls forbody() +-- * used in for_stat() +---------------------------------------------------------------------- + +local function forlist(indexname) + -- forlist -> NAME {, NAME} IN explist1 DO body + -- create control variables + new_localvarliteral("(for generator)") + new_localvarliteral("(for state)") + new_localvarliteral("(for control)") + -- create declared variables + new_localvar(indexname) + local nvars = 1 + while testnext(",") do + new_localvar(str_checkname()) + nvars = nvars + 1 + end + checknext("in") + explist1() + forbody(nvars) +end + +---------------------------------------------------------------------- +-- parse a function name specification +-- * used in func_stat() +---------------------------------------------------------------------- + +local function funcname(v) + -- funcname -> NAME {field} [':' NAME] + local needself = false + singlevar(v) + while tok == "." do + field(v) + end + if tok == ":" then + needself = true + field(v) + end + return needself +end + +---------------------------------------------------------------------- +-- parse the single expressions needed in numerical for loops +-- * used in fornum() +---------------------------------------------------------------------- + +-- this is a forward-referenced local +function exp1() + -- exp1 -> expr + expr({}) +end + +---------------------------------------------------------------------- +-- parse condition in a repeat statement or an if control structure +-- * used in repeat_stat(), test_then_block() +---------------------------------------------------------------------- + +local function cond() + -- cond -> expr + expr({}) -- read condition +end + +---------------------------------------------------------------------- +-- parse part of an if control structure, including the condition +-- * used in if_stat() +---------------------------------------------------------------------- + +local function test_then_block() + -- test_then_block -> [IF | ELSEIF] cond THEN block + nextt() -- skip IF or ELSEIF + cond() + checknext("then") + block() -- 'then' part +end + +---------------------------------------------------------------------- +-- parse a local function statement +-- * used in local_stat() +---------------------------------------------------------------------- + +local function localfunc() + -- localfunc -> NAME body + new_localvar(str_checkname()) + adjustlocalvars(1) + body(false, ln) +end + +---------------------------------------------------------------------- +-- parse a local variable declaration statement +-- * used in local_stat() +---------------------------------------------------------------------- + +local function localstat() + -- localstat -> NAME {',' NAME} ['=' explist1] + local nvars = 0 + repeat + new_localvar(str_checkname()) + nvars = nvars + 1 + until not testnext(",") + if testnext("=") then + explist1() + else + -- VVOID + end + adjustlocalvars(nvars) +end + +---------------------------------------------------------------------- +-- parse a list of comma-separated expressions +-- * used in return_stat(), localstat(), funcargs(), assignment(), +-- forlist() +---------------------------------------------------------------------- + +-- this is a forward-referenced local +function explist1() + -- explist1 -> expr { ',' expr } + local e = {} + expr(e) + while testnext(",") do + expr(e) + end +end + +---------------------------------------------------------------------- +-- parse function declaration body +-- * used in simpleexp(), localfunc(), func_stat() +---------------------------------------------------------------------- + +-- this is a forward-referenced local +function body(needself, line) + -- body -> '(' parlist ')' chunk END + open_func() + checknext("(") + if needself then + new_localvarliteral("self", true) + adjustlocalvars(1) + end + parlist() + checknext(")") + chunk() + check_match("end", "function", line) + close_func() +end + +---------------------------------------------------------------------- +-- parse a code block or unit +-- * used in do_stat(), while_stat(), forbody(), test_then_block(), +-- if_stat() +---------------------------------------------------------------------- + +-- this is a forward-referenced local +function block() + -- block -> chunk + enterblock(false) + chunk() + leaveblock() +end + +--[[-------------------------------------------------------------------- +-- second level parsing functions, all with '_stat' suffix +-- * since they are called via a table lookup, they cannot be local +-- functions (a lookup table of local functions might be smaller...) +-- * stat() -> *_stat() +----------------------------------------------------------------------]] + +---------------------------------------------------------------------- +-- initial parsing for a for loop, calls fornum() or forlist() +-- * removed 'line' parameter (used to set debug information only) +-- * used in stat() +---------------------------------------------------------------------- + +local function for_stat() + -- stat -> for_stat -> FOR (fornum | forlist) END + local line = line + enterblock(true) -- scope for loop and control variables + nextt() -- skip 'for' + local varname = str_checkname() -- first variable name + local c = tok + if c == "=" then + fornum(varname) + elseif c == "," or c == "in" then + forlist(varname) + else + syntaxerror("'=' or 'in' expected") + end + check_match("end", "for", line) + leaveblock() -- loop scope (`break' jumps to this point) +end + +---------------------------------------------------------------------- +-- parse a while-do control structure, body processed by block() +-- * used in stat() +---------------------------------------------------------------------- + +local function while_stat() + -- stat -> while_stat -> WHILE cond DO block END + local line = line + nextt() -- skip WHILE + cond() -- parse condition + enterblock(true) + checknext("do") + block() + check_match("end", "while", line) + leaveblock() +end + +---------------------------------------------------------------------- +-- parse a repeat-until control structure, body parsed by chunk() +-- * originally, repeatstat() calls breakstat() too if there is an +-- upvalue in the scope block; nothing is actually lexed, it is +-- actually the common code in breakstat() for closing of upvalues +-- * used in stat() +---------------------------------------------------------------------- + +local function repeat_stat() + -- stat -> repeat_stat -> REPEAT block UNTIL cond + local line = line + enterblock(true) -- loop block + enterblock(false) -- scope block + nextt() -- skip REPEAT + chunk() + check_match("until", "repeat", line) + cond() + -- close upvalues at scope level below + leaveblock() -- finish scope + leaveblock() -- finish loop +end + +---------------------------------------------------------------------- +-- parse an if control structure +-- * used in stat() +---------------------------------------------------------------------- + +local function if_stat() + -- stat -> if_stat -> IF cond THEN block + -- {ELSEIF cond THEN block} [ELSE block] END + local line = line + test_then_block() -- IF cond THEN block + while tok == "elseif" do + test_then_block() -- ELSEIF cond THEN block + end + if tok == "else" then + nextt() -- skip ELSE + block() -- 'else' part + end + check_match("end", "if", line) +end + +---------------------------------------------------------------------- +-- parse a return statement +-- * used in stat() +---------------------------------------------------------------------- + +local function return_stat() + -- stat -> return_stat -> RETURN explist + nextt() -- skip RETURN + local c = tok + if block_follow[c] or c == ";" then + -- return no values + else + explist1() -- optional return values + end +end + +---------------------------------------------------------------------- +-- parse a break statement +-- * used in stat() +---------------------------------------------------------------------- + +local function break_stat() + -- stat -> break_stat -> BREAK + local bl = fs.bl + nextt() -- skip BREAK + while bl and not bl.isbreakable do -- find a breakable block + bl = bl.prev + end + if not bl then + syntaxerror("no loop to break") + end +end + +---------------------------------------------------------------------- +-- parse a label statement +-- * this function has been added later, it just parses label statement +-- without any validation! +-- * used in stat() +---------------------------------------------------------------------- + +local function label_stat() + -- stat -> label_stat -> '::' NAME '::' + nextt() -- skip '::' + str_checkname() + checknext("::") +end + +---------------------------------------------------------------------- +-- parse a goto statement +-- * this function has been added later, it just parses goto statement +-- without any validation! +-- * used in stat() +---------------------------------------------------------------------- + +local function goto_stat() + -- stat -> goto_stat -> GOTO NAME + nextt() -- skip GOTO + str_checkname() +end + +---------------------------------------------------------------------- +-- parse a function call with no returns or an assignment statement +-- * the struct with .prev is used for name searching in lparse.c, +-- so it is retained for now; present in assignment() also +-- * used in stat() +---------------------------------------------------------------------- + +local function expr_stat() + local id = tpos - 1 + -- stat -> expr_stat -> func | assignment + local v = { v = {} } + primaryexp(v.v) + if v.v.k == "VCALL" then -- stat -> func + -- call statement uses no results + statinfo[id] = "call" + else -- stat -> assignment + v.prev = nil + assignment(v) + statinfo[id] = "assign" + end +end + +---------------------------------------------------------------------- +-- parse a function statement +-- * used in stat() +---------------------------------------------------------------------- + +local function function_stat() + -- stat -> function_stat -> FUNCTION funcname body + local line = line + nextt() -- skip FUNCTION + local needself = funcname({}) + body(needself, line) +end + +---------------------------------------------------------------------- +-- parse a simple block enclosed by a DO..END pair +-- * used in stat() +---------------------------------------------------------------------- + +local function do_stat() + -- stat -> do_stat -> DO block END + local line = line + nextt() -- skip DO + block() + check_match("end", "do", line) +end + +---------------------------------------------------------------------- +-- parse a statement starting with LOCAL +-- * used in stat() +---------------------------------------------------------------------- + +local function local_stat() + -- stat -> local_stat -> LOCAL FUNCTION localfunc + -- -> LOCAL localstat + nextt() -- skip LOCAL + if testnext("function") then -- local function? + localfunc() + else + localstat() + end +end + +--[[-------------------------------------------------------------------- +-- main functions, top level parsing functions +-- * accessible functions are: init(lexer), parser() +-- * [entry] -> parser() -> chunk() -> stat() +----------------------------------------------------------------------]] + +---------------------------------------------------------------------- +-- initial parsing for statements, calls '_stat' suffixed functions +-- * used in chunk() +---------------------------------------------------------------------- + +local stat_call = { -- lookup for calls in stat() + ["if"] = if_stat, + ["while"] = while_stat, + ["do"] = do_stat, + ["for"] = for_stat, + ["repeat"] = repeat_stat, + ["function"] = function_stat, + ["local"] = local_stat, + ["return"] = return_stat, + ["break"] = break_stat, + ["goto"] = goto_stat, + ["::"] = label_stat, +} + +local function stat() + -- stat -> if_stat while_stat do_stat for_stat repeat_stat + -- function_stat local_stat return_stat break_stat + -- expr_stat + line = ln -- may be needed for error messages + local c = tok + local fn = stat_call[c] + -- handles: if while do for repeat function local return break + if fn then + statinfo[tpos - 1] = c + fn() + -- return must be last statement + if c == "return" then return true end + else + expr_stat() + end + return false +end + +---------------------------------------------------------------------- +-- parse a chunk, which consists of a bunch of statements +-- * used in parser(), body(), block(), repeat_stat() +---------------------------------------------------------------------- + +-- this is a forward-referenced local +function chunk() + -- chunk -> { stat [';'] } + local islast = false + while not islast and not block_follow[tok] do + islast = stat() + testnext(";") + end +end + +---------------------------------------------------------------------- +-- initialization function +---------------------------------------------------------------------- + +local function init(tokorig, seminfoorig, toklnorig) + tpos = 1 -- token position + top_fs = {} -- reset top level function state + ------------------------------------------------------------------ + -- set up grammar-only token tables; impedance-matching... + -- note that constants returned by the lexer is source-level, so + -- for now, fake(!) constant tokens (TK_NUMBER|TK_STRING|TK_LSTRING) + ------------------------------------------------------------------ + local j = 1 + toklist, seminfolist, toklnlist, xreflist = {}, {}, {}, {} + for i = 1, #tokorig do + local tok = tokorig[i] + local yep = true + if tok == "TK_KEYWORD" or tok == "TK_OP" then + tok = seminfoorig[i] + elseif tok == "TK_NAME" then + tok = "" + seminfolist[j] = seminfoorig[i] + elseif tok == "TK_NUMBER" then + tok = "" + seminfolist[j] = 0 -- fake! + elseif tok == "TK_STRING" or tok == "TK_LSTRING" then + tok = "" + seminfolist[j] = "" -- fake! + elseif tok == "TK_EOS" then + tok = "" + else + -- non-grammar tokens; ignore them + yep = false + end + if yep then -- set rest of the information + toklist[j] = tok + toklnlist[j] = toklnorig[i] + xreflist[j] = i + j = j + 1 + end + end--for + ------------------------------------------------------------------ + -- initialize data structures for variable tracking + ------------------------------------------------------------------ + globalinfo, globallookup, localinfo = {}, {}, {} + ilocalinfo, ilocalrefs = {}, {} + statinfo = {} -- experimental +end + +---------------------------------------------------------------------- +-- performs parsing, returns parsed data structure +---------------------------------------------------------------------- + +function M.parse(tokens, seminfo, tokens_ln) + init(tokens, seminfo, tokens_ln) + + open_func() + fs.is_vararg = true -- main func. is always vararg + nextt() -- read first token + chunk() + check("") + close_func() + return { -- return everything + globalinfo = globalinfo, + localinfo = localinfo, + statinfo = statinfo, + toklist = toklist, + seminfolist = seminfolist, + toklnlist = toklnlist, + xreflist = xreflist, + } +end + +return M diff --git a/tools/luasrcdiet/optlex.lua b/tools/luasrcdiet/optlex.lua new file mode 100644 index 0000000..3bbd8e2 --- /dev/null +++ b/tools/luasrcdiet/optlex.lua @@ -0,0 +1,852 @@ +--------- +-- This module does lexer-based optimizations. +-- +-- **Notes:** +-- +-- * TODO: General string delimiter conversion optimizer. +-- * TODO: (numbers) warn if overly significant digit. +---- +local char = string.char +local find = string.find +local match = string.match +local rep = string.rep +local sub = string.sub +local tonumber = tonumber +local tostring = tostring + +local print -- set in optimize() + +local M = {} + +-- error function, can override by setting own function into module +M.error = error + +M.warn = {} -- table for warning flags + +local stoks, sinfos, stoklns -- source lists + +local is_realtoken = { -- significant (grammar) tokens + TK_KEYWORD = true, + TK_NAME = true, + TK_NUMBER = true, + TK_STRING = true, + TK_LSTRING = true, + TK_OP = true, + TK_EOS = true, +} +local is_faketoken = { -- whitespace (non-grammar) tokens + TK_COMMENT = true, + TK_LCOMMENT = true, + TK_EOL = true, + TK_SPACE = true, +} + +local opt_details -- for extra information + +--- Returns true if current token is at the start of a line. +-- +-- It skips over deleted tokens via recursion. +-- +-- @tparam int i +-- @treturn bool +local function atlinestart(i) + local tok = stoks[i - 1] + if i <= 1 or tok == "TK_EOL" then + return true + elseif tok == "" then + return atlinestart(i - 1) + end + return false +end + +--- Returns true if current token is at the end of a line. +-- +-- It skips over deleted tokens via recursion. +-- +-- @tparam int i +-- @treturn bool +local function atlineend(i) + local tok = stoks[i + 1] + if i >= #stoks or tok == "TK_EOL" or tok == "TK_EOS" then + return true + elseif tok == "" then + return atlineend(i + 1) + end + return false +end + +--- Counts comment EOLs inside a long comment. +-- +-- In order to keep line numbering, EOLs need to be reinserted. +-- +-- @tparam string lcomment +-- @treturn int +local function commenteols(lcomment) + local sep = #match(lcomment, "^%-%-%[=*%[") + local z = sub(lcomment, sep + 1, -(sep - 1)) -- remove delims + local i, c = 1, 0 + while true do + local p, _, r, s = find(z, "([\r\n])([\r\n]?)", i) + if not p then break end -- if no matches, done + i = p + 1 + c = c + 1 + if #s > 0 and r ~= s then -- skip CRLF or LFCR + i = i + 1 + end + end + return c +end + +--- Compares two tokens (i, j) and returns the whitespace required. +-- +-- See documentation for a reference table of interactions. +-- +-- Only two grammar/real tokens are being considered: +-- +-- * if `""`, no separation is needed, +-- * if `" "`, then at least one whitespace (or EOL) is required. +-- +-- Note: This doesn't work at the start or the end or for EOS! +-- +-- @tparam int i +-- @tparam int j +-- @treturn string +local function checkpair(i, j) + local t1, t2 = stoks[i], stoks[j] + + if t1 == "TK_STRING" or t1 == "TK_LSTRING" or + t2 == "TK_STRING" or t2 == "TK_LSTRING" then + return "" + + elseif t1 == "TK_OP" or t2 == "TK_OP" then + if (t1 == "TK_OP" and (t2 == "TK_KEYWORD" or t2 == "TK_NAME")) or + (t2 == "TK_OP" and (t1 == "TK_KEYWORD" or t1 == "TK_NAME")) then + return "" + end + if t1 == "TK_OP" and t2 == "TK_OP" then + -- for TK_OP/TK_OP pairs, see notes in technotes.txt + local op, op2 = sinfos[i], sinfos[j] + if (match(op, "^%.%.?$") and match(op2, "^%.")) or + (match(op, "^[~=<>]$") and op2 == "=") or + (op == "[" and (op2 == "[" or op2 == "=")) then + return " " + end + return "" + end + -- "TK_OP" + "TK_NUMBER" case + local op = sinfos[i] + if t2 == "TK_OP" then op = sinfos[j] end + if match(op, "^%.%.?%.?$") then + return " " + end + return "" + + else-- "TK_KEYWORD" | "TK_NAME" | "TK_NUMBER" then + return " " + + end +end + +--- Repack tokens, removing deletions caused by optimization process. +local function repack_tokens() + local dtoks, dinfos, dtoklns = {}, {}, {} + local j = 1 + for i = 1, #stoks do + local tok = stoks[i] + if tok ~= "" then + dtoks[j], dinfos[j], dtoklns[j] = tok, sinfos[i], stoklns[i] + j = j + 1 + end + end + stoks, sinfos, stoklns = dtoks, dinfos, dtoklns +end + +--- Does number optimization. +-- +-- Optimization using string formatting functions is one way of doing this, +-- but here, we consider all cases and handle them separately (possibly an +-- idiotic approach...). +-- +-- Scientific notation being generated is not in canonical form, this may or +-- may not be a bad thing. +-- +-- Note: Intermediate portions need to fit into a normal number range. +-- +-- Optimizations can be divided based on number patterns: +-- +-- * hexadecimal: +-- (1) no need to remove leading zeros, just skip to (2) +-- (2) convert to integer if size equal or smaller +-- * change if equal size -> lose the 'x' to reduce entropy +-- (3) number is then processed as an integer +-- (4) note: does not make 0[xX] consistent +-- * integer: +-- (1) reduce useless fractional part, if present, e.g. 123.000 -> 123. +-- (2) remove leading zeros, e.g. 000123 +-- * float: +-- (1) split into digits dot digits +-- (2) if no integer portion, take as zero (can omit later) +-- (3) handle degenerate .000 case, after which the fractional part +-- must be non-zero (if zero, it's matched as float .0) +-- (4) remove trailing zeros for fractional portion +-- (5) p.q where p > 0 and q > 0 cannot be shortened any more +-- (6) otherwise p == 0 and the form is .q, e.g. .000123 +-- (7) if scientific shorter, convert, e.g. .000123 -> 123e-6 +-- * scientific: +-- (1) split into (digits dot digits) [eE] ([+-] digits) +-- (2) if significand is zero, just use .0 +-- (3) remove leading zeros for significand +-- (4) shift out trailing zeros for significand +-- (5) examine exponent and determine which format is best: +-- number with fraction, or scientific +-- +-- Note: Number with fraction and scientific number is never converted +-- to integer, because Lua 5.3 distinguishes between integers and floats. +-- +-- +-- @tparam int i +local function do_number(i) + local before = sinfos[i] -- 'before' + local z = before -- working representation + local y -- 'after', if better + -------------------------------------------------------------------- + if match(z, "^0[xX]") then -- hexadecimal number + local v = tostring(tonumber(z)) + if #v <= #z then + z = v -- change to integer, AND continue + else + return -- no change; stick to hex + end + end + + if match(z, "^%d+$") then -- integer + if tonumber(z) > 0 then + y = match(z, "^0*([1-9]%d*)$") -- remove leading zeros + else + y = "0" -- basic zero + end + + elseif not match(z, "[eE]") then -- float + local p, q = match(z, "^(%d*)%.(%d*)$") -- split + if p == "" then p = 0 end -- int part zero + if q == "" then q = "0" end -- fraction part zero + if tonumber(q) == 0 and p == 0 then + y = ".0" -- degenerate .000 to .0 + else + -- now, q > 0 holds and p is a number + local zeros_cnt = #match(q, "0*$") -- remove trailing zeros + if zeros_cnt > 0 then + q = sub(q, 1, #q - zeros_cnt) + end + -- if p > 0, nothing else we can do to simplify p.q case + if tonumber(p) > 0 then + y = p.."."..q + else + y = "."..q -- tentative, e.g. .000123 + local v = #match(q, "^0*") -- # leading spaces + local w = #q - v -- # significant digits + local nv = tostring(#q) + -- e.g. compare 123e-6 versus .000123 + if w + 2 + #nv < 1 + #q then + y = sub(q, -w).."e-"..nv + end + end + end + + else -- scientific number + local sig, ex = match(z, "^([^eE]+)[eE]([%+%-]?%d+)$") + ex = tonumber(ex) + -- if got ".", shift out fractional portion of significand + local p, q = match(sig, "^(%d*)%.(%d*)$") + if p then + ex = ex - #q + sig = p..q + end + if tonumber(sig) == 0 then + y = ".0" -- basic float zero + else + local v = #match(sig, "^0*") -- remove leading zeros + sig = sub(sig, v + 1) + v = #match(sig, "0*$") -- shift out trailing zeros + if v > 0 then + sig = sub(sig, 1, #sig - v) + ex = ex + v + end + -- examine exponent and determine which format is best + local nex = tostring(ex) + if ex >= 0 and (ex <= 1 + #nex) then -- a float + y = sig..rep("0", ex).."." + elseif ex < 0 and (ex >= -#sig) then -- fraction, e.g. .123 + v = #sig + ex + y = sub(sig, 1, v).."."..sub(sig, v + 1) + elseif ex < 0 and (#nex >= -ex - #sig) then + -- e.g. compare 1234e-5 versus .01234 + -- gives: #sig + 1 + #nex >= 1 + (-ex - #sig) + #sig + -- -> #nex >= -ex - #sig + v = -ex - #sig + y = "."..rep("0", v)..sig + else -- non-canonical scientific representation + y = sig.."e"..ex + end + end--if sig + end + + if y and y ~= sinfos[i] then + if opt_details then + print(" (line "..stoklns[i]..") "..sinfos[i].." -> "..y) + opt_details = opt_details + 1 + end + sinfos[i] = y + end +end + +--- Does string optimization. +-- +-- Note: It works on well-formed strings only! +-- +-- Optimizations on characters can be summarized as follows: +-- +-- \a\b\f\n\r\t\v -- no change +-- \\ -- no change +-- \"\' -- depends on delim, other can remove \ +-- \[\] -- remove \ +-- \ -- general escape, remove \ (Lua 5.1 only) +-- \ -- normalize the EOL only +-- \ddd -- if \a\b\f\n\r\t\v, change to latter +-- if other < ascii 32, keep ddd but zap leading zeros +-- but cannot have following digits +-- if >= ascii 32, translate it into the literal, then also +-- do escapes for \\,\",\' cases +-- -- no change +-- +-- Switch delimiters if string becomes shorter. +-- +-- @tparam int I +local function do_string(I) + local info = sinfos[I] + local delim = sub(info, 1, 1) -- delimiter used + local ndelim = (delim == "'") and '"' or "'" -- opposite " <-> ' + local z = sub(info, 2, -2) -- actual string + local i = 1 + local c_delim, c_ndelim = 0, 0 -- "/' counts + + while i <= #z do + local c = sub(z, i, i) + + if c == "\\" then -- escaped stuff + local j = i + 1 + local d = sub(z, j, j) + local p = find("abfnrtv\\\n\r\"\'0123456789", d, 1, true) + + if not p then -- \ -- remove \ (Lua 5.1 only) + z = sub(z, 1, i - 1)..sub(z, j) + i = i + 1 + + elseif p <= 8 then -- \a\b\f\n\r\t\v\\ + i = i + 2 -- no change + + elseif p <= 10 then -- \ -- normalize EOL + local eol = sub(z, j, j + 1) + if eol == "\r\n" or eol == "\n\r" then + z = sub(z, 1, i).."\n"..sub(z, j + 2) + elseif p == 10 then -- \r case + z = sub(z, 1, i).."\n"..sub(z, j + 1) + end + i = i + 2 + + elseif p <= 12 then -- \"\' -- remove \ for ndelim + if d == delim then + c_delim = c_delim + 1 + i = i + 2 + else + c_ndelim = c_ndelim + 1 + z = sub(z, 1, i - 1)..sub(z, j) + i = i + 1 + end + + else -- \ddd -- various steps + local s = match(z, "^(%d%d?%d?)", j) + j = i + 1 + #s -- skip to location + local cv = tonumber(s) + local cc = char(cv) + p = find("\a\b\f\n\r\t\v", cc, 1, true) + if p then -- special escapes + s = "\\"..sub("abfnrtv", p, p) + elseif cv < 32 then -- normalized \ddd + if match(sub(z, j, j), "%d") then + -- if a digit follows, \ddd cannot be shortened + s = "\\"..s + else + s = "\\"..cv + end + elseif cc == delim then -- \ + s = "\\"..cc + c_delim = c_delim + 1 + elseif cc == "\\" then -- \\ + s = "\\\\" + else -- literal character + s = cc + if cc == ndelim then + c_ndelim = c_ndelim + 1 + end + end + z = sub(z, 1, i - 1)..s..sub(z, j) + i = i + #s + + end--if p + + else-- c ~= "\\" -- -- no change + i = i + 1 + if c == ndelim then -- count ndelim, for switching delimiters + c_ndelim = c_ndelim + 1 + end + + end--if c + end--while + + -- Switching delimiters, a long-winded derivation: + -- (1) delim takes 2+2*c_delim bytes, ndelim takes c_ndelim bytes + -- (2) delim becomes c_delim bytes, ndelim becomes 2+2*c_ndelim bytes + -- simplifying the condition (1)>(2) --> c_delim > c_ndelim + if c_delim > c_ndelim then + i = 1 + while i <= #z do + local p, _, r = find(z, "([\'\"])", i) + if not p then break end + if r == delim then -- \ -> + z = sub(z, 1, p - 2)..sub(z, p) + i = p + else-- r == ndelim -- -> \ + z = sub(z, 1, p - 1).."\\"..sub(z, p) + i = p + 2 + end + end--while + delim = ndelim -- actually change delimiters + end + + z = delim..z..delim + if z ~= sinfos[I] then + if opt_details then + print(" (line "..stoklns[I]..") "..sinfos[I].." -> "..z) + opt_details = opt_details + 1 + end + sinfos[I] = z + end +end + +--- Does long string optimization. +-- +-- * remove first optional newline +-- * normalize embedded newlines +-- * reduce '=' separators in delimiters if possible +-- +-- Note: warning flagged if trailing whitespace found, not trimmed. +-- +-- @tparam int I +local function do_lstring(I) + local info = sinfos[I] + local delim1 = match(info, "^%[=*%[") -- cut out delimiters + local sep = #delim1 + local delim2 = sub(info, -sep, -1) + local z = sub(info, sep + 1, -(sep + 1)) -- lstring without delims + local y = "" + local i = 1 + + while true do + local p, _, r, s = find(z, "([\r\n])([\r\n]?)", i) + -- deal with a single line + local ln + if not p then + ln = sub(z, i) + elseif p >= i then + ln = sub(z, i, p - 1) + end + if ln ~= "" then + -- flag a warning if there are trailing spaces, won't optimize! + if match(ln, "%s+$") then + M.warn.LSTRING = "trailing whitespace in long string near line "..stoklns[I] + end + y = y..ln + end + if not p then -- done if no more EOLs + break + end + -- deal with line endings, normalize them + i = p + 1 + if p then + if #s > 0 and r ~= s then -- skip CRLF or LFCR + i = i + 1 + end + -- skip first newline, which can be safely deleted + if not(i == 1 and i == p) then + y = y.."\n" + end + end + end--while + + -- handle possible deletion of one or more '=' separators + if sep >= 3 then + local chk, okay = sep - 1 + -- loop to test ending delimiter with less of '=' down to zero + while chk >= 2 do + local delim = "%]"..rep("=", chk - 2).."%]" + if not match(y.."]", delim) then okay = chk end + chk = chk - 1 + end + if okay then -- change delimiters + sep = rep("=", okay - 2) + delim1, delim2 = "["..sep.."[", "]"..sep.."]" + end + end + + sinfos[I] = delim1..y..delim2 +end + +--- Does long comment optimization. +-- +-- * trim trailing whitespace +-- * normalize embedded newlines +-- * reduce '=' separators in delimiters if possible +-- +-- Note: It does not remove first optional newline. +-- +-- @tparam int I +local function do_lcomment(I) + local info = sinfos[I] + local delim1 = match(info, "^%-%-%[=*%[") -- cut out delimiters + local sep = #delim1 + local delim2 = sub(info, -(sep - 2), -1) + local z = sub(info, sep + 1, -(sep - 1)) -- comment without delims + local y = "" + local i = 1 + + while true do + local p, _, r, s = find(z, "([\r\n])([\r\n]?)", i) + -- deal with a single line, extract and check trailing whitespace + local ln + if not p then + ln = sub(z, i) + elseif p >= i then + ln = sub(z, i, p - 1) + end + if ln ~= "" then + -- trim trailing whitespace if non-empty line + local ws = match(ln, "%s*$") + if #ws > 0 then ln = sub(ln, 1, -(ws + 1)) end + y = y..ln + end + if not p then -- done if no more EOLs + break + end + -- deal with line endings, normalize them + i = p + 1 + if p then + if #s > 0 and r ~= s then -- skip CRLF or LFCR + i = i + 1 + end + y = y.."\n" + end + end--while + + -- handle possible deletion of one or more '=' separators + sep = sep - 2 + if sep >= 3 then + local chk, okay = sep - 1 + -- loop to test ending delimiter with less of '=' down to zero + while chk >= 2 do + local delim = "%]"..rep("=", chk - 2).."%]" + if not match(y, delim) then okay = chk end + chk = chk - 1 + end + if okay then -- change delimiters + sep = rep("=", okay - 2) + delim1, delim2 = "--["..sep.."[", "]"..sep.."]" + end + end + + sinfos[I] = delim1..y..delim2 +end + +--- Does short comment optimization. +-- +-- * trim trailing whitespace +-- +-- @tparam int i +local function do_comment(i) + local info = sinfos[i] + local ws = match(info, "%s*$") -- just look from end of string + if #ws > 0 then + info = sub(info, 1, -(ws + 1)) -- trim trailing whitespace + end + sinfos[i] = info +end + +--- Returns true if string found in long comment. +-- +-- This is a feature to keep copyright or license texts. +-- +-- @tparam bool opt_keep +-- @tparam string info +-- @treturn bool +local function keep_lcomment(opt_keep, info) + if not opt_keep then return false end -- option not set + local delim1 = match(info, "^%-%-%[=*%[") -- cut out delimiters + local sep = #delim1 + local z = sub(info, sep + 1, -(sep - 1)) -- comment without delims + if find(z, opt_keep, 1, true) then -- try to match + return true + end +end + +--- The main entry point. +-- +-- * currently, lexer processing has 2 passes +-- * processing is done on a line-oriented basis, which is easier to +-- grok due to the next point... +-- * since there are various options that can be enabled or disabled, +-- processing is a little messy or convoluted +-- +-- @tparam {[string]=bool,...} option +-- @tparam {string,...} toklist +-- @tparam {string,...} semlist +-- @tparam {int,...} toklnlist +-- @treturn {string,...} toklist +-- @treturn {string,...} semlist +-- @treturn {int,...} toklnlist +function M.optimize(option, toklist, semlist, toklnlist) + -- Set option flags. + local opt_comments = option["opt-comments"] + local opt_whitespace = option["opt-whitespace"] + local opt_emptylines = option["opt-emptylines"] + local opt_eols = option["opt-eols"] + local opt_strings = option["opt-strings"] + local opt_numbers = option["opt-numbers"] + local opt_x = option["opt-experimental"] + local opt_keep = option.KEEP + opt_details = option.DETAILS and 0 -- upvalues for details display + print = M.print or _G.print + if opt_eols then -- forced settings, otherwise won't work properly + opt_comments = true + opt_whitespace = true + opt_emptylines = true + elseif opt_x then + opt_whitespace = true + end + + -- Variable initialization. + stoks, sinfos, stoklns -- set source lists + = toklist, semlist, toklnlist + local i = 1 -- token position + local tok, info -- current token + local prev -- position of last grammar token + -- on same line (for TK_SPACE stuff) + + -- Changes a token, info pair. + local function settoken(tok, info, I) --luacheck: ignore 431 + I = I or i + stoks[I] = tok or "" + sinfos[I] = info or "" + end + + -- Experimental optimization for ';' operator. + if opt_x then + while true do + tok, info = stoks[i], sinfos[i] + if tok == "TK_EOS" then -- end of stream/pass + break + elseif tok == "TK_OP" and info == ";" then + -- ';' operator found, since it is entirely optional, set it + -- as a space to let whitespace optimization do the rest + settoken("TK_SPACE", " ") + end + i = i + 1 + end + repack_tokens() + end + + -- Processing loop (PASS 1) + i = 1 + while true do + tok, info = stoks[i], sinfos[i] + + local atstart = atlinestart(i) -- set line begin flag + if atstart then prev = nil end + + if tok == "TK_EOS" then -- end of stream/pass + break + + elseif tok == "TK_KEYWORD" or -- keywords, identifiers, + tok == "TK_NAME" or -- operators + tok == "TK_OP" then + -- TK_KEYWORD and TK_OP can't be optimized without a big + -- optimization framework; it would be more of an optimizing + -- compiler, not a source code compressor + -- TK_NAME that are locals needs parser to analyze/optimize + prev = i + + elseif tok == "TK_NUMBER" then -- numbers + if opt_numbers then + do_number(i) -- optimize + end + prev = i + + elseif tok == "TK_STRING" or -- strings, long strings + tok == "TK_LSTRING" then + if opt_strings then + if tok == "TK_STRING" then + do_string(i) -- optimize + else + do_lstring(i) -- optimize + end + end + prev = i + + elseif tok == "TK_COMMENT" then -- short comments + if opt_comments then + if i == 1 and sub(info, 1, 1) == "#" then + -- keep shbang comment, trim whitespace + do_comment(i) + else + -- safe to delete, as a TK_EOL (or TK_EOS) always follows + settoken() -- remove entirely + end + elseif opt_whitespace then -- trim whitespace only + do_comment(i) + end + + elseif tok == "TK_LCOMMENT" then -- long comments + if keep_lcomment(opt_keep, info) then + -- if --keep, we keep a long comment if is found; + -- this is a feature to keep copyright or license texts + if opt_whitespace then -- trim whitespace only + do_lcomment(i) + end + prev = i + elseif opt_comments then + local eols = commenteols(info) + + -- prepare opt_emptylines case first, if a disposable token + -- follows, current one is safe to dump, else keep a space; + -- it is implied that the operation is safe for '-', because + -- current is a TK_LCOMMENT, and must be separate from a '-' + if is_faketoken[stoks[i + 1]] then + settoken() -- remove entirely + tok = "" + else + settoken("TK_SPACE", " ") + end + + -- if there are embedded EOLs to keep and opt_emptylines is + -- disabled, then switch the token into one or more EOLs + if not opt_emptylines and eols > 0 then + settoken("TK_EOL", rep("\n", eols)) + end + + -- if optimizing whitespaces, force reinterpretation of the + -- token to give a chance for the space to be optimized away + if opt_whitespace and tok ~= "" then + i = i - 1 -- to reinterpret + end + else -- disabled case + if opt_whitespace then -- trim whitespace only + do_lcomment(i) + end + prev = i + end + + elseif tok == "TK_EOL" then -- line endings + if atstart and opt_emptylines then + settoken() -- remove entirely + elseif info == "\r\n" or info == "\n\r" then + -- normalize the rest of the EOLs for CRLF/LFCR only + -- (note that TK_LCOMMENT can change into several EOLs) + settoken("TK_EOL", "\n") + end + + elseif tok == "TK_SPACE" then -- whitespace + if opt_whitespace then + if atstart or atlineend(i) then + -- delete leading and trailing whitespace + settoken() -- remove entirely + else + + -- at this point, since leading whitespace have been removed, + -- there should be a either a real token or a TK_LCOMMENT + -- prior to hitting this whitespace; the TK_LCOMMENT case + -- only happens if opt_comments is disabled; so prev ~= nil + local ptok = stoks[prev] + if ptok == "TK_LCOMMENT" then + -- previous TK_LCOMMENT can abut with anything + settoken() -- remove entirely + else + -- prev must be a grammar token; consecutive TK_SPACE + -- tokens is impossible when optimizing whitespace + local ntok = stoks[i + 1] + if is_faketoken[ntok] then + -- handle special case where a '-' cannot abut with + -- either a short comment or a long comment + if (ntok == "TK_COMMENT" or ntok == "TK_LCOMMENT") and + ptok == "TK_OP" and sinfos[prev] == "-" then + -- keep token + else + settoken() -- remove entirely + end + else--is_realtoken + -- check a pair of grammar tokens, if can abut, then + -- delete space token entirely, otherwise keep one space + local s = checkpair(prev, i + 1) + if s == "" then + settoken() -- remove entirely + else + settoken("TK_SPACE", " ") + end + end + end + + end + end + + else + error("unidentified token encountered") + end + + i = i + 1 + end--while + repack_tokens() + + -- Processing loop (PASS 2) + if opt_eols then + i = 1 + -- Aggressive EOL removal only works with most non-grammar tokens + -- optimized away because it is a rather simple scheme -- basically + -- it just checks 'real' token pairs around EOLs. + if stoks[1] == "TK_COMMENT" then + -- first comment still existing must be shbang, skip whole line + i = 3 + end + while true do + tok = stoks[i] + + if tok == "TK_EOS" then -- end of stream/pass + break + + elseif tok == "TK_EOL" then -- consider each TK_EOL + local t1, t2 = stoks[i - 1], stoks[i + 1] + if is_realtoken[t1] and is_realtoken[t2] then -- sanity check + local s = checkpair(i - 1, i + 1) + if s == "" or t2 == "TK_EOS" then + settoken() -- remove entirely + end + end + end--if tok + + i = i + 1 + end--while + repack_tokens() + end + + if opt_details and opt_details > 0 then print() end -- spacing + return stoks, sinfos, stoklns +end + +return M diff --git a/tools/luasrcdiet/optparser.lua b/tools/luasrcdiet/optparser.lua new file mode 100644 index 0000000..162b881 --- /dev/null +++ b/tools/luasrcdiet/optparser.lua @@ -0,0 +1,644 @@ +--------- +-- This module does parser-based optimizations. +-- +-- **Notes:** +-- +-- * The processing load is quite significant, but since this is an +-- off-line text processor, I believe we can wait a few seconds. +-- * TODO: Might process "local a,a,a" wrongly... need tests! +-- * TODO: Remove position handling if overlapped locals (rem < 0) +-- needs more study, to check behaviour. +-- * TODO: There are probably better ways to do allocation, e.g. by +-- choosing better methods to sort and pick locals... +-- * TODO: We don't need 53*63 two-letter identifiers; we can make +-- do with significantly less depending on how many that are really +-- needed and improve entropy; e.g. 13 needed -> choose 4*4 instead. +---- +local byte = string.byte +local char = string.char +local concat = table.concat +local fmt = string.format +local pairs = pairs +local rep = string.rep +local sort = table.sort +local sub = string.sub + + +local M = {} + +-- Letter frequencies for reducing symbol entropy (fixed version) +-- * Might help a wee bit when the output file is compressed +-- * See Wikipedia: http://en.wikipedia.org/wiki/Letter_frequencies +-- * We use letter frequencies according to a Linotype keyboard, plus +-- the underscore, and both lower case and upper case letters. +-- * The arrangement below (LC, underscore, %d, UC) is arbitrary. +-- * This is certainly not optimal, but is quick-and-dirty and the +-- process has no significant overhead +local LETTERS = "etaoinshrdlucmfwypvbgkqjxz_ETAOINSHRDLUCMFWYPVBGKQJXZ" +local ALPHANUM = "etaoinshrdlucmfwypvbgkqjxz_0123456789ETAOINSHRDLUCMFWYPVBGKQJXZ" + +-- Names or identifiers that must be skipped. +-- (The first two lines are for keywords.) +local SKIP_NAME = {} +for v in ([[ +and break do else elseif end false for function if in +local nil not or repeat return then true until while +self _ENV]]):gmatch("%S+") do + SKIP_NAME[v] = true +end + + +local toklist, seminfolist, -- token lists (lexer output) + tokpar, seminfopar, xrefpar, -- token lists (parser output) + globalinfo, localinfo, -- variable information tables + statinfo, -- statment type table + globaluniq, localuniq, -- unique name tables + var_new, -- index of new variable names + varlist -- list of output variables + +--- Preprocesses information table to get lists of unique names. +-- +-- @tparam {table,...} infotable +-- @treturn table +local function preprocess(infotable) + local uniqtable = {} + for i = 1, #infotable do -- enumerate info table + local obj = infotable[i] + local name = obj.name + + if not uniqtable[name] then -- not found, start an entry + uniqtable[name] = { + decl = 0, token = 0, size = 0, + } + end + + local uniq = uniqtable[name] -- count declarations, tokens, size + uniq.decl = uniq.decl + 1 + local xref = obj.xref + local xcount = #xref + uniq.token = uniq.token + xcount + uniq.size = uniq.size + xcount * #name + + if obj.decl then -- if local table, create first,last pairs + obj.id = i + obj.xcount = xcount + if xcount > 1 then -- if ==1, means local never accessed + obj.first = xref[2] + obj.last = xref[xcount] + end + + else -- if global table, add a back ref + uniq.id = i + end + + end--for + return uniqtable +end + +--- Calculates actual symbol frequencies, in order to reduce entropy. +-- +-- * This may help further reduce the size of compressed sources. +-- * Note that since parsing optimizations is put before lexing +-- optimizations, the frequency table is not exact! +-- * Yes, this will miss --keep block comments too... +-- +-- @tparam table option +local function recalc_for_entropy(option) + -- table of token classes to accept in calculating symbol frequency + local ACCEPT = { + TK_KEYWORD = true, TK_NAME = true, TK_NUMBER = true, + TK_STRING = true, TK_LSTRING = true, + } + if not option["opt-comments"] then + ACCEPT.TK_COMMENT = true + ACCEPT.TK_LCOMMENT = true + end + + -- Create a new table and remove any original locals by filtering. + local filtered = {} + for i = 1, #toklist do + filtered[i] = seminfolist[i] + end + for i = 1, #localinfo do -- enumerate local info table + local obj = localinfo[i] + local xref = obj.xref + for j = 1, obj.xcount do + local p = xref[j] + filtered[p] = "" -- remove locals + end + end + + local freq = {} -- reset symbol frequency table + for i = 0, 255 do freq[i] = 0 end + for i = 1, #toklist do -- gather symbol frequency + local tok, info = toklist[i], filtered[i] + if ACCEPT[tok] then + for j = 1, #info do + local c = byte(info, j) + freq[c] = freq[c] + 1 + end + end--if + end--for + + -- Re-sorts symbols according to actual frequencies. + -- + -- @tparam string symbols + -- @treturn string + local function resort(symbols) + local symlist = {} + for i = 1, #symbols do -- prepare table to sort + local c = byte(symbols, i) + symlist[i] = { c = c, freq = freq[c], } + end + sort(symlist, function(v1, v2) -- sort selected symbols + return v1.freq > v2.freq + end) + local charlist = {} -- reconstitute the string + for i = 1, #symlist do + charlist[i] = char(symlist[i].c) + end + return concat(charlist) + end + + LETTERS = resort(LETTERS) -- change letter arrangement + ALPHANUM = resort(ALPHANUM) +end + +--- Returns a string containing a new local variable name to use, and +-- a flag indicating whether it collides with a global variable. +-- +-- Trapping keywords and other names like 'self' is done elsewhere. +-- +-- @treturn string A new local variable name. +-- @treturn bool Whether the name collides with a global variable. +local function new_var_name() + local var + local cletters, calphanum = #LETTERS, #ALPHANUM + local v = var_new + if v < cletters then -- single char + v = v + 1 + var = sub(LETTERS, v, v) + else -- longer names + local range, sz = cletters, 1 -- calculate # chars fit + repeat + v = v - range + range = range * calphanum + sz = sz + 1 + until range > v + local n = v % cletters -- left side cycles faster + v = (v - n) / cletters -- do first char first + n = n + 1 + var = sub(LETTERS, n, n) + while sz > 1 do + local m = v % calphanum + v = (v - m) / calphanum + m = m + 1 + var = var..sub(ALPHANUM, m, m) + sz = sz - 1 + end + end + var_new = var_new + 1 + return var, globaluniq[var] ~= nil +end + +--- Calculates and prints some statistics. +-- +-- Note: probably better in main source, put here for now. +-- +-- @tparam table globaluniq +-- @tparam table localuniq +-- @tparam table afteruniq +-- @tparam table option +local function stats_summary(globaluniq, localuniq, afteruniq, option) --luacheck: ignore 431 + local print = M.print or print + local opt_details = option.DETAILS + if option.QUIET then return end + + local uniq_g , uniq_li, uniq_lo = 0, 0, 0 + local decl_g, decl_li, decl_lo = 0, 0, 0 + local token_g, token_li, token_lo = 0, 0, 0 + local size_g, size_li, size_lo = 0, 0, 0 + + local function avg(c, l) -- safe average function + if c == 0 then return 0 end + return l / c + end + + -- Collect statistics (Note: globals do not have declarations!) + for _, uniq in pairs(globaluniq) do + uniq_g = uniq_g + 1 + token_g = token_g + uniq.token + size_g = size_g + uniq.size + end + for _, uniq in pairs(localuniq) do + uniq_li = uniq_li + 1 + decl_li = decl_li + uniq.decl + token_li = token_li + uniq.token + size_li = size_li + uniq.size + end + for _, uniq in pairs(afteruniq) do + uniq_lo = uniq_lo + 1 + decl_lo = decl_lo + uniq.decl + token_lo = token_lo + uniq.token + size_lo = size_lo + uniq.size + end + local uniq_ti = uniq_g + uniq_li + local decl_ti = decl_g + decl_li + local token_ti = token_g + token_li + local size_ti = size_g + size_li + local uniq_to = uniq_g + uniq_lo + local decl_to = decl_g + decl_lo + local token_to = token_g + token_lo + local size_to = size_g + size_lo + + -- Detailed stats: global list + if opt_details then + local sorted = {} -- sort table of unique global names by size + for name, uniq in pairs(globaluniq) do + uniq.name = name + sorted[#sorted + 1] = uniq + end + sort(sorted, function(v1, v2) + return v1.size > v2.size + end) + + do + local tabf1, tabf2 = "%8s%8s%10s %s", "%8d%8d%10.2f %s" + local hl = rep("-", 44) + print("*** global variable list (sorted by size) ***\n"..hl) + print(fmt(tabf1, "Token", "Input", "Input", "Global")) + print(fmt(tabf1, "Count", "Bytes", "Average", "Name")) + print(hl) + for i = 1, #sorted do + local uniq = sorted[i] + print(fmt(tabf2, uniq.token, uniq.size, avg(uniq.token, uniq.size), uniq.name)) + end + print(hl) + print(fmt(tabf2, token_g, size_g, avg(token_g, size_g), "TOTAL")) + print(hl.."\n") + end + + -- Detailed stats: local list + do + local tabf1, tabf2 = "%8s%8s%8s%10s%8s%10s %s", "%8d%8d%8d%10.2f%8d%10.2f %s" + local hl = rep("-", 70) + print("*** local variable list (sorted by allocation order) ***\n"..hl) + print(fmt(tabf1, "Decl.", "Token", "Input", "Input", "Output", "Output", "Global")) + print(fmt(tabf1, "Count", "Count", "Bytes", "Average", "Bytes", "Average", "Name")) + print(hl) + for i = 1, #varlist do -- iterate according to order assigned + local name = varlist[i] + local uniq = afteruniq[name] + local old_t, old_s = 0, 0 + for j = 1, #localinfo do -- find corresponding old names and calculate + local obj = localinfo[j] + if obj.name == name then + old_t = old_t + obj.xcount + old_s = old_s + obj.xcount * #obj.oldname + end + end + print(fmt(tabf2, uniq.decl, uniq.token, old_s, avg(old_t, old_s), + uniq.size, avg(uniq.token, uniq.size), name)) + end + print(hl) + print(fmt(tabf2, decl_lo, token_lo, size_li, avg(token_li, size_li), + size_lo, avg(token_lo, size_lo), "TOTAL")) + print(hl.."\n") + end + end--if opt_details + + -- Display output + do + local tabf1, tabf2 = "%-16s%8s%8s%8s%8s%10s", "%-16s%8d%8d%8d%8d%10.2f" + local hl = rep("-", 58) + print("*** local variable optimization summary ***\n"..hl) + print(fmt(tabf1, "Variable", "Unique", "Decl.", "Token", "Size", "Average")) + print(fmt(tabf1, "Types", "Names", "Count", "Count", "Bytes", "Bytes")) + print(hl) + print(fmt(tabf2, "Global", uniq_g, decl_g, token_g, size_g, avg(token_g, size_g))) + print(hl) + print(fmt(tabf2, "Local (in)", uniq_li, decl_li, token_li, size_li, avg(token_li, size_li))) + print(fmt(tabf2, "TOTAL (in)", uniq_ti, decl_ti, token_ti, size_ti, avg(token_ti, size_ti))) + print(hl) + print(fmt(tabf2, "Local (out)", uniq_lo, decl_lo, token_lo, size_lo, avg(token_lo, size_lo))) + print(fmt(tabf2, "TOTAL (out)", uniq_to, decl_to, token_to, size_to, avg(token_to, size_to))) + print(hl.."\n") + end +end + +--- Does experimental optimization for f("string") statements. +-- +-- It's safe to delete parentheses without adding whitespace, as both +-- kinds of strings can abut with anything else. +local function optimize_func1() + + local function is_strcall(j) -- find f("string") pattern + local t1 = tokpar[j + 1] or "" + local t2 = tokpar[j + 2] or "" + local t3 = tokpar[j + 3] or "" + if t1 == "(" and t2 == "" and t3 == ")" then + return true + end + end + + local del_list = {} -- scan for function pattern, + local i = 1 -- tokens to be deleted are marked + while i <= #tokpar do + local id = statinfo[i] + if id == "call" and is_strcall(i) then -- found & mark () + del_list[i + 1] = true -- '(' + del_list[i + 3] = true -- ')' + i = i + 3 + end + i = i + 1 + end + + -- Delete a token and adjust all relevant tables. + -- * Currently invalidates globalinfo and localinfo (not updated), + -- so any other optimization is done after processing locals + -- (of course, we can also lex the source data again...). + -- * Faster one-pass token deletion. + local del_list2 = {} + do + local i, dst, idend = 1, 1, #tokpar + while dst <= idend do -- process parser tables + if del_list[i] then -- found a token to delete? + del_list2[xrefpar[i]] = true + i = i + 1 + end + if i > dst then + if i <= idend then -- shift table items lower + tokpar[dst] = tokpar[i] + seminfopar[dst] = seminfopar[i] + xrefpar[dst] = xrefpar[i] - (i - dst) + statinfo[dst] = statinfo[i] + else -- nil out excess entries + tokpar[dst] = nil + seminfopar[dst] = nil + xrefpar[dst] = nil + statinfo[dst] = nil + end + end + i = i + 1 + dst = dst + 1 + end + end + + do + local i, dst, idend = 1, 1, #toklist + while dst <= idend do -- process lexer tables + if del_list2[i] then -- found a token to delete? + i = i + 1 + end + if i > dst then + if i <= idend then -- shift table items lower + toklist[dst] = toklist[i] + seminfolist[dst] = seminfolist[i] + else -- nil out excess entries + toklist[dst] = nil + seminfolist[dst] = nil + end + end + i = i + 1 + dst = dst + 1 + end + end +end + +--- Does local variable optimization. +-- +-- @tparam {[string]=bool,...} option +local function optimize_locals(option) + var_new = 0 -- reset variable name allocator + varlist = {} + + -- Preprocess global/local tables, handle entropy reduction. + globaluniq = preprocess(globalinfo) + localuniq = preprocess(localinfo) + if option["opt-entropy"] then -- for entropy improvement + recalc_for_entropy(option) + end + + -- Build initial declared object table, then sort according to + -- token count, this might help assign more tokens to more common + -- variable names such as 'e' thus possibly reducing entropy. + -- * An object knows its localinfo index via its 'id' field. + -- * Special handling for "self" and "_ENV" special local (parameter) here. + local object = {} + for i = 1, #localinfo do + object[i] = localinfo[i] + end + sort(object, function(v1, v2) -- sort largest first + return v1.xcount > v2.xcount + end) + + -- The special "self" and "_ENV" function parameters must be preserved. + -- * The allocator below will never use "self", so it is safe to + -- keep those implicit declarations as-is. + local temp, j, used_specials = {}, 1, {} + for i = 1, #object do + local obj = object[i] + if not obj.is_special then + temp[j] = obj + j = j + 1 + else + used_specials[#used_specials + 1] = obj.name + end + end + object = temp + + -- A simple first-come first-served heuristic name allocator, + -- note that this is in no way optimal... + -- * Each object is a local variable declaration plus existence. + -- * The aim is to assign short names to as many tokens as possible, + -- so the following tries to maximize name reuse. + -- * Note that we preserve sort order. + local nobject = #object + while nobject > 0 do + local varname, gcollide + repeat + varname, gcollide = new_var_name() -- collect a variable name + until not SKIP_NAME[varname] -- skip all special names + varlist[#varlist + 1] = varname -- keep a list + local oleft = nobject + + -- If variable name collides with an existing global, the name + -- cannot be used by a local when the name is accessed as a global + -- during which the local is alive (between 'act' to 'rem'), so + -- we drop objects that collides with the corresponding global. + if gcollide then + -- find the xref table of the global + local gref = globalinfo[globaluniq[varname].id].xref + local ngref = #gref + -- enumerate for all current objects; all are valid at this point + for i = 1, nobject do + local obj = object[i] + local act, rem = obj.act, obj.rem -- 'live' range of local + -- if rem < 0, it is a -id to a local that had the same name + -- so follow rem to extend it; does this make sense? + while rem < 0 do + rem = localinfo[-rem].rem + end + local drop + for j = 1, ngref do + local p = gref[j] + if p >= act and p <= rem then drop = true end -- in range? + end + if drop then + obj.skip = true + oleft = oleft - 1 + end + end--for + end--if gcollide + + -- Now the first unassigned local (since it's sorted) will be the + -- one with the most tokens to rename, so we set this one and then + -- eliminate all others that collides, then any locals that left + -- can then reuse the same variable name; this is repeated until + -- all local declaration that can use this name is assigned. + -- + -- The criteria for local-local reuse/collision is: + -- A is the local with a name already assigned + -- B is the unassigned local under consideration + -- => anytime A is accessed, it cannot be when B is 'live' + -- => to speed up things, we have first/last accesses noted + while oleft > 0 do + local i = 1 + while object[i].skip do -- scan for first object + i = i + 1 + end + + -- First object is free for assignment of the variable name + -- [first,last] gives the access range for collision checking. + oleft = oleft - 1 + local obja = object[i] + i = i + 1 + obja.newname = varname + obja.skip = true + obja.done = true + local first, last = obja.first, obja.last + local xref = obja.xref + + -- Then, scan all the rest and drop those colliding. + -- If A was never accessed then it'll never collide with anything + -- otherwise trivial skip if: + -- * B was activated after A's last access (last < act), + -- * B was removed before A's first access (first > rem), + -- if not, see detailed skip below... + if first and oleft > 0 then -- must have at least 1 access + local scanleft = oleft + while scanleft > 0 do + while object[i].skip do -- next valid object + i = i + 1 + end + scanleft = scanleft - 1 + local objb = object[i] + i = i + 1 + local act, rem = objb.act, objb.rem -- live range of B + -- if rem < 0, extend range of rem thru' following local + while rem < 0 do + rem = localinfo[-rem].rem + end + + if not(last < act or first > rem) then -- possible collision + + -- B is activated later than A or at the same statement, + -- this means for no collision, A cannot be accessed when B + -- is alive, since B overrides A (or is a peer). + if act >= obja.act then + for j = 1, obja.xcount do -- ... then check every access + local p = xref[j] + if p >= act and p <= rem then -- A accessed when B live! + oleft = oleft - 1 + objb.skip = true + break + end + end--for + + -- A is activated later than B, this means for no collision, + -- A's access is okay since it overrides B, but B's last + -- access need to be earlier than A's activation time. + else + if objb.last and objb.last >= obja.act then + oleft = oleft - 1 + objb.skip = true + end + end + end + + if oleft == 0 then break end + end + end--if first + + end--while + + -- After assigning all possible locals to one variable name, the + -- unassigned locals/objects have the skip field reset and the table + -- is compacted, to hopefully reduce iteration time. + local temp, j = {}, 1 + for i = 1, nobject do + local obj = object[i] + if not obj.done then + obj.skip = false + temp[j] = obj + j = j + 1 + end + end + object = temp -- new compacted object table + nobject = #object -- objects left to process + + end--while + + -- After assigning all locals with new variable names, we can + -- patch in the new names, and reprocess to get 'after' stats. + for i = 1, #localinfo do -- enumerate all locals + local obj = localinfo[i] + local xref = obj.xref + if obj.newname then -- if got new name, patch it in + for j = 1, obj.xcount do + local p = xref[j] -- xrefs indexes the token list + seminfolist[p] = obj.newname + end + obj.name, obj.oldname -- adjust names + = obj.newname, obj.name + else + obj.oldname = obj.name -- for cases like 'self' + end + end + + -- Deal with statistics output. + for _, name in ipairs(used_specials) do + varlist[#varlist + 1] = name + end + local afteruniq = preprocess(localinfo) + stats_summary(globaluniq, localuniq, afteruniq, option) +end + +--- The main entry point. +-- +-- @tparam table option +-- @tparam {string,...} _toklist +-- @tparam {string,...} _seminfolist +-- @tparam table xinfo +function M.optimize(option, _toklist, _seminfolist, xinfo) + -- set tables + toklist, seminfolist -- from lexer + = _toklist, _seminfolist + tokpar, seminfopar, xrefpar -- from parser + = xinfo.toklist, xinfo.seminfolist, xinfo.xreflist + globalinfo, localinfo, statinfo -- from parser + = xinfo.globalinfo, xinfo.localinfo, xinfo.statinfo + + -- Optimize locals. + if option["opt-locals"] then + optimize_locals(option) + end + + -- Other optimizations. + if option["opt-experimental"] then -- experimental + optimize_func1() + -- WARNING globalinfo and localinfo now invalidated! + end +end + +return M diff --git a/tools/luasrcdiet/plugin/example.lua b/tools/luasrcdiet/plugin/example.lua new file mode 100644 index 0000000..6a04e33 --- /dev/null +++ b/tools/luasrcdiet/plugin/example.lua @@ -0,0 +1,90 @@ +--------- +-- Example of a plugin for LuaSrcDiet. +-- +-- WARNING: highly experimental! interface liable to change +-- +-- **Notes:** +-- +-- * Any function can be omitted and LuaSrcDiet won't call it. +-- * The functions are: +-- (1) init(_option, _srcfl, _destfl) +-- (2) post_load(z) can return z +-- (3) post_lex(toklist, seminfolist, toklnlist) +-- (4) post_parse(globalinfo, localinfo) +-- (5) post_optparse() +-- (6) post_optlex(toklist, seminfolist, toklnlist) +-- * Older tables can be copied and kept in the plugin and used later. +-- * If you modify 'option', remember that LuaSrcDiet might be +-- processing more than one file. +-- * Arrangement of the functions is not final! +-- * TODO: can't process additional options from command line yet +---- + +local M = {} + +local option -- local reference to list of options +local srcfl, destfl -- filenames +local old_quiet + +local function print(...) -- handle quiet option + if option.QUIET then return end + _G.print(...) +end + +--- Initialization. +-- +-- @tparam {[string]=bool,...} _option +-- @tparam string _srcfl Path of the source file. +-- @tparam string _destfl Path of the destination file. +function M.init(_option, _srcfl, _destfl) + option = _option + srcfl, destfl = _srcfl, _destfl + -- plugin can impose its own option starting from here +end + +--- Message display, post-load processing, can return z. +function M.post_load(z) + -- this message will print after the LuaSrcDiet title message + print([[ +Example plugin module for LuaSrcDiet +]]) + print("Example: source file name is '"..srcfl.."'") + print("Example: destination file name is '"..destfl.."'") + print("Example: the size of the source file is "..#z.." bytes") + -- returning z is optional; this allows optional replacement of + -- the source data prior to lexing + return z +end + +--- Post-lexing processing, can work on lexer table output. +function M.post_lex(toklist, seminfolist, toklnlist) --luacheck: ignore + print("Example: the number of lexed elements is "..#toklist) +end + +--- Post-parsing processing, gives globalinfo, localinfo. +function M.post_parse(globalinfo, localinfo) + print("Example: size of globalinfo is "..#globalinfo) + print("Example: size of localinfo is "..#localinfo) + old_quiet = option.QUIET + option.QUIET = true +end + +--- Post-parser optimization processing, can get tables from elsewhere. +function M.post_optparse() + option.QUIET = old_quiet + print("Example: pretend to do post-optparse") +end + +--- Post-lexer optimization processing, can get tables from elsewhere. +function M.post_optlex(toklist, seminfolist, toklnlist) --luacheck: ignore + print("Example: pretend to do post-optlex") + -- restore old settings, other file might need original settings + option.QUIET = old_quiet + -- option.EXIT can be set at the end of any post_* function to stop + -- further processing and exit for the current file being worked on + -- in this case, final stats printout is disabled and the output will + -- not be written to the destination file + option.EXIT = true +end + +return M diff --git a/tools/luasrcdiet/plugin/html.lua b/tools/luasrcdiet/plugin/html.lua new file mode 100644 index 0000000..2305ee7 --- /dev/null +++ b/tools/luasrcdiet/plugin/html.lua @@ -0,0 +1,177 @@ +--------- +-- Turns Lua 5.1 source code into HTML files. +-- +-- WARNING: highly experimental! interface liable to change +-- +-- **Notes:** +-- +-- * This HTML highlighter marks globals brightly so that their usage +-- can be manually optimized. +-- * Either uses a .html extension for output files or it follows the +-- -o option. +-- * The HTML style tries to follow that of the Lua wiki. +---- +local fs = require "luasrcdiet.fs" + +local concat = table.concat +local find = string.find +local fmt = string.format +local sub = string.sub + +local M = {} + +local HTML_EXT = ".html" +local ENTITIES = { + ["&"] = "&", ["<"] = "<", [">"] = ">", + ["'"] = "'", ["\""] = """, +} + +-- simple headers and footers +local HEADER = [[ + + + +%s + + + + +
+]]
+local FOOTER = [[
+
+ + +]] +-- for more, please see wikimain.css from the Lua wiki site +local STYLESHEET = [[ +BODY { + background: white; + color: navy; +} +pre.code { color: black; } +span.comment { color: #00a000; } +span.string { color: #009090; } +span.keyword { color: black; font-weight: bold; } +span.number { color: #993399; } +span.operator { } +span.name { } +span.global { color: #ff0000; font-weight: bold; } +span.local { color: #0000ff; font-weight: bold; } +]] + +local option -- local reference to list of options +local srcfl, destfl -- filenames +local toklist, seminfolist -- token data + +local function print(...) -- handle quiet option + if option.QUIET then return end + _G.print(...) +end + +--- Initialization. +function M.init(_option, _srcfl) + option = _option + srcfl = _srcfl + local extb, _ = find(srcfl, "%.[^%.%\\%/]*$") + local basename = srcfl + if extb and extb > 1 then + basename = sub(srcfl, 1, extb - 1) + end + destfl = basename..HTML_EXT + if option.OUTPUT_FILE then + destfl = option.OUTPUT_FILE + end + if srcfl == destfl then + error("output filename identical to input filename") + end +end + +--- Message display, post-load processing. +function M.post_load() + print([[ +HTML plugin module for LuaSrcDiet +]]) + print("Exporting: "..srcfl.." -> "..destfl.."\n") +end + +--- Post-lexing processing, can work on lexer table output. +function M.post_lex(_toklist, _seminfolist) + toklist, seminfolist = _toklist, _seminfolist +end + +--- Escapes the usual suspects for HTML/XML. +local function do_entities(z) + local i = 1 + while i <= #z do + local c = sub(z, i, i) + local d = ENTITIES[c] + if d then + c = d + z = sub(z, 1, i - 1)..c..sub(z, i + 1) + end + i = i + #c + end--while + return z +end + +--- Post-parsing processing, gives globalinfo, localinfo. +function M.post_parse(globalinfo, localinfo) + local html = {} + local function add(s) -- html helpers + html[#html + 1] = s + end + local function span(class, s) + add(''..s..'') + end + + for i = 1, #globalinfo do -- mark global identifiers as TK_GLOBAL + local obj = globalinfo[i] + local xref = obj.xref + for j = 1, #xref do + local p = xref[j] + toklist[p] = "TK_GLOBAL" + end + end--for + + for i = 1, #localinfo do -- mark local identifiers as TK_LOCAL + local obj = localinfo[i] + local xref = obj.xref + for j = 1, #xref do + local p = xref[j] + toklist[p] = "TK_LOCAL" + end + end--for + + add(fmt(HEADER, -- header and leading stuff + do_entities(srcfl), + STYLESHEET)) + for i = 1, #toklist do -- enumerate token list + local tok, info = toklist[i], seminfolist[i] + if tok == "TK_KEYWORD" then + span("keyword", info) + elseif tok == "TK_STRING" or tok == "TK_LSTRING" then + span("string", do_entities(info)) + elseif tok == "TK_COMMENT" or tok == "TK_LCOMMENT" then + span("comment", do_entities(info)) + elseif tok == "TK_GLOBAL" then + span("global", info) + elseif tok == "TK_LOCAL" then + span("local", info) + elseif tok == "TK_NAME" then + span("name", info) + elseif tok == "TK_NUMBER" then + span("number", info) + elseif tok == "TK_OP" then + span("operator", do_entities(info)) + elseif tok ~= "TK_EOS" then -- TK_EOL, TK_SPACE + add(info) + end + end--for + add(FOOTER) + assert(fs.write_file(destfl, concat(html), "wb")) + option.EXIT = true +end + +return M diff --git a/tools/luasrcdiet/plugin/sloc.lua b/tools/luasrcdiet/plugin/sloc.lua new file mode 100644 index 0000000..50b811f --- /dev/null +++ b/tools/luasrcdiet/plugin/sloc.lua @@ -0,0 +1,89 @@ +--------- +-- Calculates SLOC for Lua 5.1 scripts +-- +-- WARNING: highly experimental! interface liable to change +-- +-- **Notes:** +-- +-- * SLOC's behaviour is based on David Wheeler's SLOCCount. +-- * Empty lines and comment don't count as significant. +-- * Empty lines in long strings are also insignificant. This is +-- debatable. In SLOCCount, this allows counting of invalid multi- +-- line strings for C. But an empty line is still an empty line. +-- * Ignores the --quiet option, print own result line. +---- + +local M = {} + +local option -- local reference to list of options +local srcfl -- source file name + +function M.init(_option, _srcfl) + option = _option + option.QUIET = true + srcfl = _srcfl +end + +--- Splits a block into a table of lines (minus EOLs). +-- +-- @tparam string blk +-- @treturn {string,...} lines +local function split(blk) + local lines = {} + local i, nblk = 1, #blk + while i <= nblk do + local p, q, r, s = blk:find("([\r\n])([\r\n]?)", i) + if not p then + p = nblk + 1 + end + lines[#lines + 1] = blk:sub(i, p - 1) + i = p + 1 + if p < nblk and q > p and r ~= s then -- handle Lua-style CRLF, LFCR + i = i + 1 + end + end + return lines +end + +--- Post-lexing processing, can work on lexer table output. +function M.post_lex(toklist, seminfolist, toklnlist) + local lnow, sloc = 0, 0 + local function chk(ln) -- if a new line, count it as an SLOC + if ln > lnow then -- new line # must be > old line # + sloc = sloc + 1; lnow = ln + end + end + for i = 1, #toklist do -- enumerate over all tokens + local tok, info, ln + = toklist[i], seminfolist[i], toklnlist[i] + + if tok == "TK_KEYWORD" or tok == "TK_NAME" or -- significant + tok == "TK_NUMBER" or tok == "TK_OP" then + chk(ln) + + -- Both TK_STRING and TK_LSTRING may be multi-line, hence, a loop + -- is needed in order to mark off lines one-by-one. Since llex.lua + -- currently returns the line number of the last part of the string, + -- we must subtract in order to get the starting line number. + elseif tok == "TK_STRING" then -- possible multi-line + local t = split(info) + ln = ln - #t + 1 + for _ = 1, #t do + chk(ln); ln = ln + 1 + end + + elseif tok == "TK_LSTRING" then -- possible multi-line + local t = split(info) + ln = ln - #t + 1 + for j = 1, #t do + if t[j] ~= "" then chk(ln) end + ln = ln + 1 + end + -- Other tokens are comments or whitespace and are ignored. + end + end--for + print(srcfl..": "..sloc) -- display result + option.EXIT = true +end + +return M diff --git a/tools/luasrcdiet/utils.lua b/tools/luasrcdiet/utils.lua new file mode 100644 index 0000000..611e9de --- /dev/null +++ b/tools/luasrcdiet/utils.lua @@ -0,0 +1,30 @@ +--------- +-- General utility functions. +-- +-- **Note: This module is not part of public API!** +---- +local ipairs = ipairs +local pairs = pairs + +local M = {} + +--- Returns a new table containing the contents of all the given tables. +-- Tables are iterated using @{pairs}, so this function is intended for tables +-- that represent *associative arrays*. Entries with duplicate keys are +-- overwritten with the values from a later table. +-- +-- @tparam {table,...} ... The tables to merge. +-- @treturn table A new table. +function M.merge (...) + local result = {} + + for _, tab in ipairs{...} do + for key, val in pairs(tab) do + result[key] = val + end + end + + return result +end + +return M diff --git a/websrv_diet.lua b/websrv_diet.lua new file mode 100644 index 0000000..1456b1b --- /dev/null +++ b/websrv_diet.lua @@ -0,0 +1,270 @@ +local o="config.lua" +local n=false +local t=0 +function sendPage(o,e,i) +collectgarbage() +print("Sending "..e.." "..t.."B already; "..node.heap().."B in heap") +o:on("sent",function(a) +if(t==0)then +a:close() +print("Page sent") +collectgarbage() +n=false +else +collectgarbage() +sendPage(a,e,i) +end +end) +if file.open(e,"r")then +local e="" +if(t<=0)then +e=e.."HTTP/1.1 200 OK\r\n" +e=e.."Content-Type: text/html\r\n" +e=e.."Connection: close\r\n" +e=e.."Date: Thu, 29 Dec 2016 20:18:20 GMT\r\n" +e=e.."\r\n\r\n" +end +file.seek("set",t) +local a=file.readline() +while(a~=nil)do +if(a:find("$")~=nil)then +if(i~=nil)then +for e,t in pairs(i) +do +a=string.gsub(a,e,t) +end +end +end +t=t+string.len(a) +e=e..a +if((string.len(e)>=500)or(node.heap()<2000))then +a=nil +o:send(e) +print("Sent part of "..t.."B") +return +else +a=file.readline() +end +end +t=0 +if(string.len(e)>0)then +o:send(e) +print("Sent rest") +end +end +end +function fillDynamicMap() +replaceMap={} +ssid,_=wifi.sta.getconfig() +if(ssid==nil)then return replaceMap end +if(sntpserverhostname==nil)then sntpserverhostname="ptbtime1.ptb.de"end +if(timezoneoffset==nil)then timezoneoffset=1 end +if(color==nil)then color=string.char(0,0,250)end +if(color1==nil)then color1=color end +if(color2==nil)then color2=color end +if(color3==nil)then color3=color end +if(color4==nil)then color4=color end +if(colorBg==nil)then colorBg=string.char(0,0,0)end +local t="#"..string.format("%02x",string.byte(color,2))..string.format("%02x",string.byte(color,1))..string.format("%02x",string.byte(color,3)) +local n="#"..string.format("%02x",string.byte(color1,2))..string.format("%02x",string.byte(color1,1))..string.format("%02x",string.byte(color1,3)) +local e="#"..string.format("%02x",string.byte(color2,2))..string.format("%02x",string.byte(color2,1))..string.format("%02x",string.byte(color2,3)) +local i="#"..string.format("%02x",string.byte(color3,2))..string.format("%02x",string.byte(color3,1))..string.format("%02x",string.byte(color3,3)) +local o="#"..string.format("%02x",string.byte(color4,2))..string.format("%02x",string.byte(color4,1))..string.format("%02x",string.byte(color4,3)) +local a="#"..string.format("%02x",string.byte(colorBg,2))..string.format("%02x",string.byte(colorBg,1))..string.format("%02x",string.byte(colorBg,3)) +replaceMap["$SSID"]=ssid +replaceMap["$SNTPSERVER"]=sntpserverhostname +replaceMap["$TIMEOFFSET"]=timezoneoffset +replaceMap["$THREEQUATER"]=(threequater and"checked"or"") +replaceMap["$ADDITIONAL_LINE"]="" +replaceMap["$HEXCOLORFG"]=t +replaceMap["$HEXCOLOR1"]=n +replaceMap["$HEXCOLOR2"]=e +replaceMap["$HEXCOLOR3"]=i +replaceMap["$HEXCOLOR4"]=o +replaceMap["$HEXCOLORBG"]=a +replaceMap["$INV46"]=((inv46~=nil and inv46=="on")and"checked"or"") +replaceMap["$AUTODIM"]=((dim~=nil and dim=="on")and"checked"or"") +return replaceMap +end +function startWebServer() +srv=net.createServer(net.TCP) +srv:listen(80,function(i) +i:on("receive",function(t,e) +if(n)then +print("HTTP sending... be patient!") +return +end +if(e:find("GET /")~=nil)then +n=true +if(color==nil)then +color=string.char(0,128,0) +end +ws2812.write(string.char(0,0,0):rep(56)..color:rep(2)..string.char(0,0,0):rep(4)..color:rep(2)..string.char(0,0,0):rep(48)) +if(sendPage~=nil)then +print("Sending webpage.html ("..tostring(node.heap()).."B free) ...") +replaceMap=fillDynamicMap() +sendPage(t,"webpage.html",replaceMap) +end +else if(e:find("POST /")~=nil)then +_,postdatastart=e:find("\r\n\r\n") +if postdatastart==nil then postdatastart=1 end +local a=string.sub(e,postdatastart+1) +local e={} +for t,a in string.gmatch(a,"(%w+)=([^&]+)&*")do +e[t]=a +end +if(e.action~=nil and e.action=="Reboot")then +node.restart() +return +end +if((e.ssid~=nil)and(e.sntpserver~=nil)and(e.timezoneoffset~=nil))then +print("New config!") +if(e.password==nil)then +_,password,_,_=wifi.sta.getconfig() +print("Restoring password : "..password) +e.password=password +password=nil +end +file.remove(o..".new") +sec,_=rtctime.get() +file.open(o..".new","w+") +file.write("-- Config\n".."station_cfg={}\nstation_cfg.ssid=\""..e.ssid.."\"\nstation_cfg.pwd=\""..e.password.."\"\nstation_cfg.save=false\nwifi.sta.config(station_cfg)\n") +file.write("sntpserverhostname=\""..e.sntpserver.."\"\n".."timezoneoffset=\""..e.timezoneoffset.."\"\n".."inv46=\""..tostring(e.inv46).."\"\n".."dim=\""..tostring(e.dim).."\"\n") +if(e.fcolor~=nil)then +print("Got fcolor: "..e.fcolor) +local e=string.sub(e.fcolor,4) +local t=tonumber(string.sub(e,1,2),16) +local a=tonumber(string.sub(e,3,4),16) +local e=tonumber(string.sub(e,5,6),16) +file.write("color=string.char("..a..","..t..","..e..")\n") +color=string.char(a,t,e) +end +if(e.colorMin1~=nil)then +local e=string.sub(e.colorMin1,4) +local t=tonumber(string.sub(e,1,2),16) +local a=tonumber(string.sub(e,3,4),16) +local e=tonumber(string.sub(e,5,6),16) +file.write("color1=string.char("..a..","..t..","..e..")\n") +color1=string.char(a,t,e) +end +if(e.colorMin2~=nil)then +local e=string.sub(e.colorMin2,4) +local a=tonumber(string.sub(e,1,2),16) +local t=tonumber(string.sub(e,3,4),16) +local e=tonumber(string.sub(e,5,6),16) +file.write("color2=string.char("..t..","..a..","..e..")\n") +color2=string.char(t,a,e) +end +if(e.colorMin3~=nil)then +local e=string.sub(e.colorMin3,4) +local t=tonumber(string.sub(e,1,2),16) +local a=tonumber(string.sub(e,3,4),16) +local e=tonumber(string.sub(e,5,6),16) +file.write("color3=string.char("..a..","..t..","..e..")\n") +color3=string.char(a,t,e) +end +if(e.colorMin4~=nil)then +local e=string.sub(e.colorMin4,4) +local t=tonumber(string.sub(e,1,2),16) +local a=tonumber(string.sub(e,3,4),16) +local e=tonumber(string.sub(e,5,6),16) +file.write("color4=string.char("..a..","..t..","..e..")\n") +color4=string.char(a,t,e) +end +if(e.bcolor~=nil)then +local e=string.sub(e.bcolor,4) +local t=tonumber(string.sub(e,1,2),16) +local a=tonumber(string.sub(e,3,4),16) +local e=tonumber(string.sub(e,5,6),16) +file.write("colorBg=string.char("..a..","..t..","..e..")\n") +colorBg=string.char(a,t,e) +end +if(getTime~=nil)then +time=getTime(sec,timezoneoffset) +file.write("print(\"Config from "..time.year.."-"..time.month.."-"..time.day.." "..time.hour..":"..time.minute..":"..time.second.."\")\n") +end +if(e.threequater~=nil)then +file.write("threequater=true\n") +threequater=true +else +file.write("threequater=nil\n") +threequater=nil +end +file.close() +collectgarbage() +sec=nil +file.remove(o) +print("Rename config") +if(file.rename(o..".new",o))then +print("Successfully") +local e=tmr.create() +e:register(50,tmr.ALARM_SINGLE,function(e) +replaceMap=fillDynamicMap() +replaceMap["$ADDITIONAL_LINE"]="

New configuration saved

" +print("Send success to client") +sendPage(t,"webpage.html",replaceMap) +e:unregister() +end) +e:start() +else +local e=tmr.create() +e:register(50,tmr.ALARM_SINGLE,function(e) +replaceMap=fillDynamicMap() +replaceMap["$ADDITIONAL_LINE"]="

ERROR

" +sendPage(t,"webpage.html",replaceMap) +e:unregister() +end) +e:start() +end +else +replaceMap=fillDynamicMap() +replaceMap["$ADDITIONAL_LINE"]="

Not all parameters set

" +sendPage(t,"webpage.html",replaceMap) +end +else +print("Hello via telnet") +global_c=t +function s_output(e) +if(global_c~=nil) +then global_c:send(e) +end +end +node.output(s_output,0) +global_c:on("receive",function(t,e) +node.input(e) +end) +global_c:on("disconnection",function(e) +node.output(nil) +global_c=nil +end) +print("Welcome to Word Clock") +end +end +end) +i:on("disconnection",function(e) +print("Goodbye") +node.output(nil) +collectgarbage() +t=0 +end) +end) +end +function startSetupMode() +collectgarbage() +wifi.setmode(wifi.SOFTAP) +cfg={} +cfg.ssid="wordclock" +cfg.pwd="wordclock" +wifi.ap.config(cfg) +local t=string.char(0,128,0) +local e=string.char(0,0,0) +local a=e:rep(6)..t..e:rep(7)..t:rep(3)..e:rep(44)..t:rep(3)..e:rep(50) +ws2812.write(a) +t=nil +e=nil +a=nil +print("Waiting in access point >wordclock< for Clients") +print("Please visit 192.168.4.1") +startWebServer() +collectgarbage() +end From 6699b70f14be262f1b0955ffa33d3b174414a225 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 5 Feb 2021 21:50:02 +0100 Subject: [PATCH 078/204] Handle overflow in bootloop --- init.lua | 4 ++++ tools/initialFlash.sh | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/init.lua b/init.lua index 7a0e284..3ea263e 100644 --- a/init.lua +++ b/init.lua @@ -10,6 +10,9 @@ bootledtimer:register(500, tmr.ALARM_AUTO, function (t) counter1=counter1+1 spaceLeds = math.max(MAXLEDS - (counter1*2), 0) ws2812.write(string.char(128,0,0):rep(counter1) .. string.char(0,0,0):rep(spaceLeds) .. string.char(0,0,64):rep(counter1)) + if ((counter1*2) > 114) then + t:unregister() + end end) bootledtimer:start() @@ -59,6 +62,7 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) (file.open("timecore.lua")) or (file.open("wordclock.lua")) or (file.open("displayword.lua")) or + (file.open("websrv_diet.lua")) or (file.open("mqtt.lua")) or (file.open("ds18b20.lua")) or (file.open("telnet.lua")) diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index 858bfe7..ce22f43 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -26,7 +26,7 @@ if [ $# -eq 0 ]; then fi if [ $# -eq 1 ]; then - FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua telnet.lua wordclock.lua init.lua" + FILES="displayword.lua main.lua timecore.lua webpage.html websrv_diet.lua telnet.lua wordclock.lua init.lua" else FILES=$2 fi From 716b31303f2422b565cfc0e4f53c14f7c73de94b Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 7 Feb 2021 17:45:50 +0100 Subject: [PATCH 079/204] Keep the basename in the diet file --- tools/Readme.md | 2 +- websrv_diet.lua => webserver_diet.lua | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename websrv_diet.lua => webserver_diet.lua (100%) diff --git a/tools/Readme.md b/tools/Readme.md index e9f1bb9..98c23cc 100644 --- a/tools/Readme.md +++ b/tools/Readme.md @@ -10,4 +10,4 @@ LuaSrcDiet reduces the size of Lua 5.1+ source files by aggressively removing al https://raw.githubusercontent.com/jirutka/luasrcdiet/master/bin/luasrcdiet ## Example: - bin/luasrcdiet ../webserver.lua -o ../websrv_diet.lua + bin/luasrcdiet ../webserver.lua -o ../webserver_diet.lua diff --git a/websrv_diet.lua b/webserver_diet.lua similarity index 100% rename from websrv_diet.lua rename to webserver_diet.lua From fbbecd0b6dcb552efcbd9d4958c53233ca2bd626 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 7 Feb 2021 17:51:57 +0100 Subject: [PATCH 080/204] Move the complete logic of the http server into webserver.lua --- init.lua | 8 ++++++-- tools/initialFlash.sh | 2 +- webserver.lua | 42 ++++++++++++++++++++---------------------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/init.lua b/init.lua index 3ea263e..69e5349 100644 --- a/init.lua +++ b/init.lua @@ -45,6 +45,10 @@ function mydofile(mod) dofile( mod .. ".lua") elseif (file.open(mod .. ".lc")) then dofile(mod .. ".lc") + elseif (file.open(mod .. "_diet.lc")) then + dofile(mod .. "_diet.lc") + elseif (file.open(mod .. "_diet.lua")) then + dofile(mod .. "_diet.lua") elseif (file.open(mod)) then dofile(mod) else @@ -62,7 +66,7 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) (file.open("timecore.lua")) or (file.open("wordclock.lua")) or (file.open("displayword.lua")) or - (file.open("websrv_diet.lua")) or + (file.open("webserver.lua")) or (file.open("mqtt.lua")) or (file.open("ds18b20.lua")) or (file.open("telnet.lua")) @@ -83,7 +87,7 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) dofile("config.lua") normalOperation() else - mydofile("websrv_diet") + mydofile("webserver") -- Logic for inital setup startSetupMode() end diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index ce22f43..a4f58df 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -26,7 +26,7 @@ if [ $# -eq 0 ]; then fi if [ $# -eq 1 ]; then - FILES="displayword.lua main.lua timecore.lua webpage.html websrv_diet.lua telnet.lua wordclock.lua init.lua" + FILES="displayword.lua main.lua timecore.lua webpage.html webserver_diet.lua telnet.lua wordclock.lua init.lua" else FILES=$2 fi diff --git a/webserver.lua b/webserver.lua index f8b6f2f..77b87fd 100644 --- a/webserver.lua +++ b/webserver.lua @@ -292,26 +292,24 @@ function startWebServer() end -function startSetupMode() - -- start the webserver module - collectgarbage() - wifi.setmode(wifi.SOFTAP) - cfg={} - cfg.ssid="wordclock" - cfg.pwd="wordclock" - wifi.ap.config(cfg) +-- start the webserver module +collectgarbage() +wifi.setmode(wifi.SOFTAP) +cfg={} +cfg.ssid="wordclock" +cfg.pwd="wordclock" +wifi.ap.config(cfg) - -- Write the buffer to the LEDs - local color=string.char(0,128,0) - local white=string.char(0,0,0) - local ledBuf= white:rep(6) .. color .. white:rep(7) .. color:rep(3) .. white:rep(44) .. color:rep(3) .. white:rep(50) - ws2812.write(ledBuf) - color=nil - white=nil - ledBuf=nil - - print("Waiting in access point >wordclock< for Clients") - print("Please visit 192.168.4.1") - startWebServer() - collectgarbage() -end \ No newline at end of file +-- Write the buffer to the LEDs +local color=string.char(0,128,0) +local white=string.char(0,0,0) +local ledBuf= white:rep(6) .. color .. white:rep(7) .. color:rep(3) .. white:rep(44) .. color:rep(3) .. white:rep(50) +ws2812.write(ledBuf) +color=nil +white=nil +ledBuf=nil + +print("Waiting in access point >wordclock< for Clients") +print("Please visit 192.168.4.1") +startWebServer() +collectgarbage() \ No newline at end of file From 08f310c149fa4b89e3aeb6bc07cedf867b430cef Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 7 Feb 2021 17:57:58 +0100 Subject: [PATCH 081/204] Further RAM optimization --- init.lua | 9 +++++---- webserver_diet.lua | 2 -- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/init.lua b/init.lua index 69e5349..2dc59f0 100644 --- a/init.lua +++ b/init.lua @@ -2,8 +2,8 @@ uart.setup(0, 115200, 8, 0, 1, 1 ) print("Autostart in 5 seconds...") ws2812.init() -- WS2812 LEDs initialized on GPIO2 -MAXLEDS=110 -counter1=0 +local MAXLEDS=110 +local counter1=0 ws2812.write(string.char(0,0,0):rep(114)) local bootledtimer = tmr.create() bootledtimer:register(500, tmr.ALARM_AUTO, function (t) @@ -60,6 +60,8 @@ initTimer = tmr.create() initTimer:register(5000, tmr.ALARM_SINGLE, function (t) bootledtimer:unregister() t:unregister() + initTimer=nil + bootledtimer=nil collectgarbage() if ( (file.open("main.lua")) or @@ -87,9 +89,8 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) dofile("config.lua") normalOperation() else - mydofile("webserver") -- Logic for inital setup - startSetupMode() + mydofile("webserver") end end end) diff --git a/webserver_diet.lua b/webserver_diet.lua index 1456b1b..df80b0a 100644 --- a/webserver_diet.lua +++ b/webserver_diet.lua @@ -249,7 +249,6 @@ t=0 end) end) end -function startSetupMode() collectgarbage() wifi.setmode(wifi.SOFTAP) cfg={} @@ -267,4 +266,3 @@ print("Waiting in access point >wordclock< for Clients") print("Please visit 192.168.4.1") startWebServer() collectgarbage() -end From 404bb708db9e170c50d6fd19010b4aabd640f3de Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 8 Feb 2021 19:18:55 +0100 Subject: [PATCH 082/204] Webserver is running without compiling anything --- init.lua | 66 ++++++++------------------------------------------------ 1 file changed, 9 insertions(+), 57 deletions(-) diff --git a/init.lua b/init.lua index 2dc59f0..ab9be2b 100644 --- a/init.lua +++ b/init.lua @@ -16,37 +16,9 @@ bootledtimer:register(500, tmr.ALARM_AUTO, function (t) end) bootledtimer:start() -local blacklistfile="init.lua config.lua config.lua.new webpage.html" -function recompileAll() - -- 3, discard Local, Upvalue and line-number debug info - node.stripdebug(3) - -- compile all files - l = file.list(); - for k,_ in pairs(l) do - if (string.find(k, ".lc", -3)) then - print ("Skipping " .. k) - elseif (string.find(blacklistfile, k) == nil) then - -- Only look at lua files - if (string.find(k, ".lua") ~= nil) then - print("Compiling and deleting " .. k) - node.compile(k) - -- remove the lua file - file.remove(k) - node.restart() - else - print("No code: " .. k) - end - end - end -end - function mydofile(mod) if (file.open(mod .. ".lua")) then dofile( mod .. ".lua") - elseif (file.open(mod .. ".lc")) then - dofile(mod .. ".lc") - elseif (file.open(mod .. "_diet.lc")) then - dofile(mod .. "_diet.lc") elseif (file.open(mod .. "_diet.lua")) then dofile(mod .. "_diet.lua") elseif (file.open(mod)) then @@ -62,36 +34,16 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) t:unregister() initTimer=nil bootledtimer=nil - collectgarbage() - if ( - (file.open("main.lua")) or - (file.open("timecore.lua")) or - (file.open("wordclock.lua")) or - (file.open("displayword.lua")) or - (file.open("webserver.lua")) or - (file.open("mqtt.lua")) or - (file.open("ds18b20.lua")) or - (file.open("telnet.lua")) - ) then - c = string.char(0,128,0) - w = string.char(0,0,0) - ws2812.write(w:rep(4) .. c .. w:rep(15) .. c .. w:rep(9) .. c .. w:rep(30) .. c .. w:rep(41) .. c ) - recompileAll() - print("Rebooting ...") - -- reboot repairs everything - node.restart() + if ( file.open("config.lua") ) then + --- Normal operation + print("Starting main") + mydofile("main") + wifi.setmode(wifi.STATION) + dofile("config.lua") + normalOperation() else - if ( file.open("config.lua") ) then - --- Normal operation - print("Starting main") - dofile("main.lc") - wifi.setmode(wifi.STATION) - dofile("config.lua") - normalOperation() - else - -- Logic for inital setup - mydofile("webserver") - end + -- Logic for inital setup + mydofile("webserver") end end) initTimer:start() From 55e4c7857265330f7c5db9e73f9c442659c6c0bf Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 8 Feb 2021 19:20:12 +0100 Subject: [PATCH 083/204] Added folder for the compressed files --- webserver_diet.lua => diet/webserver_diet.lua | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename webserver_diet.lua => diet/webserver_diet.lua (100%) diff --git a/webserver_diet.lua b/diet/webserver_diet.lua similarity index 100% rename from webserver_diet.lua rename to diet/webserver_diet.lua From e9325a6c194379dea64ec36cf324d778424bb981 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 8 Feb 2021 19:47:35 +0100 Subject: [PATCH 084/204] Second flash script added, to compress lua on the host, not on the ESP8266 --- diet/webserver_diet.lua | 2 +- tools/initialDietFlash.sh | 82 +++++++++++++++++++++++++++++++++++++++ tools/initialFlash.sh | 13 +------ 3 files changed, 84 insertions(+), 13 deletions(-) create mode 100755 tools/initialDietFlash.sh diff --git a/diet/webserver_diet.lua b/diet/webserver_diet.lua index df80b0a..ba330cf 100644 --- a/diet/webserver_diet.lua +++ b/diet/webserver_diet.lua @@ -265,4 +265,4 @@ a=nil print("Waiting in access point >wordclock< for Clients") print("Please visit 192.168.4.1") startWebServer() -collectgarbage() +collectgarbage() \ No newline at end of file diff --git a/tools/initialDietFlash.sh b/tools/initialDietFlash.sh new file mode 100755 index 0000000..f5ede3e --- /dev/null +++ b/tools/initialDietFlash.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +TOOLDIR=tools/ +LUATOOL=${TOOLDIR}luatool.py + +DIET=bin/luasrcdiet + +DEVICE=$1 +BAUD=115200 + +# check environment +if [ ! -f $LUATOOL ]; then + echo "$LUATOOL not found" + echo "is the command prompt at the same level as the tools folder ?" + exit 1 +fi + +# check the serial connection + +if [ ! -c $DEVICE ]; then + echo "$DEVICE does not exist" + exit 1 +fi + +if [ $# -eq 0 ]; then + echo "" + echo "e.g. usage $0 []" + exit 1 +fi + +if [ $# -eq 1 ]; then + FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua telnet.lua wordclock.lua init.lua" +else + FILES=$2 +fi + +echo "Generate DIET version of the files" +OUTFILES="" +ROOTDIR=$PWD +cd $TOOLDIR +for f in $FILES; do + if [[ "$f" == *.lua ]] && [[ "$f" != init.lua ]]; then + echo "Compress $f ..." + out=$(echo "$f" | sed 's/.lua/_diet.lua/g') + $DIET ../$f -o ../diet/$out + OUTFILES="$OUTFILES diet/$out" + else + OUTFILES="$OUTFILES $f" + fi +done +FILES=$OUTFILES +cd $ROOTDIR + +if [ $# -eq 1 ]; then + # Format filesystem first + echo "Format the complete ESP" + python3 $LUATOOL -p $DEVICE -w -b $BAUD + if [ $? -ne 0 ]; then + echo "STOOOOP" + exit 1 + fi +fi + +echo "Start Flasing ..." +for f in $FILES; do + if [ ! -f $f ]; then + echo "Cannot find $f" + echo "place the terminal into the folder where the lua files are present" + exit 1 + fi + echo "------------- $f ------------" + python3 $LUATOOL -p $DEVICE -f $f -b $BAUD -t $f + if [ $? -ne 0 ]; then + echo "STOOOOP" + exit 1 + fi +done + +echo "Reboot the ESP" +echo "node.restart()" >> $DEVICE + +exit 0 diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh index a4f58df..565cd83 100755 --- a/tools/initialFlash.sh +++ b/tools/initialFlash.sh @@ -26,7 +26,7 @@ if [ $# -eq 0 ]; then fi if [ $# -eq 1 ]; then - FILES="displayword.lua main.lua timecore.lua webpage.html webserver_diet.lua telnet.lua wordclock.lua init.lua" + FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua telnet.lua wordclock.lua init.lua" else FILES=$2 fi @@ -42,17 +42,6 @@ if [ $# -eq 1 ]; then fi fi -#stty -F $DEVICE $BAUD -#echo "Reboot the ESP" -#echo "node.restart()" >> $DEVICE -#sleep 1 -#for i in $(seq 0 5); do -# echo "Stop TMR $i" -# echo "tmr.stop($i)" >> $DEVICE -# sleep 1 -#done - -#echo echo "Start Flasing ..." for f in $FILES; do if [ ! -f $f ]; then From 1f92adc1951c6a31fa15ac39aa2089c62a6dcf61 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 8 Feb 2021 19:51:54 +0100 Subject: [PATCH 085/204] Subfolder does not exist on esp8266 --- tools/initialDietFlash.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/initialDietFlash.sh b/tools/initialDietFlash.sh index f5ede3e..70f8b71 100755 --- a/tools/initialDietFlash.sh +++ b/tools/initialDietFlash.sh @@ -68,8 +68,10 @@ for f in $FILES; do echo "place the terminal into the folder where the lua files are present" exit 1 fi - echo "------------- $f ------------" - python3 $LUATOOL -p $DEVICE -f $f -b $BAUD -t $f + + espFile=$(echo "$f" | sed 's;diet/;;g') + echo "------------- $espFile ------------" + python3 $LUATOOL -p $DEVICE -f $f -b $BAUD -t $espFile if [ $? -ne 0 ]; then echo "STOOOOP" exit 1 From 0b9e96518f07caae254921da1ef946981a9a07a8 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 9 Feb 2021 19:58:59 +0100 Subject: [PATCH 086/204] Clock is booting without mqtt --- main.lua | 3 +- tools/initialDietFlash.sh | 2 +- tools/initialFlash.sh | 63 --------------------------------------- 3 files changed, 3 insertions(+), 65 deletions(-) delete mode 100755 tools/initialFlash.sh diff --git a/main.lua b/main.lua index 63afaf1..6b5a1aa 100644 --- a/main.lua +++ b/main.lua @@ -2,6 +2,7 @@ local looptimer = tmr.create() displayword = {} +rowbgColor= {} function syncTimeFromInternet() if (syncRunning == nil) then @@ -37,7 +38,7 @@ function displayTime() else words.briPercent=nil end - dofile("displayword.lc") + mydofile("displayword") if (displayword ~= nil) then --if lines 4 to 6 are inverted due to hardware-fuckup, unfuck it here local invertRows=false diff --git a/tools/initialDietFlash.sh b/tools/initialDietFlash.sh index 70f8b71..56f8a57 100755 --- a/tools/initialDietFlash.sh +++ b/tools/initialDietFlash.sh @@ -18,7 +18,7 @@ fi # check the serial connection if [ ! -c $DEVICE ]; then - echo "$DEVICE does not exist" + echo "Serial target: $DEVICE does not exist" exit 1 fi diff --git a/tools/initialFlash.sh b/tools/initialFlash.sh deleted file mode 100755 index 565cd83..0000000 --- a/tools/initialFlash.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash - -LUATOOL=./tools/luatool.py - -DEVICE=$1 -BAUD=115200 - -# check environment -if [ ! -f $LUATOOL ]; then - echo "$LUATOOL not found" - echo "is the command prompt at the same level as the tools folder ?" - exit 1 -fi - -# check the serial connection - -if [ ! -c $DEVICE ]; then - echo "$DEVICE does not exist" - exit 1 -fi - -if [ $# -eq 0 ]; then - echo "" - echo "e.g. usage $0 []" - exit 1 -fi - -if [ $# -eq 1 ]; then - FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua telnet.lua wordclock.lua init.lua" -else - FILES=$2 -fi - - -if [ $# -eq 1 ]; then - # Format filesystem first - echo "Format the complete ESP" - python3 $LUATOOL -p $DEVICE -w -b $BAUD - if [ $? -ne 0 ]; then - echo "STOOOOP" - exit 1 - fi -fi - -echo "Start Flasing ..." -for f in $FILES; do - if [ ! -f $f ]; then - echo "Cannot find $f" - echo "place the terminal into the folder where the lua files are present" - exit 1 - fi - echo "------------- $f ------------" - python3 $LUATOOL -p $DEVICE -f $f -b $BAUD -t $f - if [ $? -ne 0 ]; then - echo "STOOOOP" - exit 1 - fi -done - -echo "Reboot the ESP" -echo "node.restart()" >> $DEVICE - -exit 0 From 92276aff2d50e4af9a44310d6de54b1f604eda85 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 9 Feb 2021 20:07:21 +0100 Subject: [PATCH 087/204] Less memory --- main.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/main.lua b/main.lua index 6b5a1aa..2b330c9 100644 --- a/main.lua +++ b/main.lua @@ -135,10 +135,11 @@ function normalOperation() local setupCounter=5 local alive=0 - looptimer:register(5000, tmr.ALARM_AUTO, function (lt) + looptimer:register(1000, tmr.ALARM_AUTO, function (lt) if (setupCounter > 4) then syncTimeFromInternet() setupCounter=setupCounter-1 + alive = 1 elseif (setupCounter > 3) then if (startMqttClient ~= nil) then startMqttClient() @@ -154,18 +155,17 @@ function normalOperation() displayTime() end setupCounter=setupCounter-1 - elseif ((alive % 60) == 0) then - -- sync the time every 5 minutes + elseif ( (alive % 300) == 0) then + -- sync the time every 5 minutes syncTimeFromInternet() - displayTime() - alive = alive + 1 + alive = alive + 1 else displayTime() - alive = alive + 1 + alive = alive + 1 end collectgarbage() - -- Feed the system watchdog. - tmr.wdclr() + -- Feed the system watchdog. + tmr.wdclr() end) looptimer:start() From 0857eb0e3c05684937ba484da7684f52bffc3fba Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 9 Feb 2021 20:18:24 +0100 Subject: [PATCH 088/204] tweaked timings --- main.lua | 6 +++--- mqtt.lua | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/main.lua b/main.lua index 2b330c9..1f04a16 100644 --- a/main.lua +++ b/main.lua @@ -10,7 +10,6 @@ function syncTimeFromInternet() sntp.sync(sntpserverhostname, function(sec,usec,server) print('sync', sec, usec, server) - displayTime() syncRunning=nil end, function() @@ -23,6 +22,7 @@ end briPercent = 50 function displayTime() + collectgarbage() local sec, usec = rtctime.get() -- Handle lazy programmer: if (timezoneoffset == nil) then @@ -135,7 +135,7 @@ function normalOperation() local setupCounter=5 local alive=0 - looptimer:register(1000, tmr.ALARM_AUTO, function (lt) + looptimer:register(2500, tmr.ALARM_AUTO, function (lt) if (setupCounter > 4) then syncTimeFromInternet() setupCounter=setupCounter-1 @@ -155,7 +155,7 @@ function normalOperation() displayTime() end setupCounter=setupCounter-1 - elseif ( (alive % 300) == 0) then + elseif ( (alive % 120) == 0) then -- sync the time every 5 minutes syncTimeFromInternet() alive = alive + 1 diff --git a/mqtt.lua b/mqtt.lua index 9784fe2..6cbadea 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -158,7 +158,6 @@ function startMqttClient() local temp = nil if (t ~= nil) then temp=readTemp() - print(tostring(temp) .. "°C") end if (oldBrightness ~= briPercent) then m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) From 84f5611a67466ab90345a8217473c81f9ddfa0b0 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 9 Feb 2021 20:22:05 +0100 Subject: [PATCH 089/204] mqtt cleanup --- mqtt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 6cbadea..7346850 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -3,7 +3,6 @@ m=nil mqttConnected = false -- Temp: t=nil -rowbgColor= {} function handleSingleCommand(client, topic, data) if (data == "ON") then @@ -158,6 +157,7 @@ function startMqttClient() local temp = nil if (t ~= nil) then temp=readTemp() + print(tostring(temp) .. "°C") end if (oldBrightness ~= briPercent) then m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) From 7941501cc531aeaec545e1bc3cbc50f5dc37e4e9 Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 10 Feb 2021 19:45:08 +0100 Subject: [PATCH 090/204] Shrinked wordclock struct --- displayword.lua | 144 +++++++++++++++++++++++++----------------------- wordclock.lua | 92 ++++++++++++++++--------------- 2 files changed, 123 insertions(+), 113 deletions(-) diff --git a/displayword.lua b/displayword.lua index b860ce4..ffdeece 100644 --- a/displayword.lua +++ b/displayword.lua @@ -7,13 +7,13 @@ local updateColor = function (data) if (div < 1) then return data.colorFg elseif (div < 2) then - return data.colorMin1 + return data.colorM1 elseif (div < 3) then - return data.colorMin2 + return data.colorM2 elseif (div < 4) then - return data.colorMin3 + return data.colorM3 elseif (div < 5) then - return data.colorMin4 + return data.colorM4 else return data.colorFg end @@ -53,8 +53,18 @@ end local data={} +-- @fn generateLEDs -- Module displaying of the words -local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, colorMin3, colorMin4, invertRows, amountOfChars) +-- @param words +-- @param colorBg background color +-- @param colorFg foreground color +-- @param colorM1 foreground color if one minute after a displayable time is present +-- @param colorM2 foreground color if two minutes after a displayable time is present +-- @param colorM3 foreground color if three minutes after a displayable time is present +-- @param colorM4 foreground color if four minutes after a displayable time is present +-- @param invertRows wheather line 4,5 and 6 shall be inverted or not +-- @param amountOfChars Amount of characters to be displayed +local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3, colorM4, invertRows, amountOfChars) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil @@ -64,13 +74,13 @@ local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, col end local minutes=1 - if (words.min1 == 1) then + if (words.m1 == 1) then minutes = minutes + 1 - elseif (words.min2 == 1) then + elseif (words.m2 == 1) then minutes = minutes + 2 - elseif (words.min3 == 1) then + elseif (words.m3 == 1) then minutes = minutes + 3 - elseif (words.min4 == 1) then + elseif (words.m4 == 1) then minutes = minutes + 4 end -- always set a foreground value @@ -89,17 +99,17 @@ local generateLEDs = function(words, colorBg, colorFg, colorMin1, colorMin2, col words.briPercent = tonumber( ((words.briPercent * 4) + per) / 5) print("Minutes : " .. tostring(minutes) .. " bright: " .. tostring(words.briPercent) .. "% current: " .. tostring(per) .. "%") data.colorFg = string.char(string.byte(colorFg,1) * briPercent / 100, string.byte(colorFg,2) * briPercent / 100, string.byte(colorFg,3) * briPercent / 100) - data.colorMin1 = string.char(string.byte(colorMin1,1) * briPercent / 100, string.byte(colorMin1,2) * briPercent / 100, string.byte(colorMin1,3) * briPercent / 100) - data.colorMin2 = string.char(string.byte(colorMin2,1) * briPercent / 100, string.byte(colorMin2,2) * briPercent / 100, string.byte(colorMin2,3) * briPercent / 100) - data.colorMin3 = string.char(string.byte(colorMin3,1) * briPercent / 100, string.byte(colorMin3,2) * briPercent / 100, string.byte(colorMin3,3) * briPercent / 100) - data.colorMin4 = string.char(string.byte(colorMin4,1) * briPercent / 100, string.byte(colorMin4,2) * briPercent / 100, string.byte(colorMin4,3) * briPercent / 100) + data.colorM1 = string.char(string.byte(colorM1,1) * briPercent / 100, string.byte(colorM1,2) * briPercent / 100, string.byte(colorM1,3) * briPercent / 100) + data.colorM2 = string.char(string.byte(colorM2,1) * briPercent / 100, string.byte(colorM2,2) * briPercent / 100, string.byte(colorM2,3) * briPercent / 100) + data.colorM3 = string.char(string.byte(colorM3,1) * briPercent / 100, string.byte(colorM3,2) * briPercent / 100, string.byte(colorM3,3) * briPercent / 100) + data.colorM4 = string.char(string.byte(colorM4,1) * briPercent / 100, string.byte(colorM4,2) * briPercent / 100, string.byte(colorM4,3) * briPercent / 100) else -- devide by five (Minute 0, Minute 1 to Minute 4 takes the last chars) data.colorFg=colorFg - data.colorMin1=colorMin1 - data.colorMin2=colorMin2 - data.colorMin3=colorMin3 - data.colorMin4=colorMin4 + data.colorM1=colorM1 + data.colorM2=colorM2 + data.colorM3=colorM3 + data.colorM4=colorM4 end data.drawnCharacters=0 local charsPerLine=11 @@ -135,7 +145,7 @@ buf=buf .. space:rep(1) end -- L fill character buf=buf .. space:rep(1) -if (words.fiveMin== 1) then +if (words.m5== 1) then buf= buf .. drawLEDs(data,4) -- FUENF else buf= buf .. space:rep(4) @@ -146,12 +156,12 @@ if (words.fiveMin== 1) then else space = colorBg end - if (words.tenMin == 1) then + if (words.m10 == 1) then line= drawLEDs(data,4) -- ZEHN else line= space:rep(4) end - if (words.twenty == 1) then + if (words.m20 == 1) then line= line .. drawLEDs(data,7) -- ZWANZIG else line= line .. space:rep(7) @@ -167,9 +177,9 @@ if (words.fiveMin== 1) then else space = colorBg end - if (words.threequater == 1) then - line= drawLEDs(data,11) -- Dreiviertel - elseif (words.quater == 1) then + if (words.h3q == 1) then + line= drawLEDs(data,11) -- DREIVIERTEL + elseif (words.hq == 1) then line= space:rep(4) line= line .. drawLEDs(data,7) -- VIERTEL else @@ -183,13 +193,13 @@ if (words.fiveMin== 1) then else space = colorBg end - if (words.after == 1) then + if (words.ha == 1) then line= space:rep(2) -- TG line= line .. drawLEDs(data,4) -- NACH else line= space:rep(6) end - if (words.before == 1) then + if (words.hb == 1) then line= line .. drawLEDs(data,3) -- VOR line= line .. space:rep(2) else @@ -214,7 +224,7 @@ if (words.fiveMin== 1) then else line= space:rep(5) end - if (words.twelve == 1) then + if (words.h12 == 1) then line= line .. drawLEDs(data,5) -- ZWOELF line= line .. space:rep(1) -- P else @@ -233,18 +243,18 @@ if (words.fiveMin== 1) then else space = colorBg end - if (words.seven == 1) then + if (words.h7 == 1) then line= space:rep(5) line= line .. drawLEDs(data,6) -- SIEBEN - elseif (words.oneLong == 1) then + elseif (words.h1l == 1) then line= space:rep(2) line= line .. drawLEDs(data,4) -- EINS line= line .. space:rep(5) - elseif (words.one == 1) then + elseif (words.h1 == 1) then line= space:rep(2) line= line .. drawLEDs(data,3) -- EIN line= line .. space:rep(6) - elseif (words.two == 1) then + elseif (words.h2 == 1) then line= drawLEDs(data,4) -- ZWEI line= line .. space:rep(7) else @@ -263,11 +273,11 @@ if (words.fiveMin== 1) then else space = colorBg end - if (words.three == 1) then + if (words.h3 == 1) then line= space:rep(1) line= line .. drawLEDs(data,4) -- DREI line= line .. space:rep(6) - elseif (words.five == 1) then + elseif (words.h5 == 1) then line= space:rep(7) line= line .. drawLEDs(data,4) -- FUENF else @@ -280,15 +290,15 @@ if (words.fiveMin== 1) then else space = colorBg end - if (words.four == 1) then + if (words.h4 == 1) then line= space:rep(7) line= line .. drawLEDs(data,4) -- VIER - elseif (words.nine == 1) then + elseif (words.h9 == 1) then line= space:rep(3) line= line .. drawLEDs(data,4) -- NEUN line= line .. space:rep(4) - elseif (words.eleven == 1) then - line= drawLEDs(data,3) -- ELEVEN + elseif (words.h11 == 1) then + line= drawLEDs(data,3) -- ELF line= line .. space:rep(8) else line= space:rep(11) @@ -303,11 +313,11 @@ if (words.fiveMin== 1) then else space = colorBg end - if (words.eight == 1) then + if (words.h8 == 1) then line= space:rep(1) line= line .. drawLEDs(data,4) -- ACHT line= line .. space:rep(6) - elseif (words.ten == 1) then + elseif (words.h10 == 1) then line= space:rep(5) line= line .. drawLEDs(data,4) -- ZEHN line= line .. space:rep(2) @@ -321,14 +331,14 @@ if (words.fiveMin== 1) then else space = colorBg end - if (words.six == 1) then + if (words.h6 == 1) then line= space:rep(1) line= line .. drawLEDs(data,5) -- SECHS line= line .. space:rep(2) else line= space:rep(8) end - if (words.clock == 1) then + if (words.cl == 1) then line= line .. drawLEDs(data,3) -- UHR else line= line .. space:rep(3) @@ -338,22 +348,22 @@ if (words.fiveMin== 1) then buf = buf .. line:sub((11-i)*3-2,(11-i)*3) end ------ Minutes ----------- - if (words.min1 == 1) then + if (words.m1 == 1) then buf= buf .. colorFg else buf= buf .. space:rep(1) end - if (words.min2 == 1) then + if (words.m2 == 1) then buf= buf .. colorFg else buf= buf .. space:rep(1) end - if (words.min3 == 1) then + if (words.m3 == 1) then buf= buf .. colorFg else buf= buf .. space:rep(1) end - if (words.min4 == 1) then + if (words.m4 == 1) then buf= buf .. colorFg else buf= buf .. space:rep(1) @@ -371,53 +381,51 @@ local countChars = function(words) characters = characters + 2 elseif (key == "is") then characters = characters + 3 - elseif (key == "fiveMin") then + elseif (key == "m5") then characters = characters + 4 - elseif (key == "tenMin") then + elseif (key == "m10") then characters = characters + 4 - elseif (key == "after") then + elseif (key == "ha") then characters = characters + 4 - elseif (key == "before") then + elseif (key == "hb") then characters = characters + 3 - elseif (key == "threeHour") then + elseif (key == "h3") then characters = characters + 4 - elseif (key == "quater") then + elseif (key == "hq") then characters = characters + 7 - elseif (key == "threequater") then + elseif (key == "h3q") then characters = characters + 11 elseif (key == "half") then characters = characters + 4 - elseif (key == "one") then + elseif (key == "h1") then characters = characters + 3 - elseif (key == "oneLong") then + elseif (key == "h1l") then characters = characters + 4 - elseif (key == "two") then + elseif (key == "h2") then characters = characters + 4 - elseif (key == "three") then + elseif (key == "h3") then characters = characters + 4 - elseif (key == "four") then + elseif (key == "h4") then characters = characters + 4 - elseif (key == "five") then + elseif (key == "h5") then characters = characters + 4 - elseif (key == "six") then + elseif (key == "h6") then characters = characters + 4 - elseif (key == "seven") then + elseif (key == "h7") then characters = characters + 6 - elseif (key == "eight") then + elseif (key == "h8") then characters = characters + 4 - elseif (key == "nine") then + elseif (key == "h9") then characters = characters + 4 - elseif (key == "ten") then + elseif (key == "h10") then characters = characters + 4 - elseif (key == "eleven") then + elseif (key == "h11") then characters = characters + 3 - elseif (key == "twelve") then + elseif (key == "h12") then characters = characters + 5 - elseif (key == "twenty") then + elseif (key == "m20") then characters = characters + 7 - elseif (key == "clock") then - characters = characters + 3 - elseif (key == "sr_nc") then + elseif (key == "cl") then characters = characters + 3 end end diff --git a/wordclock.lua b/wordclock.lua index 0228c51..b71c206 100755 --- a/wordclock.lua +++ b/wordclock.lua @@ -1,5 +1,5 @@ -- Revese engeeniered code of display_wc_ger.c by Vlad Tepesch --- See https://www.mikrocontroller.net/articles/Word_Clock_Variante_1#Download +-- See https://www.mikrocontroller.net/articles/Word_cl_Variante_1#Download -- @fn display_timestat -- Return the leds to use the granuality is 5 minutes @@ -12,10 +12,12 @@ function display_timestat(hours, minutes, longmode) end -- generate an empty return type - local ret = { it=0, is=0, fiveMin=0, tenMin=0, after=0, before=0, threeHour=0, quater=0, threequater=0, half=0, s=0, - one=0, oneLong=0, two=0, three=0, four=0, five=0, six=0, seven=0, eight=0, nine=0, ten=0, eleven=0, twelve=0, - twenty=0, - clock=0, sr_nc=0, min1=0, min2=0, min3=0, min4=0 } + -- Values: it, is, 5 minutes, 10 minutes, afer, before, three hour, quarter, dreiviertel, half, s + -- hours: one, one Long, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve + -- Special ones: twenty, clock, minute 1 flag, minute 2 flag, minute 3 flag, minute 4 flag + local ret = { it=0, is=0, m5=0, m10=0, ha=0, hb=0, h3=0, hq=0, h3q=0, half=0, s=0, + h1=0, h1l=0, h2=0, h3=0, h4=0, h5=0, h6=0, h7=0, h8=0, h9=0, h10=0, h11=0, h12=0, + m20=0, cl=0, m1=0, m2=0, m3=0, m4=0 } -- return black screen if there is no real time given if (hours == nil or minutes == nil) then @@ -38,61 +40,61 @@ function display_timestat(hours, minutes, longmode) -- Handle minutes if (minutes > 0) then if (minutes==1) then - ret.fiveMin=1 - ret.after=1 + ret.m5=1 + ret.ha=1 elseif (minutes==2) then - ret.tenMin=1 - ret.after=1 + ret.m10=1 + ret.ha=1 elseif (minutes==3) then - ret.quater=1 - ret.after=1 + ret.hq=1 + ret.ha=1 elseif (minutes==4) then - ret.twenty=1 - ret.after=1 + ret.m20=1 + ret.ha=1 elseif (minutes==5) then - ret.fiveMin=1 + ret.m5=1 ret.half=1 - ret.before=1 + ret.hb=1 elseif (minutes==6) then ret.half=1 elseif (minutes==7) then - ret.fiveMin=1 + ret.m5=1 ret.half=1 - ret.after=1 + ret.ha=1 elseif (minutes==8) then - ret.twenty=1 - ret.before=1 + ret.m20=1 + ret.hb=1 elseif (minutes==9) then -- Hande if three quater or quater before is displayed if ((threequater ~= nil) and (threequater==true or threequater=="on")) then - ret.threequater=1 + ret.h3q=1 else - ret.quater = 1 - ret.before = 1 + ret.hq = 1 + ret.hb = 1 end elseif (minutes==10) then - ret.tenMin=1 - ret.before=1 + ret.m10=1 + ret.hb=1 elseif (minutes==11) then - ret.fiveMin=1 - ret.before=1 + ret.m5=1 + ret.hb=1 end if (minutes > 4) then hours=hours+1 end else - ret.clock=1 + ret.cl=1 end - -- Display the minutes as as extra gimmic on min1 to min 4 to display the cut number + -- Display the minutes as as extra gimmic on m1 to min 4 to display the cut number if (minutesLeds==1) then - ret.min1=1 + ret.m1=1 elseif (minutesLeds==2) then - ret.min2=1 + ret.m2=1 elseif (minutesLeds==3) then - ret.min3=1 + ret.m3=1 elseif (minutesLeds==4) then - ret.min4=1 + ret.m4=1 end -- handle hours @@ -106,32 +108,32 @@ function display_timestat(hours, minutes, longmode) if (hours == 1) then if ((ret.it == 1) and (ret.half == 0) ) then - ret.one=1 + ret.h1=1 else - ret.oneLong=1 + ret.h1l=1 end elseif (hours == 2) then - ret.two=1 + ret.h2=1 elseif (hours == 3) then - ret.three=1 + ret.h3=1 elseif (hours == 4) then - ret.four=1 + ret.h4=1 elseif (hours == 5) then - ret.five=1 + ret.h5=1 elseif (hours == 6) then - ret.six=1 + ret.h6=1 elseif (hours == 7) then - ret.seven=1 + ret.h7=1 elseif (hours == 8) then - ret.eight=1 + ret.h8=1 elseif (hours == 9) then - ret.nine=1 + ret.h9=1 elseif (hours == 10) then - ret.ten=1 + ret.h10=1 elseif (hours == 11) then - ret.eleven=1 + ret.h11=1 elseif (hours == 12) then - ret.twelve=1 + ret.h12=1 end collectgarbage() return ret From 40447dd521533e2d984bb409e5a7fbd296e653ea Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 10 Feb 2021 19:45:28 +0100 Subject: [PATCH 091/204] Used more local variables --- main.lua | 2 +- mqtt.lua | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/main.lua b/main.lua index 1f04a16..7bb98a4 100644 --- a/main.lua +++ b/main.lua @@ -84,7 +84,7 @@ function normalOperation() end print("Fg Color: " .. tostring(string.byte(color,1)) .. "x" .. tostring(string.byte(color,2)) .. "x" .. tostring(string.byte(color,3)) ) - connect_counter=0 + local connect_counter=0 -- Wait to be connect to the WiFi access point. local wifitimer = tmr.create() wifitimer:register(5000, tmr.ALARM_SINGLE, function (t) diff --git a/mqtt.lua b/mqtt.lua index 7346850..ae5efc4 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -1,8 +1,8 @@ -- Global variable -m=nil -mqttConnected = false +local m=nil +local mqttConnected = false -- Temp: -t=nil +local t=nil function handleSingleCommand(client, topic, data) if (data == "ON") then @@ -157,7 +157,6 @@ function startMqttClient() local temp = nil if (t ~= nil) then temp=readTemp() - print(tostring(temp) .. "°C") end if (oldBrightness ~= briPercent) then m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) From e4b22a9921cd82869dc51bff6fd7f2a7d34e3c16 Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 10 Feb 2021 19:55:07 +0100 Subject: [PATCH 092/204] Removed debug code in main; shrinked struct name in displayword --- displayword.lua | 24 +++++++++++++++--------- main.lua | 23 ++++++----------------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/displayword.lua b/displayword.lua index ffdeece..56cbbaf 100644 --- a/displayword.lua +++ b/displayword.lua @@ -1,9 +1,15 @@ -- Module filling a buffer, sent to the LEDs local M do + +-- @fn generateLEDs +-- Module displaying of the words +-- @param data struct with the following paramter: +-- aoC amount of characters to be used +-- dC drawn characters local updateColor = function (data) - if (data.amountOfChars > 0) then - local div = tonumber(data.drawnCharacters/data.amountOfChars) + if (data.aoC > 0) then + local div = tonumber(data.dC/data.aoC) if (div < 1) then return data.colorFg elseif (div < 2) then @@ -33,7 +39,7 @@ local drawLEDs = function(data, numberNewChars) else tmpBuf=tmpBuf .. updateColor(data) end - data.drawnCharacters=data.drawnCharacters+1 + data.dC=data.dC+1 end return tmpBuf end @@ -63,8 +69,8 @@ local data={} -- @param colorM3 foreground color if three minutes after a displayable time is present -- @param colorM4 foreground color if four minutes after a displayable time is present -- @param invertRows wheather line 4,5 and 6 shall be inverted or not --- @param amountOfChars Amount of characters to be displayed -local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3, colorM4, invertRows, amountOfChars) +-- @param aoC Amount of characters to be displayed +local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3, colorM4, invertRows, aoC) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil @@ -88,10 +94,10 @@ local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3 colorFg = string.char(255,255,255) end - if (amountOfChars ~= nil) then - data.amountOfChars = amountOfChars/minutes + if (aoC ~= nil) then + data.aoC = aoC/minutes else - data.amountOfChars = 0 + data.aoC = 0 end if ( (adc ~= nil) and (words.briPercent ~= nil) ) then @@ -111,7 +117,7 @@ local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3 data.colorM3=colorM3 data.colorM4=colorM4 end - data.drawnCharacters=0 + data.dC=0 local charsPerLine=11 -- Space / background has no color by default diff --git a/main.lua b/main.lua index 7bb98a4..6267604 100644 --- a/main.lua +++ b/main.lua @@ -51,24 +51,13 @@ function displayTime() displayword = nil if (ledBuf ~= nil) then ws2812.write(ledBuf) - else - if ((colorBg ~= nil) and (color ~= nil)) then - ws2812.write(colorBg:rep(107) .. color:rep(3)) - else - local space=string.char(0,0,0) - -- set FG to fix value: - colorFg = string.char(255,0,0) - ws2812.write(space:rep(107) .. colorFg:rep(3)) - end - end - -- Used for debugging - if (clockdebug ~= nil) then - for key,value in pairs(words) do - if (value > 0) then - print(key,value) - end - end + else + -- set FG to fix value: RED + local space=string.char(0,0,0) + local color = string.char(255,0,0) + ws2812.write(space:rep(107) .. color:rep(3)) -- UHR end + -- cleanup briPercent=words.briPercent words=nil From 712ddaafeb05eaab97a93ed0c21366ab0c5c3f3a Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 10 Feb 2021 20:04:22 +0100 Subject: [PATCH 093/204] Renamed briPercent to briPer --- displayword.lua | 16 ++++++++-------- main.lua | 12 ++++++------ mqtt.lua | 16 ++++++++-------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/displayword.lua b/displayword.lua index 56cbbaf..bf5303f 100644 --- a/displayword.lua +++ b/displayword.lua @@ -100,15 +100,15 @@ local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3 data.aoC = 0 end - if ( (adc ~= nil) and (words.briPercent ~= nil) ) then + if ( (adc ~= nil) and (words.briPer ~= nil) ) then local per = math.floor(100*adc.read(0)/1000) - words.briPercent = tonumber( ((words.briPercent * 4) + per) / 5) - print("Minutes : " .. tostring(minutes) .. " bright: " .. tostring(words.briPercent) .. "% current: " .. tostring(per) .. "%") - data.colorFg = string.char(string.byte(colorFg,1) * briPercent / 100, string.byte(colorFg,2) * briPercent / 100, string.byte(colorFg,3) * briPercent / 100) - data.colorM1 = string.char(string.byte(colorM1,1) * briPercent / 100, string.byte(colorM1,2) * briPercent / 100, string.byte(colorM1,3) * briPercent / 100) - data.colorM2 = string.char(string.byte(colorM2,1) * briPercent / 100, string.byte(colorM2,2) * briPercent / 100, string.byte(colorM2,3) * briPercent / 100) - data.colorM3 = string.char(string.byte(colorM3,1) * briPercent / 100, string.byte(colorM3,2) * briPercent / 100, string.byte(colorM3,3) * briPercent / 100) - data.colorM4 = string.char(string.byte(colorM4,1) * briPercent / 100, string.byte(colorM4,2) * briPercent / 100, string.byte(colorM4,3) * briPercent / 100) + words.briPer = tonumber( ((words.briPer * 4) + per) / 5) + print("Minutes : " .. tostring(minutes) .. " bright: " .. tostring(words.briPer) .. "% current: " .. tostring(per) .. "%") + data.colorFg = string.char(string.byte(colorFg,1) * briPer / 100, string.byte(colorFg,2) * briPer / 100, string.byte(colorFg,3) * briPer / 100) + data.colorM1 = string.char(string.byte(colorM1,1) * briPer / 100, string.byte(colorM1,2) * briPer / 100, string.byte(colorM1,3) * briPer / 100) + data.colorM2 = string.char(string.byte(colorM2,1) * briPer / 100, string.byte(colorM2,2) * briPer / 100, string.byte(colorM2,3) * briPer / 100) + data.colorM3 = string.char(string.byte(colorM3,1) * briPer / 100, string.byte(colorM3,2) * briPer / 100, string.byte(colorM3,3) * briPer / 100) + data.colorM4 = string.char(string.byte(colorM4,1) * briPer / 100, string.byte(colorM4,2) * briPer / 100, string.byte(colorM4,3) * briPer / 100) else -- devide by five (Minute 0, Minute 1 to Minute 4 takes the last chars) data.colorFg=colorFg diff --git a/main.lua b/main.lua index 6267604..b637e5e 100644 --- a/main.lua +++ b/main.lua @@ -20,7 +20,6 @@ function syncTimeFromInternet() end end -briPercent = 50 function displayTime() collectgarbage() local sec, usec = rtctime.get() @@ -31,12 +30,12 @@ function displayTime() local time = getTime(sec, timezoneoffset) local words = display_timestat(time.hour, time.minute) if ((dim ~= nil) and (dim == "on")) then - words.briPercent=briPercent - if (words.briPercent ~= nil and words.briPercent < 3) then - words.briPercent=3 + words.briPer=briPer + if (words.briPer ~= nil and words.briPer < 3) then + words.briPer=3 end else - words.briPercent=nil + words.briPer=nil end mydofile("displayword") if (displayword ~= nil) then @@ -59,7 +58,7 @@ function displayTime() end -- cleanup - briPercent=words.briPercent + briPer=words.briPer words=nil time=nil collectgarbage() @@ -169,6 +168,7 @@ function normalOperation() end -------------------main program ----------------------------- +briPer = 50 -- Default brightness is set to 50% ws2812.init() -- WS2812 LEDs initialized on GPIO2 ----------- button --------- diff --git a/mqtt.lua b/mqtt.lua index ae5efc4..9b611dc 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -6,10 +6,10 @@ local t=nil function handleSingleCommand(client, topic, data) if (data == "ON") then - briPercent=100 + briPer=100 m:publish(mqttPrefix .. "/clock", "ON", 0, 0) elseif (data == "OFF") then - briPercent=0 + briPer=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) elseif ((data:sub(1,1) == "#" and data:len() == 7) or (string.match(data, "%d+,%d+,%d+"))) then local red=0 @@ -22,7 +22,7 @@ function handleSingleCommand(client, topic, data) else red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") end - colorBg=string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) + colorBg=string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) if (displayTime~= nil) then @@ -30,7 +30,7 @@ function handleSingleCommand(client, topic, data) end else if (tonumber(data) >= 0 and tonumber(data) <= 100) then - briPercent=tonumber(data) + briPer=tonumber(data) m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) else print "Unknown MQTT command" @@ -55,7 +55,7 @@ function parseBgColor(data, row) end if ((red ~= nil) and (green ~= nil) and (blue ~= nil) ) then m:publish(mqttPrefix .. "/"..row, tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) - return string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) + return string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) else return nil end @@ -158,15 +158,15 @@ function startMqttClient() if (t ~= nil) then temp=readTemp() end - if (oldBrightness ~= briPercent) then - m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) + if (oldBrightness ~= briPer) then + m:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) elseif (temp ~= nil and temp ~= oldTemp) then oldTemp = temp m:publish(mqttPrefix .. "/temp", tostring(temp/100).."."..tostring(temp%100), 0, 0) else m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) end - oldBrightness = briPercent + oldBrightness = briPer end end) mqtttimer:start() From 3059744dd71b14a4db3734c0e56f450f30485e10 Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 10 Feb 2021 21:51:11 +0100 Subject: [PATCH 094/204] Update Readme --- Readme.md | 10 +++++++++- tools/Readme.md | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 4b0038d..55e8c3f 100644 --- a/Readme.md +++ b/Readme.md @@ -19,9 +19,17 @@ node.restart() Then disconnect the serial terminal and copy the required files to the microcontroller:
-./tools/initialFlash.sh /dev/ttyUSB0
+./tools/initialDietFlash.sh /dev/ttyUSB0
 
+Install the optional packages: +
+./tools/initialDietFlash.sh /dev/ttyUSB0 mqtt.lua
+./tools/initialDietFlash.sh /dev/ttyUSB0 ds18b20.lua
+
+ + + ### Upgrade Determine the IP address of your clock and execute the following script: diff --git a/tools/Readme.md b/tools/Readme.md index 98c23cc..82058d8 100644 --- a/tools/Readme.md +++ b/tools/Readme.md @@ -1,5 +1,5 @@ # luatool.py -**Not** supported with python 3.x +Version 0.8.0 upgraded supported with python 3.x ## Source: https://github.com/4refr0nt/luatool/tree/master/luatool # LuaSrcDiet From b5f36e54456cf33af0929183f4df906739823079 Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 10 Feb 2021 23:05:54 +0100 Subject: [PATCH 095/204] Serial flashing while controller is running is possible --- mqtt.lua | 18 +++++++++--------- tools/initialDietFlash.sh | 19 +++++++++++++++++-- tools/luatool.py | 37 +++++++++++++++++++++++++------------ tools/stopController.lua | 2 ++ 4 files changed, 53 insertions(+), 23 deletions(-) create mode 100644 tools/stopController.lua diff --git a/mqtt.lua b/mqtt.lua index 9b611dc..4137e33 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -6,10 +6,10 @@ local t=nil function handleSingleCommand(client, topic, data) if (data == "ON") then - briPer=100 + briPercent=100 m:publish(mqttPrefix .. "/clock", "ON", 0, 0) elseif (data == "OFF") then - briPer=0 + briPercent=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) elseif ((data:sub(1,1) == "#" and data:len() == 7) or (string.match(data, "%d+,%d+,%d+"))) then local red=0 @@ -22,7 +22,7 @@ function handleSingleCommand(client, topic, data) else red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") end - colorBg=string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) + colorBg=string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) if (displayTime~= nil) then @@ -30,7 +30,7 @@ function handleSingleCommand(client, topic, data) end else if (tonumber(data) >= 0 and tonumber(data) <= 100) then - briPer=tonumber(data) + briPercent=tonumber(data) m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) else print "Unknown MQTT command" @@ -55,7 +55,7 @@ function parseBgColor(data, row) end if ((red ~= nil) and (green ~= nil) and (blue ~= nil) ) then m:publish(mqttPrefix .. "/"..row, tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) - return string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) + return string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) else return nil end @@ -116,7 +116,7 @@ function registerMqtt() end end) - m:connect(mqttServer, 1883, 0, function(client) + m:connect(mqttServer, 1883, false, function(client) print("MQTT is connected") mqttConnected = true -- subscribe topic with qos = 0 @@ -158,15 +158,15 @@ function startMqttClient() if (t ~= nil) then temp=readTemp() end - if (oldBrightness ~= briPer) then - m:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) + if (oldBrightness ~= briPercent) then + m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) elseif (temp ~= nil and temp ~= oldTemp) then oldTemp = temp m:publish(mqttPrefix .. "/temp", tostring(temp/100).."."..tostring(temp%100), 0, 0) else m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) end - oldBrightness = briPer + oldBrightness = briPercent end end) mqtttimer:start() diff --git a/tools/initialDietFlash.sh b/tools/initialDietFlash.sh index 56f8a57..f258f67 100755 --- a/tools/initialDietFlash.sh +++ b/tools/initialDietFlash.sh @@ -8,6 +8,8 @@ DIET=bin/luasrcdiet DEVICE=$1 BAUD=115200 +LUASCRIPT_STOP=${TOOLDIR}/stopController.lua + # check environment if [ ! -f $LUATOOL ]; then echo "$LUATOOL not found" @@ -59,6 +61,17 @@ if [ $# -eq 1 ]; then echo "STOOOOP" exit 1 fi +else + echo "Reboot ESP and stop init timer" + if [ ! -f $LUASCRIPT_STOP ]; then + echo "Cannot find $LUASCRIPT_STOP" + exit 1 + fi + python3 $LUATOOL -p $DEVICE -f $LUASCRIPT_STOP -b $BAUD --volatile --delay 2 + if [ $? -ne 0 ]; then + echo "Could not reboot" + exit 1 + fi fi echo "Start Flasing ..." @@ -78,7 +91,9 @@ for f in $FILES; do fi done -echo "Reboot the ESP" -echo "node.restart()" >> $DEVICE +if [ $# -eq 1 ]; then + echo "Reboot the ESP" + echo "node.restart()" >> $DEVICE +fi exit 0 diff --git a/tools/luatool.py b/tools/luatool.py index 5bfb296..4f87995 100755 --- a/tools/luatool.py +++ b/tools/luatool.py @@ -54,6 +54,9 @@ class AbstractTransport: def writer(self, data): self.writeln("file.writeline([==[" + data + "]==])\r") + def execute(self, data): + self.writeln(data + "\r") + def performcheck(self, expected): line = '' char = '' @@ -190,6 +193,7 @@ if __name__ == '__main__': parser.add_argument('-e', '--echo', action='store_true', help='Echo output of MCU until script is terminated.') parser.add_argument('--delay', default=0.3, help='Delay in seconds between each write.', type=float) parser.add_argument('--delete', default=None, help='Delete a lua/lc file from device.') + parser.add_argument('--volatile', action='store_true', help='Volatile (nothing stored on ESP)') parser.add_argument('--ip', default=None, help='Connect to a telnet server on the device (--ip IP[:port])') args = parser.parse_args() @@ -201,7 +205,7 @@ if __name__ == '__main__': char = transport.read(1) if char == '' or char == chr(62): break - sys.stdout.write(char) + sys.stdout.write(str.encode(char)) sys.exit(0) if args.id: @@ -212,7 +216,7 @@ if __name__ == '__main__': if char == '' or char == chr(62): break if char.isdigit(): - id += char + id += char.decode("utf-8") print("\n"+id) sys.exit(0) @@ -222,10 +226,10 @@ if __name__ == '__main__': fn = "" while True: char = transport.read(1) - if char == '' or ord(char) == 62: + if char == '' or len(char) == 0 or ord(char) == 62: break if char not in ['\r', '\n']: - fn += char.decode("utf-8") + fn += str(char) else: if fn: file_list.append(fn.strip()) @@ -270,7 +274,7 @@ if __name__ == '__main__': sys.stderr.write("Upload starting\r\n") # remove existing file on device - if args.append==False: + if args.append==False and not args.volatile: if args.verbose: sys.stderr.write("Stage 1. Deleting old file from flash memory") transport.writeln("file.open(\"" + args.dest + "\", \"w\")\r") @@ -284,23 +288,31 @@ if __name__ == '__main__': # read source file line by line and write to device if args.verbose: sys.stderr.write("\r\nStage 2. Creating file in flash memory and write first line") - if args.append: - transport.writeln("file.open(\"" + args.dest + "\", \"a+\")\r") + if not args.volatile: + if args.append: + transport.writeln("file.open(\"" + args.dest + "\", \"a+\")\r") + else: + transport.writeln("file.open(\"" + args.dest + "\", \"w+\")\r") else: - transport.writeln("file.open(\"" + args.dest + "\", \"w+\")\r") + if args.verbose: + sys.stderr.write("\r\nStage 2. Directly execute the script...") line = f.readline() if args.verbose: sys.stderr.write("\r\nStage 3. Start writing data to flash memory...") while line != '': - transport.writer(line.strip()) + if args.volatile: + transport.execute(line.strip()) + else: + transport.writer(line.strip()) line = f.readline() # close both files f.close() if args.verbose: sys.stderr.write("\r\nStage 4. Flush data and closing file") - transport.writeln("file.flush()\r") - transport.writeln("file.close()\r") + if not args.volatile: + transport.writeln("file.flush()\r") + transport.writeln("file.close()\r") # compile? if args.compile: @@ -319,7 +331,8 @@ if __name__ == '__main__': if args.verbose: sys.stderr.write("\r\nEchoing MCU output, press Ctrl-C to exit") while True: - sys.stdout.write(transport.read(1)) + data = transport.read(1) + sys.stdout.write( data.decode("ascii") ) # close serial port transport.close() diff --git a/tools/stopController.lua b/tools/stopController.lua new file mode 100644 index 0000000..be33f8e --- /dev/null +++ b/tools/stopController.lua @@ -0,0 +1,2 @@ +node.restart() +if (initTimer ~= nil) then initTimer:unregister() end From 407ea2d2fa5ac01ec29fc10c64b9bb6f3ee71666 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 11 Feb 2021 20:51:05 +0100 Subject: [PATCH 096/204] Shrinked RTC to the necessary modules --- os/0x00000.bin | Bin 31360 -> 31360 bytes os/0x10000.bin | Bin 413696 -> 413696 bytes os/Readme.md | 2 -- 3 files changed, 2 deletions(-) diff --git a/os/0x00000.bin b/os/0x00000.bin index 4fdaaf9ea508cdc817052a11050a213102f90272..86291858ea0f8e695321bea5541e5d7ed87da9f9 100644 GIT binary patch delta 236 zcmZqp%GmIgaRUz%Q^k$Vd`zp@*a9A^IYd0%ypO|tJlxF3 zlf}qZ02JHvaC05+CPt=)hntP~t@xN&csA$BhOskkaM*lIrHlz|&K`%&PU_dh!R!kT zo8|2134+--95x>c$P?p;xS{3{z{cP(d19K(=8*I|ymAb;fwm!G79bmj9ULe7mD;g5 dI;lHMRxB&nRCa(_%@fG+B8VqHtDMQW8vr`(P_+O6 delta 236 zcmZqp%GmIgaRUz%(~tX``IuI*v0Zqf=5XW1=6xJ?%t8_`)f^rG`3wvU4h22`>`h*7 z=Htm?WcvUVvw69>j&~Cy6T{2RM*LQMOcR7R=gEe#Gd=L!d`zW`32e?A&&^Ki*TlhW z2CvO>_VWb6Y!0u@hXV4%IBwima|mE#aF{$XO=fdQ`W;@mhDT}+$hZZ_hv5RR$$q7F fEQQ|c4wDtj3O1D;U{Thn9R#0WCx#G?Bn?(L?$Jzll-v`R{^WJOBKl}yckC2mn&L@H5+ZuCX8i)38h z#*?v+1!cTEIxT^e4JGmecco>DWkci2GQ$^!PcF*{k)qVR!a6~x)0t~@a^A+L;+dcy zcOuO(@x;cc#9}d0yigPznU+P$j3Qd7?lBwZnx{w+YDQ78^Uq@Q#%B8~E%QQE*F?!`~Wqq1x$??#+IdZT+_F9T7NH%5$9NwVBLPEU0b$tOCA z@)ysJlcItnqqavF+LSZn7PaS>#x~w5PR z#LJOsMUNQWqogRY5&tUN{IO5?%{9X88r|%Xlf{-%cys@#jWtC{WVBd67EkJ^+DxN( zSK+MF=Olg6Po1TYG?dQRTQ)SvDk{H@dU^BJdBM7}xPD87y&-8mNZDXf-ab~1^=pgo zA`w2T6{9wW+;f*e)Om|0PZ&(qpT{nGZ$c#%o5n6mxwnj{(>Bh(_iieRkBwDI7oEQU z;cms4nlf@!9nrRF(kS3i8L@Hl13AL|>YOpjKO4fYMei&p~?vO@$lx zzv~R*V}PX?)x>Cm-jt$D3o9IZ7*qERr)J=dskQ&VF%?mO`*cQf^fU5w=UD>n*656-iKOH)YOaQ6LN zp(k13aGjmYYvLTPee;C8ZluQHidrHpP1KH2t;6;8m%`#$@_rU8suw;XVw~$ry&&qf z+MNy;IUsa~k=+hPP6~BeVFNlkDf|>9M6qSfLY?pso6#b~hsyN>^uPFZx`Pha!WJP} zNZQvwS29~;h&9?mYIVB&5FMVnEbPu{qrN}e?-oXo-ThrL9$}t9loGbYD-0%TvFm_W zSP@L>9j=$!1y3wF>To^QmE6`#e`8jfBls8B$}IAxaL3%;X^xmZX%5aAf^GsXy5R5A z9GTcI&{v2}j-pjjVidhac3C=IjIM2X1L`Lwr8xQnun{lWNs@jF-aG!iYpI=_BUElr zWQzunV!llm2at(m)L<4lGAP>h;6TzSl4nmc`%v;LIeLOc<&rs6+-qiU>^jA)O_TCxglHbT)B3$>{D)pJ&Qm zJX?j z8pVC-Y zYfJiKvo8M`VwG|YVqLnqB-LJ$CJxFeB*hdg2wf{*rL*VmCXboFNiQZ@BaB5Qee+5z zO5dCrBY>2HULC;mF-4jT!m<{)woaa*B06NCt*%9B7rK6m`=;mOF)X51o#xxq#PCvB^`& zouSHmM$95iTs4qwnnF^^X9L;MDP*MMQ?ywPSO-}0M(6N04BCDs&9NEJI|228gMj6| zb)d~!DLUlBo)bqJ_Y(K^YwP8jfow_%899wStX(VO07B$=p>v-ck&_mG6s z?BYXYLQ?8!kQE>YFs3BM;lOny;BCxv`59I=m83;JH&6^|i>L~=7{67LmkPXCoTGwETn zTfYt?;4J<8Fv;t_6Zbfs<(H(O5S!Xx$R(!V{c@fwyNnDLNc$N!^AWO7e-*86oMCy> z$cM2(XL0ZWsgjRlRQX%7{ET8N!F3t0nBCwE13QdvPK}E4qyqhNI~331AaEgH-YHw zYyIjJUHt~DRDMeNZ~!ZxMG{H%0QUYY^zqIBc4HQaC+`kmJ!X^KiX5)eCH*Fnlp;rZVK*i*AfpQxjlL>pjAWV)jr*BfWqhS|hSULU{?%_bSbZHu2I z-NLg5W@Zms7$Zex2$o1Oi={qE%y9#a8IcLw>UY=pq9PMGLN{xmL{~+XQ`FGYF{JHS=j= z7xa_x5aD6Vo+0Oi=UneROOEKtiT><~3i3QT(x3S%NGUnc-!*P7sS#577DjDv*ijO? zy~CgNq;W>jICW93P}rqdAF}?)TgQmJ4U%9Uu@KI4hrLQ}2v4|%DC8$1j9}5PlY!k| z86bs8F~woVyBFDOp0*lB*~T@@QRcBJuag%99KzShvslqRZ;(tOlg)dBjKsory+Qg3 zsqD%d#3-0q+?ym>FtVIC$rPa{d-qK;Oo(NN-z2AnV76^OP8ngQD)Jt=n$5OV0V9{Q z*{@Y3iL__CI;+V20{JzY-TyCQB1f~?i~l0ekRP+z<$saa$uHS#?!Uncj%2fC|0XHq zP`2xbe-keuOS0MKg(RE2lg(NelIO^$*{*4eNRU7lWwV)YlhNc~*=)<(IH9j+yQ1D9 zrGhZq_0(e0QxG0w3m6$KJj{+VGEgXC(M!k(p_tvf1ZU)a_SOvb=cDj;t+0M}pq(hQ zU*9D&g<-7lJ(81jTlU29Io;B-d!&s>D~rx75G`Z!(5cxf6iR9i`{X_HgkW>Uyid9b zz-jMl^1OZ;2x9Ijwz3+iaNAi!HR-Q^0%fl@v(OJnWzuTgudYr39UKptwWs9BcrZWb zHCrp~2vUExvo#-(&&feMEB=tg>u+-8mp%kX{=u$s|hOhCtSW|c zw6Ofo$s=G>Yd$9f^<(hH6D`d1Irv#s3wwGEPWO@)_TCzDn|>YY4z{qL*MKeUb~E!@ zayfKbUb-Wuy>ocM2xeYKCX>58Y~DJsmsK`)Y8^=@%WX_rk3N>!Sk`(njC^QgPpl_> z$VWDIVLgdv>(-Mf@~(~TX_ zyU0C4IUBp1^fB18?4~%gDKTs4T+z;6+f9lhGPCkbrXrIOrQ`b7ikZy4n`D9C_1r`9 z^_i{EZd+N|9;nHYt_yp}mq^%!&zn%=p+<7j|VVm(M~Qk|`1`~{ z1JOHx-R~ibAg|7Oz#Y=rKrb#S>?JQ57`6cI)&X_`HeY5tyku?Hn7-!ex}Ty*-Ms=E z*GA%q8p#&>Ai27->ppNNk=@@4g_yE=t>Aq+whT|C)5`X@f*ahhvP-Slk84&Ie-6)A ztZeu>JhxlfBj-q8a>2^jIZ{TvR^~rP4v=51?BIFwDESHP+DLD5(8?ZfBYC93%GS0) zox)NRE|6TJTG;~^APv7k`wL_yaaq~Oi=-m+O)Cy)v^wBwdArn&pHKN&Q1f%Hf_+!A^A{naUu6-ONNmCzT8+{VHS#=butI?I_l5X(|BvZ6j09F7um|+$U?IFA{%y@+$P-1p1Vv&ce{aVoSi);w?Inh zkw_dLv49=94BX$rIxds@`1W4`aX8o~S3q5Z*}*Fy+yP8~mE2Z1=zj)`xPWW{!F0(lMJw^_pI1qKg4jK* zt)Eet(gXv+Xg6BJ)ox+&$M^x3)7kl}q+evJRa4v7T$NJli=gHAV*Rc`UpBFKu7O&6 zvTv@DA~5F2>rj=VnC&`=4jqHJ1YL%8{2ROTIw?*Fv(|~QM>Q)b!U~TM{($x4!;GSV z?Yd5qx^=N~>qPtvcK0oO-hGK(zfNS*k;$CDlR;6b7r^-VNkHcduqV%6VsHLVc96N3 z*qt{>-+|{cZSCMfQc$r$op4o(uG)bGpU>13<9Dw}DStnce*f#}=hHK6!wqs7T|4H2g(kGK*iLd+ z@%Ndqf+cxxrd7h?Hr6QCWtLwIp0&H=@c0(zRrtTSILm2gb)E1pe3!|3`N<;_w`O+D%QXOJE&gNV zkXeu@Xn#8fEF4t%Qc`ET!y9{NE187)+mY@@USJm91C#Y-op9{bUmrbWG4ig-j{1aoRVvR%r5|20kwdgfZc$4 zz;Qqup#3r%Na)?M|IDleB^}=j%eXe>mA&9HMrD4ctA@}-0aE81N|WJ4`<2pRVbT>? zA%OM{Oyi2HcM#PJTz#;MbYS1oOmn8rLgbb!e-d9g8dn2~KE8f^Gp;vaCm+T&=&Eb6 zNU1>O>TaxBPsfqCtL&VfP9~14t~WBzQb+qYI9p!kA3r=+y zucxt7A#^U;8Ot6HrCW#+$;@5pD?|=qpLM0VU9+y?Bm?GLOJnD|(m~nYKF+)R)50=> za`dLNol?*!(lw?0VEPxqCbwTc(JenpSANoYXQwec;`ZoZ(;2^byc@euq9&>y>&9M` zXiE5Ibk_hl4hX{dYbA_-st>anXc`q8y1DK*&^c6?%JxT4BM{aWK}UwS!^gz;q#Q(^ zg_lM|(rj`e)Aej5?N7oTIEwwR!z%z7iP|mEbWYfJnR=s6XZsb@E!SnT+!)%6;5s#i zPNCz_Xjcqf0bO`jH#&k&#j~p$O$A##+KtYGMe<-Q?JE?rf5pOpT8da$}4w2#o8UF<=}fL{&oNe2kw?5Uma%Mnk5 zNSB}+pvB+Q*yu!>CG=+HiFCJ+=#rCYwm^5H{Dow?L=aptMj9=UUA_7U@GNlu3=fUlhOh-AKsrTbP{fM^`~#qSJCi+0n{YW z<0z^ah*x~L`D7q<4&x4qPyJv~AbkfE_5xhT0r>9D!4)!tyKlI8<#z5RN5)^XDNaaz zjp>hM=0UU=(sJ$~`cZWMjHbOp3jNtLIkZ>oRt&WOT`mDs z1C|4(oM#(ys8gSwf$dCV*K)9(smwf>jtfi9sEpC+>}xy0r{p9ycQCb(Z!B!(U^-3c z#-eYd&aMsU;V|GvM;d$ZHaaVLGtU23=;X%En{sq7glOi0V-Ox8HswBc{x&)wIun&y z0PaEHr*T|o8XGi(&L?Z4+0G%f7wE||gqG4NC?7kNItjSZ!lAUN>omOd1fU!h=ZDe) za?-*E=h8>IY(`-%3O~!GNzlFOa_O2b$5GaTvKNNYeq^78tsX`*lg9zmRe&jgHZ-^a z2*!N`V2(eHT^UAyB41eouHjR|sa2rMQ5@~0k9OILHplVsij$5a!8+GICw+;KI32rl zB<-yqs!Ml_(Xp3C(kA^h+#@b9L8dJ|ojm{NYKtqTyi5c&pJ)va|xr5sD zo6**%W3%s|og`Rr%^ppO&@(|ucUS=Z0S>@8z$CzQf&FU?T`3H34KAe7M2K+}j-@mx z>{ZlN0TuvO3$Dp`K`7{V;vtT>mfb@SQGFX8bi_69KKeB!IfM->rhUoXgv~6b1EHzA zmK9UDL!KavJV@=Kt$&jC5XhEZtbPu)!>hgcDeUUXUhK$I^Z@ywmut<_^cevj z*tBPHcq-Vd&(bDxB-u6bIXZ@rNt7*nf#!35b?yaPMy69Xp`1=21(dBRr-w*?$|_&P zwVblaFVW|d#6IC%H&XVdB7C@h_s56dYI*tUtf=i-PztIjyZjOzWZ0H!Mf~MFx4YFK zc3TBa?otcAP2G{orc}@&RJjtyKCHmeklVr#OM$X;OUwF{va=QR-l)~Qhu_XY1w8I( zw;GiHhOx18X+c-*xN7D$yD4E#(sO5n#kL! zEN&iZlpWe=@$Acav}afGy+9A*KU3My^XQ}y@pzcFph`CU6*@39y%z=m3xH#;;uSiv zyXg93ink0XzkfGn=U#zAqExu7uj0glo&Tef&Wak7`gavPOJo--=}$ti>-*Peyg;s` zx|&}H_a`S)*`PP+JaQz}wdGCvi4fhM!a11Oo?;8?v`RTtxs>9XRYl{1gmTxL3+PON z6o{_tZ_y!wP~;l8h%!OQaqWAXrW1IGE-$8a0=bsr`eq4*Z}@bIEABnoA&{LZuI|{*Gco5!Y!5`8g;cxQt2}HC?s1#mfMIX`$73GLLP8ZW1a{%RlR{^gBssPKu-QUI) zPE)9T@S7fai4RN8)d4a3P(elSWI6Dk#3x9eQ{(5(7&Md1GpRIgvcDhjr zFZA`+oD!{QkJ))fE0V9ZTE^QeKAYY<8;pFn*$FL{tD09^bDX@TT4#11(~8u~tvLvm zsH)ldbD-e2)*KTGcAA}sv;w8QH761U-#2z4Y z|0F$M7+dxc9UiBSsF(6GoT9_Gd;BqSVf?xY(*?_T`EJ(n5lzSz54IL0<%WZX547eb zh&c)HMXhSJgq4{MSd>9_nW3W#;+j^wDF`ZK9zu(3ObzWFuZ(GeY2xT_948y6Ofae! z{5OMu{z>eu8fr{Yvw=uULiwpdQ4$NeK zw(2!ohij(G&G;{+NI@cD-9Dzqp7OH?prd1pFX_x{JM%IH+l{pue6k^I?8h{J}XvWOeG#$0CTrH{nRaxY(FGjC*owYP;gG8Bf16gT3B=1QtzhAB@qJo}V#$ZO2g{9Vd|)|=+<`)18nAV@!GZwf}TWDy(H+Erl#qS@Tkwb)WckD~vq@cLKBsw@f;t zA>9!H=nL2^r8|b=D&dMbgxGeJ5Fq*9pKO=?&MW9ro#x}WmvJlN_BX%tH{2@hiBITl zMmfk=Fx^(Vwu8v;Vc%^Ju7%b7ZmTsMCSOCLQDNVILLH;zPHzXP$}L#k{I+ zPGmyRpf5sgS2?2l_$tG6u~B|yMI*ehFJ`C6n2H3c!THMS^-v%>jKwGc2P*}>s(Cpk=~er8*Z4|d6G?KSudb_3e816LBG|VFS%s>Z^2nbg z0z*e(zb>Oi!+5YG3lnw#3IG!UQvq`Ta{+GymIJl|>H)_AZGanqh+sDJGx}78+|^e| zDl>8JoBT>Bzt6yZgI^8d_i4D_=NGm66rHW!F9)Nz&WLT*+4lJ5E_ljM)Y*3XRXuOt z6UB9YQM>Q1v+eZDB5#kSqGG!r2LbIPb+%f+N_qRR(J24MFKQ26alh3s6JEg?(bs-O z;P>Epw#|N3$M1pPO@3q#seW)0oY|njX*D87GLe10oW|ve>AqHSG|v)gubG>^(SV}} zqWRs+gOWO(G*yBWSCf3$%oMrVXNz2eN5$7coIXEJhfo|Y#<4CdXkxI48iX_Fv&Tx-nQ0}>zC(G} zTaasWecnpce%et}Tm5?pCJ-j?_u1BeZVgjs_@)UN36Ex4^>6}}G+8o19%5;eIg{8< z`sFFS-~_Jh!-XfF87ZdFLpXcw(*j2BNxaQaqxkf zu)ngiEFfqkM-pH10Q3AE=QUW9fY}tD_{A_O4Hkh8yhMh?l$=@-1&LIP;{OfE*JZF&+^^A94TXH z^(Xl}`v&xeqFuZbJD+G;%E{!)Ji67 z2(n}XS0jK;dyQXAZi+1p20>+H$|IZVVs+x0A4g_nPPnMEZQuiJ=L3L_G2l8s!kEfu zKi=$3e*VW+vUMq-QlvGAsa| zs{yM4Rjk|Rz_s$FH@{G)y9hj=*V$g{Jl@wRf8nhx;6vgbyh3jC8XMZ{_u8Obg((}n zl}=tKWrJ{5`al?iomCsay0Z&~Yl8B#H^T`^I%-;$XGh@(KL(?n7I&22W2WL}~-^ab)p|cp$ zqV#Fz;rb+<&UDtF8z#K7x>l#FFKXIr%e``skaSo}vwS6R|yncHlc^AST0*&-vche1-qy{dK`s z>ufImELHIW3cr?=t+4;DrHNr9ft_)HDS#(JSm-*q#1z(V9qn16Zuc6E?HNws%fnME z)K|Q9#oEYl5*G^UYH$5QP5Q|5yp{Lr?AwFIUmKcgL}>)d*I+&BTyN!g3^v*+u7oNQ zo2RoxPS~N-5Vm`K6CjG5-X zx-xTdQ(rRSbG`h?j~RU-`WOaLp7&PfV1bJ}3&X^cACCx@zPUo7LCyX#msFcAeFvAw zQ+_&=-#l^~c4i&hnk;fxe~ z^qkjf0J-G*IExj}cr(Vp{8(tP{g*ShiQar18>~E&nlpv?k)wu6;e!@N1G9z%d4$h4 zZxy;wPk6Nh{Zwb|BqO*7_$V8-ky^UUUS&1h=Tz9UcqrbAscY&u4+MnRjuG`qNVh7x zMdKyEc3`wZuRaVu6l6mK@$Fooh-17+(bR#*;UN!cO!K|D#FAM?MLP+tL`7aGD&!Yf z$3|-FrsR9!uC|!#FLLeaDHHySPq7hSP)mgJ`}cfb)F)vlLdZPEUigCcja7$vE3v*D zbNwZL0A}zv5UKn23pz1eZPVTmAJyJ~tL00$WmR_nm$c^~@nU1_MZuB@+jf1UB~$6v zqz}@mZH-4V4@>+&@^t06A0?8(pP^FfY}0RmSF%-K(xl*{E1`9ViQ8G@m+*ic4Pj@$ zq{$UxhPM)8%3?k&ZC#j_*rj?~nl%mjoE;hFpEYt`*tIFpA@n(&PCTm(R>?cp$%Y@z zHM*uu9T;<3VoYqJKFumNZe9uXs?oKwGL*Mz{9>+X%F&7@3rZ5T)Z~cphFtyaJ?6dX=p(L z{wILy!_;+N_SR#_>S*3XyQPTxJ$s4in&0-%l?6No_b@;8VTA@|=*_bsPGiX~&XJ0| z^8GFFw*0)>2 zoR@H5rD*Jc(%l=-qh&w1lazwJEgRlb8RI=h%r$-~?57PwG;ahFD`UK{WONm>-WMB% z8A>S;PNO);dy?oZLV1TY9C;`FJVI!3GJD?Ls1TQ?_-LIG@*^Z^lmf=+Um@>v&oCt*v0Xi<54VLjzU$$v8jeJ<_@Z`f3foz5$ z>GhV`Gb~Q{9Yi0JDoc<_?;o^5vbAv8EnoN4!9@Uvf}=%m;6#Q(2+q8kASJ=e-zpRo zy>BmqxKj9)sOYxLxpt!2IJqqID{3FEWO-jCn_z$K25t+xC>K3?Y(w65sc3s}>GmM- zkv=V&+s16-4j&{4b2pD-GI8gQY+@gLMNJh-Z>)fKvW|CRP<)=sSdC*~yDZ)e0cwyW z<0euXfs%BubXNx_!gO#-=^^y?UvG63zY#CNLI8acN6I4kldgFt!EVwOhtCM(493vH z9g1?C>Hm00Cn61~3MgK#p}Fm*d8@HFBMjWsz~nTWAD%I{r!wl687BoPX746*SiozR zqBMIr5$bAlBO4CX+P1TIzNW@rN;n_#FX;w;e@u9~BNd>7v7CeJm~i&<*N8-_>^d$L z@~Z52_Jl z!m77$|I&myjy0vz_;(lT6igbDKyx9I5Zhj&b^+?EmTEaZ;`biT)WlJBH=VZEjR6D% z47cEjbcfULhX)c7rS*G0KJu3P52%hCr774K)lc2uuRl3&hkluaY+{J!S;D|8JZF7#z-$t5|!mb(9M8|1tP=)Ji+NFf1}b+H5A&|XvJAB^zp|Cx`%Q%#(C zXnY)#AthaSTF5mB_B|!?h5#lF>H$yJlZ)@vS;Eu%N={@?z%Jz0`1>Ancu@5`Niq(b z_kF+H>~_S7am-XBoAfP>(@(=1UyoqVe@l}FsVgBpaEJ}?5H)ymq(gbS_z@2C+_O<& z<3a~X-zaoY-mhHlEz9dEr4+*VEWXe7e@hdve?IhQRsQXn=yVwcNsVy#?OPoC?S_u;4KMdd+@_c$N zjSo>?^I+e(#=W4H#>U7$cypY58^>pjoM#OyzjS}Q%DzTJDz7lI!?hYsUah5xY2ve< zd`YLfZpEnn53$SmlnZ_gFwv~MdG>lPTffJK$D)hbUO3CbbU{*l!m z2~}48;NkKIM)t4m^zJBmxhKBdIlnWvO9osH&;3JISo?Ow$mN+Veg}QgtUk}r2m}wo zTCLIp+43vizn)Aa$$hg!h?y&vT;q2tJ3@R3jJfL03$eZ5U z2t;jPeJldUnG-K^nr_lBI0-wyllJT;-ww`Q7pg0po#3qPKpW2HSdvN;hRZ`e+EGjO z#@jEaKol1v;~j<w&e7g{A z%xC)DaBwTE|8AOQRg*l$8b7&D5FPw1YZDMhfVprnD#a*yd|G$GHx3GYZ8z;*p}wbr znEps`0@@KTe-~u|j0ac>c4ChS4Bvu)pZEft=znmNN!YMyfH{D<0C4zRfpd7Y&Tq$% zBPFWd?&a!$oMGgwguCVM^X5bXr=rDJp@~rxP4wnyihsJ%*{U^CCwR4RQ7@y@6DYXH z%fp;EeaJj`J}Fyc?140;rV;^pO1nH5Gg?l#f$-{70sg z8*@-o1B`}meL66|>7OB5lmNMPK6m#SVH3X5IWKbY3+hz7ZrlWvK{b){bMjYr9+#NM z;cE$*#h&<{iWPE#kz-PfHfnLQC?oQk&41=Ke-W4r`sK!&TR29saa^6*>uEKV*}Fr> zm(-q^-6lJq68Bvwr`%HCyc+(URG6#-@({EN!AfCOr0{+I+jLk}IgutSD?&B>AoOqI z2ccMuJ~Bqz5l$?o8-9L(FNN5C$M%Vb+{|4GuC&0&nYZYL144eD| z?J0>%Lo;5sZ;!y2szceUKTvap_>Cv6C`60vKt3LH2adLSJz4X0h=lLXjpP$2{grXp zWNt_7^uXoO#OVOJbV{Q;pNHJgs@4-bualn)WmAA5L?K8~eo5Tysh?K}sm~AlKJ<_L zIK0MB(TLj2SfkkJiSXBCgqI({o0pO`PWK`kQcrutsEU_o(y70Crftu07V2AxU}e+l z=~$#BZLX&Uf{h7#X>Z{Hmbn*4w^pkB^LW zIOae?LKzfO*$;bZQiUAVoDn(SCY7p@%^5bniQ-Sme2b)!>Q#@e2Qa6q z|LpD{%cA17(f8nGge?VeL2K1K+bO&N&(&wGoIk6~vyUeBP(E_wSn!n$@aEMB4u95l zMEAr!$;`MPl1I#8!}lZSMrD)tBacDep3JKEQ%k5Eq$#iRH_2?@eroEf?7~jg3|bg( z`-olNkI4TL7TZ8mDr8skUrw?=0iUh~SRKUF&9I;Hx!X4IQzwsdsj7#6vsQjd*@q(n zOg#`_Gc)-G0Xj95OJtmtn_|j;6?l`n;nNC0D!>BR+JK}uT;~ADx^C?21{z->E_1gM z@u^Uuq#C>@;Zl0GWDOH0^M@Q^P*fNQ9ykE8i*wy(6XdV1XotYy(vlz{ zkB>Ob+1uLHT$-ojoZ(TY8UyY%&AHlKtOu=O{Yr;#nzQ^;A-IKD0WB0f{RwoJZ_$B+ zZU+Yy$A@M_9xW|~Cqip~-Dlgz(Kmw+n#A3om`dLEpdzeC@5Q{?fktW@Aphnw*F2p5 zQJ8HxTFcYWnn#8($+Gm147N{EC_cgmf`w6*9Af*J_sIq~0e@G2O?B)BLa}*L3RmlS z#F(?Zi5@AbY6E09nm+DC?4e;0&e}Yy!Jpao#j~_{O z@GqM9B%^sy8xvHOz!Yxxq?JbT-qlx=5nAT>snMzPJ+@aqfx>`CaWflqfF=?7Wp?iY zWWtHBu$K=&e^tFI-vM_?7f!Y$V6mdqf6n4SmuR{<3>>RADzbE!$SB^r+`#U_j zqr#7o_;W(fPk;em9>|qT%&G1Id>xv%Q;>?lU*&aY%SfnZAS*fU{PCLe+aMVDD~06f zQqIlc7h-*Wr16m?Q0gOrQgIl&_eW}+ba^QnA0tOgc`*=HV3J0Zf9a4T@KJ&z+c?++ zs#x2pPSUnnIqR8VzgV>fTzsTds{H3{9e(_wRINEH6)81m-DnG)c%)M9k&2Ll!q|Zy zY36<6ogU}=+VMv}Z+db}Qes1P1oE|UM($5`F81@)i*I-=7#VrKpoNLa&P7_O`WohA zuBmZ2gCj(JHtZ)F7e4D<>_mZ+ z&!Je5W%lq-)Lx-J=n+>3PKYBJ*+be9d%`1}>qKLXbq!B;{-71h|M1AiLX5Ye2XR=k zbC*^q&h*GR-<;-F+FcYt9ZAMx1M;7+u9oS$nY>cbw}YTT)P zJkC{tlBpis3SQFNTGZOO$+@pI|~Zo3+$7O z8z}g_leMvWCyVa{P@a*QEWCXS(_%)lvMYdJ*^(?a1TdJMtTt+QVmfmiK@?C){Trvk zH}6RBjX-X_#x`$$Q>G>+W2#U2u=q>rukNy|PP_9Tz5m_($S`i9Trkm#GU(M${t8| zjq~uifeCKL3gNjm$kd}vGNm{Oq*=X#KLAx;H@=NO?w79xi_h%@v(|zINqejk!bxgy zGBI^wr+=m?1C-B0Y;IxKhG6-d9=kSN%kQd7OXycWUD?({b0fwNHMw%KY)&Ei8rIj< zTzhh!x}^sj`U@S#J>TJNHZtjDB{@*3V{r*>&AV` z{0AlsZsSQ~hg7FUj06;l5>&-pU{&eL6$eOt9bDIV+}pxEEjrzmH6c9x5Z)lQsRf!c zzEn~}F7Q+YgL)&0o&E(Hp7K&l!A#p|7@|rHP=wgX?@0k75XXZE{*Re;%aG^E?(%WB z?YAw*AYPUKVg|k!3rcM{*bsT5+tz&pQrXK_co+215MNiD^l@Ha zJxaww7IBQmRKz4|)W^S;<~y^O9t(;+fYglyP>4KWpZZu!j?_xZXejVXWsje4xP1oq z%I!FKw8{2cO~DLnn0&jNXFi3=8(O$MB|p+qc?s5>?$%dHQQ9|2eh0>y0?0gy?_7RK zbr_GORyeA(2{Zs<_(b%k6L>GVHcR=bC16vC)ouwv&9u@mDFryy*4YAo1vg}r!yMNT zgzvg}-UG;iKPl^4PzSwy2}+|hN@wn>d4VLikF>{VUZ~ z10DU(1h`Jhtq-kKm2Y9R_?r6|iJcb$o;4LS-Gb3T>xx@SjJ=5Ms=%*j)S$&C`v_QD z+-g$ZZwc@wP>AgS<}B_>(sb5P&K@qodf?qE6>iN3@LiHb%M2vHr%oE7@4>AKtQOTE z`<-}K=92(V(QEI@<=VUI3mVOfwMqJm71(m*iee|x_?TNuV-R-)2Bd)jp9>85teZ0_ zbt|Ik9HCp2v;h!m62C=*@>5W-ufj9HS@NGr-Rm?$;l6CHEaNyn4ffX!@1sQhkK1;2 ztiKRvQ{3d%>vbqYje5pkKqf}rVV|FkygRv8U4FAyjrVF=@6FDXS?CObC@3t8!4%QW zMtoy(9Gj}FPx^~+Xh-;Rb&_UTz>47evzLggk~p$)z~*BXe!*M=f~w!aeF243-p!{2 z0@Iv3@;YrJ)rlG&Acy|awSOxX*bq1kO(h}6C`^}+L!9ex#ze~8W%fkA;o=u9aNLET zjT#HFrY)byjU@%Gm^G-+M{cC8M%9Ns8uHzxWcUjxSfe7g(Ic z`%$*JW6h$?$S0^&^N~2|Pi4JN(u^?*XOv)IJGF@*9=RY1+7cK#a>BJW2+Fh;GeV&M z^HHN;I{lY}!Of+rB=*rs+MS4t*yfWoElPboi8Dm;Bzo3#yVqFTNjfJ{dB&X+KCxt) z^R|29%Ph(Fg+J;{e+NNdkO>m&UOq*mL*;5rsxTY`z&<=h;|jzOPh})b3HimO%5YrO z@}z?Cd}-efvA7znqx=*mE`FGxHgmIZzqqZv6R^3`CJRXA^Di*bU+3zj1nl_ZwM#q7%{=!*A#T8_9`e zIp7XyZ?B%AX`roDXYkS6b$0X&K9}0X@cS6Ogl)`n77<-}LXvF@=N`n(jsM&ro*HX$ z#u6T*j8^VWvTfvhF6-R3M}Zb43}^x03+$fGsvVDjl#ot?ED?SRk>2;XqwiRIjwU;{(i&S?v5ned~Jr8TY@jZn}cNczXav|^*T6k6gzJnlt|LDi> zKRg0+Jk95+1yDfqu+#!+J7OwkTffkW z?UUqe(wZpuqhuJ~?VaS@A1JvGCBspYkp$b0cLR;hE;uScm6jyu?m*GKC~~4CJ;}+X z9n6CX8YxOsnu;Yk@nj^KO|eTuz+XlFU@)vr+?mO z8^q+6jPYSe42kIjZ>*fuQXpg`4S_O+&{AScMqdkZ{6?cjP2e@d9zYF}{^DCQ?&LL( zqejHT425| z+zd)Wo%&U<6!;Yg%td5JFW{2{`Fe9Jk@o}(8*cT&9ja^j19zxO&Qz@r_^RZC&05r1 z60bBLBVt{!u3d#U`EQ9!HX9Htzf=467?j&K6LW$iQI~s zdy%ukwq|H8-v$eB{@J4>ymqTc$$6s_N;c1SlD}`}JaKg}-h~|e)8CScGZwI<;AZLY z7Yd_oA+y9Ug0;ZUg+zW>lnaS}kN@y*S{*QED-eY{SrU9=dFQoR7m`0HKn`#~--aNS z$G1q)1U zs-_$y+XvVoaQk2{ZNg|2yYRY(ZLJR^Y$_q{$}@hx|0&`@_Fg;94p$bol+BKD+B!AW zXd64)PK{xi*g*&2pfTOC+lb!@p~-3L2hElI3kBpT!Mi)2M}(Dq%@YxZj=v{YqOXYh?Z{ zpNU53$`*FVWtu)fexsR3Q*U-E$s0fumc#;Kq8Z2+an#ZmX<}dg>W^2|FWIuobWoDI zBGGJm9_KkL`Z#U;erbUPH zSg#~L#vZwflR6R`BzaOD1-O=U@NjFP{!#qcnWQfk0^bF3e?Td6bXoI+g+YxMJ5FqQ zKal;cUTqGjMnx^vJIYFXae`3Ca{3OF&oyTlOdh}L2*w8T=)quQ+XVxKIvf9NQkl|> zlS{NOlvae)_Q_MHMs3qLZPn7JOTmq!>HpXZG=s=Z5V})kl1dJPHgkLQT zK3ZhD;uoLng8%C5E{I3~tM@eL3p&$pesxxtKsLs$Uqs=dE$%ea%va7_=7OehoaEsx z_&SVh&dSrU?Q!V`yr>J&8T7j0Evxf*q1vmZLOU>4R4O|Ic5Eu{#UW^j1De8;@p3OcPl^KTu5x^uS^UAPRiTGLz)dD577D+ zlhC)-Q1Mr@GYcp&#UOX6O``ZY$zB{6zx$QaF3Qm0`lZPKR7<+xzf#iWR(6EnpU|G_ z2!@KZ0Du>vZUsW_;)c`dCq?mhKgZk^zw%MA?Ux(yQ}Rum&}{qcMj*ITA>Y%CHU1@X zh)&Q0`T;sco90bb{*m}sJox=Jfx*D?xP2Tzhpj~mvqpJ2mzbA8gJswUUIW^ym;RZv*kN+nSMm2!ES! z!Cwn6I($Rwom#wAoyyMqPH%rmIrp8$q8|L88UJ-vYO~fxDgK`}JGE6E$Ev`m;6dbW zDmd?oAfhZnLVH*Hp#BBpi`KD!-=O1=cdf0e&B-3e5VZ10q_TYZi<-HfiA?b1(=rdrTsn zsGQ5FqagMv0`|9pzdmi?1v^T5Vh6KQjP~v0NJ+eEtz&O>(8R8C1%f4Zd?TCN!oKRD zgDL_aFxTuTiM`d{K}xzem2^{M>&&Kz`lT3dIGCs=HxR$!7|mUF0`;GI%xrN zr0eV$?MaN*pY80VX`#yFftNE{SbHZOnI`HqY7~3@?Ns`4Y+)4u;sB{BY_gxGKcHss ztOMT@?K^Q24f0t?hqNeCX@iGcCM_NOA-^wv{=5(=fS}kN`{s;^;UNS8;clHS6RCZ; zZ(D$S?k|P{>Eu5j1AX}J7Iysqk@YQbQ5Eg~d(O_`dblHZba&;ltDx-S1x=J)JqU>x zFilHK&`1+6sHGOY2zpEnOHCUsE4-DJm6nOUWdU-~6mQtg(v)3TG;fHOm(=}#=Pdg6 z>(A#i>^U=Yo-^l}ndf=tndf=NrHwW=KPZzU&NF9mR+f9-!p(-3SRc!l1IUp^onP0L zbPJWnI043A4modSyVOjqKEE!XMD?kA2qo~msLcsQe{#E73v!61CWYO7Cb94Y&rUw4WO=99Y8&K!v;m80rlnn><3A-p??S$crr7pvNSVHJ^n zKJ0b>#+pC_jM;04i2jEB?J5#P!F1lR`7wrsC1L~SlpAge)2D-Yx?1WK=m4IiJR=p>MKkgKPR#$MNdISk zZ*$M@TmPz4hfu~tAf2XQoD4t;u31!@-?=eA)}9~3=XYt(kH$8@8LhC8p5RGnu6YB7 zqCXHgcDP@vqlU6Ste%^8?zg8QkpEz|st!Va!mY zd$yM^^c|550h!>r$l=0P(LP#&y@fcZ!M}Tff0Bt?RLCtjs;(R@HP*Zu-K42zSh6nG zlC<8j+VlQn|8t!&Y!v#iB5%uF(Sj2W``m z_(b8|*202F#(;!#z#-_&TfiaK3XAb0d?P4t)G>-rE6cT=N~O2d${6|5X|=LI)yh&S zex$vEvQ(}7fVNBl+7=)!Lt2lt1L+&2Uyv>#-9Yk+gL55H98wBW7ScGRc}UBUwj=FE zYC!ThjemFJ=ud>ClnSr6V!`NfUSnMaIhK*OCNu)N^_8t*um)wCi#J=tHWOP-3A+&v zIBohaXZR$3=;wZJEJDS$nPq}3C3D=$*MWYZ2U_|AF;*xlffD(&3Q}6udWm@vTWc}s zfIsD3r$^~8&oJ*;uv62JE@Zs|A80%sc zi1fW1Y0q~6k>@=CBCKxJotszB^r>tekEQVn=hCGb(XEN!8Do9k4M0%=2*v0~CJeD1 z#n~8m3G6j_SXwdCTdM40Q~sn}gvxO8jgvlLQ3h5DXrpyX2LhHjJ!U;Xru4sgZ{Kx4r?g4ORYmD_# zHwwQ}fy>W40Ip1N1IG*m@UECA@2kLt{0`vC+W;<=tHArafeQnF_gcc0uSs!`3xu94s*Lz>UEd1wYoqtQh^|zU>Hy|11f>yqA+iqb@>5=q;q_hDRIU<(YxRak zy`I$u+fQ)I{v84qOwr&Te*`W)s(c0QhBV1p4U3}Cx`%6qhe9UU#XkhIwN76H=E9zd z-qzAnch$Kx!3n8VxwT)F?vz(LILX83U7_*NLL$W>ZN;8*5`NcIR<8=GuFdbk=l5*P zPd4;l{ zg{g(hN6vy6YXf=>BFJ{+OvU&@&iC$|50EnrIWNS(C5_dQ-fy)8^~L~yK1QXK$l2DK z8HW8jE4UJCS(o9go#|W>VRwlS+agVCHRvN%*>QG^n7kBQ>-fl=P*y91J;DSW9lMKq z_>554N>hBv0KQi|o#{)$ljN}dg~1|Lo@@ot*Xa?VGDGF(kFFC_-pg-Hm$zf zFbA$CyL?Gpl(MnKA_nA%Vu9#4NAyqj>&FfEhp;QWg`kC`hh9i*-LZys1OjY4?o89W z>8rQ(7eofefJt@Ifg&4(U)HfzgghbU-%|ZJ^m7r?BBWJF+mZGn9Yi{f)P_VbFhh}y zNWGBmUeIWU;CCES5z->0RY*IL>X4d|+K@0OFn+M~@AMd-pIDop(3l^8gtzC%wdZ%0 zB`0kcNm8lAhzxj=A11Y@dKK0hRv@^!#%wv$*{F}fqUpMCa^e@Fs)Gh+(6d}fG5+9+ zudW34MZ$)O%{sNwI!Vrqu`W;-tXRY|h>|BblBa6uVEsm&;YzGCvmHICv3C8+oe|^A zyuvatt-)0MTE8hTxo)c|0?r0HX|*50W@aRqVsr;nd`^9-&5$3t6vUhv3W02dJ2Ou) z7|2yMbm=kHD=L!~^3--H_nct{l_*N2bw@dCn)0XQ;F+y>KR~wQ1JtgO zt~pCirdR?CLsAPZZuUD6Z(-b5QyA>)W{HB>iiYk<_O?!TBS^qor`9u3f(g#R7;$E< zWG^*Xr@DEx&@INg&Hc_nZk+w$49jERQ+i#v=G@rGzD(|mS7G64^R_Zp2k}M&z|)vw z$eQEMaJ6L42iQttuufAkCCA06QW!e4pLHO5mbmtOhrC?&)scZ%(j&Hy-6*orMLZOtw(IaY73_8XX^_ zGCJiawxaYG2>gQ(9CU@(8bUu_@lpg>R;Y0vk zsB*$e2n$6aOoc9-V9>!uW#5?O(g2~IEMNtXsP#l$ez7p5Wr`KWD5cX zgX%{Z+@W1SJmX10q}ww}y)yyUPauJU1H(f0I&(Z_Uf*CpC<+wq8EJQIL$G|hR`5Kd z5!J68nN6;nPzuLhAWrI!SA8*nQeYx(ES z^Ah)?57;k8yx;@2Jt4$B;n?;dC~;#8W8Hmg-Kq_!`yR61f3Ec8#cn!%C;I=c2DjoJ zJ4*5I2c%0#w~zvjFb6{Fg_MOFOu#Z?Wll zrv2c8E9lS=l9aA|*Ru2}O-?EfxyW%?tenB>J}{*v8kz!CVz{kRIAt5)yNAdQ=MEd2 zesVkA8A3W`%l~a@v}!$6;>2t_K_|XyLD#G61NenwG@XrxNvGQ9H{8(PbB3+K$`S2; z--(bmD!5D3Ka@mtmv^@q5cqhXXk{DQ0QLpDk3OSIt~OXnJrnyjs0G63G&dB4UivxO zy4nr>k{dd8h83W#Ov-=PxzVm($;~ZH!~$`9#r^arXtj{Z2%vR|J7-4=1SNx2P$&2a z_-TMzNciQHm36>nF!bw)knv-5vfolcV`h7V(&m=>QeJ~yLWXzD;SXA{jrC9qcf;MA zZhgH7v?J0N*NEP%sQVc^I58Twu!l@^*=c?p(1dz6$v9bIUvW|(t>!VvmFt`q4qqc2 zVV)x=WxiE)coFtHZJgG^k+fv7e=pxu>9E@1dy1yjJVMp7*5EndSpHspPI5V+Lc?-i z1FLUFn%<=EbRyB-(kyid3-z=Hx24jYT2+6!|6e1TIdA_%XvLHhjwAcpC}2Q9vq zJ*htC^=!CKYpK_2q_{evD{CDd+JIL7lQ>48g=t7bkj5cRL4tk+UC;EnP~$e{N80lv z+VjKFYQu#$`6k&^dQjT!`96XdwdHHcC8~x9~ z=E7E!fuXSsR4Fh?Nau%sDY6J!qA(FdE3*VxIK`a`I;B5lK4m?Xdn*4_G57k4YKe$(Gxh zd-)b%o?317RE1FZ0kBpogPm@XPkI!T5AM(y0IOOsc*T<}+S)EQ=;b`Lb7>xEh7r~c zYJ*DGx?7at+>xh#Y$oWNj|#AYJ-x>uy4`t3;!%$wc+{lM9$py$&I<}7yo~9JS(E@c zVydz*I+Jaes-v>MGr__Re+Uu!qiz>`{)?->_jLxn7EQXcsKa3~#FQY19y5w3POZr*2W|Ejs$0@vKauqY z47I*T)BMc3}2uRnu866c0>sg z+|*B=;r=9uYFRRmn9;T&yMzr~VpE?hZv6h!3k zAp}?0a{jPEWFBMO(%-3f7m^q5vk4D9*n+#!6V4&fDr*wxoGzrhPP+!4@>qGwD_C>= zvO?1RmF4csuGpAePWN>okCa|oZLuK=5ofXS7MnI}3420$#F>RY#BpGp@?uL`01Q}2 z)*F~7{!;&kCBi~?NodwdRwAc4*%QBr^8A)@B0klWERw_VocVV&(Fm&;^Ze%~lEVhB z2g?uzuU*LkjJD`}9qFD>vwApIxq<~l9YZHPnlVG!4|mcY3_r1}tx_XHSAS4PV)(rg z)TtxJ;P+R9tjpb_YR0x1ru7g83|IHajakD-eu;n(f@g^)Jh z*H}m!Mn+$xyA7o8B&qD?cCO+HW01)Tbp`j_eKs{VloLU+J)} zkI_QZvvxG4%+Vw6H?lCkV%a@woYa(`aIEoQAi zg|kuCb*@siO9Gr}{zk`+0&DrS++!<5E%zd;qtpGVNe$Aaf_(~SqTs9rLCjAPQ8!mv zVSsVw{As8<`(IV1U!$z$YEMf(XjksnE37l784N+F`pmzo%0EYyS{JxSg(s`Kb48ln z*lx|A29J(zUGc>De?Rd<6x(lN!-$|AFptp=lTJoir@3FK?Z|snXpFKxqvi>`(~RXa zDr%JDQPzC-!y4?BDYJ0x!8{zKD>NydOpBAp-aN7Vp8mQk&2Jpn*U&}3Cn z5ntVZOomd;We=oZ#gmwROU@<-92#?OOf~l5##_081A(q_R@~^uROijmu!CyuwIc7t zZ!Ys`*RPG|lHm=jQ)fDXZUT~e$aNO(^TAx4=sK|QLSTmOAxfx7vW^SB{B@_1zdz<;#R8tLHf9Mt5 zm`+7v{7)po7A$W|a;u$pS$EwVRC+c9G3V zpV4DUq?4~SvnAQ@7U-As3B8&`^gb16TqV-(6dILGObA)f3?X5%hB0yB4@A%zYhz5j ztK!}AesHjQ<r>Ur z5K0q9kbD01H(c^(e_4_>O~YTab@em5?wYhE;=vnWt*rb> z-|hj%AY7(j^}xzS&^BXW^7`;(zgm4*qrQ_}AKI=D39gys*VfAnk4q5X9Q-b_fFL71 zhU*>I?+;Q#GO>V6-VfXl9zlnRUodrmj~bkV360ujeVZ%yn(N%Fg<9LFjIn*Txt;1ag#(ksn) zq5gZA+tv<+ z8I~Otq!tI$DQ3j!rY|96S89`9!hv8`%5m@|~yG?QtXy>1svotwq3XPELk zmNf9W+J9S)H+PTESb#JI!$d!lEkC`@CC!%FUbX_wFhk!p zH<>-y+$QDHIsIQQX>Jn?!@SI<$uLBpi{&M@voBdlXoey?YA!(~nU+(rKWhRuz=s4u zsSWG(99xoS$(7d7*lYPKK|lh8sFth}cA?}qWAhPP3KvR**jAd6N|LzO=!{g-TReB6 ztv#^6YmzHac!_?RN+L?rRz8sc3MDE5EzGh_z7eTL;kyyp9;>l**0i}H z@;p61%D^Jt?HL>~Dqbg_I#=JZsy0<>A(BaAE9mUM58T*|?mUPzYufB*Pn+q?UL^W) z<%Z+h3Yf>30*st+!(r+IyXnCQhjr6Y!>#nq%PKV@?o!??t&-i0lF`bR=J$h5>`MBm zxnd4bTPnuZd%_SzgJ2}ed#IEyN&}nexn9_JQU)-*jx+{{``JXbxQy&PR^>~FvCAHV z4`vO!hi$I|08>Fk67qr&K23$CmA-J~^%Ry8H)yR~-E4XqA(InRPfz5{#;2m=6I1;~ zt&tn9MMO5K53~NmgHo?nOHZM;QezrjI@Kyw{(>IqOTtBY zccjHn$HwOrfwuJ}kuWOtNh9WHA-3A&uf$f@{009aqnHKcPlN?tHTUItIyQ~yx|IAq zbdP6yk;d?hre7!PXH#K{C>2|sT6AC(_5e*h5s(Fg78I6006+do0Q>>U@VokRl2^Fq57`k0LIG`R+7Ip2z zb@mya!~MA9Khv}QNg@V==OaWH2I6LZ`c&;C1R`%2MM@R~h}&~Y4oXTMajJQyo+`1I=Kw93@pGLpl4M`TqTy zTP~9}H&`~`y>AVa!G%JywOn7dh0MNPB;4~q10Yj_Vlh7vhlTu1#}6Pl9pZ|;$@|r; z3F-cDzgW_oRiw(8i`nQ(2p({WM;u!wbRKeG?4j&7Dk|SQM9b|WLynFaKtR&yWcaMy zmgIp9H@{O3IM^u1K)~mNS}Wzw2d45J2PUeljTwdZxWFmLzpGL1n?(7POP<>7+*|>A<&crRx6<5P{}oW;#|Ej+=NuIc>+p z7b_YH#DJ##E9iUaq?3N%3icsFakI+v{KYQP>}Eq!NJYE36;WhXa*g!IbZpohVgT|g z5w+QKd{SOc1$zim&~ElcCF8h?QnocST#&an|C{@`Tsi2baY(A;*SQB>|Ih=!4|;xV zK?pMn1`I*($Q*^CS?jWG`H9=XUJI)SI(HxmjZ(geRJLGs5HvQ#we&Xgjx+B@wX@uN zbkjf*7QR8P%^QlM@dX=s#G|lnxyY@hM+cJd$k$k*p%MX&!wpFhVZogF9Tfk?Eu;5Q zTw4CHIPzM-3IwT#03dC4lw3hnV_aUSkT*H9cBq#dl}bm}H|pgM0hbNxg6Tr9SCR_?p`QK4;bz*Z**j`VPdFU)h!7}46YqS;u4tfwYED} zP{39R(h{UmI7Y7mziW{;BIWqe-v^P1CxsZtJ$|e`%F67_u}tuAoC&Be(jf3U=#C3L zy>uGl^{X!021Wx?l|R653+E)VkXHU&SEj9nU)CDZ6tyDjbw-WAJ=C99Xl@1xDGg^e zz;eb0dp7y6$a+sLTj{Q{#9?|5JFe(}qb{r@IkBVe=`~H-6G$7dlL?Og#g>O|5$N0qg?O^waXJ zv+4(ys&%Co9FLpM!kh(_-&QOC@Br@Sro+p#uDZXFZAall=Q>PR5sd=Oc zjUFfZp`NJw9%=wbA;3YuvXW?@?dZw9NH|dZcPojRto&`qELan471dcFIqk{f(qS65 zOX??_wby4o2)aI;6TBR1g#C*slFryYY5dnq6|sV z?#vC`PCC&>262`29UIu;h6h!maaamo@q-!z;J7HA)g6z%+ zE=`y_57;PTYzf>=+IKMNm7p}+F^FrutUFbwGwGO}O%>%%ga`V`wrzJ{+#(ipX!T$c z8YcbGkk%6>g+^_I!5C7p8F~!Cc!YjEn8X;AXCsvnysc-@*icvI9XASZL@-SkxCcT; z$k*xZ!KAy-q@nQ{y4?7TTfJ$IA*4&1tUUrD3Y{sr8q`fCg&e_aqvEjFR~Tv7w%gJ$ zA<(c$8j0fpZNa>lXDBj2xIazhA*6q)Fg4N?bP=u^_FPY4Mr7JIzciTiZ6_CFB^WzC ztt2tzG38l1D0dJnQw>2LVK#E@^0MLhz+`{no+Ar%AlYBO>qrZ-1$iLr2M1zN`)?d< z3-S!Rp%G5vbQeruqV#QMn}aNt8=UflzReF}atA&P%I#{vQ2L=a9U&1zhAe#t{)w-d z2rDxw*p4mb&@yzKsTkBJ|3a>EGQv{19m>?HSiRdSw;$oT&zP2|F*d zrHa#`c4`!uJUH>&j>y#rTGp7({2pyJF;auwv|8-pW^59Lcr>7285?SVd&WKh#&K^% zU+GuYF&3z!q8(L}{cJT6@`=MhZlZ%TNsvWY?GU@L z0zmy4BL%|z`vy+z;(kba-7$8K#;{dm+EmY@n=#XWq)Ri&c32NJwR)Z z$KH(){TcCKvuHhy&n5#$NCPl;e!#@B88lF31;~Th>|xXr9sh&8E`kvq5tE}nQ=^gB zVmva94bv~c_-rWrFMfB`57emf`Q&HpbXPWs?e7GCFJ+$$;ctF^uR_lsOS< zbP_?b*N@Z)b2?Ba|Lw3{nO)P>tEb5Nos3GsB3fhmc`k`iP1#d?t{VVO^w5 z#XQ1!9(sndf%bY8rA(J2y-0iIkY4eM(P7#4LsV*(7Fc9@NIBk-b;j(&u-ITXdoe8T zrz>+97N7YS7N^kW9AI(k11z>#C5A;N` zuw9b6+dZCO4gba6@W3I9gvUTi5gq;l8ZMdanRzN^e~B8RHa^d8+14DDYSO}XIarjY z*lpX+MPZH4EWG5&cDiXec%MLKo)`=HUJx9B<6myt%s)&=*Yu8 zUJKh&qU1Q}snO&juZ*MhkCAx(>JobSG17yVN7L9bDtA`S$ESBY*GHkuJTzwM$#86cvcP|G!9cOLz`=_l6J5Gz8UN;Yeyb@_A(%u2_85=X= zGmejn%wqA~GoHxUP9eBb1boN}Q?dNtfC+=ea}q*hqigc%Ur-OAr)vb!?5DLJ6N z@S_gleL|DRc8#&;X}kI0tt8&IbuQ;%IuTP(OxtsKKzgF7{yhu;#@b@E{Q^u~3?nO? z$;@hr=>d3UlwIs4#(z_gF1%_*^|B`DSHX~zwf(Hh5A?k!h&fow2CvR49+$skO}c<_ zG{H{oPmsQ&<*yH?<&MkGDmI1KpVno}(=|Q4`0-Ep%oGij)tCd>#pCm3o1HzmvA~^W z%l90gFIm;ROT0&rrlYEwucX;&(UWjJQ<{Gt2P5-zLCUpH1QJAkRM$7MiaoS!W&u!k zv62fAIMEOmx}qR8;jE|Vc}@Kn4^2*CR4BW6VXkaJji%m<7vvTeM6*n(r`^4Dk$-AZ z_cEj-O$%~Oug_0TO!rI{=j01=Pdlp}QOfS+B)fYVBcDWdwtR0gy{C3SH+xno%MlvY z0_9+nd6vsmnj9c4K5WJ=V?b@?DrL#xLs)-smNs;T8QY9Z&(F;|hC5?WAwRW|zuM=dLlA_^f~ud()5Q ziEA+v)sK6T(M5md%O+F6a2_%cVhh@n_G9M!VNa@qr_cU{c#)d_MH5`h!8C*c;7`%% zK+L#s_1VYqQ*u&TX>Yi!9)Opo1qI>0Sd9l!0Jp?&uhM^oH<|}grUZ%kiZV9_uSl#z zalaNRqdyE9utuGS#Lhfi@n6b^m)P%d^+lNw>yLN^}d?+qa3=6L6-9IC<~^oEVkc_ z{fO>=iUemBJwS;vC_K$izrt10q8nV9MII0JHO~ZiX`($7s;E4J&(Kc(dlvherJVmgkkkYs zu@#bC;%?FH<9_8F;tPkP$HcC}nWn;mUh37aP3AM~HS&TcM89pie*fH=pnLqUJ+k-` zUl{#(ntv(-8cXTp`9$a4fNSaHrrUmRzRQQ|wvLU@s05ADKRC-kUi!QFxBG_48d&QJ zeXHs2e0YuSJ5F!slQAH@BMZnQk;?PohWuQF@MAWE&xebHhieV_u%wdcmIBgal=4*g z&3CL&eKCFvp+uS;ZVAvtyZW0AgEc?DcfKCsjBNT`gMJhwAz?yz9=jfG)8~ycFA|;% z2Q71-3ue)eVz|qv`pIMn-d#AE;E466gp7lK-XHYMK>GP)lE^1srN2#P%%dOmor0al z^efcFeuEd#p;O3QFubp)kfFRXjFM-_2u`XR{R}DRko{93v2;_C!^d%!9|gnY?v^da z{=Jh0!4N)`>(*zIVU;a-fJOU6GN~BMwiT%5Su#FC@DI0PqvHoWkc9m+!7p5|MTB~M z__M^!A0J46dY1HIR!aU;NkOOX%ur#fKG~z*A8}p$ZJl|JpHJnfWI}KNE5f=5MqTNC z1L8Q}%k=tG@)&>O1)4pLbm0RB(dVX-g?;bNM?K7WaCk(^cyo@=t$|^)1Vex(3`c7R za5w%@eAV@4x!0``$h|tBMm+~hr!(_u{&S=o-#DMHe2(-HlsjQw#WdwPK9V*)M-2S# z`Ba!rrtw2xptGl|ivAVT8LlqSE=5H0fXFnF2()t%8HQMsY98HLLlC!JnpjjlAj~GOs znnjFSL8_+9XOR!JQvYh&dp7B-mHSlFS+mI_TE$XLKbcMLga}=$3-m%orlGP(GE~E_ z&rnVOTTCYLZF6YM9E_Mn2WkH~B-(4?L75INaxQXJ^3SZ=yq0X;z3$J zhxE~pRBKhcP}fk|iyOvnnN=wFHOtcPoI_*hqI$+b`p8^(E2SKy3+DnY%2xW>TwrU# z9O{}&lD)JlnEEla*F4gfzkYzum`A#L{c(Ub;gd0R{XD>EI#9J|9{HH#&lXoregXZ; z>ju$}7Lay6We|OLAqm$Cp=asdg`_A}e)l^ZrRQrf#o#m`rm(T+bY@{-G~#A?1GTt9TbLgWlk))_W7tlhJsBd?jO1dyWK7SeqRt)E}CkSils+Y)YHU;<+h|ONC9uBMB zd@tS4R;fdDx55%^5ws|DeF>RK{a*&c+g!%jhG5|?HNQ;KN{{z8iHOppAN?bKy*2ti zJ@D(P(Z86EUqPdPirs73F`D>A*oyz!OyWPJGAPdBa8PrUg?t7o8iJ+k*jqC^3|`S| zkh-(Z>L?HE2-jRj5wSpY#@2EM7L&moZ*tPIB_t#&=R!h;8f*!2>O6cl zi-WQNzZHY%r%OoKw9I0>u`sx|I}{{$Zvk#&X29kju~R{Kx!Wv5TnWcxGc=4M_orH6 zwC?2MOdQB2t}Hb4RL}k5uBrtqH@2&1Bybni+sjb9pJR`;E}+RW%q5RfNycjDQcE?> zC?lb?LMBr^cA`BcgXkTZ{E*_!L~J3+H)uul)l7uw_|kp3No;36swl*cbUhFxNvqOcG2}*tO>|Cp0b*4(6s$XKV3mi z`9C_}P!z<@)y2oHnMK#VN(y=91$ysQaxePw3n;5Mfvu%O-H9Oc!Ix;K zm82j4)k}2LN)pQNeu);YBys#lFVTvXQIAahub2>fqCb5P6c^G+yr^$j6V@|p!98?yXxucD=Hzfo8zx_vjX*w;V zB#%FMnEpt~sNglMEGsCD)5R@f;(f$)+IKy1@-G~wT{e*3QOBP{d1F#oR*A(=W2+0r zfn3Jn2z;a%$Zo?t^#zyGeR=NvNJKcj@aflw~zo!>Ak)8aX$Ex1mOa^kn2N<*KXt*sujN5;ZUfe?Te*b0p>gRA( z2WjM1GK+uvAYHMQr1I-#)9<#D{{*jlH8Vp4zPk3+%z^Cp)QPH*+lYw^=)#^o;vOMf z%t89f`(Thh2kFuGagf=g&r`1tNOsT##!o>@*f1Jj%(Wb#1s{-Uev!{Vo9vnFxfJli zo~OTjK>CO8Wi_)9J)whkWZcNk=e{^VP20&kA+NGR-3U+?z{xmwgL~xwJ+&QUrgaug z{*V;&V-C>D4>3j-Zp=!(b;98D6c!^!t78k^6SuqZ; zu)NWCV4iUh#{KH_M{$nyNGaxN<6usGYU%4A`u`!l}{;j^=G7u-wBqj zW^zZBs(qgkk@I_1&11OZmMQe7on&y}e0P?nONPdM11xsJZPhvfNrt6AzddeqU=d&q#uoBPqAJe=;#r;K6z2nNBUs&8=D_EU2e z8Q<$yR(u9y6I-!gve}lEkC95+l7nDFe3BK45yQP0-$RY%aIfHw?x){Yk@v&4vcg6c z@EHaeT1oD`{q)7Xq<62?tn4z=75H&Q>iplO5{4d(!mLoCM$Yio6}-V}Y}hny7bowp za_l8O9N&^zb@eN9lI#3rIbe({x>b@aqz5pfaIh8`=>ZJeN-aJ2H5tTzSxfcbkZAtX zS~~C>(kHT#RjCa!;A0zVG@V(uGMe~SEnWEy+0EZAql5R6{{+sH*&14-pDSZv>h~U| zC-#xa$tmpNdrScE=aSj=O7(hq6X(fD&H^S5crtO|1Q%aR^S>nvLV7R&0F*3ujO^mW zOcDsA{CDKhpg(Hx7(0i&%y2*VUxU`qt)bm($ddtk z83Q+7MJxdEF|K-2)w&uo0b=(7dcBsc=l33{TDhO(aKWE0_6T7w{bVuIacT7J-_whA zWL@yY>W{ zHtgGRkZKQs;p;ZhfrrTGn8@z{u{{V!nPru=jb@#kPDVkVDdU2_qn{kYYANtpHb!6I zFMdn24uh38d|Oq27%EnNyh44Bkf(VZ5HtM

)EG`lDny-&RL=93?Zj$7s|sayHnx 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 delta 68359 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 V(6mAobIgTCqcjWLx+gt>{2!h66662? diff --git a/os/Readme.md b/os/Readme.md index d258434..383f4ca 100644 --- a/os/Readme.md +++ b/os/Readme.md @@ -12,8 +12,6 @@ Firmware was compiled with the following modules: * LUA_USE_MODULES_NET * LUA_USE_MODULES_NODE * LUA_USE_MODULES_OW - * LUA_USE_MODULES_RTCFIFO - * LUA_USE_MODULES_RTCMEM * LUA_USE_MODULES_RTCTIME * LUA_USE_MODULES_SNTP * LUA_USE_MODULES_TMR From bb1aaa32a61564fa1ecf95b44554afcb14c5b534 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 11 Feb 2021 21:23:32 +0100 Subject: [PATCH 097/204] Changed architecture of lua modules --- displayword.lua | 2 +- main.lua | 55 +++++++++++++++++++++++++++---------------------- timecore.lua | 15 +++++++++++--- wordclock.lua | 12 +++++++++-- 4 files changed, 53 insertions(+), 31 deletions(-) diff --git a/displayword.lua b/displayword.lua index bf5303f..558697e 100644 --- a/displayword.lua +++ b/displayword.lua @@ -448,4 +448,4 @@ M = { countChars = countChars } end -displayword = M +dw = M diff --git a/main.lua b/main.lua index b637e5e..36aeec0 100644 --- a/main.lua +++ b/main.lua @@ -1,7 +1,5 @@ -- Main Module - local looptimer = tmr.create() -displayword = {} rowbgColor= {} function syncTimeFromInternet() @@ -13,7 +11,7 @@ function syncTimeFromInternet() syncRunning=nil end, function() - print('failed!') + print('NTP failed!') syncRunning=nil end ) @@ -27,27 +25,39 @@ function displayTime() if (timezoneoffset == nil) then timezoneoffset=0 end - local time = getTime(sec, timezoneoffset) - local words = display_timestat(time.hour, time.minute) - if ((dim ~= nil) and (dim == "on")) then - words.briPer=briPer - if (words.briPer ~= nil and words.briPer < 3) then - words.briPer=3 - end - else - words.briPer=nil + mydofile("timecore") + if (tc == nil) then + return end + local time = tc.getTime(sec, timezoneoffset) + tc = nil + collectgarbage() + mydofile("wordclock") + if (wc ~= nil) then + local words = wc.timestat(time.hour, time.minute) + if ((dim ~= nil) and (dim == "on")) then + words.briPer=briPer + if (words.briPer ~= nil and words.briPer < 3) then + words.briPer=3 + end + else + words.briPer=nil + end + end + wc = nil + collectgarbage() + print("Heap: " .. tostring(node.heap())) mydofile("displayword") - if (displayword ~= nil) then + if (dw ~= nil) then --if lines 4 to 6 are inverted due to hardware-fuckup, unfuck it here local invertRows=false if ((inv46 ~= nil) and (inv46 == "on")) then invertRows=true end - local characters = displayword.countChars(words) - ledBuf = displayword.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, characters) + local c = dw.countChars(words) + ledBuf = dw.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, c) end - displayword = nil + dw = nil if (ledBuf ~= nil) then ws2812.write(ledBuf) else @@ -114,12 +124,7 @@ function normalOperation() t:unregister() print('IP: ',wifi.sta.getip()) -- Here the WLAN is found, and something is done - print("Solving dependencies") - local dependModules = { "timecore" , "wordclock", "mqtt" } - for _,mod in pairs(dependModules) do - print("Loading " .. mod) - mydofile(mod) - end + mydofile("mqtt") local setupCounter=5 local alive=0 @@ -146,10 +151,10 @@ function normalOperation() elseif ( (alive % 120) == 0) then -- sync the time every 5 minutes syncTimeFromInternet() - alive = alive + 1 + alive = alive + 1 else - displayTime() - alive = alive + 1 + displayTime() + alive = alive + 1 end collectgarbage() -- Feed the system watchdog. diff --git a/timecore.lua b/timecore.lua index 4983a15..e7bb36c 100755 --- a/timecore.lua +++ b/timecore.lua @@ -1,3 +1,6 @@ +local M +do + --Summer winter time convertion --See: https://arduinodiy.wordpress.com/2015/10/13/the-arduino-and-daylight-saving-time/ -- @@ -27,7 +30,7 @@ -- @var dow Current day of week range (1 - 7) (1 is Monday, 7 is Sunday) -- @return true if we have currently summer time -- @return false if we have winter time -function isSummerTime(time) +local function isSummerTime(time) -- we are in 100% in the summer time if (time.month > 3 and time.month < 10) then return true @@ -103,7 +106,7 @@ local yearsize = function(year) end end -function getUTCtime(unixtimestmp) +local function getUTCtime(unixtimestmp) local year = EPOCH_YR local dayclock = math.floor(unixtimestmp % SECS_DAY) local dayno = math.floor(unixtimestmp / SECS_DAY) @@ -131,10 +134,16 @@ function getUTCtime(unixtimestmp) end -function getTime(unixtimestmp, timezoneoffset) +local getTime = function(unixtimestmp, timezoneoffset) local time = getUTCtime(unixtimestmp + (3600 * timezoneoffset)) if ( isSummerTime(time) ) then time = getUTCtime(unixtimestmp + (3600 * (timezoneoffset + 1)) ) end return time end +-- Pack everything into a module +M = { + getTime = getTime +} +end +tc = M diff --git a/wordclock.lua b/wordclock.lua index b71c206..11be758 100755 --- a/wordclock.lua +++ b/wordclock.lua @@ -1,12 +1,14 @@ -- Revese engeeniered code of display_wc_ger.c by Vlad Tepesch -- See https://www.mikrocontroller.net/articles/Word_cl_Variante_1#Download +local M +do --- @fn display_timestat +-- @fn wc_timestat -- Return the leds to use the granuality is 5 minutes -- @param hours the current hours (0-23) -- @param minutes the current minute (0-59) -- @param longmode (optional parameter) 0: no long mode, 1: long mode (itis will be set) -function display_timestat(hours, minutes, longmode) +local timestat=function (hours, minutes, longmode) if (longmode == nil) then longmode=0 end @@ -138,3 +140,9 @@ function display_timestat(hours, minutes, longmode) collectgarbage() return ret end +-- Pack everything into a module +M = { + timestat = timestat +} +end +wc = M From 744c36b8b5c778a2e0b2493846ca24dbaa7b8137 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 11 Feb 2021 21:33:06 +0100 Subject: [PATCH 098/204] Dump memory usage on several places --- main.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/main.lua b/main.lua index 36aeec0..09c3644 100644 --- a/main.lua +++ b/main.lua @@ -46,7 +46,7 @@ function displayTime() end wc = nil collectgarbage() - print("Heap: " .. tostring(node.heap())) + print("wc: " .. tostring(node.heap())) mydofile("displayword") if (dw ~= nil) then --if lines 4 to 6 are inverted due to hardware-fuckup, unfuck it here @@ -58,6 +58,8 @@ function displayTime() ledBuf = dw.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, c) end dw = nil + collectgarbage() + print("dw: " .. tostring(node.heap())) if (ledBuf ~= nil) then ws2812.write(ledBuf) else @@ -80,12 +82,12 @@ function normalOperation() -- Color is defined as GREEN, RED, BLUE color=string.char(0,0,250) end - print("Fg Color: " .. tostring(string.byte(color,1)) .. "x" .. tostring(string.byte(color,2)) .. "x" .. tostring(string.byte(color,3)) ) + print("start: " , node.heap()) local connect_counter=0 -- Wait to be connect to the WiFi access point. local wifitimer = tmr.create() - wifitimer:register(5000, tmr.ALARM_SINGLE, function (t) + wifitimer:register(2000, tmr.ALARM_SINGLE, function (t) connect_counter=connect_counter+1 if wifi.sta.status() ~= 5 then print(connect_counter .. "/60 Connecting to AP...") @@ -122,7 +124,7 @@ function normalOperation() end else t:unregister() - print('IP: ',wifi.sta.getip()) + print('IP: ',wifi.sta.getip(), " heap: ", node.heap()) -- Here the WLAN is found, and something is done mydofile("mqtt") From 72734f1337eaf3f896e10353bda8ae7aea7740a5 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 11 Feb 2021 21:48:05 +0100 Subject: [PATCH 099/204] clear more variables --- main.lua | 112 +++++++++++++++++++++++++++---------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/main.lua b/main.lua index 09c3644..ad5846a 100644 --- a/main.lua +++ b/main.lua @@ -34,15 +34,15 @@ function displayTime() collectgarbage() mydofile("wordclock") if (wc ~= nil) then - local words = wc.timestat(time.hour, time.minute) - if ((dim ~= nil) and (dim == "on")) then - words.briPer=briPer - if (words.briPer ~= nil and words.briPer < 3) then - words.briPer=3 - end - else - words.briPer=nil - end + local words = wc.timestat(time.hour, time.minute) + if ((dim ~= nil) and (dim == "on")) then + words.briPer=briPer + if (words.briPer ~= nil and words.briPer < 3) then + words.briPer=3 + end + else + words.briPer=nil + end end wc = nil collectgarbage() @@ -51,7 +51,7 @@ function displayTime() if (dw ~= nil) then --if lines 4 to 6 are inverted due to hardware-fuckup, unfuck it here local invertRows=false - if ((inv46 ~= nil) and (inv46 == "on")) then + if ((inv46 ~= nil) and (inv46 == "on")) then invertRows=true end local c = dw.countChars(words) @@ -83,11 +83,51 @@ function normalOperation() color=string.char(0,0,250) end print("start: " , node.heap()) - + ------------------------------------------------------------- + -- Define the main loop + local setupCounter=5 + local alive=0 + looptimer:register(2500, tmr.ALARM_AUTO, function (lt) + if (setupCounter > 4) then + syncTimeFromInternet() + setupCounter=setupCounter-1 + alive = 1 + elseif (setupCounter > 3) then + -- Here the WLAN is found, and something is done + mydofile("mqtt") + if (startMqttClient ~= nil) then + startMqttClient() + else + print("NO Mqtt found") + mydofile("telnet") + end + setupCounter=setupCounter-1 + elseif (setupCounter > 2) then + if (startTelnetServer ~= nil) then + startTelnetServer() + else + displayTime() + end + setupCounter=setupCounter-1 + elseif ( (alive % 120) == 0) then + -- sync the time every 5 minutes + syncTimeFromInternet() + alive = alive + 1 + collectgarbage() + else + displayTime() + alive = alive + 1 + end + -- Feed the system watchdog. + tmr.wdclr() + end) + + ------------------------------------------------------------- + -- Connect to Wifi local connect_counter=0 -- Wait to be connect to the WiFi access point. local wifitimer = tmr.create() - wifitimer:register(2000, tmr.ALARM_SINGLE, function (t) + wifitimer:register(2000, tmr.ALARM_AUTO, function (timer) connect_counter=connect_counter+1 if wifi.sta.status() ~= 5 then print(connect_counter .. "/60 Connecting to AP...") @@ -123,51 +163,11 @@ function normalOperation() ws2812.write(string.char(0,0,0):rep(114)) end else - t:unregister() + timer:unregister() + wifitimer=nil + connect_counter=nil print('IP: ',wifi.sta.getip(), " heap: ", node.heap()) - -- Here the WLAN is found, and something is done - mydofile("mqtt") - - local setupCounter=5 - local alive=0 - looptimer:register(2500, tmr.ALARM_AUTO, function (lt) - if (setupCounter > 4) then - syncTimeFromInternet() - setupCounter=setupCounter-1 - alive = 1 - elseif (setupCounter > 3) then - if (startMqttClient ~= nil) then - startMqttClient() - else - print("NO Mqtt found") - mydofile("telnet") - end - setupCounter=setupCounter-1 - elseif (setupCounter > 2) then - if (startTelnetServer ~= nil) then - startTelnetServer() - else - displayTime() - end - setupCounter=setupCounter-1 - elseif ( (alive % 120) == 0) then - -- sync the time every 5 minutes - syncTimeFromInternet() - alive = alive + 1 - else - displayTime() - alive = alive + 1 - end - collectgarbage() - -- Feed the system watchdog. - tmr.wdclr() - end) - looptimer:start() - - end - -- when no wifi available, open an accesspoint and ask the user - if (connect_counter >= 60) then -- 300 is 30 sec in 100ms cycle - startSetupMode() + looptimer:start() end end) wifitimer:start() From a355cff6e22ec0ce57753d7f1fd517f970e86f46 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 11 Feb 2021 22:14:04 +0100 Subject: [PATCH 100/204] timecore and displayword needs to be compiled --- init.lua | 17 ++++++++++++++++- main.lua | 4 ++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/init.lua b/init.lua index ab9be2b..f513b3d 100644 --- a/init.lua +++ b/init.lua @@ -21,10 +21,12 @@ function mydofile(mod) dofile( mod .. ".lua") elseif (file.open(mod .. "_diet.lua")) then dofile(mod .. "_diet.lua") + elseif (file.open(mod .. "_diet.lc")) then + dofile(mod .. "_diet.lc") elseif (file.open(mod)) then dofile(mod) else - print("Error: " .. mod) + print("NA: " .. mod) end end @@ -34,6 +36,19 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) t:unregister() initTimer=nil bootledtimer=nil + local modlist = { "timecore" , "displayword" } + for i,mod in pairs(modlist) do + if (file.open(mod .. "_diet.lua")) then + print(tostring(i) .. ". Compile " .. mod) + ws2812.write(string.char(0,0,0):rep(11*i)..string.char(128,0,0):rep(11)) + node.compile(mod .. "_diet.lua") + print("cleanup..") + file.remove(mod .. "_diet.lua") + node.restart() + return + end + end + if ( file.open("config.lua") ) then --- Normal operation print("Starting main") diff --git a/main.lua b/main.lua index ad5846a..5a45fcb 100644 --- a/main.lua +++ b/main.lua @@ -34,7 +34,7 @@ function displayTime() collectgarbage() mydofile("wordclock") if (wc ~= nil) then - local words = wc.timestat(time.hour, time.minute) + words = wc.timestat(time.hour, time.minute) if ((dim ~= nil) and (dim == "on")) then words.briPer=briPer if (words.briPer ~= nil and words.briPer < 3) then @@ -51,7 +51,7 @@ function displayTime() if (dw ~= nil) then --if lines 4 to 6 are inverted due to hardware-fuckup, unfuck it here local invertRows=false - if ((inv46 ~= nil) and (inv46 == "on")) then + if ((inv46 ~= nil) and (inv46 == "on")) then invertRows=true end local c = dw.countChars(words) From d1908c99c4c4e2990b806db70dd835ecb139fe47 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 13 Feb 2021 13:39:40 +0100 Subject: [PATCH 101/204] Brightness is published on mqtt --- mqtt.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 4137e33..5f35423 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -6,10 +6,10 @@ local t=nil function handleSingleCommand(client, topic, data) if (data == "ON") then - briPercent=100 + briPer=100 m:publish(mqttPrefix .. "/clock", "ON", 0, 0) elseif (data == "OFF") then - briPercent=0 + briPer=0 m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) elseif ((data:sub(1,1) == "#" and data:len() == 7) or (string.match(data, "%d+,%d+,%d+"))) then local red=0 @@ -22,7 +22,7 @@ function handleSingleCommand(client, topic, data) else red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") end - colorBg=string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) + colorBg=string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) if (displayTime~= nil) then @@ -30,7 +30,7 @@ function handleSingleCommand(client, topic, data) end else if (tonumber(data) >= 0 and tonumber(data) <= 100) then - briPercent=tonumber(data) + briPer=tonumber(data) m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) else print "Unknown MQTT command" @@ -55,7 +55,7 @@ function parseBgColor(data, row) end if ((red ~= nil) and (green ~= nil) and (blue ~= nil) ) then m:publish(mqttPrefix .. "/"..row, tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) - return string.char(green * briPercent / 100, red * briPercent / 100, blue * briPercent / 100) + return string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) else return nil end @@ -149,7 +149,7 @@ function startMqttClient() readTemp() -- read once, to setup chip print "Setup temperature" end - oldBrightness=0 + local oldBrightness=0 oldTemp=0 local mqtttimer = tmr.create() mqtttimer:register(5001, tmr.ALARM_AUTO, function (t) @@ -158,15 +158,15 @@ function startMqttClient() if (t ~= nil) then temp=readTemp() end - if (oldBrightness ~= briPercent) then - m:publish(mqttPrefix .. "/brightness", tostring(briPercent), 0, 0) + if (oldBrightness ~= briPer) then + m:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) elseif (temp ~= nil and temp ~= oldTemp) then oldTemp = temp m:publish(mqttPrefix .. "/temp", tostring(temp/100).."."..tostring(temp%100), 0, 0) else m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) end - oldBrightness = briPercent + oldBrightness = briPer end end) mqtttimer:start() From d309315e289a8e7c7ac10350288abc71e1a104ba Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 13 Feb 2021 14:17:58 +0100 Subject: [PATCH 102/204] Mainloop is stopped on upload --- main.lua | 8 ++++---- mqtt.lua | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/main.lua b/main.lua index 5a45fcb..dbf70ef 100644 --- a/main.lua +++ b/main.lua @@ -1,5 +1,5 @@ -- Main Module -local looptimer = tmr.create() +mlt = tmr.create() -- Main loop timer rowbgColor= {} function syncTimeFromInternet() @@ -87,7 +87,7 @@ function normalOperation() -- Define the main loop local setupCounter=5 local alive=0 - looptimer:register(2500, tmr.ALARM_AUTO, function (lt) + mlt:register(2500, tmr.ALARM_AUTO, function (lt) if (setupCounter > 4) then syncTimeFromInternet() setupCounter=setupCounter-1 @@ -167,7 +167,7 @@ function normalOperation() wifitimer=nil connect_counter=nil print('IP: ',wifi.sta.getip(), " heap: ", node.heap()) - looptimer:start() + mlt:start() end end) wifitimer:start() @@ -185,7 +185,7 @@ local btnCounter=0 local btntimer = tmr.create() btntimer:register(5000, tmr.ALARM_AUTO, function (t) if (gpio.read(3) == 0) then - looptimer:unregister() + mlt:unregister() print("Button pressed " .. tostring(btnCounter)) btnCounter = btnCounter + 5 local ledBuf= string.char(128,0,0):rep(btnCounter) .. string.char(0,0,0):rep(110 - btnCounter) diff --git a/mqtt.lua b/mqtt.lua index 5f35423..d71de9b 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -95,8 +95,10 @@ function registerMqtt() m=nil t=nil mqttConnected = false - if (looptimer ~= nil) then - looptimer:unregister() + if (mlt ~= nil) then + mlt:unregister() + else + print("main loop unstoppable") end collectgarbage() mydofile("telnet") From 621cef2ab5de4397e1dcbb65d793c5b4bf0b9d5f Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 13 Feb 2021 14:25:57 +0100 Subject: [PATCH 103/204] Extract IP address for telnet server from MQTT --- tools/remoteFlash.sh | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/tools/remoteFlash.sh b/tools/remoteFlash.sh index c8d3446..3f679a0 100755 --- a/tools/remoteFlash.sh +++ b/tools/remoteFlash.sh @@ -1,38 +1,46 @@ #!/bin/bash -IP=$1 +MQTTSERVER=$1 +MQTTPREFIX=$2 FLASHTOOL=./tools/tcpFlash.py +UPGRADEPREP=/tmp/upgradeCMD4clock.txt + if [ ! -f $FLASHTOOL ]; then echo "Execute the script in root folder of the project" exit 2 fi -if [ "$IP" == "" ]; then - echo "IP address of ESP required" +if [[ "$MQTTPREFIX" == "" ]] || [[ "$MQTTSERVER" == "" ]]; then + echo "MQTTSERVER: ip address to mqtt server" + echo "MQTTPREFIX: configured prefex in MQTT of ESP required" echo "usage:" - echo "$0 " - echo "$0 192.168.0.2" + echo "$0 " + echo "$0 192.168.0.2 basetopic" exit 1 fi # check the connection -echo "Searching $IP ..." -ping $IP -c 2 >> /dev/null +echo "Searching $MQTTPREFIX ..." +mosquitto_sub -h $MQTTSERVER -t "$MQTTPREFIX/#" -C 1 -v if [ $? -ne 0 ]; then - echo "Entered IP address: $IP is NOT online" + echo "Entered Wordclock address: $MQTTPREFIX on $MQTTSERVER is NOT online" exit 2 fi -echo "Upgrading $IP" +echo "Activate Telnet server" +mosquitto_pub -h $MQTTSERVER -t "$MQTTPREFIX/cmd/telnet" -m "a" +TELNETIP=$(mosquitto_sub -h $MQTTSERVER -t "$MQTTPREFIX/telnet" -C 1) +echo "Upgrading $MQTTPREFIX via telenet on $TELNETIP" -echo "stopWordclock()" > /tmp/wordClockCMD.txt -echo "uart.write(0, tostring(node.heap())" >> /tmp/wordClockCMD.txt -echo "c = string.char(0,0,128)" >> /tmp/wordClockCMD.txt -echo "w = string.char(0,0,0)" >> /tmp/wordClockCMD.txt -echo "ws2812.write(w:rep(4) .. c .. w:rep(15) .. c .. w:rep(9) .. c .. w:rep(30) .. c .. w:rep(41) .. c )" >> /tmp/wordClockCMD.txt -$FLASHTOOL -f /tmp/wordClockCMD.txt -t $IP -v +echo "stopWordclock()" > $UPGRADEPREP +echo "uart.write(0, tostring(node.heap())" >> $UPGRADEPREP +echo "c = string.char(0,0,128)" >> $UPGRADEPREP +echo "w = string.char(0,0,0)" >> $UPGRADEPREP +echo "ws2812.write(w:rep(4) .. c .. w:rep(15) .. c .. w:rep(9) .. c .. w:rep(30) .. c .. w:rep(41) .. c )" >> $UPGRADEPREP +$FLASHTOOL -f $UPGRADEPREP -t $TELNETIP -v +exit 2 FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua wordclock.lua init.lua" echo "Start Flasing ..." @@ -43,7 +51,7 @@ for f in $FILES; do exit 1 fi echo "------------- $f ------------" - $FLASHTOOL -t $IP -f $f + $FLASHTOOL -t $TELNETIP -f $f if [ $? -ne 0 ]; then echo "STOOOOP" exit 1 @@ -51,6 +59,6 @@ for f in $FILES; do done echo "TODO: Reboot the ESP" -#echo "node.restart()" | nc $IP 80 +#echo "node.restart()" | nc $TELNETIP 23 exit 0 From 6232bf5180d51f0f0eea24fb5ddc59363fe76c8c Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 13 Feb 2021 15:11:42 +0100 Subject: [PATCH 104/204] Use table syntax to work with >lines< --- telnet.lua | 66 +++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/telnet.lua b/telnet.lua index 9bac3bc..8138adb 100644 --- a/telnet.lua +++ b/telnet.lua @@ -1,36 +1,40 @@ +-- Telnet client +local telnetClient=nil +lines = {} -- Telnet Server function startTelnetServer() s=net.createServer(net.TCP, 180) s:listen(23,function(c) - global_c=c - printlines = {} - function s_output(str) - if(global_c~=nil) then - if #printlines > 0 then - printlines[ #printlines + 1] = str - else - printlines[ #printlines + 1] = str - global_c:send("\r") -- Send something, so the queue is read after sending - end - end - end - node.output(s_output, 0) - c:on("receive",function(c,l) - node.input(l) + telnetClient=c + function s_output(str) + if (telnetClient ~= nil) then + if (#lines > 0) then + table.insert(lines, str) + else + table.insert(lines, str) + telnetClient:send("\r") -- Send something, so the queue is read after sending + end + end + end + node.output(s_output, 0) + c:on("receive",function(c,l) + node.input(l) + end) + c:on("disconnection",function(c) + node.output(nil) + telnetClient=nil + end) + c:on("sent", function() + if (#lines > 0) then + local localstr = table.remove(lines, 1) + print( tostring(localstr) ) + telnetClient:send(localstr) + end + end) + print("Welcome to the Wordclock.") + print("- mydofile(\"commands\")") + print("- storeConfig()") + print("Visite https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en for further commands") end) - c:on("disconnection",function(c) - node.output(nil) - global_c=nil - end) - c:on("sent", function() - if #printlines > 0 then - global_c:send(table.remove(printlines, 1)) - end - end) - print("Welcome to the Wordclock.") - print("- mydofile(\"commands\")") - print("- storeConfig()") - print("Visite https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en for further commands") - end) - print("Telnetserver is up") -end \ No newline at end of file + print("Telnetserver started") +end From c5a99e58f07dc247714bb512532bc9f4d7bf928d Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 13 Feb 2021 15:12:11 +0100 Subject: [PATCH 105/204] Documented parameter for diet tool once everything is working --- tools/initialDietFlash.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/initialDietFlash.sh b/tools/initialDietFlash.sh index f258f67..0df989c 100755 --- a/tools/initialDietFlash.sh +++ b/tools/initialDietFlash.sh @@ -3,6 +3,7 @@ TOOLDIR=tools/ LUATOOL=${TOOLDIR}luatool.py +#DIET=bin/luasrcdiet --maximum DIET=bin/luasrcdiet DEVICE=$1 From bf360700d3d6413b377bf5c6680fd04e12c059ed Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 13 Feb 2021 15:39:43 +0100 Subject: [PATCH 106/204] Different way to access table --- telnet.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/telnet.lua b/telnet.lua index 8138adb..cd30e31 100644 --- a/telnet.lua +++ b/telnet.lua @@ -26,9 +26,13 @@ function startTelnetServer() end) c:on("sent", function() if (#lines > 0) then - local localstr = table.remove(lines, 1) - print( tostring(localstr) ) - telnetClient:send(localstr) + l1=nil + for k,v in pairs(lines) do if (k==1) then l1=v end end + if (l1 ~= nil) then + table.remove(lines, 1) + print( tostring(l1) ) + telnetClient:send(l1) + end end end) print("Welcome to the Wordclock.") From b02392dc642f15ded9422d3c7e051869f9d01927 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 13:20:38 +0100 Subject: [PATCH 107/204] Refactored telnet code --- telnet.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/telnet.lua b/telnet.lua index cd30e31..da97109 100644 --- a/telnet.lua +++ b/telnet.lua @@ -26,13 +26,13 @@ function startTelnetServer() end) c:on("sent", function() if (#lines > 0) then - l1=nil - for k,v in pairs(lines) do if (k==1) then l1=v end end - if (l1 ~= nil) then - table.remove(lines, 1) - print( tostring(l1) ) - telnetClient:send(l1) - end + local line1=nil + for k,v in pairs(lines) do if (k==1) then line1=v end end + if ( line1 ~= nil ) then + table.remove(lines, 1) + print( tostring(line1) ) + telnetClient:send(line1) + end end end) print("Welcome to the Wordclock.") From 9da84127f4750d7783529b55bad6f65ce87f1c1a Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 13:23:14 +0100 Subject: [PATCH 108/204] Formatting --- main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.lua b/main.lua index dbf70ef..96a1fcd 100644 --- a/main.lua +++ b/main.lua @@ -109,7 +109,7 @@ function normalOperation() displayTime() end setupCounter=setupCounter-1 - elseif ( (alive % 120) == 0) then + elseif ( (alive % 120) == 0) then -- sync the time every 5 minutes syncTimeFromInternet() alive = alive + 1 From dcc660d8d65cf98b4fa64789c3143190a42ca189 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 13:44:54 +0100 Subject: [PATCH 109/204] Set connection status, if MQTT get disconnected --- mqtt.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index d71de9b..987cdff 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -117,7 +117,11 @@ function registerMqtt() end end end) - + m:on("offline", function(client) + print("MQTT Disconnected") + mqttConnected = false + end + ) m:connect(mqttServer, 1883, false, function(client) print("MQTT is connected") mqttConnected = true From 5fafff7abc0c02b8ac9f3f42b4e585548b375cea Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 14:13:46 +0100 Subject: [PATCH 110/204] Main function has buffer included --- main.lua | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/main.lua b/main.lua index 96a1fcd..440596b 100644 --- a/main.lua +++ b/main.lua @@ -1,6 +1,10 @@ -- Main Module mlt = tmr.create() -- Main loop timer rowbgColor= {} +-- Buffer of the clock +rgbBuffer = ws2812.newBuffer(114, 3) +-- 110 Character plus one LED for each minute, +-- that cannot be displayed, as the clock as only a resolution of 5 minutes function syncTimeFromInternet() if (syncRunning == nil) then @@ -64,12 +68,14 @@ function displayTime() ws2812.write(ledBuf) else -- set FG to fix value: RED - local space=string.char(0,0,0) local color = string.char(255,0,0) - ws2812.write(space:rep(107) .. color:rep(3)) -- UHR + rgbBuffer.fill(0,0,0) -- disable all LEDs + for i=108,110, 1 do rgbBuffer.set(i, color) end + ws2812.write(rgbBuffer) end -- cleanup + i=nil briPer=words.briPer words=nil time=nil @@ -131,37 +137,23 @@ function normalOperation() connect_counter=connect_counter+1 if wifi.sta.status() ~= 5 then print(connect_counter .. "/60 Connecting to AP...") + rgbBuffer.fill(0,0,0) -- clear all LEDs if (connect_counter % 5 ~= 4) then local wlanColor=string.char((connect_counter % 6)*20,(connect_counter % 5)*20,(connect_counter % 3)*20) - local space=string.char(0,0,0) - local buf=space:rep(6) if ((connect_counter % 5) >= 1) then - buf = buf .. wlanColor - else - buf = buf .. space + rgbBuffer.set(7, wlanColor) end - buf = buf .. space:rep(4) - buf= buf .. space:rep(3) if ((connect_counter % 5) >= 3) then - buf = buf .. wlanColor - else - buf = buf .. space + rgbBuffer.set(15, wlanColor) end if ((connect_counter % 5) >= 2) then - buf = buf .. wlanColor - else - buf = buf .. space + rgbBuffer.set(16, wlanColor) end if ((connect_counter % 5) >= 0) then - buf = buf .. wlanColor - else - buf = buf .. space + rgbBuffer.set(17, wlanColor) end - buf = buf .. space:rep(100) - ws2812.write(buf) - else - ws2812.write(string.char(0,0,0):rep(114)) end + ws2812.write(rgbBuffer) else timer:unregister() wifitimer=nil @@ -188,8 +180,8 @@ btntimer:register(5000, tmr.ALARM_AUTO, function (t) mlt:unregister() print("Button pressed " .. tostring(btnCounter)) btnCounter = btnCounter + 5 - local ledBuf= string.char(128,0,0):rep(btnCounter) .. string.char(0,0,0):rep(110 - btnCounter) - ws2812.write(ledBuf) + for i=1,btnCounter do rgbBuffer.set(i, 128, 0, 0) end + ws2812.write(rgbBuffer) if (btnCounter >= 110) then file.remove("config.lua") file.remove("config.lc") From 7b31b0125968a5b2d48b5e2b4ec31c8f8fa5103e Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 15:45:32 +0100 Subject: [PATCH 111/204] Added serial debug information --- telnet.lua | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/telnet.lua b/telnet.lua index da97109..d09d96c 100644 --- a/telnet.lua +++ b/telnet.lua @@ -1,21 +1,25 @@ -- Telnet client -local telnetClient=nil -lines = {} +telnetClient=nil +local lines = {} + +-- Helper function +function s_output(str) + uart.write(0, "T:" .. tostring(str)) + if (telnetClient ~= nil) then + if (#lines > 0) then + table.insert(lines, str) + else + table.insert(lines, str) + telnetClient:send("\r") -- Send something, so the queue is read after sending + end + end +end + -- Telnet Server function startTelnetServer() s=net.createServer(net.TCP, 180) s:listen(23,function(c) telnetClient=c - function s_output(str) - if (telnetClient ~= nil) then - if (#lines > 0) then - table.insert(lines, str) - else - table.insert(lines, str) - telnetClient:send("\r") -- Send something, so the queue is read after sending - end - end - end node.output(s_output, 0) c:on("receive",function(c,l) node.input(l) @@ -27,10 +31,15 @@ function startTelnetServer() c:on("sent", function() if (#lines > 0) then local line1=nil - for k,v in pairs(lines) do if (k==1) then line1=v end end + for k,v in pairs(lines) do if (k==1) then + line1=v + end + uart.write(0, "Lines:" .. tostring(v) .. "\r\n") + + end if ( line1 ~= nil ) then table.remove(lines, 1) - print( tostring(line1) ) + uart.write(0, "Telent[" .. tostring(#lines) .. "]" .. tostring(line1) .. "\r\n" ) telnetClient:send(line1) end end @@ -39,6 +48,7 @@ function startTelnetServer() print("- mydofile(\"commands\")") print("- storeConfig()") print("Visite https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en for further commands") + uart.write(0, "New client connected\r\n") end) print("Telnetserver started") end From eb1760cbaa2d67e38765c732660508c62907d1a4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 15:53:11 +0100 Subject: [PATCH 112/204] Added pipe module to the firmware --- os/0x10000.bin | Bin 413696 -> 413696 bytes os/Readme.md | 1 + 2 files changed, 1 insertion(+) diff --git a/os/0x10000.bin b/os/0x10000.bin index 01b82ffe22ac43c75679a2bfb66225447546b27e..62a7c137d776c3cb17e9da4498ff4f57b605311f 100644 GIT binary patch delta 10264 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 T2w>F`EPP`ezyGklJooS~DD1d?pR`<^{#TVAJ~ zdCYw0e(vx7?z!jB@BC$3x>H-aQ~mw>4JXYt^LHKE&kyY!?;HN z%3r-tJ55L#f2mPBNQ{&(b4(Y%`{&v<#Ha>4_@3?By7@%sCw6KFE+uZZr%T&xG~iJy zvpuUlLVEcV&uWV`($DukhrEyhwsN=jB?<7%=e5mxG}|-qwoD@XkORu#PyI%FQA^E> z%QaJQp9cBA$T6L`=0nAN!%Nz6N=$asUhO%f9Hs{L)n26D&hCE&CGBKSzoM-&{CF_R zK79ohH^ejdX`2bDXT-?=Hpi^yb?<81DBAYOutqgw^t&8$f`9q}@G!RW@c+~ZHIdK&ZFA71ltgJ z6!Nf#k7?@+6ZJ91J~@Vpn&eyliu$nWQ>b>x&fon~+e%0VEBHz~ZYzeV5~}CfUn3t0 zUa%h;gaZ7~H(K*NEpme0a8mn-q_E_$_Khw7do=l1Ic6!dozk96aEn{02A}U>FTq5H zSjlPa5iRmPf9JIJOOoI?i9#WQ({L^0n`RIdwsNq3I>!vM^=A>ImF&z}tvS(o0(B>{ zgQs46qlrCwPCJYiTOUENwZYoM_D4{{E?|I@^V&R;5CmJocmc_!vE&QdK2pTrzM#bu zQqGUeYD>v-Hy$@Yh0|H4M+h8uCd(WSXPK?wcF2M6jm~D7UT~Nd5c=mOBGcVSwGZlt z2B1M`2pWch&=iD@tkEw?f_)mD1`3}S9cGD6Zzri9+;>4g*nReF0N2Q|3v0%3)%jBf zy@Q}uzqQiM#N_Me(d}Bg=#VutIcCK?r|Gac%_*zX^x!@v&WY~wg^g0p<~oCVgc{km z@$^7K05}2#A)W8F)5mqggF12XwTX0_mSCb%3(w}5MNldK?Zp%oQ^DR&qQ^-se=V8L z64K6JTST`Lgl0i1U8Ea&1cm0eq|;>@Y&$NeFHEq>w&Bs@dCx^hwgnH?E)fDr%=ustR8 zLn8>BWII;V&FK}$Wjj;@O~D+2;=m55k)K*kG3xnP;##`R=!YrDcCMxCNF4veTH36k zf!CMPrADzO*DPlbmeP+gOy71B{WBqrZ28UfFBqSb%jg}N5r9XC-TQB7kT`ztI!Z}u z8p$>DphC!mDxhkpogAhmr#EWGAUK8Z*+7p{V+w5HJ2%odC@Eqk zo9Ht1w7WOa>(KIhHqjpu(!j`OdX3GaAt9)Xmu#jOaeb^{E4|U?hiL#B<~z31qlAp` z+v?~VBF6fkh{~McFWreCCl-F*OM49dWbTN z+@~Hw)w&t1*P$T4lS|Kmg1^HOr^YmbHMnbOXfUbf9_FS_V zS36(%0(ur^-;zD_XJnM^-$U<74B@3Pq|eJW_GNmI*u3B_sF&OJ(g#Rp zKX?QhheA*Uve=L<$N}Z^J+IJPNkS>O0;+);IPud5G{Xz-;X7Xy4c5<}K7b%WXa4*( zx|P@_@T?pa;NiD$M1@fs<%a|G05RIZK34KN-IbWMAlGz47Kg=BgljoF@;bt_1`{eu z6UP(!(ajO*yWgb0LbDhAj(&{cpJ@l_PYt&NEynIWNIxV#zIK3KEW&8RArXA&%5RBq znq(&q(>F*t+dD`vCl3CHK@n7iEb|?B)$#}55yM#Z#kr;%YJ^(YsUh?>(Fvpq}M zwagjZ+mmz6B*+QnLH#2bIdN@-{CxiieU4y~yX_+kLvDWRBScK%2p)|=Q_u{g^Bto| z&Tw3UWY|l8q{}uXAs6Mit%PczdZ-C%g*u^LXb>8P#vpwWaslN-MNk=31yw`cP$N2~ z57$0ul&?5SS7}Cc=3)1LO5Z0*eC>auvW-Uck{Z78GkTbiB$oa;-Ii>oBL`6aI3}3S zFtL2@G~3y;pVMh9WS;sHD!q%J_>+hiKeGktlSUZ5u$S!)(mRZPyf?zm2kB?%{hxk8 zw`!OXN+#%EG&0OGzodtavCDGJ3HH^O^!AmaGTq4L$Q9^GFh`)c%TX*S4f>}&8a=z3 z-#8nn0UUuWcsGM3oJ9CJ+4_^HFBeM<)9Z{lWYxV^8DF(?Fup*Sb{G~|R_P#IJOH9~EW59))4p>ZhUTG`%see22|SbCvR zC_;!sPa=XJT%doJAcp0?jq|L|q5qyZ zSV5wGJTYYndJ9wvRYA49V4?nkW;B7@_$NvFVjaqCaEn1d0Om@VYDYU0OmP?uVdz?rOMmoS({v4b$|FW%?>x?KQdP z^GDs52L9$UQ46i?{Br%EA;#lQe&}j_o7n6X6zZF?MR=@G$ADA50{Q1}UaRjS+2SJ| zOHos>d7xIP0?V{^TsxpHsGQdo>C?pUfdhQY_4+;37zU5>PfGMVG*Zh7O#Nhnn9PDO zCtWK7ykM=4HBTYGrVbVGh9P@HXcnc3z@MYcJ}AN_&; zF}>(Tp>?M6sU;61SUpkAmC8h}bu#ENA15A~xO_BT5= z>IcQHb7i%jrDJN@RHI`qa_|#d^pgfwsmJcr*V(Y&S$;3V$HlYn6K=@*&-LwuIQgON z`T>Gn>is+PM+lax=l?@rq@|W)Gay!tCW_R!21QOrzs0qk7d)unObkER!*@KSe^^QK zAGzgYo!|1YF_p+xA2XKCzq(-g@{Frp*B4&LwjVPxIXh;o(3`{9ltrL8BrWzDDNqKK z2f3gk$b`zE3aARIf!t679c_)3b{)auS?%9v88jb#{<9-KB_)DpU}fgOM*AUj)r z)|lNgiOr}ZMS4$x%}XTDh>hwZ$@)3CE4G9E$|ngNNR~cn;5@}n@KBPpJJ=KF&?@=- zwR6TJl*F-;S=<(}Ewjd=%oMB}`--sc!BxM`8O^>ZLLTlttDV?6KRs)_uQ!iV%xb%2 zf)ilhe@YI48x;4VHhOkSyI3YU6-U7S7HRK6TQ?|<({s(qW@%3X_bSFDV>T+z2e+V%*F;Bwr{6SEvk?gKLz%iX|A zFUbSo$Pn{E7DI12`m*gYMd}Ks%61Y#X6YPFo`s9O?UX)x6wkR$K zcVm?)!cOd6TH|x0J-!ll0-G2ks@U>)YgYOIOw~}|9_d~WHWho=y>O|k#M@#R4ZbE_ z#L#NTR!)o|t#B`YS=!sdh04d3jrMy*+B;y^{gR`(c~x>3>|F;Wce6A2RCC8a`IOi- zicg8D)v;H)|9?K^L-N7>(%%oxP@nx*SqRL}oo~kV&B@PY*W2-3OByopkL4Fz+J7v6 zH$Kv;-fw5;?Pyq>k0w~JA<@w8`K?TP46l|c79rdgkakgJ6JTUw(i{2E@aWdyPm9Y~SA+HrId4cuiB_1qxdf$+rYXgs| zPj`Z2$@YL}*%yngms$;B^K+ZS8n4w&;;2R+l<#(6K6m|2WgEpDRrYS!V@2?RV`=uy z;ek0m!*lH8!XEuD+jq_|njH(#tq_?#Z>sMgGRv_M6)htUHT&L@b}@^!C=MYF=R3+D z?C6)=gKnuGlpKM*NwJP^R2@?OSk(qpnb7U8FiQvIgE%-94@nj~Ft2h7vXvL3YCHL+ zi>+7aV!e`y)0;hutlPEbNo*uT&=eGb>{w@s$|%OQ{8O2hSbG&6m0S)EEtZ9=1o!?? z+H1f=>f80;acsLq1vG$XK9W8jaINxh2YW`H&C$_8OlUpoWid$2d@Nt+fK#7h`;}O; zzc20Gu(v6@Pb8|?4-UO2efq(rBa#Qfl`0d%;67y^O=(87BbOq2gLu%bI0PR5P`*3^ z_AAy?(Q6btz%IpNX;h6(wHWGBV0V8Y*$J*tHIWA%`h&C=gR4Yg*wc%xi$AN%&*b|hMAr`$=iba31D;Dp>{{EGZm}UF_N2a5*CoZ!tORPom z;(N)K3!+&qh5X267#7xw8B&}eh=rN3i*mTXm9L6_hxtO1#i(BSrLtql2p*SQ#nLma zi<)b3h|qXKn#B6kaZ+*v>t+yr~achaXtuu85C-1LpKd%+IHo#22C-jXEHH?PGrgn#2G6a zT)fI{fZ;tR>fk$TOFS*2Nxaft*Zw~ z;K8uWLsjVaO`7!U|pp%ILChk9L=csN)R`(M5n;9mn~Sw#9p?8 z4V6#|7#Pi59y?Ni<&Zrefg?^`t+LjO;L>48Ho<8#vO>$iDXNt!z}?DT1FoHxK5lTw zDaj4s8C|9$mLoyM9@vK!`>eTEb3n8V+cIrj!XCfMYNSsU$PBsE#~f(-VU=hX+kX}E z?8Pfyq%*3?^t-@zD%l5aQ+83VnhP>NVre&gUUDDUt9SrhxKO@31fD!6eMZ5)vyw%5 z+f{i{mS)qd9*Dwt6bHe5%1KmQ+?)!kP!$w{efYFYGz@N6Y(XQ0RT)J^>#FRcLR*ym z@6jEH;SGJDD;ymbte1!u9pPt|St+@E6o*$mIkGt8;PPb2lVE2?HrqUHq~o+~<#Ow- zq*Cn(!@<>;!k@NzMny!qNqf zb*v(AEJRDM&b>PNAz>(=<5UTTDH@|ybGSzM$c5RhB{**AVjHiq{<+zY^E6kX{B8iO zEA9tRT_f#-;Fe{QtHHf4$;03_#bQg{t^7w}k7Z#394pHdI93+%9DnTiVyis=sB;y{ zA-HR~OkIr9#W-LSqjUss4qYwnaq#n~FNxr`D7)DFyVSc5_{7pl0~e}XI$6OA48eo^ zwiVWCt$7^habqPi*$MDDoX&{)v|NWqRh$MsuQ(rkL2(%v81=6Oi`T@vP2gA|JHfHS z_km-LHwMP|GB5f<eY`irc2Q)iYT61Z$s9euR=^!dD#ul7B#!BS?$4cb{ z$4XTMj+Lqu92+&Oz=o<3H`uD!1D>bY3r1hOG+GNixS6jW#9?OaUH!LVO@wQ6XEA0o z_{1{N4~}JG2pr4AC^(jh32-bEVQ?%HmQ{bxgdL1bMDvgWwkggB$MR#Y!k87W9#r8$ zg5p~6MT#513lz73@sB}SFmR&c0C=I|5wKX1h>TBylN8T@MaT=g1BDjD6Sb_fSe&?7 zq#hK3QxsQ#hZNU<-&I@>eot`|_$$BG&SqhKvuvAscpAFG$xBOjj^PeVWvkRQR-G%jQ>G z%tH1Bl54KQ`B#-%a(K~~Lu#!vjNx`yr{fVRB z*x9K#0`5U}MP*iD1g^(%oZu#$_qX8m4%}=hLlLX+<0kPyoZBUZFRT%qheNEsh&=Ig zfh*K$p$QJ-cQWFmr6^mE;xgDhiYvgT;wo^$+7glA!v7`&i%2Mqmn Date: Sun, 14 Mar 2021 16:23:33 +0100 Subject: [PATCH 113/204] used new example with pipe based telnet server --- telnet.lua | 89 ++++++++++++++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/telnet.lua b/telnet.lua index d09d96c..8193728 100644 --- a/telnet.lua +++ b/telnet.lua @@ -1,54 +1,51 @@ -- Telnet client -telnetClient=nil -local lines = {} +--[[ A telnet server T. Ellison, June 2019 --- Helper function -function s_output(str) - uart.write(0, "T:" .. tostring(str)) - if (telnetClient ~= nil) then - if (#lines > 0) then - table.insert(lines, str) - else - table.insert(lines, str) - telnetClient:send("\r") -- Send something, so the queue is read after sending - end - end +This version of the telnet server demonstrates the use of the new stdin and stout +pipes, which is a C implementation of the Lua fifosock concept moved into the +Lua core. These two pipes are referenced in the Lua registry. + +]] +--luacheck: no unused args + +local telnetS = nil + +local function telnet_session(socket) + local node = node + local stdout + + local function output_CB(opipe) -- upval: socket + stdout = opipe + local rec = opipe:read(1400) + if rec and (#rec > 0) then socket:send(rec) end + return false -- don't repost as the on:sent will do this + end + + local function onsent_CB(skt) -- upval: stdout + local rec = stdout:read(1400) + if rec and #rec > 0 then skt:send(rec) end + end + + local function disconnect_CB(skt) -- upval: socket, stdout + node.output() + socket, stdout = nil, nil -- set upvals to nl to allow GC + end + + node.output(output_CB, 0) + socket:on("receive", function(_,rec) node.input(rec) end) + socket:on("sent", onsent_CB) + socket:on("disconnection", disconnect_CB) + print( ("Welcome to the Wordclock. (%d mem free, %s)"):format(node.heap(), wifi.sta.getip())) + print("- mydofile(\"commands\")") + print("- storeConfig()") + print("Visite https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en for further commands") + uart.write(0, "New client connected\r\n") end + -- Telnet Server function startTelnetServer() - s=net.createServer(net.TCP, 180) - s:listen(23,function(c) - telnetClient=c - node.output(s_output, 0) - c:on("receive",function(c,l) - node.input(l) - end) - c:on("disconnection",function(c) - node.output(nil) - telnetClient=nil - end) - c:on("sent", function() - if (#lines > 0) then - local line1=nil - for k,v in pairs(lines) do if (k==1) then - line1=v - end - uart.write(0, "Lines:" .. tostring(v) .. "\r\n") - - end - if ( line1 ~= nil ) then - table.remove(lines, 1) - uart.write(0, "Telent[" .. tostring(#lines) .. "]" .. tostring(line1) .. "\r\n" ) - telnetClient:send(line1) - end - end - end) - print("Welcome to the Wordclock.") - print("- mydofile(\"commands\")") - print("- storeConfig()") - print("Visite https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en for further commands") - uart.write(0, "New client connected\r\n") - end) + telnetS=net.createServer(net.TCP, 180) + telnetS:listen(23, telnet_session) print("Telnetserver started") end From 34e7f173fc70a4ed3dc558fd930ab7bc68362a52 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 16:52:53 +0100 Subject: [PATCH 114/204] Fixed WS2812 buffer manipulation --- main.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/main.lua b/main.lua index 440596b..3ff2c9e 100644 --- a/main.lua +++ b/main.lua @@ -69,8 +69,8 @@ function displayTime() else -- set FG to fix value: RED local color = string.char(255,0,0) - rgbBuffer.fill(0,0,0) -- disable all LEDs - for i=108,110, 1 do rgbBuffer.set(i, color) end + rgbBuffer:fill(0,0,0) -- disable all LEDs + for i=108,110, 1 do rgbBuffer:set(i, color) end ws2812.write(rgbBuffer) end @@ -137,20 +137,20 @@ function normalOperation() connect_counter=connect_counter+1 if wifi.sta.status() ~= 5 then print(connect_counter .. "/60 Connecting to AP...") - rgbBuffer.fill(0,0,0) -- clear all LEDs + rgbBuffer:fill(0,0,0) -- clear all LEDs if (connect_counter % 5 ~= 4) then local wlanColor=string.char((connect_counter % 6)*20,(connect_counter % 5)*20,(connect_counter % 3)*20) if ((connect_counter % 5) >= 1) then - rgbBuffer.set(7, wlanColor) + rgbBuffer:set(7, wlanColor) end if ((connect_counter % 5) >= 3) then - rgbBuffer.set(15, wlanColor) + rgbBuffer:set(15, wlanColor) end if ((connect_counter % 5) >= 2) then - rgbBuffer.set(16, wlanColor) + rgbBuffer:set(16, wlanColor) end if ((connect_counter % 5) >= 0) then - rgbBuffer.set(17, wlanColor) + rgbBuffer:set(17, wlanColor) end end ws2812.write(rgbBuffer) @@ -180,7 +180,7 @@ btntimer:register(5000, tmr.ALARM_AUTO, function (t) mlt:unregister() print("Button pressed " .. tostring(btnCounter)) btnCounter = btnCounter + 5 - for i=1,btnCounter do rgbBuffer.set(i, 128, 0, 0) end + for i=1,btnCounter do rgbBuffer:set(i, 128, 0, 0) end ws2812.write(rgbBuffer) if (btnCounter >= 110) then file.remove("config.lua") From d4f9e53ad4665dcc08217afdda25981dcd388529 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 18:57:02 +0100 Subject: [PATCH 115/204] Speedup initialization screen --- init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.lua b/init.lua index f513b3d..c1a5eac 100644 --- a/init.lua +++ b/init.lua @@ -6,7 +6,7 @@ local MAXLEDS=110 local counter1=0 ws2812.write(string.char(0,0,0):rep(114)) local bootledtimer = tmr.create() -bootledtimer:register(500, tmr.ALARM_AUTO, function (t) +bootledtimer:register(100, tmr.ALARM_AUTO, function (t) counter1=counter1+1 spaceLeds = math.max(MAXLEDS - (counter1*2), 0) ws2812.write(string.char(128,0,0):rep(counter1) .. string.char(0,0,0):rep(spaceLeds) .. string.char(0,0,64):rep(counter1)) From 6b67a058cb547176eb262e56cdb09c9901c38fb8 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 14 Mar 2021 21:52:46 +0100 Subject: [PATCH 116/204] Start displayword refactoring --- displayword.lua | 237 ++++++++++++++++++++---------------------------- main.lua | 2 +- 2 files changed, 99 insertions(+), 140 deletions(-) diff --git a/displayword.lua b/displayword.lua index 558697e..866ee99 100644 --- a/displayword.lua +++ b/displayword.lua @@ -32,13 +32,12 @@ local drawLEDs = function(data, numberNewChars) if (numberNewChars == nil) then numberNewChars=0 end + if (data.rgbBuffer == nil) then + return + end local tmpBuf=nil for i=1,numberNewChars do - if (tmpBuf == nil) then - tmpBuf = updateColor(data) - else - tmpBuf=tmpBuf .. updateColor(data) - end + data.rgbBuffer:set(data.dC + 1, updateColor(data)) data.dC=data.dC+1 end return tmpBuf @@ -61,6 +60,7 @@ local data={} -- @fn generateLEDs -- Module displaying of the words +-- @param rgbBuffer OutputBuffer with 114 LEDs -- @param words -- @param colorBg background color -- @param colorFg foreground color @@ -70,7 +70,7 @@ local data={} -- @param colorM4 foreground color if four minutes after a displayable time is present -- @param invertRows wheather line 4,5 and 6 shall be inverted or not -- @param aoC Amount of characters to be displayed -local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3, colorM4, invertRows, aoC) +local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, colorM2, colorM3, colorM4, invertRows, aoC) -- Set the local variables needed for the colored progress bar if (words == nil) then return nil @@ -99,6 +99,7 @@ local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3 else data.aoC = 0 end + data.rgbBuffer = rgbBuffer if ( (adc ~= nil) and (words.briPer ~= nil) ) then local per = math.floor(100*adc.read(0)/1000) @@ -129,253 +130,211 @@ local generateLEDs = function(words, colorBg, colorFg, colorM1, colorM2, colorM3 else colorBg = space end + rgbBuffer:fill(colorBg) -- draw the background -- Set the foreground color as the default color local buf=data.colorFg - local line=space -- line 1---------------------------------------------- if (rowbgColor[1] ~= nil) then - space = rowbgColor[1] + for i=1,11, 1 do data.rgbBuffer:set(i, rowbgColor[1]) end end if (words.it==1) then - buf=drawLEDs(data,2) -- ES + drawLEDs(data,2) -- ES else - buf=space:rep(2) + data.dC=data.dC+2 end -- K fill character buf=buf .. space:rep(1) if (words.is == 1) then - buf=buf .. drawLEDs(data,3) -- IST + drawLEDs(data,3) -- IST else - buf=buf .. space:rep(3) + data.dC=data.dC+3 end -- L fill character buf=buf .. space:rep(1) if (words.m5== 1) then - buf= buf .. drawLEDs(data,4) -- FUENF + drawLEDs(data,4) -- FUENF else - buf= buf .. space:rep(4) + data.dC=data.dC+4 end -- line 2-- even row (so inverted) -------------------- if (rowbgColor[2] ~= nil) then - space = rowbgColor[2] - else - space = colorBg + for i=12,23, 1 do data.rgbBuffer:set(i, rowbgColor[2]) end end if (words.m10 == 1) then - line= drawLEDs(data,4) -- ZEHN + drawLEDs(data,4) -- ZEHN else - line= space:rep(4) + data.dC=data.dC+4 end if (words.m20 == 1) then - line= line .. drawLEDs(data,7) -- ZWANZIG + drawLEDs(data,7) -- ZWANZIG else - line= line .. space:rep(7) - end - -- fill, the buffer - for i = 0,10 do - buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + data.dC=data.dC+7 end -- line3---------------------------------------------- if (rowbgColor[3] ~= nil) then - space = rowbgColor[3] - else - space = colorBg + for i=23,34, 1 do data.rgbBuffer:set(i, rowbgColor[3]) end end if (words.h3q == 1) then line= drawLEDs(data,11) -- DREIVIERTEL elseif (words.hq == 1) then - line= space:rep(4) - line= line .. drawLEDs(data,7) -- VIERTEL + data.dC=data.dC+4 + drawLEDs(data,7) -- VIERTEL else - line= space:rep(11) + data.dC=data.dC+11 end - -- fill, the buffer - buf = buf .. line --line 4-------- even row (so inverted) ------------- if (rowbgColor[4] ~= nil) then - space = rowbgColor[4] - else - space = colorBg + for i=34,45, 1 do data.rgbBuffer:set(i, rowbgColor[4]) end end if (words.ha == 1) then - line= space:rep(2) -- TG - line= line .. drawLEDs(data,4) -- NACH + data.dC=data.dC+2 -- TG + drawLEDs(data,4) -- NACH else - line= space:rep(6) + data.dC=data.dC+6 end if (words.hb == 1) then - line= line .. drawLEDs(data,3) -- VOR - line= line .. space:rep(2) + drawLEDs(data,3) -- VOR + data.dC=data.dC+2 else - line= line .. space:rep(5) + data.dC=data.dC+5 end - if (invertRows == true) then - buf = buf .. line - else + if (invertRows ~= true) then for i = 0,10 do + -- TODO swap line in buffer buf = buf .. line:sub((11-i)*3-2,(11-i)*3) end end ------------------------------------------------ if (rowbgColor[5] ~= nil) then - space = rowbgColor[5] - else - space = colorBg + for i=45,56, 1 do data.rgbBuffer:set(i, rowbgColor[5]) end end if (words.half == 1) then - line= drawLEDs(data,4) -- HALB - line= line .. space:rep(1) -- X + drawLEDs(data,4) -- HALB + data.dC=data.dC+1 -- X else - line= space:rep(5) + data.dC=data.dC+5 end if (words.h12 == 1) then - line= line .. drawLEDs(data,5) -- ZWOELF - line= line .. space:rep(1) -- P + drawLEDs(data,5) -- ZWOELF + data.dC=data.dC+1 -- P else - line= line .. space:rep(6) + data.dC=data.dC+6 end if (invertRows == true) then for i = 0,10 do + --TODO swap line in the buffer buf = buf .. line:sub((11-i)*3-2,(11-i)*3) end - else - buf=buf .. line end ------------even row (so inverted) --------------------- if (rowbgColor[6] ~= nil) then - space = rowbgColor[6] - else - space = colorBg + for i=56,67, 1 do data.rgbBuffer:set(i, rowbgColor[6]) end end if (words.h7 == 1) then - line= space:rep(5) - line= line .. drawLEDs(data,6) -- SIEBEN + data.dC=data.dC+5 + drawLEDs(data,6) -- SIEBEN elseif (words.h1l == 1) then - line= space:rep(2) - line= line .. drawLEDs(data,4) -- EINS - line= line .. space:rep(5) + data.dC=data.dC+2 + drawLEDs(data,4) -- EINS + data.dC=data.dC+5 elseif (words.h1 == 1) then - line= space:rep(2) - line= line .. drawLEDs(data,3) -- EIN - line= line .. space:rep(6) + data.dC=data.dC+2 + drawLEDs(data,3) -- EIN + data.dC=data.dC+6 elseif (words.h2 == 1) then - line= drawLEDs(data,4) -- ZWEI - line= line .. space:rep(7) + drawLEDs(data,4) -- ZWEI + data.dC=data.dC+7 else - line= space:rep(11) + data.dC=data.dC+7 end - if (invertRows == true) then - buf = buf .. line - else + if (invertRows ~= true) then + --TODO invert buffer for i = 0,10 do buf = buf .. line:sub((11-i)*3-2,(11-i)*3) end end ------------------------------------------------ if (rowbgColor[7] ~= nil) then - space = rowbgColor[7] - else - space = colorBg + for i=67,78, 1 do data.rgbBuffer:set(i, rowbgColor[7]) end end if (words.h3 == 1) then - line= space:rep(1) + data.dC=data.dC+1 line= line .. drawLEDs(data,4) -- DREI - line= line .. space:rep(6) + data.dC=data.dC+6 elseif (words.h5 == 1) then - line= space:rep(7) + data.dC=data.dC+7 line= line .. drawLEDs(data,4) -- FUENF else - line= space:rep(11) + data.dC=data.dC+11 end - buf = buf .. line ------------even row (so inverted) --------------------- if (rowbgColor[8] ~= nil) then - space = rowbgColor[8] - else - space = colorBg + for i=78,89, 1 do data.rgbBuffer:set(i, rowbgColor[8]) end end if (words.h4 == 1) then - line= space:rep(7) - line= line .. drawLEDs(data,4) -- VIER + data.dC=data.dC+7 + drawLEDs(data,4) -- VIER elseif (words.h9 == 1) then - line= space:rep(3) - line= line .. drawLEDs(data,4) -- NEUN - line= line .. space:rep(4) + data.dC=data.dC+3 + drawLEDs(data,4) -- NEUN + data.dC=data.dC+4 elseif (words.h11 == 1) then - line= drawLEDs(data,3) -- ELF - line= line .. space:rep(8) + drawLEDs(data,3) -- ELF + data.dC=data.dC+8 else - line= space:rep(11) + data.dC=data.dC+11 end - for i = 0,10 do - buf = buf .. line:sub((11-i)*3-2,(11-i)*3) - end + ------------------------------------------------ if (rowbgColor[9] ~= nil) then - space = rowbgColor[9] - else - space = colorBg + for i=89,99, 1 do data.rgbBuffer:set(i, rowbgColor[9]) end end if (words.h8 == 1) then - line= space:rep(1) - line= line .. drawLEDs(data,4) -- ACHT - line= line .. space:rep(6) + data.dC=data.dC+1 + drawLEDs(data,4) -- ACHT + data.dC=data.dC+6 elseif (words.h10 == 1) then - line= space:rep(5) - line= line .. drawLEDs(data,4) -- ZEHN - line= line .. space:rep(2) + data.dC=data.dC+5 + drawLEDs(data,4) -- ZEHN + data.dC=data.dC+2 else - line= space:rep(11) - end - buf = buf .. line - ------------even row (so inverted) --------------------- - if (rowbgColor[10] ~= nil) then - space = rowbgColor[10] - else - space = colorBg - end - if (words.h6 == 1) then - line= space:rep(1) - line= line .. drawLEDs(data,5) -- SECHS - line= line .. space:rep(2) - else - line= space:rep(8) - end - if (words.cl == 1) then - line= line .. drawLEDs(data,3) -- UHR - else - line= line .. space:rep(3) + data.dC=data.dC+11 end - for i = 0,10 do - buf = buf .. line:sub((11-i)*3-2,(11-i)*3) + ------------even row (so inverted) --------------------- + if (rowbgColor[10] ~= nil) then + for i=100,110, 1 do data.rgbBuffer:set(i, rowbgColor[10]) end + end + if (words.h6 == 1) then + data.dC=data.dC+1 + drawLEDs(data,5) -- SECHS + data.dC=data.dC+2 + else + data.dC=data.dC+8 end + if (words.cl == 1) then + drawLEDs(data,3) -- UHR + else + data.dC=data.dC+3 + end + ------ Minutes ----------- if (words.m1 == 1) then - buf= buf .. colorFg - else - buf= buf .. space:rep(1) + data.rgbBuffer:set(111, colorFg) end if (words.m2 == 1) then - buf= buf .. colorFg - else - buf= buf .. space:rep(1) + data.rgbBuffer:set(112, colorFg) end if (words.m3 == 1) then - buf= buf .. colorFg - else - buf= buf .. space:rep(1) + data.rgbBuffer:set(113, colorFg) end if (words.m4 == 1) then - buf= buf .. colorFg - else - buf= buf .. space:rep(1) + data.rgbBuffer:set(114, colorFg) end collectgarbage() - return buf end -- Count amount of characters to display diff --git a/main.lua b/main.lua index 3ff2c9e..a5edddf 100644 --- a/main.lua +++ b/main.lua @@ -59,7 +59,7 @@ function displayTime() invertRows=true end local c = dw.countChars(words) - ledBuf = dw.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, c) + ledBuf = dw.generateLEDs(rgbBuffer, words, colorBg, color, color1, color2, color3, color4, invertRows, c) end dw = nil collectgarbage() From cf74a0ae90d1a11a58859fbf2f8b447321be06a6 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 16 Mar 2021 22:11:28 +0100 Subject: [PATCH 117/204] Added rgbBuffer as argument --- main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.lua b/main.lua index a5edddf..3ff2c9e 100644 --- a/main.lua +++ b/main.lua @@ -59,7 +59,7 @@ function displayTime() invertRows=true end local c = dw.countChars(words) - ledBuf = dw.generateLEDs(rgbBuffer, words, colorBg, color, color1, color2, color3, color4, invertRows, c) + ledBuf = dw.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, c) end dw = nil collectgarbage() From 87c157fd109ae18c75d1202797e2d32d52dd5cd5 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 16 Mar 2021 22:12:02 +0100 Subject: [PATCH 118/204] Simulation starts implementation of dynamic nodemcu tasks --- simulation/src/de/c3ma/ollo/LuaThreadTmr.java | 4 +- .../src/de/c3ma/ollo/mockup/ESP8266Tmr.java | 69 +++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/LuaThreadTmr.java b/simulation/src/de/c3ma/ollo/LuaThreadTmr.java index 0a958fd..20d61e8 100644 --- a/simulation/src/de/c3ma/ollo/LuaThreadTmr.java +++ b/simulation/src/de/c3ma/ollo/LuaThreadTmr.java @@ -18,7 +18,7 @@ public class LuaThreadTmr extends Thread { private LuaValue code; - private final int delay; + private int delay; private final int timerNumber; @@ -28,7 +28,7 @@ public class LuaThreadTmr extends Thread { this.delay = delay; this.timerNumber = timerNumber; } - + @Override public void run() { try { diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java index 4c1782a..a57e750 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java @@ -6,6 +6,7 @@ import org.luaj.vm2.Varargs; import org.luaj.vm2.lib.OneArgFunction; import org.luaj.vm2.lib.TwoArgFunction; import org.luaj.vm2.lib.VarArgFunction; +import org.luaj.vm2.lib.ZeroArgFunction; import de.c3ma.ollo.LuaThreadTmr; @@ -21,6 +22,8 @@ public class ESP8266Tmr extends TwoArgFunction { private static final int MAXTHREADS = 7; private static LuaThreadTmr[] allThreads = new LuaThreadTmr[MAXTHREADS]; + private static LuaThreadTmr[] dynamicThreads = new LuaThreadTmr[MAXTHREADS]; + private static int dynamicThreadCounter=0; public static int gTimingFactor = 1; @@ -30,6 +33,7 @@ public class ESP8266Tmr extends TwoArgFunction { final LuaTable tmr = new LuaTable(); tmr.set("stop", new stop()); tmr.set("alarm", new alarm()); + tmr.set("create", new create()); env.set("tmr", tmr); env.get("package").get("loaded").set("tmr", tmr); @@ -37,6 +41,9 @@ public class ESP8266Tmr extends TwoArgFunction { for (Thread t : allThreads) { t = null; } + for (Thread t : dynamicThreads) { + t = null; + } return tmr; } @@ -87,6 +94,68 @@ public class ESP8266Tmr extends TwoArgFunction { } } + private class dynRegister extends VarArgFunction { + private final int dynIndex; + public dynRegister(int index) { + this.dynIndex = index; + } + public Varargs invoke(Varargs varargs) { + if (varargs.narg() == 4) { + final String endlessloop = varargs.arg(3).toString().toString(); + final int delay = varargs.arg(2).toint(); + final LuaValue code = varargs.arg(4); + dynamicThreads[dynIndex] = new LuaThreadTmr(dynIndex, code, (endlessloop.contains("AUTO")), Math.max(delay / gTimingFactor, 1)); + System.out.println("[TMR] DynTimer" + dynamicThreadCounter + " registered"); + } + return LuaValue.valueOf(true); + } + } + + private class dynStart extends VarArgFunction { + private final int dynIndex; + public dynStart(int index) { + this.dynIndex = index; + } + public Varargs invoke(Varargs varargs) { + if (varargs.narg()== 0) { + if (dynamicThreads[dynIndex] != null) { + dynamicThreads[dynIndex].start(); + System.out.println("[TMR] DynTimer" + dynIndex + " started"); + } + } + return LuaValue.valueOf(true); + } + } + + private class dynStop extends ZeroArgFunction { + private final int dynIndex; + public dynStop(int index) { + this.dynIndex = index; + } + public LuaValue call() { + if (dynamicThreads[dynIndex] != null) { + dynamicThreads[dynIndex].stopThread(); + dynamicThreads[dynIndex] = null; + System.out.println("[TMR] DynTimer" + dynIndex + " stopped"); + } + return LuaValue.valueOf(true); + } + } + + private class create extends ZeroArgFunction { + public LuaValue call() { + if (dynamicThreadCounter >= MAXTHREADS) { + return LuaValue.error("[TMR] DynTimer" + dynamicThreadCounter + " exeeded maximum"); + } + final LuaTable dynTimer = new LuaTable(); + dynTimer.set("register", new dynRegister(dynamicThreadCounter)); + dynTimer.set("start", new dynStart(dynamicThreadCounter)); + dynTimer.set("unregister", new dynStop(dynamicThreadCounter)); + dynamicThreadCounter++; + return dynTimer; + } + } + public void stopAllTimer() { for (int i = 0; i < allThreads.length; i++) { stopTmr(i); From 780ea8f738710324259cebb1d2034cc8cb2918ba Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 16 Mar 2021 22:12:54 +0100 Subject: [PATCH 119/204] Fixed debug output --- simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java index a57e750..6432075 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java @@ -105,7 +105,7 @@ public class ESP8266Tmr extends TwoArgFunction { final int delay = varargs.arg(2).toint(); final LuaValue code = varargs.arg(4); dynamicThreads[dynIndex] = new LuaThreadTmr(dynIndex, code, (endlessloop.contains("AUTO")), Math.max(delay / gTimingFactor, 1)); - System.out.println("[TMR] DynTimer" + dynamicThreadCounter + " registered"); + System.out.println("[TMR] DynTimer" + dynIndex + " registered"); } return LuaValue.valueOf(true); } From 07e4ac2c438f0bc98c1a0f1f737459fb9f61aeeb Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 17 Mar 2021 21:47:48 +0100 Subject: [PATCH 120/204] Defined lua function with the correct amount of arguments --- .../src/de/c3ma/ollo/mockup/ESP8266Tmr.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java index a57e750..3c39469 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java @@ -111,19 +111,19 @@ public class ESP8266Tmr extends TwoArgFunction { } } - private class dynStart extends VarArgFunction { + private class dynStart extends ZeroArgFunction { private final int dynIndex; public dynStart(int index) { this.dynIndex = index; } - public Varargs invoke(Varargs varargs) { - if (varargs.narg()== 0) { - if (dynamicThreads[dynIndex] != null) { - dynamicThreads[dynIndex].start(); - System.out.println("[TMR] DynTimer" + dynIndex + " started"); - } + public LuaValue call() { + if (dynamicThreads[dynIndex] != null) { + dynamicThreads[dynIndex].start(); + System.out.println("[TMR] DynTimer" + dynIndex + " started"); + return LuaValue.valueOf(true); + } else { + return LuaValue.valueOf(false); } - return LuaValue.valueOf(true); } } @@ -133,12 +133,14 @@ public class ESP8266Tmr extends TwoArgFunction { this.dynIndex = index; } public LuaValue call() { + boolean status = false; if (dynamicThreads[dynIndex] != null) { dynamicThreads[dynIndex].stopThread(); dynamicThreads[dynIndex] = null; System.out.println("[TMR] DynTimer" + dynIndex + " stopped"); + status = true; } - return LuaValue.valueOf(true); + return LuaValue.valueOf(status); } } From 5f8aa3c221b60615270330f3998e8acea87b9434 Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 17 Mar 2021 21:52:44 +0100 Subject: [PATCH 121/204] adapted code to be executable in the simulation --- init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.lua b/init.lua index c1a5eac..e8cdc94 100644 --- a/init.lua +++ b/init.lua @@ -33,7 +33,7 @@ end initTimer = tmr.create() initTimer:register(5000, tmr.ALARM_SINGLE, function (t) bootledtimer:unregister() - t:unregister() + initTimer:unregister() initTimer=nil bootledtimer=nil local modlist = { "timecore" , "displayword" } From efee1dab1f06507dfe87447962ade53bfacbe806 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 18 Mar 2021 21:05:20 +0100 Subject: [PATCH 122/204] WS2812 Buffer is initialized in simulator, too --- .../de/c3ma/ollo/mockup/ESP8266Ws2812.java | 66 ++++++++++++++++++- .../de/c3ma/ollo/mockup/ui/WS2812Layout.java | 13 ++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index ee5e04e..f27a944 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -7,11 +7,14 @@ import javax.swing.SwingUtilities; import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; import org.luaj.vm2.lib.OneArgFunction; import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.VarArgFunction; import org.luaj.vm2.lib.ZeroArgFunction; import de.c3ma.ollo.LuaSimulation; +import de.c3ma.ollo.LuaThreadTmr; import de.c3ma.ollo.mockup.ui.WS2812Layout; /** @@ -32,6 +35,7 @@ public class ESP8266Ws2812 extends TwoArgFunction { final LuaTable ws2812 = new LuaTable(); ws2812.set("init", new init()); ws2812.set("write", new write()); + ws2812.set("newBuffer", new newBuffer()); env.set("ws2812", ws2812); env.get("package").get("loaded").set("ws2812", ws2812); return ws2812; @@ -75,8 +79,11 @@ public class ESP8266Ws2812 extends TwoArgFunction { System.out.println("[WS2812] write length:" + length); } else { } + return LuaValue.valueOf(true); + } else { + System.out.println("[WS2812] write no string given"); + return LuaValue.NIL; } - return LuaValue.valueOf(true); } } @@ -85,4 +92,61 @@ public class ESP8266Ws2812 extends TwoArgFunction { ESP8266Ws2812.layout = WS2812Layout.parse(file, nodemcuSimu); } } + + private class newBuffer extends VarArgFunction { + + public Varargs invoke(Varargs varargs) { + if (varargs.narg() == 2) { + final int leds = varargs.arg(1).toint(); + final int bytesPerLeds = varargs.arg(2).toint(); + final LuaTable rgbBuffer = new LuaTable(); + rgbBuffer.set("fill", new bufferFill()); + rgbBuffer.set("set", new bufferWrite()); + System.out.println("[WS2812] " + leds + "leds (" + bytesPerLeds + "bytes per led)"); + return rgbBuffer; + } else { + return LuaValue.NIL; + } + } + } + + private class bufferFill extends VarArgFunction { + + public Varargs invoke(Varargs varargs) { + if (varargs.narg() == 3) { + final int red = varargs.arg(1).toint(); + final int green = varargs.arg(2).toint(); + final int blue = varargs.arg(3).toint(); + if (ESP8266Ws2812.layout != null) { + ESP8266Ws2812.layout.fillLEDs(red, green, blue); + } + + return LuaValue.valueOf(true); + } else { + return LuaValue.NIL; + } + } + } + + private class bufferWrite extends VarArgFunction { + + public Varargs invoke(Varargs varargs) { + if (varargs.narg() == 2) { + final int index = varargs.arg(1).toint(); + final LuaString color = varargs.arg(2).checkstring(); + final int length = color.rawlen(); + if (length == 3) { + final byte[] array = color.m_bytes; + int r = array[0]+(Byte.MIN_VALUE*-1); + int b = array[1]+(Byte.MIN_VALUE*-1); + int g = array[2]+(Byte.MIN_VALUE*-1); + ESP8266Ws2812.layout.updateLED(index, r, g, b); + } + + return LuaValue.valueOf(true); + } else { + return LuaValue.NIL; + } + } + } } diff --git a/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java b/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java index f59fa4b..278f3a5 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java +++ b/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java @@ -319,5 +319,18 @@ public class WS2812Layout extends JFrame { } } } + + public void fillLEDs(int r, int g, int b) { + if (mElements != null) { + for(int i=0;(i < mElements.length); i++) { + for (int j=0; (j < mElements[i].length); j++) { + if (mElements[i][j] != null) { + Element curlbl = mElements[i][j]; + curlbl.setColor(r, g, b); + } + } + } + } + } } From 890c84dfbd971732480596359d70f4128c8f8047 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 18 Mar 2021 21:32:03 +0100 Subject: [PATCH 123/204] GPIO module added to simulation --- .../src/de/c3ma/ollo/WS2812Simulation.java | 3 + .../src/de/c3ma/ollo/mockup/ESP8266Gpio.java | 90 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 simulation/src/de/c3ma/ollo/mockup/ESP8266Gpio.java diff --git a/simulation/src/de/c3ma/ollo/WS2812Simulation.java b/simulation/src/de/c3ma/ollo/WS2812Simulation.java index 1c4cff9..4c15f8d 100644 --- a/simulation/src/de/c3ma/ollo/WS2812Simulation.java +++ b/simulation/src/de/c3ma/ollo/WS2812Simulation.java @@ -13,6 +13,7 @@ import org.luaj.vm2.lib.jse.JsePlatform; import de.c3ma.ollo.mockup.DoFileFunction; import de.c3ma.ollo.mockup.ESP8266Adc; import de.c3ma.ollo.mockup.ESP8266File; +import de.c3ma.ollo.mockup.ESP8266Gpio; import de.c3ma.ollo.mockup.ESP8266Net; import de.c3ma.ollo.mockup.ESP8266Node; import de.c3ma.ollo.mockup.ESP8266Time; @@ -37,6 +38,7 @@ public class WS2812Simulation implements LuaSimulation { private ESP8266Node espNode = new ESP8266Node(this); private DoFileFunction doFile = new DoFileFunction(globals); private ESP8266Ws2812 ws2812 = new ESP8266Ws2812(); + private ESP8266Gpio gpio = new ESP8266Gpio(); private ESP8266Adc adc = new ESP8266Adc(); private String scriptName; @@ -47,6 +49,7 @@ public class WS2812Simulation implements LuaSimulation { globals.load(espFile); globals.load(espNode); globals.load(adc); + globals.load(gpio); globals.load(new ESP8266Wifi()); globals.load(new ESP8266Net()); globals.load(new ESP8266Time()); diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Gpio.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Gpio.java new file mode 100644 index 0000000..93ee00c --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Gpio.java @@ -0,0 +1,90 @@ +package de.c3ma.ollo.mockup; + +import java.util.HashMap; + +import javax.swing.SwingUtilities; + +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.VarArgFunction; + +/** + * created at 18.03.2021 - 21:09:03
+ * creator: ollo
+ * project: Esp8266 GPIO Emulation
+ * $Id: $
+ * @author ollo
+ */ +public class ESP8266Gpio extends TwoArgFunction { + + private static final String DIRECTION_INPUT = "input"; + private HashMap mInputs = new HashMap(); + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + env.checkglobals(); + final LuaTable gpio = new LuaTable(); + gpio.set("mode", new Mode(this)); + gpio.set("read", new Read(this)); + gpio.set("INPUT", DIRECTION_INPUT); + env.set("gpio", gpio); + env.get("package").get("loaded").set("gpio", gpio); + return gpio; + } + + private class Mode extends VarArgFunction { + + private ESP8266Gpio gpio; + + public Mode(ESP8266Gpio a) { + this.gpio = a; + } + + public Varargs invoke(Varargs varargs) { + if (varargs.narg() == 2) { + final int pin = varargs.arg(1).toint(); + final LuaString lsDirection = varargs.arg(2).checkstring(); + String direction = lsDirection.toString(); + if (direction.equals(DIRECTION_INPUT)) { + gpio.mInputs.put(pin, -1); + } + System.out.println("[GPIO] PIN" + pin +" as " + direction); + return LuaValue.valueOf(true); + } else { + return LuaValue.NIL; + } + } + } + + private class Read extends OneArgFunction { + + private ESP8266Gpio gpio; + + public Read(ESP8266Gpio a) { + this.gpio = a; + } + + @Override + public LuaValue call(LuaValue arg) { + int pin = arg.toint(); + if (mInputs.containsKey(pin)) { + return LuaValue.valueOf(mInputs.get(pin)); + } else { + System.out.println("[GPIO] pin" + pin + " not defined (gpio.mode missing)"); + return LuaValue.NIL; + } + } + } + + public void setPin(int pin, int newValue) { + if (mInputs.containsKey(pin)) { + mInputs.put(pin, newValue); + } else { + System.out.println("[GPIO] PIN" + pin +" not defined (missing gpio.mode)"); + } + } +} From d1a67f1cb4b2e9b721a4f6d05bba8117f60ecabc Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 18 Mar 2021 21:38:10 +0100 Subject: [PATCH 124/204] Fixed code for simulation --- main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.lua b/main.lua index 3ff2c9e..b5683df 100644 --- a/main.lua +++ b/main.lua @@ -155,7 +155,7 @@ function normalOperation() end ws2812.write(rgbBuffer) else - timer:unregister() + wifitimer:unregister() wifitimer=nil connect_counter=nil print('IP: ',wifi.sta.getip(), " heap: ", node.heap()) From 238618b245c4305715165dd8ca5250cfb5bdec6d Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 18 Mar 2021 21:38:26 +0100 Subject: [PATCH 125/204] All functions implement, but not running --- simulation/src/de/c3ma/ollo/mockup/ESP8266Node.java | 13 +++++++++++++ simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Node.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Node.java index 1ff7824..efc1d86 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Node.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Node.java @@ -34,6 +34,7 @@ public class ESP8266Node extends TwoArgFunction { final LuaTable node = new LuaTable(); node.set("compile", new CompileFunction()); node.set("restart", new RestartFunction()); + node.set("heap", new HeapFunction()); env.set("node", node); env.get("package").get("loaded").set("node", node); return node; @@ -73,6 +74,18 @@ public class ESP8266Node extends TwoArgFunction { } + private class HeapFunction extends ZeroArgFunction { + + @Override + public LuaValue call() { + System.out.println("[Node] Heap"); + return LuaValue.valueOf(Runtime.getRuntime().freeMemory()); + } + + } + + + public void setWorkingDirectory(File workingDir) { this.workingDir = workingDir; } diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java index aa5e207..5802d18 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java @@ -34,6 +34,7 @@ public class ESP8266Tmr extends TwoArgFunction { tmr.set("stop", new stop()); tmr.set("alarm", new alarm()); tmr.set("create", new create()); + tmr.set("wdclr", new watchDog()); env.set("tmr", tmr); env.get("package").get("loaded").set("tmr", tmr); @@ -127,6 +128,15 @@ public class ESP8266Tmr extends TwoArgFunction { } } + private class watchDog extends ZeroArgFunction { + + public LuaValue call() { + System.out.println("[TMR] Watchdog fed"); + return LuaValue.valueOf(true); + + } + } + private class dynStop extends ZeroArgFunction { private final int dynIndex; public dynStop(int index) { From a66f2839c3193c74f05612aa70737c48e2210381 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 18 Mar 2021 21:50:44 +0100 Subject: [PATCH 126/204] Added timer ALARM constants --- simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java index 5802d18..ad2f4b8 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java @@ -35,6 +35,8 @@ public class ESP8266Tmr extends TwoArgFunction { tmr.set("alarm", new alarm()); tmr.set("create", new create()); tmr.set("wdclr", new watchDog()); + tmr.set("ALARM_AUTO", "ALARM_AUTO"); + tmr.set("ALARM_SINGLE", "ALARM_SINGLE"); env.set("tmr", tmr); env.get("package").get("loaded").set("tmr", tmr); From feaddece6e3eea3a0629391dad45c7b4d2e3362a Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 18 Mar 2021 21:55:10 +0100 Subject: [PATCH 127/204] Fixed generateLEDs call --- main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.lua b/main.lua index b5683df..4ca1b1b 100644 --- a/main.lua +++ b/main.lua @@ -59,7 +59,7 @@ function displayTime() invertRows=true end local c = dw.countChars(words) - ledBuf = dw.generateLEDs(words, colorBg, color, color1, color2, color3, color4, invertRows, c) + ledBuf = dw.generateLEDs(rgbBuffer, words, colorBg, color, color1, color2, color3, color4, invertRows, c) end dw = nil collectgarbage() From a7bec1452118f10cbea412ece9f2fba4a699f5e1 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 18 Mar 2021 21:55:26 +0100 Subject: [PATCH 128/204] Debug message on wrong parameter count added --- simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java | 1 + 1 file changed, 1 insertion(+) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index f27a944..109e8ce 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -123,6 +123,7 @@ public class ESP8266Ws2812 extends TwoArgFunction { return LuaValue.valueOf(true); } else { + System.err.println("[WS2812] fill with " + varargs.narg() + " arguments undefined."); return LuaValue.NIL; } } From 6f7b4b111e4de43e5ef98956e72f1c407cf66eb6 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 18 Mar 2021 21:58:59 +0100 Subject: [PATCH 129/204] next step: one argument, started --- .../src/de/c3ma/ollo/mockup/ESP8266Ws2812.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index 109e8ce..d739b3d 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -122,6 +122,18 @@ public class ESP8266Ws2812 extends TwoArgFunction { } return LuaValue.valueOf(true); + } else if (varargs.isstring(2)) { + //FIXME to be tested + final LuaString color = varargs.arg(2).checkstring(); + final int length = color.rawlen(); + if (length == 3) { + final byte[] array = color.m_bytes; + int r = array[0]+(Byte.MIN_VALUE*-1); + int b = array[1]+(Byte.MIN_VALUE*-1); + int g = array[2]+(Byte.MIN_VALUE*-1); + ESP8266Ws2812.layout.fillLEDs(r, g, b); + } + return LuaValue.valueOf(true); } else { System.err.println("[WS2812] fill with " + varargs.narg() + " arguments undefined."); return LuaValue.NIL; From 37b551c3fca4aed137600ff91040ed7ccbbb1163 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 19 Mar 2021 18:21:41 +0100 Subject: [PATCH 130/204] Added line swapping functionality --- displayword.lua | 85 ++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/displayword.lua b/displayword.lua index 866ee99..ce05d9d 100644 --- a/displayword.lua +++ b/displayword.lua @@ -58,6 +58,23 @@ end local data={} +-- @fn swapLine +-- @param lineOffset offset (starting at 1) where the line is located to be swapped +-- works on the rgbBuffer, defined in data struct +-- @return false on errors, else true +local swapLine = function(lineOffset) + if (data.rgbBuffer == nil) then + return false + end + + for i = 0,10 do + local tmpColor=data.rgbBuffer:get(lineOffset+i) + data.rgbBuffer:set(lineIdx+i, data.rgbBuffer:get(lineOffset+10-i)) + data.rgbBuffer:set(lineIdx+10-i, tmpColor) + end + return true +end + -- @fn generateLEDs -- Module displaying of the words -- @param rgbBuffer OutputBuffer with 114 LEDs @@ -134,9 +151,11 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color -- Set the foreground color as the default color local buf=data.colorFg + local lineIdx=1 -- line 1---------------------------------------------- + lineIdx=11 if (rowbgColor[1] ~= nil) then - for i=1,11, 1 do data.rgbBuffer:set(i, rowbgColor[1]) end + for i=lineIdx,11, 1 do data.rgbBuffer:set(i, rowbgColor[1]) end end if (words.it==1) then drawLEDs(data,2) -- ES @@ -158,8 +177,9 @@ if (words.m5== 1) then data.dC=data.dC+4 end -- line 2-- even row (so inverted) -------------------- + lineIdx=12 if (rowbgColor[2] ~= nil) then - for i=12,23, 1 do data.rgbBuffer:set(i, rowbgColor[2]) end + for i=lineIdx,(lineIdx+11), 1 do data.rgbBuffer:set(i, rowbgColor[2]) end end if (words.m10 == 1) then drawLEDs(data,4) -- ZEHN @@ -171,10 +191,12 @@ if (words.m5== 1) then else data.dC=data.dC+7 end - + -- swap line + swapLine(lineIdx) -- line3---------------------------------------------- + lineIdx=23 if (rowbgColor[3] ~= nil) then - for i=23,34, 1 do data.rgbBuffer:set(i, rowbgColor[3]) end + for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[3]) end end if (words.h3q == 1) then line= drawLEDs(data,11) -- DREIVIERTEL @@ -185,8 +207,9 @@ if (words.m5== 1) then data.dC=data.dC+11 end --line 4-------- even row (so inverted) ------------- - if (rowbgColor[4] ~= nil) then - for i=34,45, 1 do data.rgbBuffer:set(i, rowbgColor[4]) end + lineIdx=34 + if (rowbgColor[4] ~= nil) then + for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[4]) end end if (words.ha == 1) then data.dC=data.dC+2 -- TG @@ -201,14 +224,12 @@ if (words.m5== 1) then data.dC=data.dC+5 end if (invertRows ~= true) then - for i = 0,10 do - -- TODO swap line in buffer - buf = buf .. line:sub((11-i)*3-2,(11-i)*3) - end + swapLine(lineIdx) end ------------------------------------------------ - if (rowbgColor[5] ~= nil) then - for i=45,56, 1 do data.rgbBuffer:set(i, rowbgColor[5]) end + lineIdx=45 + if (rowbgColor[5] ~= nil) then + for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[5]) end end if (words.half == 1) then drawLEDs(data,4) -- HALB @@ -223,14 +244,12 @@ if (words.m5== 1) then data.dC=data.dC+6 end if (invertRows == true) then - for i = 0,10 do - --TODO swap line in the buffer - buf = buf .. line:sub((11-i)*3-2,(11-i)*3) - end + swapLine(lineIdx) end ------------even row (so inverted) --------------------- - if (rowbgColor[6] ~= nil) then - for i=56,67, 1 do data.rgbBuffer:set(i, rowbgColor[6]) end + lineIdx=56 + if (rowbgColor[6] ~= nil) then + for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[6]) end end if (words.h7 == 1) then data.dC=data.dC+5 @@ -250,14 +269,12 @@ if (words.m5== 1) then data.dC=data.dC+7 end if (invertRows ~= true) then - --TODO invert buffer - for i = 0,10 do - buf = buf .. line:sub((11-i)*3-2,(11-i)*3) - end + swapLine(lineIdx) end ------------------------------------------------ - if (rowbgColor[7] ~= nil) then - for i=67,78, 1 do data.rgbBuffer:set(i, rowbgColor[7]) end + lineIdx=67 + if (rowbgColor[7] ~= nil) then + for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[7]) end end if (words.h3 == 1) then data.dC=data.dC+1 @@ -270,8 +287,9 @@ if (words.m5== 1) then data.dC=data.dC+11 end ------------even row (so inverted) --------------------- - if (rowbgColor[8] ~= nil) then - for i=78,89, 1 do data.rgbBuffer:set(i, rowbgColor[8]) end + lineIdx=78 + if (rowbgColor[8] ~= nil) then + for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[8]) end end if (words.h4 == 1) then data.dC=data.dC+7 @@ -286,11 +304,11 @@ if (words.m5== 1) then else data.dC=data.dC+11 end - - + swapLine(lineIdx) ------------------------------------------------ - if (rowbgColor[9] ~= nil) then - for i=89,99, 1 do data.rgbBuffer:set(i, rowbgColor[9]) end + lineIdx=89 + if (rowbgColor[9] ~= nil) then + for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[9]) end end if (words.h8 == 1) then data.dC=data.dC+1 @@ -305,8 +323,9 @@ if (words.m5== 1) then end ------------even row (so inverted) --------------------- - if (rowbgColor[10] ~= nil) then - for i=100,110, 1 do data.rgbBuffer:set(i, rowbgColor[10]) end + lineIdx=100 + if (rowbgColor[10] ~= nil) then + for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[10]) end end if (words.h6 == 1) then data.dC=data.dC+1 @@ -320,7 +339,7 @@ if (words.m5== 1) then else data.dC=data.dC+3 end - + swapLine(lineIdx) ------ Minutes ----------- if (words.m1 == 1) then data.rgbBuffer:set(111, colorFg) From 5714c9f004c510308fb3d879ac5091862423fe0f Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 19 Mar 2021 18:36:52 +0100 Subject: [PATCH 131/204] WS2812 Buffer added get-function --- .../de/c3ma/ollo/mockup/ESP8266Ws2812.java | 37 ++++++++++++++++--- .../de/c3ma/ollo/mockup/ui/WS2812Layout.java | 21 +++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index d739b3d..50b55ec 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -1,5 +1,6 @@ package de.c3ma.ollo.mockup; +import java.awt.Color; import java.io.File; import javax.swing.SwingUtilities; @@ -16,6 +17,7 @@ import org.luaj.vm2.lib.ZeroArgFunction; import de.c3ma.ollo.LuaSimulation; import de.c3ma.ollo.LuaThreadTmr; import de.c3ma.ollo.mockup.ui.WS2812Layout; +import de.c3ma.ollo.mockup.ui.WS2812Layout.Element; /** * created at 28.12.2017 - 23:34:04
@@ -58,6 +60,12 @@ public class ESP8266Ws2812 extends TwoArgFunction { if (arg.isstring()) { LuaString jstring = arg.checkstring(); final int length = jstring.rawlen(); + + if (ESP8266Ws2812.layout == null) { + System.err.println("[WS2812] Not initialized (" + length + "bytes to be updated)"); + return LuaValue.valueOf(false); + } + if ((length % 3) == 0) { final byte[] array = jstring.m_bytes; SwingUtilities.invokeLater(new Runnable() { @@ -74,11 +82,6 @@ public class ESP8266Ws2812 extends TwoArgFunction { } }); } - - if (ESP8266Ws2812.layout == null) { - System.out.println("[WS2812] write length:" + length); - } else { - } return LuaValue.valueOf(true); } else { System.out.println("[WS2812] write no string given"); @@ -102,6 +105,7 @@ public class ESP8266Ws2812 extends TwoArgFunction { final LuaTable rgbBuffer = new LuaTable(); rgbBuffer.set("fill", new bufferFill()); rgbBuffer.set("set", new bufferWrite()); + rgbBuffer.set("get", new bufferRead()); System.out.println("[WS2812] " + leds + "leds (" + bytesPerLeds + "bytes per led)"); return rgbBuffer; } else { @@ -162,4 +166,27 @@ public class ESP8266Ws2812 extends TwoArgFunction { } } } + + private class bufferRead extends OneArgFunction { + + @Override + public LuaValue call(LuaValue arg) { + final int offset = arg.toint(); + if (ESP8266Ws2812.layout != null) { + + Element e = ESP8266Ws2812.layout.getLED(offset); + if (e != null) { + Color color = e.getColor(); + final byte[] array = new byte[3]; + array[0] = (byte) color.getRed(); + array[1] = (byte) color.getGreen(); + array[2] = (byte) color.getBlue(); + return LuaString.valueOf(array); + } + } + + System.err.println("[WS2812] reading " + offset + " impossible"); + return LuaValue.NIL; + } + } } diff --git a/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java b/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java index 278f3a5..c43fd4c 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java +++ b/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java @@ -288,6 +288,10 @@ public class WS2812Layout extends JFrame { this.setForeground(new Color(red, green, blue)); this.repaint(); } + + public Color getColor() { + return this.getForeground(); + } @Override public String toString() { @@ -320,6 +324,23 @@ public class WS2812Layout extends JFrame { } } + public Element getLED(int index) { + if (mElements != null) { + int i = (index / mColumn); + int j = (index % mColumn); + if (i % 2 == 1) { + j = (mColumn-1) - j; + } + if ((i < mElements.length) && (j < mElements[i].length) && (mElements[i][j] != null)) { + return mElements[i][j]; + } else { + return null; + } + } else { + return null; + } + } + public void fillLEDs(int r, int g, int b) { if (mElements != null) { for(int i=0;(i < mElements.length); i++) { From 639ce7ea7279fcdc7ad1b89372411eb6f8c51f0c Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 19 Mar 2021 18:44:41 +0100 Subject: [PATCH 132/204] swap line gets all as parameter --- displayword.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/displayword.lua b/displayword.lua index ce05d9d..6b0f84e 100644 --- a/displayword.lua +++ b/displayword.lua @@ -62,15 +62,15 @@ local data={} -- @param lineOffset offset (starting at 1) where the line is located to be swapped -- works on the rgbBuffer, defined in data struct -- @return false on errors, else true -local swapLine = function(lineOffset) +local swapLine = function(data, lineOffset) if (data.rgbBuffer == nil) then return false end for i = 0,10 do local tmpColor=data.rgbBuffer:get(lineOffset+i) - data.rgbBuffer:set(lineIdx+i, data.rgbBuffer:get(lineOffset+10-i)) - data.rgbBuffer:set(lineIdx+10-i, tmpColor) + data.rgbBuffer:set(lineOffset+i, data.rgbBuffer:get(lineOffset+10-i)) + data.rgbBuffer:set(lineOffset+10-i, tmpColor) end return true end @@ -192,7 +192,7 @@ if (words.m5== 1) then data.dC=data.dC+7 end -- swap line - swapLine(lineIdx) + swapLine(data,lineIdx) -- line3---------------------------------------------- lineIdx=23 if (rowbgColor[3] ~= nil) then @@ -224,7 +224,7 @@ if (words.m5== 1) then data.dC=data.dC+5 end if (invertRows ~= true) then - swapLine(lineIdx) + swapLine(data,lineIdx) end ------------------------------------------------ lineIdx=45 @@ -244,7 +244,7 @@ if (words.m5== 1) then data.dC=data.dC+6 end if (invertRows == true) then - swapLine(lineIdx) + swapLine(data,lineIdx) end ------------even row (so inverted) --------------------- lineIdx=56 @@ -269,7 +269,7 @@ if (words.m5== 1) then data.dC=data.dC+7 end if (invertRows ~= true) then - swapLine(lineIdx) + swapLine(data,lineIdx) end ------------------------------------------------ lineIdx=67 @@ -304,7 +304,7 @@ if (words.m5== 1) then else data.dC=data.dC+11 end - swapLine(lineIdx) + swapLine(data,lineIdx) ------------------------------------------------ lineIdx=89 if (rowbgColor[9] ~= nil) then @@ -339,7 +339,7 @@ if (words.m5== 1) then else data.dC=data.dC+3 end - swapLine(lineIdx) + swapLine(data,lineIdx) ------ Minutes ----------- if (words.m1 == 1) then data.rgbBuffer:set(111, colorFg) From db22d50c2640761686a70c89c45d8ae9d482d6ea Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 19 Mar 2021 18:45:07 +0100 Subject: [PATCH 133/204] Adapted multithreadding --- .../de/c3ma/ollo/mockup/ESP8266Ws2812.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index 50b55ec..a8f4110 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -131,11 +131,16 @@ public class ESP8266Ws2812 extends TwoArgFunction { final LuaString color = varargs.arg(2).checkstring(); final int length = color.rawlen(); if (length == 3) { - final byte[] array = color.m_bytes; - int r = array[0]+(Byte.MIN_VALUE*-1); - int b = array[1]+(Byte.MIN_VALUE*-1); - int g = array[2]+(Byte.MIN_VALUE*-1); - ESP8266Ws2812.layout.fillLEDs(r, g, b); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + final byte[] array = color.m_bytes; + int r = array[0]+(Byte.MIN_VALUE*-1); + int b = array[1]+(Byte.MIN_VALUE*-1); + int g = array[2]+(Byte.MIN_VALUE*-1); + ESP8266Ws2812.layout.fillLEDs(r, g, b); + } + }); } return LuaValue.valueOf(true); } else { @@ -153,11 +158,16 @@ public class ESP8266Ws2812 extends TwoArgFunction { final LuaString color = varargs.arg(2).checkstring(); final int length = color.rawlen(); if (length == 3) { - final byte[] array = color.m_bytes; - int r = array[0]+(Byte.MIN_VALUE*-1); - int b = array[1]+(Byte.MIN_VALUE*-1); - int g = array[2]+(Byte.MIN_VALUE*-1); - ESP8266Ws2812.layout.updateLED(index, r, g, b); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + final byte[] array = color.m_bytes; + int r = array[0]+(Byte.MIN_VALUE*-1); + int b = array[1]+(Byte.MIN_VALUE*-1); + int g = array[2]+(Byte.MIN_VALUE*-1); + ESP8266Ws2812.layout.updateLED(index, r, g, b); + } + }); } return LuaValue.valueOf(true); From 54a3761ceee5ae146fa25f48bd2eae8ed218775f Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 19 Mar 2021 19:02:17 +0100 Subject: [PATCH 134/204] Buffer filling works --- .../de/c3ma/ollo/mockup/ESP8266Ws2812.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index a8f4110..1902935 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -117,32 +117,41 @@ public class ESP8266Ws2812 extends TwoArgFunction { private class bufferFill extends VarArgFunction { public Varargs invoke(Varargs varargs) { - if (varargs.narg() == 3) { + if (varargs.narg() >= 3) { final int red = varargs.arg(1).toint(); final int green = varargs.arg(2).toint(); final int blue = varargs.arg(3).toint(); if (ESP8266Ws2812.layout != null) { - ESP8266Ws2812.layout.fillLEDs(red, green, blue); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ESP8266Ws2812.layout.fillLEDs(red, green, blue); + } + }); } - + System.out.println("[WS2812] buffer fill with " + red + "," + green + "," + blue); return LuaValue.valueOf(true); } else if (varargs.isstring(2)) { - //FIXME to be tested final LuaString color = varargs.arg(2).checkstring(); final int length = color.rawlen(); - if (length == 3) { + if ((length == 3) && (ESP8266Ws2812.layout != null)) { + + final byte[] array = color.m_bytes; + final int r = array[0]+(Byte.MIN_VALUE*-1); + final int b = array[1]+(Byte.MIN_VALUE*-1); + final int g = array[2]+(Byte.MIN_VALUE*-1); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - final byte[] array = color.m_bytes; - int r = array[0]+(Byte.MIN_VALUE*-1); - int b = array[1]+(Byte.MIN_VALUE*-1); - int g = array[2]+(Byte.MIN_VALUE*-1); ESP8266Ws2812.layout.fillLEDs(r, g, b); } }); + System.out.println("[WS2812] buffer fill with " + r + "," + g + "," + b); + return LuaValue.valueOf(true); + } else { + System.err.println("[WS2812] buffer not initialized ("+varargs.narg() +"args) , length "+ length + ", raw:" + color.toString()); + return LuaValue.NIL; } - return LuaValue.valueOf(true); } else { System.err.println("[WS2812] fill with " + varargs.narg() + " arguments undefined."); return LuaValue.NIL; From 48b77510927d2395521f1ef90489382f65498842 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 19 Mar 2021 19:55:15 +0100 Subject: [PATCH 135/204] Output on panel added while starting --- main.lua | 11 +++++++--- .../de/c3ma/ollo/mockup/ESP8266Ws2812.java | 22 ++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/main.lua b/main.lua index 4ca1b1b..041c85a 100644 --- a/main.lua +++ b/main.lua @@ -59,19 +59,20 @@ function displayTime() invertRows=true end local c = dw.countChars(words) - ledBuf = dw.generateLEDs(rgbBuffer, words, colorBg, color, color1, color2, color3, color4, invertRows, c) + dw.generateLEDs(rgbBuffer, words, colorBg, color, color1, color2, color3, color4, invertRows, c) end dw = nil collectgarbage() print("dw: " .. tostring(node.heap())) - if (ledBuf ~= nil) then - ws2812.write(ledBuf) + if (rgbBuffer ~= nil) then + ws2812.write(rgbBuffer) else -- set FG to fix value: RED local color = string.char(255,0,0) rgbBuffer:fill(0,0,0) -- disable all LEDs for i=108,110, 1 do rgbBuffer:set(i, color) end ws2812.write(rgbBuffer) + print("Fallback no time displayed") end -- cleanup @@ -95,6 +96,7 @@ function normalOperation() local alive=0 mlt:register(2500, tmr.ALARM_AUTO, function (lt) if (setupCounter > 4) then + rgbBuffer:fill(0,0,0) -- disable all LEDs syncTimeFromInternet() setupCounter=setupCounter-1 alive = 1 @@ -159,6 +161,9 @@ function normalOperation() wifitimer=nil connect_counter=nil print('IP: ',wifi.sta.getip(), " heap: ", node.heap()) + rgbBuffer:fill(0,0,0) -- clear all LEDs + rgbBuffer:set(13, color) + ws2812.write(rgbBuffer) mlt:start() end end) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index 1902935..f95cd1a 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -5,6 +5,7 @@ import java.io.File; import javax.swing.SwingUtilities; +import org.luaj.vm2.LuaNil; import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; @@ -162,10 +163,12 @@ public class ESP8266Ws2812 extends TwoArgFunction { private class bufferWrite extends VarArgFunction { public Varargs invoke(Varargs varargs) { - if (varargs.narg() == 2) { - final int index = varargs.arg(1).toint(); - final LuaString color = varargs.arg(2).checkstring(); - final int length = color.rawlen(); + if (varargs.narg() == 3) { + final int index = varargs.arg(2).toint(); + + + final LuaString color = varargs.arg(3).checkstring(); + final int length = color.rawlen(); if (length == 3) { SwingUtilities.invokeLater(new Runnable() { @Override @@ -177,10 +180,17 @@ public class ESP8266Ws2812 extends TwoArgFunction { ESP8266Ws2812.layout.updateLED(index, r, g, b); } }); + return LuaValue.valueOf(true); + } else { + for(int i=0; i <= varargs.narg(); i++) { + System.err.println("[WS2812] write ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); + } + + System.err.println("[WS2812] set with " + varargs.narg() + " arguments at index="+ index + " and "+ length + " charactes not matching"); + return LuaValue.NIL; } - - return LuaValue.valueOf(true); } else { + System.err.println("[WS2812] set with " + varargs.narg() + " arguments undefined."); return LuaValue.NIL; } } From e7032a62b06a38c5b14935d984c037c59e2d9815 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 15:43:59 +0100 Subject: [PATCH 136/204] Offset between LUA and simulation adapted --- simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index f95cd1a..e386ef2 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -177,7 +177,7 @@ public class ESP8266Ws2812 extends TwoArgFunction { int r = array[0]+(Byte.MIN_VALUE*-1); int b = array[1]+(Byte.MIN_VALUE*-1); int g = array[2]+(Byte.MIN_VALUE*-1); - ESP8266Ws2812.layout.updateLED(index, r, g, b); + ESP8266Ws2812.layout.updateLED(index - 1, r, g, b); } }); return LuaValue.valueOf(true); @@ -203,7 +203,7 @@ public class ESP8266Ws2812 extends TwoArgFunction { final int offset = arg.toint(); if (ESP8266Ws2812.layout != null) { - Element e = ESP8266Ws2812.layout.getLED(offset); + Element e = ESP8266Ws2812.layout.getLED(offset - 1); if (e != null) { Color color = e.getColor(); final byte[] array = new byte[3]; From 070d5de729a94e6b101cdb393be25db4a274a693 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 15:49:54 +0100 Subject: [PATCH 137/204] Show IP if connected to Wifi --- main.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/main.lua b/main.lua index 041c85a..e9caf7a 100644 --- a/main.lua +++ b/main.lua @@ -162,7 +162,12 @@ function normalOperation() connect_counter=nil print('IP: ',wifi.sta.getip(), " heap: ", node.heap()) rgbBuffer:fill(0,0,0) -- clear all LEDs - rgbBuffer:set(13, color) + rgbBuffer:set(13, color) -- I + if ((inv46 ~= nil) and (inv46 == "on")) then + rgbBuffer:set(45, color) -- P + else + rgbBuffer:set(55, color) -- P + end ws2812.write(rgbBuffer) mlt:start() end From 6a70803b6c83b740f4d5c6296810a247e7d24f1e Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 16:07:05 +0100 Subject: [PATCH 138/204] Internal variables for swapping --- displayword.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/displayword.lua b/displayword.lua index 6b0f84e..65687f2 100644 --- a/displayword.lua +++ b/displayword.lua @@ -66,11 +66,12 @@ local swapLine = function(data, lineOffset) if (data.rgbBuffer == nil) then return false end - for i = 0,10 do - local tmpColor=data.rgbBuffer:get(lineOffset+i) - data.rgbBuffer:set(lineOffset+i, data.rgbBuffer:get(lineOffset+10-i)) - data.rgbBuffer:set(lineOffset+10-i, tmpColor) + local num=tonumber(lineOffset)+i + local num2=tonumber(lineOffset)+10-i + local tmpColor=data.rgbBuffer:get(num) + data.rgbBuffer:set(num, data.rgbBuffer:get(num2)) + data.rgbBuffer:set(num2, tmpColor) end return true end From e924b638f16859d346099909c0b2fc801d0bf551 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 16:19:03 +0100 Subject: [PATCH 139/204] Handle not drawn characters --- displayword.lua | 100 ++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/displayword.lua b/displayword.lua index 65687f2..19dd757 100644 --- a/displayword.lua +++ b/displayword.lua @@ -35,12 +35,14 @@ local drawLEDs = function(data, numberNewChars) if (data.rgbBuffer == nil) then return end - local tmpBuf=nil + local skipped=0 + if (data.sC ~= nil) then + skipped=tonumber(data.sC) + end for i=1,numberNewChars do - data.rgbBuffer:set(data.dC + 1, updateColor(data)) + data.rgbBuffer:set(skipped + data.dC + 1, updateColor(data)) data.dC=data.dC+1 end - return tmpBuf end -- Utility function for round @@ -136,7 +138,8 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color data.colorM3=colorM3 data.colorM4=colorM4 end - data.dC=0 + data.dC=0 -- drawn characters + data.sC=0 -- skipped characters local charsPerLine=11 -- Space / background has no color by default @@ -151,7 +154,6 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color rgbBuffer:fill(colorBg) -- draw the background -- Set the foreground color as the default color - local buf=data.colorFg local lineIdx=1 -- line 1---------------------------------------------- lineIdx=11 @@ -161,21 +163,21 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color if (words.it==1) then drawLEDs(data,2) -- ES else - data.dC=data.dC+2 + data.sC=data.sC+2 end --- K fill character -buf=buf .. space:rep(1) + -- K fill character + data.sC=data.sC+1 if (words.is == 1) then drawLEDs(data,3) -- IST else - data.dC=data.dC+3 + data.sC=data.sC+3 end -- L fill character -buf=buf .. space:rep(1) -if (words.m5== 1) then + data.sC=data.sC+1 + if (words.m5== 1) then drawLEDs(data,4) -- FUENF else - data.dC=data.dC+4 + data.sC=data.sC+4 end -- line 2-- even row (so inverted) -------------------- lineIdx=12 @@ -185,12 +187,12 @@ if (words.m5== 1) then if (words.m10 == 1) then drawLEDs(data,4) -- ZEHN else - data.dC=data.dC+4 + data.sC=data.sC+4 end if (words.m20 == 1) then drawLEDs(data,7) -- ZWANZIG else - data.dC=data.dC+7 + data.sC=data.sC+7 end -- swap line swapLine(data,lineIdx) @@ -202,10 +204,10 @@ if (words.m5== 1) then if (words.h3q == 1) then line= drawLEDs(data,11) -- DREIVIERTEL elseif (words.hq == 1) then - data.dC=data.dC+4 + data.sC=data.sC+4 drawLEDs(data,7) -- VIERTEL else - data.dC=data.dC+11 + data.sC=data.sC+11 end --line 4-------- even row (so inverted) ------------- lineIdx=34 @@ -213,16 +215,16 @@ if (words.m5== 1) then for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[4]) end end if (words.ha == 1) then - data.dC=data.dC+2 -- TG + data.sC=data.sC+2 -- TG drawLEDs(data,4) -- NACH else - data.dC=data.dC+6 + data.sC=data.sC+6 end if (words.hb == 1) then drawLEDs(data,3) -- VOR - data.dC=data.dC+2 + data.sC=data.sC+2 else - data.dC=data.dC+5 + data.sC=data.sC+5 end if (invertRows ~= true) then swapLine(data,lineIdx) @@ -234,15 +236,15 @@ if (words.m5== 1) then end if (words.half == 1) then drawLEDs(data,4) -- HALB - data.dC=data.dC+1 -- X + data.sC=data.sC+1 -- X else - data.dC=data.dC+5 + data.sC=data.sC+5 end if (words.h12 == 1) then drawLEDs(data,5) -- ZWOELF - data.dC=data.dC+1 -- P + data.sC=data.sC+1 -- P else - data.dC=data.dC+6 + data.sC=data.sC+6 end if (invertRows == true) then swapLine(data,lineIdx) @@ -253,21 +255,21 @@ if (words.m5== 1) then for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[6]) end end if (words.h7 == 1) then - data.dC=data.dC+5 + data.sC=data.sC+5 drawLEDs(data,6) -- SIEBEN elseif (words.h1l == 1) then - data.dC=data.dC+2 + data.sC=data.sC+2 drawLEDs(data,4) -- EINS - data.dC=data.dC+5 + data.sC=data.sC+5 elseif (words.h1 == 1) then - data.dC=data.dC+2 + data.sC=data.sC+2 drawLEDs(data,3) -- EIN - data.dC=data.dC+6 + data.sC=data.sC+6 elseif (words.h2 == 1) then drawLEDs(data,4) -- ZWEI - data.dC=data.dC+7 + data.sC=data.sC+7 else - data.dC=data.dC+7 + data.sC=data.sC+7 end if (invertRows ~= true) then swapLine(data,lineIdx) @@ -278,14 +280,14 @@ if (words.m5== 1) then for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[7]) end end if (words.h3 == 1) then - data.dC=data.dC+1 + data.sC=data.sC+1 line= line .. drawLEDs(data,4) -- DREI - data.dC=data.dC+6 + data.sC=data.sC+6 elseif (words.h5 == 1) then - data.dC=data.dC+7 + data.sC=data.sC+7 line= line .. drawLEDs(data,4) -- FUENF else - data.dC=data.dC+11 + data.sC=data.sC+11 end ------------even row (so inverted) --------------------- lineIdx=78 @@ -293,17 +295,17 @@ if (words.m5== 1) then for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[8]) end end if (words.h4 == 1) then - data.dC=data.dC+7 + data.sC=data.sC+7 drawLEDs(data,4) -- VIER elseif (words.h9 == 1) then - data.dC=data.dC+3 + data.sC=data.sC+3 drawLEDs(data,4) -- NEUN - data.dC=data.dC+4 + data.sC=data.sC+4 elseif (words.h11 == 1) then drawLEDs(data,3) -- ELF - data.dC=data.dC+8 + data.sC=data.sC+8 else - data.dC=data.dC+11 + data.sC=data.sC+11 end swapLine(data,lineIdx) ------------------------------------------------ @@ -312,15 +314,15 @@ if (words.m5== 1) then for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[9]) end end if (words.h8 == 1) then - data.dC=data.dC+1 + data.sC=data.sC+1 drawLEDs(data,4) -- ACHT - data.dC=data.dC+6 + data.sC=data.sC+6 elseif (words.h10 == 1) then - data.dC=data.dC+5 + data.sC=data.sC+5 drawLEDs(data,4) -- ZEHN - data.dC=data.dC+2 + data.sC=data.sC+2 else - data.dC=data.dC+11 + data.sC=data.sC+11 end ------------even row (so inverted) --------------------- @@ -329,16 +331,16 @@ if (words.m5== 1) then for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[10]) end end if (words.h6 == 1) then - data.dC=data.dC+1 + data.sC=data.sC+1 drawLEDs(data,5) -- SECHS - data.dC=data.dC+2 + data.sC=data.sC+2 else - data.dC=data.dC+8 + data.sC=data.sC+8 end if (words.cl == 1) then drawLEDs(data,3) -- UHR else - data.dC=data.dC+3 + data.sC=data.sC+3 end swapLine(data,lineIdx) ------ Minutes ----------- From 93504e3d9612c3b14d1358456f45942105288844 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 16:19:28 +0100 Subject: [PATCH 140/204] Fix reading color from buffer --- simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java | 6 +++--- simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index e386ef2..394f1c2 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -196,11 +196,11 @@ public class ESP8266Ws2812 extends TwoArgFunction { } } - private class bufferRead extends OneArgFunction { + private class bufferRead extends VarArgFunction { @Override - public LuaValue call(LuaValue arg) { - final int offset = arg.toint(); + public Varargs invoke(Varargs varargs) { + final int offset = varargs.arg(2).toint(); if (ESP8266Ws2812.layout != null) { Element e = ESP8266Ws2812.layout.getLED(offset - 1); diff --git a/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java b/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java index c43fd4c..d99e3b9 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java +++ b/simulation/src/de/c3ma/ollo/mockup/ui/WS2812Layout.java @@ -331,6 +331,11 @@ public class WS2812Layout extends JFrame { if (i % 2 == 1) { j = (mColumn-1) - j; } + if (i < 0 || j < 0) { + System.err.println("LED index" + index + " results in " + i + "x" + j + " coordinate"); + return null; + } + if ((i < mElements.length) && (j < mElements[i].length) && (mElements[i][j] != null)) { return mElements[i][j]; } else { From d4617d9861ce80a793204d0b912c5780777fa15c Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 16:28:38 +0100 Subject: [PATCH 141/204] Removed variable, as function was refactored --- displayword.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/displayword.lua b/displayword.lua index 19dd757..f504030 100644 --- a/displayword.lua +++ b/displayword.lua @@ -202,7 +202,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[3]) end end if (words.h3q == 1) then - line= drawLEDs(data,11) -- DREIVIERTEL + drawLEDs(data,11) -- DREIVIERTEL elseif (words.hq == 1) then data.sC=data.sC+4 drawLEDs(data,7) -- VIERTEL @@ -281,11 +281,11 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color end if (words.h3 == 1) then data.sC=data.sC+1 - line= line .. drawLEDs(data,4) -- DREI + drawLEDs(data,4) -- DREI data.sC=data.sC+6 elseif (words.h5 == 1) then data.sC=data.sC+7 - line= line .. drawLEDs(data,4) -- FUENF + drawLEDs(data,4) -- FUENF else data.sC=data.sC+11 end From 273e8c5b64fd28d1c373c6e320b0de059ab4ac94 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 16:57:44 +0100 Subject: [PATCH 142/204] simulation: Color to number convertion fixed --- simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index 394f1c2..23ad6c2 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -206,10 +206,12 @@ public class ESP8266Ws2812 extends TwoArgFunction { Element e = ESP8266Ws2812.layout.getLED(offset - 1); if (e != null) { Color color = e.getColor(); - final byte[] array = new byte[3]; - array[0] = (byte) color.getRed(); - array[1] = (byte) color.getGreen(); - array[2] = (byte) color.getBlue(); + final char[] array = new char[3]; + array[0] = (char) (color.getRed() ); + array[1] = (char) (color.getGreen() ); + array[2] = (char) (color.getBlue() ); + + System.err.println("[WS2812] reading " + offset + ":" + ((int)array[0]) +"," + ((int) array[1]) + "," + ((int) array[2]) + " from " + color); return LuaString.valueOf(array); } } From 447e17bb56013b205a2d16f8f5a2f00f3ac0b7d1 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 17:24:54 +0100 Subject: [PATCH 143/204] even lines are working --- displayword.lua | 122 ++++++++++++------------------------------------ 1 file changed, 30 insertions(+), 92 deletions(-) diff --git a/displayword.lua b/displayword.lua index f504030..aa799a6 100644 --- a/displayword.lua +++ b/displayword.lua @@ -28,19 +28,15 @@ local updateColor = function (data) end end -local drawLEDs = function(data, numberNewChars) +local drawLEDs = function(data, offset, numberNewChars) if (numberNewChars == nil) then numberNewChars=0 end if (data.rgbBuffer == nil) then return end - local skipped=0 - if (data.sC ~= nil) then - skipped=tonumber(data.sC) - end for i=1,numberNewChars do - data.rgbBuffer:set(skipped + data.dC + 1, updateColor(data)) + data.rgbBuffer:set(offset + i - 1, updateColor(data)) data.dC=data.dC+1 end end @@ -139,7 +135,6 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color data.colorM4=colorM4 end data.dC=0 -- drawn characters - data.sC=0 -- skipped characters local charsPerLine=11 -- Space / background has no color by default @@ -153,31 +148,21 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color end rgbBuffer:fill(colorBg) -- draw the background - -- Set the foreground color as the default color local lineIdx=1 -- line 1---------------------------------------------- - lineIdx=11 if (rowbgColor[1] ~= nil) then for i=lineIdx,11, 1 do data.rgbBuffer:set(i, rowbgColor[1]) end end if (words.it==1) then - drawLEDs(data,2) -- ES - else - data.sC=data.sC+2 + drawLEDs(data, lineIdx, 2) -- ES end -- K fill character - data.sC=data.sC+1 if (words.is == 1) then - drawLEDs(data,3) -- IST - else - data.sC=data.sC+3 + drawLEDs(data, lineIdx+3, 3) -- IST end -- L fill character - data.sC=data.sC+1 if (words.m5== 1) then - drawLEDs(data,4) -- FUENF - else - data.sC=data.sC+4 + drawLEDs(data, lineIdx+7, 4) -- FUENF end -- line 2-- even row (so inverted) -------------------- lineIdx=12 @@ -185,14 +170,10 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,(lineIdx+11), 1 do data.rgbBuffer:set(i, rowbgColor[2]) end end if (words.m10 == 1) then - drawLEDs(data,4) -- ZEHN - else - data.sC=data.sC+4 + drawLEDs(data, lineIdx, 4) -- ZEHN end if (words.m20 == 1) then - drawLEDs(data,7) -- ZWANZIG - else - data.sC=data.sC+7 + drawLEDs(data, lineIdx + 4, 7) -- ZWANZIG end -- swap line swapLine(data,lineIdx) @@ -202,12 +183,9 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[3]) end end if (words.h3q == 1) then - drawLEDs(data,11) -- DREIVIERTEL + drawLEDs(data,lineIdx, 11) -- DREIVIERTEL elseif (words.hq == 1) then - data.sC=data.sC+4 - drawLEDs(data,7) -- VIERTEL - else - data.sC=data.sC+11 + drawLEDs(data, lineIdx + 4, 7) -- VIERTEL end --line 4-------- even row (so inverted) ------------- lineIdx=34 @@ -215,36 +193,27 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[4]) end end if (words.ha == 1) then - data.sC=data.sC+2 -- TG - drawLEDs(data,4) -- NACH - else - data.sC=data.sC+6 + -- TG + drawLEDs(data, lineIdx + 2, 4) -- NACH end if (words.hb == 1) then - drawLEDs(data,3) -- VOR - data.sC=data.sC+2 - else - data.sC=data.sC+5 + drawLEDs(data, lineIdx + 6, 3) -- VOR end if (invertRows ~= true) then swapLine(data,lineIdx) end - ------------------------------------------------ + -- line 5 ---------------------------------------------- lineIdx=45 if (rowbgColor[5] ~= nil) then for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[5]) end end if (words.half == 1) then - drawLEDs(data,4) -- HALB - data.sC=data.sC+1 -- X - else - data.sC=data.sC+5 + drawLEDs(data, lineIdx, 4) -- HALB + -- X end if (words.h12 == 1) then - drawLEDs(data,5) -- ZWOELF - data.sC=data.sC+1 -- P - else - data.sC=data.sC+6 + drawLEDs(data, lineIdx + 5,5) -- ZWOELF + -- P end if (invertRows == true) then swapLine(data,lineIdx) @@ -255,21 +224,13 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[6]) end end if (words.h7 == 1) then - data.sC=data.sC+5 - drawLEDs(data,6) -- SIEBEN + drawLEDs(data, lineIdx + 5, 6) -- SIEBEN elseif (words.h1l == 1) then - data.sC=data.sC+2 - drawLEDs(data,4) -- EINS - data.sC=data.sC+5 + drawLEDs(data, lineIdx + 2,4) -- EINS elseif (words.h1 == 1) then - data.sC=data.sC+2 - drawLEDs(data,3) -- EIN - data.sC=data.sC+6 + drawLEDs(data, lineIdx + 2, 3) -- EIN elseif (words.h2 == 1) then - drawLEDs(data,4) -- ZWEI - data.sC=data.sC+7 - else - data.sC=data.sC+7 + drawLEDs(data, lineIdx, 4) -- ZWEI end if (invertRows ~= true) then swapLine(data,lineIdx) @@ -280,14 +241,9 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[7]) end end if (words.h3 == 1) then - data.sC=data.sC+1 - drawLEDs(data,4) -- DREI - data.sC=data.sC+6 + drawLEDs(data, lineIdx + 1,4) -- DREI elseif (words.h5 == 1) then - data.sC=data.sC+7 - drawLEDs(data,4) -- FUENF - else - data.sC=data.sC+11 + drawLEDs(data, lineIdx + 7, 4) -- FUENF end ------------even row (so inverted) --------------------- lineIdx=78 @@ -295,17 +251,11 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[8]) end end if (words.h4 == 1) then - data.sC=data.sC+7 - drawLEDs(data,4) -- VIER + drawLEDs(data, lineIdx + 7, 4) -- VIER elseif (words.h9 == 1) then - data.sC=data.sC+3 - drawLEDs(data,4) -- NEUN - data.sC=data.sC+4 + drawLEDs(data, lineIdx + 3, 4) -- NEUN elseif (words.h11 == 1) then - drawLEDs(data,3) -- ELF - data.sC=data.sC+8 - else - data.sC=data.sC+11 + drawLEDs(data, lineIdx, 3) -- ELF end swapLine(data,lineIdx) ------------------------------------------------ @@ -314,15 +264,9 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[9]) end end if (words.h8 == 1) then - data.sC=data.sC+1 - drawLEDs(data,4) -- ACHT - data.sC=data.sC+6 + drawLEDs(data, lineIdx + 1, 4) -- ACHT elseif (words.h10 == 1) then - data.sC=data.sC+5 - drawLEDs(data,4) -- ZEHN - data.sC=data.sC+2 - else - data.sC=data.sC+11 + drawLEDs(data, lineIdx + 5, 4) -- ZEHN end ------------even row (so inverted) --------------------- @@ -331,16 +275,10 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[10]) end end if (words.h6 == 1) then - data.sC=data.sC+1 - drawLEDs(data,5) -- SECHS - data.sC=data.sC+2 - else - data.sC=data.sC+8 + drawLEDs(data, lineIdx + 1, 5) -- SECHS end if (words.cl == 1) then - drawLEDs(data,3) -- UHR - else - data.sC=data.sC+3 + drawLEDs(data, lineIdx + 8, 3) -- UHR end swapLine(data,lineIdx) ------ Minutes ----------- From 4d4be95a3cf7a1355f06ada1b301c5d835ca0785 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 20 Mar 2021 17:46:33 +0100 Subject: [PATCH 144/204] Double buffer for simulation added --- .../de/c3ma/ollo/mockup/ESP8266Ws2812.java | 80 +++++++++++++------ 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index 23ad6c2..7ce672c 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -2,6 +2,7 @@ package de.c3ma.ollo.mockup; import java.awt.Color; import java.io.File; +import java.util.ArrayList; import javax.swing.SwingUtilities; @@ -104,9 +105,13 @@ public class ESP8266Ws2812 extends TwoArgFunction { final int leds = varargs.arg(1).toint(); final int bytesPerLeds = varargs.arg(2).toint(); final LuaTable rgbBuffer = new LuaTable(); - rgbBuffer.set("fill", new bufferFill()); - rgbBuffer.set("set", new bufferWrite()); - rgbBuffer.set("get", new bufferRead()); + ArrayList ledList = new ArrayList(); + for(int i=0; i < leds; i++) { + ledList.add(new Color(0,0,0)); + } + rgbBuffer.set("fill", new bufferFill(ledList)); + rgbBuffer.set("set", new bufferWrite(ledList)); + rgbBuffer.set("get", new bufferRead(ledList)); System.out.println("[WS2812] " + leds + "leds (" + bytesPerLeds + "bytes per led)"); return rgbBuffer; } else { @@ -116,12 +121,23 @@ public class ESP8266Ws2812 extends TwoArgFunction { } private class bufferFill extends VarArgFunction { + + private ArrayList ledList = null; + + public bufferFill(ArrayList ledList) { + this.ledList = ledList; + } public Varargs invoke(Varargs varargs) { if (varargs.narg() >= 3) { final int red = varargs.arg(1).toint(); final int green = varargs.arg(2).toint(); final int blue = varargs.arg(3).toint(); + /* update local buffer */ + for(int i=0; i < ledList.size(); i++) { + ledList.set(i, new Color(red, green, blue)); + } + /* Update GUI */ if (ESP8266Ws2812.layout != null) { SwingUtilities.invokeLater(new Runnable() { @Override @@ -133,7 +149,8 @@ public class ESP8266Ws2812 extends TwoArgFunction { System.out.println("[WS2812] buffer fill with " + red + "," + green + "," + blue); return LuaValue.valueOf(true); } else if (varargs.isstring(2)) { - final LuaString color = varargs.arg(2).checkstring(); + final LuaString color = varargs.arg(2).checkstring(); + final int length = color.rawlen(); if ((length == 3) && (ESP8266Ws2812.layout != null)) { @@ -141,6 +158,11 @@ public class ESP8266Ws2812 extends TwoArgFunction { final int r = array[0]+(Byte.MIN_VALUE*-1); final int b = array[1]+(Byte.MIN_VALUE*-1); final int g = array[2]+(Byte.MIN_VALUE*-1); + /* update local buffer */ + for(int i=0; i < ledList.size(); i++) { + ledList.set(i, new Color(r, g, b)); + } + /* Update GUI */ SwingUtilities.invokeLater(new Runnable() { @Override public void run() { @@ -161,22 +183,29 @@ public class ESP8266Ws2812 extends TwoArgFunction { } private class bufferWrite extends VarArgFunction { - + private ArrayList ledList = null; + + public bufferWrite(ArrayList ledList) { + this.ledList = ledList; + } + public Varargs invoke(Varargs varargs) { if (varargs.narg() == 3) { final int index = varargs.arg(2).toint(); - - final LuaString color = varargs.arg(3).checkstring(); final int length = color.rawlen(); if (length == 3) { + final byte[] array = color.m_bytes; + final int r = array[0]+(Byte.MIN_VALUE*-1); + final int b = array[1]+(Byte.MIN_VALUE*-1); + final int g = array[2]+(Byte.MIN_VALUE*-1); + // update buffer + ledList.set(index - 1, new Color(r, g, b)); + + // update GUI SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - final byte[] array = color.m_bytes; - int r = array[0]+(Byte.MIN_VALUE*-1); - int b = array[1]+(Byte.MIN_VALUE*-1); - int g = array[2]+(Byte.MIN_VALUE*-1); ESP8266Ws2812.layout.updateLED(index - 1, r, g, b); } }); @@ -197,23 +226,26 @@ public class ESP8266Ws2812 extends TwoArgFunction { } private class bufferRead extends VarArgFunction { - + private ArrayList ledList = null; + + public bufferRead(ArrayList ledList) { + this.ledList = ledList; + } + @Override public Varargs invoke(Varargs varargs) { final int offset = varargs.arg(2).toint(); - if (ESP8266Ws2812.layout != null) { + + if (ledList != null) { + // receiver from buffer + Color color = ledList.get(offset - 1); + final char[] array = new char[3]; + array[0] = (char) (color.getRed() ); + array[1] = (char) (color.getGreen() ); + array[2] = (char) (color.getBlue() ); - Element e = ESP8266Ws2812.layout.getLED(offset - 1); - if (e != null) { - Color color = e.getColor(); - final char[] array = new char[3]; - array[0] = (char) (color.getRed() ); - array[1] = (char) (color.getGreen() ); - array[2] = (char) (color.getBlue() ); - - System.err.println("[WS2812] reading " + offset + ":" + ((int)array[0]) +"," + ((int) array[1]) + "," + ((int) array[2]) + " from " + color); - return LuaString.valueOf(array); - } + System.err.println("[WS2812] reading " + offset + ":" + ((int)array[0]) +"," + ((int) array[1]) + "," + ((int) array[2]) + " from " + color); + return LuaString.valueOf(array); } System.err.println("[WS2812] reading " + offset + " impossible"); From e2592cc77435d70878bbfdff5e4449d5fd906324 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 14:13:48 +0100 Subject: [PATCH 145/204] More word decoding debug output --- displayword.lua | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/displayword.lua b/displayword.lua index aa799a6..1425989 100644 --- a/displayword.lua +++ b/displayword.lua @@ -5,11 +5,12 @@ do -- @fn generateLEDs -- Module displaying of the words -- @param data struct with the following paramter: --- aoC amount of characters to be used +-- aoC amount of characters for the complete message +-- mC amout of characters per minute -- dC drawn characters local updateColor = function (data) - if (data.aoC > 0) then - local div = tonumber(data.dC/data.aoC) + if (data.aoC > 0) and (data.mC ~= nil) and (data.mC > 0) then + local div = tonumber(data.dC/data.mC) if (div < 1) then return data.colorFg elseif (div < 2) then @@ -64,7 +65,7 @@ local swapLine = function(data, lineOffset) if (data.rgbBuffer == nil) then return false end - for i = 0,10 do + for i = 0,4 do local num=tonumber(lineOffset)+i local num2=tonumber(lineOffset)+10-i local tmpColor=data.rgbBuffer:get(num) @@ -85,7 +86,7 @@ end -- @param colorM3 foreground color if three minutes after a displayable time is present -- @param colorM4 foreground color if four minutes after a displayable time is present -- @param invertRows wheather line 4,5 and 6 shall be inverted or not --- @param aoC Amount of characters to be displayed +-- @param aoC Amount of characters to be displayed local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, colorM2, colorM3, colorM4, invertRows, aoC) -- Set the local variables needed for the colored progress bar if (words == nil) then @@ -111,7 +112,8 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color end if (aoC ~= nil) then - data.aoC = aoC/minutes + data.aoC = aoC + data.mC = aoC/minutes else data.aoC = 0 end @@ -133,6 +135,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color data.colorM2=colorM2 data.colorM3=colorM3 data.colorM4=colorM4 + print("Minutes : " .. tostring(minutes) .. " using " .. tostring(data.aoC) .. " chars with " .. tostring(data.mC) .. " per color") end data.dC=0 -- drawn characters local charsPerLine=11 From 1ef3cf4f5356d9cd7a6c7dc485fe1a244a463710 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 14:14:51 +0100 Subject: [PATCH 146/204] Less debugging in simulation --- simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index 7ce672c..86a811b 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -169,7 +169,7 @@ public class ESP8266Ws2812 extends TwoArgFunction { ESP8266Ws2812.layout.fillLEDs(r, g, b); } }); - System.out.println("[WS2812] buffer fill with " + r + "," + g + "," + b); + //System.out.println("[WS2812] buffer fill with " + r + "," + g + "," + b); return LuaValue.valueOf(true); } else { System.err.println("[WS2812] buffer not initialized ("+varargs.narg() +"args) , length "+ length + ", raw:" + color.toString()); @@ -211,9 +211,9 @@ public class ESP8266Ws2812 extends TwoArgFunction { }); return LuaValue.valueOf(true); } else { - for(int i=0; i <= varargs.narg(); i++) { - System.err.println("[WS2812] write ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); - } +// for(int i=0; i <= varargs.narg(); i++) { +// System.err.println("[WS2812] write ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); +// } System.err.println("[WS2812] set with " + varargs.narg() + " arguments at index="+ index + " and "+ length + " charactes not matching"); return LuaValue.NIL; @@ -244,7 +244,7 @@ public class ESP8266Ws2812 extends TwoArgFunction { array[1] = (char) (color.getGreen() ); array[2] = (char) (color.getBlue() ); - System.err.println("[WS2812] reading " + offset + ":" + ((int)array[0]) +"," + ((int) array[1]) + "," + ((int) array[2]) + " from " + color); +// System.err.println("[WS2812] reading " + offset + ":" + ((int)array[0]) +"," + ((int) array[1]) + "," + ((int) array[2]) + " from " + color); return LuaString.valueOf(array); } From b06ee392ab1cf745dea9ba01bd687ed62364c9be Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 14:48:09 +0100 Subject: [PATCH 147/204] refactored helper function to the beginning --- displayword.lua | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/displayword.lua b/displayword.lua index 1425989..76f36b5 100644 --- a/displayword.lua +++ b/displayword.lua @@ -2,6 +2,21 @@ local M do +local data={} + +-- Utility function for round +local round = function(num) + under = math.floor(num) + upper = math.floor(num) + 1 + underV = -(under - num) + upperV = upper - num + if (upperV > underV) then + return under + else + return upper + end +end + -- @fn generateLEDs -- Module displaying of the words -- @param data struct with the following paramter: @@ -10,16 +25,19 @@ do -- dC drawn characters local updateColor = function (data) if (data.aoC > 0) and (data.mC ~= nil) and (data.mC > 0) then - local div = tonumber(data.dC/data.mC) - if (div < 1) then + local div = tonumber(data.dC / data.mC) + local divRound = round(div) + local perCentColor = tonumber(100 * data.mC / data.aoC) + print (tostring(data.dC) .. " -> " .. tostring(div) .. " " .. tostring(divRound) .. "") + if (divRound < 1) then return data.colorFg - elseif (div < 2) then + elseif (divRound < 2) then return data.colorM1 - elseif (div < 3) then + elseif (divRound < 3) then return data.colorM2 - elseif (div < 4) then + elseif (divRound < 4) then return data.colorM3 - elseif (div < 5) then + elseif (divRound < 5) then return data.colorM4 else return data.colorFg @@ -37,26 +55,11 @@ local drawLEDs = function(data, offset, numberNewChars) return end for i=1,numberNewChars do - data.rgbBuffer:set(offset + i - 1, updateColor(data)) data.dC=data.dC+1 + data.rgbBuffer:set(offset + i - 1, updateColor(data)) end end --- Utility function for round -local round = function(num) - under = math.floor(num) - upper = math.floor(num) + 1 - underV = -(under - num) - upperV = upper - num - if (upperV > underV) then - return under - else - return upper - end -end - -local data={} - -- @fn swapLine -- @param lineOffset offset (starting at 1) where the line is located to be swapped -- works on the rgbBuffer, defined in data struct @@ -113,7 +116,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color if (aoC ~= nil) then data.aoC = aoC - data.mC = aoC/minutes + data.mC = round(aoC/minutes) else data.aoC = 0 end From 2d7d1f65d564e9ac3f4b28f7c3c67406526cad1a Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 15:05:53 +0100 Subject: [PATCH 148/204] Show minutes in the first 5 characters of the word --- displayword.lua | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/displayword.lua b/displayword.lua index 76f36b5..6b3da4f 100644 --- a/displayword.lua +++ b/displayword.lua @@ -21,23 +21,26 @@ end -- Module displaying of the words -- @param data struct with the following paramter: -- aoC amount of characters for the complete message --- mC amout of characters per minute +-- mC amout of minutes to show -- dC drawn characters local updateColor = function (data) - if (data.aoC > 0) and (data.mC ~= nil) and (data.mC > 0) then - local div = tonumber(data.dC / data.mC) - local divRound = round(div) - local perCentColor = tonumber(100 * data.mC / data.aoC) - print (tostring(data.dC) .. " -> " .. tostring(div) .. " " .. tostring(divRound) .. "") - if (divRound < 1) then + if (data.aoC > 0) and (data.mC ~= nil) then + local specialChar = data.dC + if (data.mC < 1) then + specialChar = 0 + elseif (data.dC > data.mC) then + specialChar = 0 + end + print (tostring(data.dC) .. " -> " .. tostring(specialChar) .. " " .. tostring(data.mC) .. "minutes") + if (specialChar < 1) then return data.colorFg - elseif (divRound < 2) then + elseif (specialChar < 2) then return data.colorM1 - elseif (divRound < 3) then + elseif (specialChar < 3) then return data.colorM2 - elseif (divRound < 4) then + elseif (specialChar < 4) then return data.colorM3 - elseif (divRound < 5) then + elseif (specialChar < 5) then return data.colorM4 else return data.colorFg @@ -99,7 +102,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color invertRows=false end - local minutes=1 + local minutes=0 if (words.m1 == 1) then minutes = minutes + 1 elseif (words.m2 == 1) then @@ -116,7 +119,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color if (aoC ~= nil) then data.aoC = aoC - data.mC = round(aoC/minutes) + data.mC = minutes else data.aoC = 0 end @@ -138,7 +141,6 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color data.colorM2=colorM2 data.colorM3=colorM3 data.colorM4=colorM4 - print("Minutes : " .. tostring(minutes) .. " using " .. tostring(data.aoC) .. " chars with " .. tostring(data.mC) .. " per color") end data.dC=0 -- drawn characters local charsPerLine=11 From fd5ec411f18d912087875f2d7a3359749c2c68d4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 15:12:37 +0100 Subject: [PATCH 149/204] Removed debug code --- displayword.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/displayword.lua b/displayword.lua index 6b3da4f..bb567e1 100644 --- a/displayword.lua +++ b/displayword.lua @@ -31,7 +31,6 @@ local updateColor = function (data) elseif (data.dC > data.mC) then specialChar = 0 end - print (tostring(data.dC) .. " -> " .. tostring(specialChar) .. " " .. tostring(data.mC) .. "minutes") if (specialChar < 1) then return data.colorFg elseif (specialChar < 2) then From 2e77516d4323fdd197f014d9fddad2c7261b690f Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 15:31:05 +0100 Subject: [PATCH 150/204] Show boot process --- main.lua | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/main.lua b/main.lua index e9caf7a..8ba1541 100644 --- a/main.lua +++ b/main.lua @@ -64,17 +64,7 @@ function displayTime() dw = nil collectgarbage() print("dw: " .. tostring(node.heap())) - if (rgbBuffer ~= nil) then - ws2812.write(rgbBuffer) - else - -- set FG to fix value: RED - local color = string.char(255,0,0) - rgbBuffer:fill(0,0,0) -- disable all LEDs - for i=108,110, 1 do rgbBuffer:set(i, color) end - ws2812.write(rgbBuffer) - print("Fallback no time displayed") - end - + -- cleanup i=nil briPer=words.briPer @@ -100,11 +90,25 @@ function normalOperation() syncTimeFromInternet() setupCounter=setupCounter-1 alive = 1 + rgbBuffer:set(19, color) -- N + rgbBuffer:set(31, color) -- T + if ((inv46 ~= nil) and (inv46 == "on")) then + rgbBuffer:set(45, color) -- P + else + rgbBuffer:set(55, color) -- P + end elseif (setupCounter > 3) then -- Here the WLAN is found, and something is done mydofile("mqtt") + rgbBuffer:fill(0,0,0) -- disable all LEDs if (startMqttClient ~= nil) then - startMqttClient() + if ((inv46 ~= nil) and (inv46 == "on")) then + rgbBuffer:set(34, color) -- M + else + rgbBuffer:set(44, color) -- M + end + rgbBuffer:set(82, color) -- T + startMqttClient() else print("NO Mqtt found") mydofile("telnet") @@ -120,12 +124,22 @@ function normalOperation() elseif ( (alive % 120) == 0) then -- sync the time every 5 minutes syncTimeFromInternet() - alive = alive + 1 - collectgarbage() + alive = alive + 1 + collectgarbage() else displayTime() alive = alive + 1 end + if (rgbBuffer ~= nil) then + ws2812.write(rgbBuffer) + else + -- set FG to fix value: RED + local color = string.char(255,0,0) + rgbBuffer:fill(0,0,0) -- disable all LEDs + for i=108,110, 1 do rgbBuffer:set(i, color) end + ws2812.write(rgbBuffer) + print("Fallback no time displayed") + end -- Feed the system watchdog. tmr.wdclr() end) From 7939bf578d61611910cdd19fb9ef3d1423dbedd6 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 16:06:26 +0100 Subject: [PATCH 151/204] config file can be uploaded with this script, too --- tools/initialDietFlash.sh | 56 ++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/tools/initialDietFlash.sh b/tools/initialDietFlash.sh index 0df989c..41fc7a5 100755 --- a/tools/initialDietFlash.sh +++ b/tools/initialDietFlash.sh @@ -37,22 +37,35 @@ else FILES=$2 fi -echo "Generate DIET version of the files" -OUTFILES="" -ROOTDIR=$PWD -cd $TOOLDIR -for f in $FILES; do - if [[ "$f" == *.lua ]] && [[ "$f" != init.lua ]]; then - echo "Compress $f ..." - out=$(echo "$f" | sed 's/.lua/_diet.lua/g') - $DIET ../$f -o ../diet/$out - OUTFILES="$OUTFILES diet/$out" - else - OUTFILES="$OUTFILES $f" - fi -done -FILES=$OUTFILES -cd $ROOTDIR +# Convert files, if necessary +if [ "$FILES" != "config.lua" ]; then + echo "Generate DIET version of the files" + OUTFILES="" + ROOTDIR=$PWD + cd $TOOLDIR + for f in $FILES; do + if [[ "$f" == *.lua ]] && [[ "$f" != init.lua ]]; then + echo "Compress $f ..." + out=$(echo "$f" | sed 's/.lua/_diet.lua/g') + $DIET ../$f -o ../diet/$out + OUTFILES="$OUTFILES diet/$out" + else + OUTFILES="$OUTFILES $f" + fi + done + FILES=$OUTFILES + cd $ROOTDIR +fi +echo "Reboot ESP and stop init timer" +if [ ! -f $LUASCRIPT_STOP ]; then + echo "Cannot find $LUASCRIPT_STOP" + exit 1 +fi +python3 $LUATOOL -p $DEVICE -f $LUASCRIPT_STOP -b $BAUD --volatile --delay 2 +if [ $? -ne 0 ]; then + echo "Could not reboot" + exit 1 +fi if [ $# -eq 1 ]; then # Format filesystem first @@ -62,17 +75,6 @@ if [ $# -eq 1 ]; then echo "STOOOOP" exit 1 fi -else - echo "Reboot ESP and stop init timer" - if [ ! -f $LUASCRIPT_STOP ]; then - echo "Cannot find $LUASCRIPT_STOP" - exit 1 - fi - python3 $LUATOOL -p $DEVICE -f $LUASCRIPT_STOP -b $BAUD --volatile --delay 2 - if [ $? -ne 0 ]; then - echo "Could not reboot" - exit 1 - fi fi echo "Start Flasing ..." From 3832e89afa51cb5496a3c0ca9025408f39e461b0 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 17:30:50 +0100 Subject: [PATCH 152/204] Fixed ws2812 buffer on the target --- displayword.lua | 20 +++++++++----------- main.lua | 6 +++++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/displayword.lua b/displayword.lua index bb567e1..4c10bf7 100644 --- a/displayword.lua +++ b/displayword.lua @@ -58,7 +58,7 @@ local drawLEDs = function(data, offset, numberNewChars) end for i=1,numberNewChars do data.dC=data.dC+1 - data.rgbBuffer:set(offset + i - 1, updateColor(data)) + data.rgbBuffer:set(tonumber(offset + i - 1), updateColor(data)) end end @@ -72,10 +72,11 @@ local swapLine = function(data, lineOffset) end for i = 0,4 do local num=tonumber(lineOffset)+i - local num2=tonumber(lineOffset)+10-i - local tmpColor=data.rgbBuffer:get(num) - data.rgbBuffer:set(num, data.rgbBuffer:get(num2)) - data.rgbBuffer:set(num2, tmpColor) + local num2=tonumber(tonumber(lineOffset)+10-i) + local tmpC1, tmpC2, tmpC3=data.rgbBuffer:get(num) + local c1, c2, c3 =data.rgbBuffer:get(num2) + data.rgbBuffer:set(num, c1, c2, c3) + data.rgbBuffer:set(num2, tmpC1, tmpC2, tmpC3) end return true end @@ -144,16 +145,13 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color data.dC=0 -- drawn characters local charsPerLine=11 - -- Space / background has no color by default - local space=string.char(0,0,0) - -- Background color must always be set if (colorBg ~= nil) then - space = colorBg + rgbBuffer:fill(string.byte(colorBg,1), string.byte(colorBg,2), string.byte(colorBg,3)) -- draw the background else - colorBg = space + -- Space / background has no color by default + rgbBuffer:fill(0, 0, 0) -- draw the background end - rgbBuffer:fill(colorBg) -- draw the background local lineIdx=1 -- line 1---------------------------------------------- diff --git a/main.lua b/main.lua index 8ba1541..4028a29 100644 --- a/main.lua +++ b/main.lua @@ -86,7 +86,11 @@ function normalOperation() local alive=0 mlt:register(2500, tmr.ALARM_AUTO, function (lt) if (setupCounter > 4) then - rgbBuffer:fill(0,0,0) -- disable all LEDs + if (colorBg ~= nil) then + rgbBuffer:fill(string.byte(colorBg,1), string.byte(colorBg,2), string.byte(colorBg,3)) -- disable all LEDs + else + rgbBuffer:fill(0,0,0) -- disable all LEDs + end syncTimeFromInternet() setupCounter=setupCounter-1 alive = 1 From c513f7c8991ab217f26fcd4ea37653a413d00798 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 18:00:07 +0100 Subject: [PATCH 153/204] Status of mqtt connection --- main.lua | 8 +++++++- mqtt.lua | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/main.lua b/main.lua index 4028a29..eb73ea3 100644 --- a/main.lua +++ b/main.lua @@ -135,6 +135,12 @@ function normalOperation() alive = alive + 1 end if (rgbBuffer ~= nil) then + -- show Mqtt status + if (startMqttClient ~= nil) then + if (not connectedMqtt()) then + rgbBuffer:set(110-4, 128,0,0) + end + end ws2812.write(rgbBuffer) else -- set FG to fix value: RED @@ -153,7 +159,7 @@ function normalOperation() local connect_counter=0 -- Wait to be connect to the WiFi access point. local wifitimer = tmr.create() - wifitimer:register(2000, tmr.ALARM_AUTO, function (timer) + wifitimer:register(500, tmr.ALARM_AUTO, function (timer) connect_counter=connect_counter+1 if wifi.sta.status() ~= 5 then print(connect_counter .. "/60 Connecting to AP...") diff --git a/mqtt.lua b/mqtt.lua index 987cdff..5305493 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -145,6 +145,10 @@ function registerMqtt() end) end +function connectedMqtt() + return mqttConnected +end + function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then registerMqtt() From 116c30f5e5488c3434273f62ca8f23efd0e9728b Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 18:21:04 +0100 Subject: [PATCH 154/204] Remote upgrade script detects clock successfully --- tools/remoteFlash.sh | 25 +++++++++++++++++-------- tools/tcpFlash.py | 2 -- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tools/remoteFlash.sh b/tools/remoteFlash.sh index 3f679a0..7f00142 100755 --- a/tools/remoteFlash.sh +++ b/tools/remoteFlash.sh @@ -2,6 +2,7 @@ MQTTSERVER=$1 MQTTPREFIX=$2 +CUSTOMFILE=$3 FLASHTOOL=./tools/tcpFlash.py @@ -31,19 +32,27 @@ fi echo "Activate Telnet server" mosquitto_pub -h $MQTTSERVER -t "$MQTTPREFIX/cmd/telnet" -m "a" TELNETIP=$(mosquitto_sub -h $MQTTSERVER -t "$MQTTPREFIX/telnet" -C 1) -echo "Upgrading $MQTTPREFIX via telenet on $TELNETIP" - -echo "stopWordclock()" > $UPGRADEPREP +echo "Upgrading $MQTTPREFIX via telenet on $TELNETIP ..." +sleep 1 +echo "if (mlt ~= nil) then mlt:unregister() end" > $UPGRADEPREP echo "uart.write(0, tostring(node.heap())" >> $UPGRADEPREP -echo "c = string.char(0,0,128)" >> $UPGRADEPREP +echo "collectgarbage()" >> $UPGRADEPREP +echo "" >> $UPGRADEPREP +echo "download = string.char(0,0,64)" >> $UPGRADEPREP echo "w = string.char(0,0,0)" >> $UPGRADEPREP -echo "ws2812.write(w:rep(4) .. c .. w:rep(15) .. c .. w:rep(9) .. c .. w:rep(30) .. c .. w:rep(41) .. c )" >> $UPGRADEPREP +echo "ws2812.write(w:rep(4) .. download .. w:rep(15) .. download .. w:rep(9) .. download .. w:rep(30) .. download .. w:rep(41) .. download )" >> $UPGRADEPREP +echo "collectgarbage()" >> $UPGRADEPREP $FLASHTOOL -f $UPGRADEPREP -t $TELNETIP -v -exit 2 -FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua wordclock.lua init.lua" +if [[ "$CUSTOMFILE" == "" ]]; then + FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua wordclock.lua init.lua" + echo "Start Flasing ..." +else + FILES=$CUSTOMFILE + echo "Start Flasing $FILES" +fi -echo "Start Flasing ..." +exit 2 for f in $FILES; do if [ ! -f $f ]; then echo "Cannot find $f" diff --git a/tools/tcpFlash.py b/tools/tcpFlash.py index 4f7526b..45ed4d8 100755 --- a/tools/tcpFlash.py +++ b/tools/tcpFlash.py @@ -72,8 +72,6 @@ def main(nodeip, luafile, volatile=None): s.close() sys.exit(3) - sendCmd(s, "for i=0,5 do tmr.stop(i) end") - sendCmd(s, "collectgarbage()") if (volatile is None): print "Flashing " + luafile sendCmd(s, "file.remove(\"" + luafile+"\");", True) From 7a2814d32772f9cff9feabf5add3b8d1d3a3dca4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 20:37:53 +0100 Subject: [PATCH 155/204] Remove compiled file before compiling --- init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/init.lua b/init.lua index e8cdc94..4213a0a 100644 --- a/init.lua +++ b/init.lua @@ -39,6 +39,7 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) local modlist = { "timecore" , "displayword" } for i,mod in pairs(modlist) do if (file.open(mod .. "_diet.lua")) then + file.remove(mod .. "_diet.lc") print(tostring(i) .. ". Compile " .. mod) ws2812.write(string.char(0,0,0):rep(11*i)..string.char(128,0,0):rep(11)) node.compile(mod .. "_diet.lua") From 91ab8609b91b53d34026aabdad205854b96f9163 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 20:38:03 +0100 Subject: [PATCH 156/204] Remote update worked --- tools/remoteFlash.sh | 47 +++++++++++++++++++++++++++++++++----------- tools/tcpFlash.py | 30 +++++++++++++++++----------- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/tools/remoteFlash.sh b/tools/remoteFlash.sh index 7f00142..2bdeb47 100755 --- a/tools/remoteFlash.sh +++ b/tools/remoteFlash.sh @@ -5,6 +5,8 @@ MQTTPREFIX=$2 CUSTOMFILE=$3 FLASHTOOL=./tools/tcpFlash.py +TOOLDIR=tools/ +DIET=bin/luasrcdiet UPGRADEPREP=/tmp/upgradeCMD4clock.txt @@ -22,6 +24,37 @@ if [[ "$MQTTPREFIX" == "" ]] || [[ "$MQTTSERVER" == "" ]]; then exit 1 fi +# Prepare all files on host +if [[ "$CUSTOMFILE" == "" ]]; then + FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua wordclock.lua init.lua" + echo "Start Flasing ..." +else + FILES=$CUSTOMFILE + echo "Start Flasing $FILES ..." +fi + + +# Convert files, if necessary +if [ "$FILES" != "config.lua" ]; then + echo "Generate DIET version of the files" + OUTFILES="" + ROOTDIR=$PWD + cd $TOOLDIR + for f in $FILES; do + if [[ "$f" == *.lua ]] && [[ "$f" != init.lua ]]; then + echo "Compress $f ..." + out=$(echo "$f" | sed 's/.lua/_diet.lua/g') + $DIET ../$f -o ../diet/$out >> /dev/null + OUTFILES="$OUTFILES diet/$out" + else + OUTFILES="$OUTFILES $f" + fi + done + FILES=$OUTFILES + cd $ROOTDIR +fi + + # check the connection echo "Searching $MQTTPREFIX ..." mosquitto_sub -h $MQTTSERVER -t "$MQTTPREFIX/#" -C 1 -v @@ -44,23 +77,15 @@ echo "ws2812.write(w:rep(4) .. download .. w:rep(15) .. download .. w:rep(9) .. echo "collectgarbage()" >> $UPGRADEPREP $FLASHTOOL -f $UPGRADEPREP -t $TELNETIP -v -if [[ "$CUSTOMFILE" == "" ]]; then - FILES="displayword.lua main.lua timecore.lua webpage.html webserver.lua wordclock.lua init.lua" - echo "Start Flasing ..." -else - FILES=$CUSTOMFILE - echo "Start Flasing $FILES" -fi - -exit 2 for f in $FILES; do if [ ! -f $f ]; then echo "Cannot find $f" echo "place the terminal into the folder where the lua files are present" exit 1 fi - echo "------------- $f ------------" - $FLASHTOOL -t $TELNETIP -f $f + espFile=$(echo "$f" | sed 's;diet/;;g') + echo "------------- $espFile ------------" + $FLASHTOOL -t $TELNETIP -f $f -o $espFile if [ $? -ne 0 ]; then echo "STOOOOP" exit 1 diff --git a/tools/tcpFlash.py b/tools/tcpFlash.py index 45ed4d8..b2a2be1 100755 --- a/tools/tcpFlash.py +++ b/tools/tcpFlash.py @@ -43,7 +43,7 @@ def sendCmd(s, message, cleaningEnter=False): print "ERROR, received : " + reply return False -def main(nodeip, luafile, volatile=None): +def main(nodeip, luafile, volatile=None, outfile=None): if ( not os.path.isfile(luafile) ): print "The file " + luafile + " is not available" else: @@ -71,12 +71,16 @@ def main(nodeip, luafile, volatile=None): print "NOT communicating with an ESP8266 running LUA (nodemcu) firmware" s.close() sys.exit(3) - + if (volatile is None): - print "Flashing " + luafile - sendCmd(s, "file.remove(\"" + luafile+"\");", True) + if (outfile is None): + print "Flashing " + luafile + outfile=luafile + else: + print "Flashing " + luafile + " as " + outfile + sendCmd(s, "file.remove(\"" + outfile +"\");", True) sendCmd(s, "w= file.writeline", True) - sendCmd(s, "file.open(\"" + luafile + "\",\"w+\");", True) + sendCmd(s, "file.open(\"" + outfile + "\",\"w+\");", True) else: print "Executing " + luafile + " on nodemcu" @@ -112,11 +116,11 @@ def main(nodeip, luafile, volatile=None): sys.exit(4) # Check if the file exists: - if (not sendRecv(s, "=file.exists(\"" + luafile + "\")", "true")): - print("Cannot send " + luafile + " to the ESP") + if (not sendRecv(s, "=file.exists(\"" + outfile + "\")", "true")): + print("Cannot send " + outfile + " to the ESP") sys.exit(4) else: - print("Updated " + luafile + " successfully") + print("Updated " + outfile + " successfully") else: print("Send " + luafile + " successfully") @@ -131,12 +135,16 @@ if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-t', '--target', help='IP address or dns of the ESP to flash') parser.add_argument('-f', '--file', help='LUA file, that should be updated') + parser.add_argument('-o', '--outfile', help='LUA file name on the microcontroller (default: same name as on host)') parser.add_argument('-v', '--volatile', help='File is executed at the commandline', action='store_const', const=1) args = parser.parse_args() - - if (args.target and args.file and args.volatile): - main(args.target, args.file, args.volatile) + if (args.target and args.file and args.volatile and args.outfile): + main(args.target, args.file, args.volatile, args.outfile) + elif (args.target and args.file and args.outfile): + main(args.target, args.file, None, args.outfile) + elif (args.target and args.file and args.volatile): + main(args.target, args.file, args.volatile) elif (args.target and args.file): main(args.target, args.file) else: From 9cd54da7748f9d7804671ed521d442efa0eebf69 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 20:52:27 +0100 Subject: [PATCH 157/204] Temperature library can be initialized --- mqtt.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 5305493..5efaea3 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -104,6 +104,8 @@ function registerMqtt() mydofile("telnet") if (startTelnetServer ~= nil) then startTelnetServer() + else + print("Cannost start Telnet Server!") end else for i=1,10,1 do @@ -153,8 +155,8 @@ function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then registerMqtt() print "Started MQTT client" - if (file.open("ds18b20.lc")) then - t=require("ds18b20") + if (file.open("ds18b20_diet.lua")) then + t=require("ds18b20_diet") t.setup(2) -- GPIO4 readTemp() -- read once, to setup chip print "Setup temperature" From 7d604058779f9180b792e4ce835867ecad62b14e Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 21:00:47 +0100 Subject: [PATCH 158/204] Temperature must be compiled --- init.lua | 2 +- mqtt.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index 4213a0a..fba9d65 100644 --- a/init.lua +++ b/init.lua @@ -36,7 +36,7 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) initTimer:unregister() initTimer=nil bootledtimer=nil - local modlist = { "timecore" , "displayword" } + local modlist = { "timecore" , "displayword", "ds18b20" } for i,mod in pairs(modlist) do if (file.open(mod .. "_diet.lua")) then file.remove(mod .. "_diet.lc") diff --git a/mqtt.lua b/mqtt.lua index 5efaea3..9c1a6bf 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -155,7 +155,7 @@ function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then registerMqtt() print "Started MQTT client" - if (file.open("ds18b20_diet.lua")) then + if (file.open("ds18b20_diet.lc")) then t=require("ds18b20_diet") t.setup(2) -- GPIO4 readTemp() -- read once, to setup chip From 7ef7efbdad7615b05dce80a2eee7d1ba764f8c88 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 21 Mar 2021 21:05:27 +0100 Subject: [PATCH 159/204] MQTT status character updated --- main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.lua b/main.lua index eb73ea3..026f881 100644 --- a/main.lua +++ b/main.lua @@ -138,7 +138,7 @@ function normalOperation() -- show Mqtt status if (startMqttClient ~= nil) then if (not connectedMqtt()) then - rgbBuffer:set(110-4, 128,0,0) + rgbBuffer:set(103, 0, 64,0) end end ws2812.write(rgbBuffer) From 667350781c8505e0e3f29ee8457317b0ae62ac79 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 23 Mar 2021 21:32:53 +0100 Subject: [PATCH 160/204] row has one LED less --- displayword.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/displayword.lua b/displayword.lua index 4c10bf7..18d0052 100644 --- a/displayword.lua +++ b/displayword.lua @@ -156,7 +156,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color local lineIdx=1 -- line 1---------------------------------------------- if (rowbgColor[1] ~= nil) then - for i=lineIdx,11, 1 do data.rgbBuffer:set(i, rowbgColor[1]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[1]) end end if (words.it==1) then drawLEDs(data, lineIdx, 2) -- ES @@ -172,7 +172,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color -- line 2-- even row (so inverted) -------------------- lineIdx=12 if (rowbgColor[2] ~= nil) then - for i=lineIdx,(lineIdx+11), 1 do data.rgbBuffer:set(i, rowbgColor[2]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[2]) end end if (words.m10 == 1) then drawLEDs(data, lineIdx, 4) -- ZEHN @@ -185,7 +185,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color -- line3---------------------------------------------- lineIdx=23 if (rowbgColor[3] ~= nil) then - for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[3]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[3]) end end if (words.h3q == 1) then drawLEDs(data,lineIdx, 11) -- DREIVIERTEL @@ -195,7 +195,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color --line 4-------- even row (so inverted) ------------- lineIdx=34 if (rowbgColor[4] ~= nil) then - for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[4]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[4]) end end if (words.ha == 1) then -- TG @@ -210,7 +210,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color -- line 5 ---------------------------------------------- lineIdx=45 if (rowbgColor[5] ~= nil) then - for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[5]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[5]) end end if (words.half == 1) then drawLEDs(data, lineIdx, 4) -- HALB @@ -226,7 +226,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color ------------even row (so inverted) --------------------- lineIdx=56 if (rowbgColor[6] ~= nil) then - for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[6]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[6]) end end if (words.h7 == 1) then drawLEDs(data, lineIdx + 5, 6) -- SIEBEN @@ -243,7 +243,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color ------------------------------------------------ lineIdx=67 if (rowbgColor[7] ~= nil) then - for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[7]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[7]) end end if (words.h3 == 1) then drawLEDs(data, lineIdx + 1,4) -- DREI @@ -253,7 +253,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color ------------even row (so inverted) --------------------- lineIdx=78 if (rowbgColor[8] ~= nil) then - for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[8]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[8]) end end if (words.h4 == 1) then drawLEDs(data, lineIdx + 7, 4) -- VIER @@ -266,7 +266,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color ------------------------------------------------ lineIdx=89 if (rowbgColor[9] ~= nil) then - for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[9]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[9]) end end if (words.h8 == 1) then drawLEDs(data, lineIdx + 1, 4) -- ACHT @@ -277,7 +277,7 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color ------------even row (so inverted) --------------------- lineIdx=100 if (rowbgColor[10] ~= nil) then - for i=lineIdx,lineIdx+11, 1 do data.rgbBuffer:set(i, rowbgColor[10]) end + for i=lineIdx,lineIdx+10, 1 do data.rgbBuffer:set(i, rowbgColor[10]) end end if (words.h6 == 1) then drawLEDs(data, lineIdx + 1, 5) -- SECHS From 92a1c2c8d23b74387523badeaa8a922790adbda1 Mon Sep 17 00:00:00 2001 From: Ollo Date: Tue, 23 Mar 2021 21:48:57 +0100 Subject: [PATCH 161/204] Only update in main loop --- mqtt.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 9c1a6bf..7c9be19 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -25,9 +25,6 @@ function handleSingleCommand(client, topic, data) colorBg=string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) - if (displayTime~= nil) then - displayTime() - end else if (tonumber(data) >= 0 and tonumber(data) <= 100) then briPer=tonumber(data) From 94e554843f36563b79bef292311fd7c7b3b416a9 Mon Sep 17 00:00:00 2001 From: Ollo Date: Wed, 24 Mar 2021 21:01:34 +0100 Subject: [PATCH 162/204] Added MQTT simulation --- .../src/de/c3ma/ollo/WS2812Simulation.java | 3 + .../src/de/c3ma/ollo/mockup/ESP8266Mqtt.java | 82 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java diff --git a/simulation/src/de/c3ma/ollo/WS2812Simulation.java b/simulation/src/de/c3ma/ollo/WS2812Simulation.java index 4c15f8d..5dfb44a 100644 --- a/simulation/src/de/c3ma/ollo/WS2812Simulation.java +++ b/simulation/src/de/c3ma/ollo/WS2812Simulation.java @@ -14,6 +14,7 @@ import de.c3ma.ollo.mockup.DoFileFunction; import de.c3ma.ollo.mockup.ESP8266Adc; import de.c3ma.ollo.mockup.ESP8266File; import de.c3ma.ollo.mockup.ESP8266Gpio; +import de.c3ma.ollo.mockup.ESP8266Mqtt; import de.c3ma.ollo.mockup.ESP8266Net; import de.c3ma.ollo.mockup.ESP8266Node; import de.c3ma.ollo.mockup.ESP8266Time; @@ -39,6 +40,7 @@ public class WS2812Simulation implements LuaSimulation { private DoFileFunction doFile = new DoFileFunction(globals); private ESP8266Ws2812 ws2812 = new ESP8266Ws2812(); private ESP8266Gpio gpio = new ESP8266Gpio(); + private ESP8266Mqtt mqtt = new ESP8266Mqtt(); private ESP8266Adc adc = new ESP8266Adc(); private String scriptName; @@ -50,6 +52,7 @@ public class WS2812Simulation implements LuaSimulation { globals.load(espNode); globals.load(adc); globals.load(gpio); + globals.load(mqtt); globals.load(new ESP8266Wifi()); globals.load(new ESP8266Net()); globals.load(new ESP8266Time()); diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java new file mode 100644 index 0000000..65149cb --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java @@ -0,0 +1,82 @@ +package de.c3ma.ollo.mockup; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.VarArgFunction; + +/** + * + * @author ollo + * + */ +public class ESP8266Mqtt extends TwoArgFunction { + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + env.checkglobals(); + final LuaTable mqtt = new LuaTable(); + mqtt.set("Client", new MqttClient()); + env.set("mqtt", mqtt); + env.get("package").get("loaded").set("tmr", mqtt); + + return mqtt; + } + + private class MqttClient extends VarArgFunction { + public LuaValue invoke(Varargs varargs) { + final LuaTable dynMqtt = new LuaTable(); + if (varargs.narg() == 2) { + final String client = varargs.arg(2).toString().toString(); + final int timeout = varargs.arg(3).toint(); + dynMqtt.set("on", new OnMqtt(client, timeout)); + dynMqtt.set("publish", new PublishMqtt()); + dynMqtt.set("subscribe", new SubscribeMqtt()); + System.out.println("[MQTT] New " + client + " client"); + } + return dynMqtt; + } + } + + private class OnMqtt extends VarArgFunction { + + private String client=null; + private int timeout = 0; + + private OnMqtt(String client, int timeout) { + this.client = client; + this.timeout = timeout; + } + + public LuaValue invoke(Varargs varargs) { + final LuaTable onMqtt = new LuaTable(); + if (varargs.narg() == 2) { + System.out.println("[MQTT] On " + this.client); + } + return onMqtt; + } + } + + private class PublishMqtt extends VarArgFunction { + + public LuaValue invoke(Varargs varargs) { + final LuaTable onMqtt = new LuaTable(); + if (varargs.narg() == 2) { + System.out.println("[MQTT] publish "); + } + return onMqtt; + } + } + + private class SubscribeMqtt extends VarArgFunction { + + public LuaValue invoke(Varargs varargs) { + final LuaTable onMqtt = new LuaTable(); + if (varargs.narg() == 2) { + System.out.println("[MQTT] subscribe "); + } + return onMqtt; + } + } +} From 41179c4afdc9cab849b9b434d2a6a31eccaffad7 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 26 Mar 2021 21:54:42 +0100 Subject: [PATCH 163/204] set buffer with red, green and blue --- .../src/de/c3ma/ollo/mockup/ESP8266Mqtt.java | 15 ++++++++++ .../de/c3ma/ollo/mockup/ESP8266Ws2812.java | 28 +++++++++++++------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java index 65149cb..758ab76 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java @@ -53,6 +53,11 @@ public class ESP8266Mqtt extends TwoArgFunction { final LuaTable onMqtt = new LuaTable(); if (varargs.narg() == 2) { System.out.println("[MQTT] On " + this.client); + } else { + for(int i=0; i <= varargs.narg(); i++) { + System.err.println("[MQTT] On ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); + } + return LuaValue.NIL; } return onMqtt; } @@ -64,6 +69,11 @@ public class ESP8266Mqtt extends TwoArgFunction { final LuaTable onMqtt = new LuaTable(); if (varargs.narg() == 2) { System.out.println("[MQTT] publish "); + } else { + for(int i=0; i <= varargs.narg(); i++) { + System.err.println("[MQTT] publish ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); + } + return LuaValue.NIL; } return onMqtt; } @@ -75,6 +85,11 @@ public class ESP8266Mqtt extends TwoArgFunction { final LuaTable onMqtt = new LuaTable(); if (varargs.narg() == 2) { System.out.println("[MQTT] subscribe "); + } else { + for(int i=0; i <= varargs.narg(); i++) { + System.err.println("[MQTT] subscribe ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); + } + return LuaValue.NIL; } return onMqtt; } diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index 86a811b..69a4d75 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import javax.swing.SwingUtilities; -import org.luaj.vm2.LuaNil; import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; @@ -17,9 +16,7 @@ import org.luaj.vm2.lib.VarArgFunction; import org.luaj.vm2.lib.ZeroArgFunction; import de.c3ma.ollo.LuaSimulation; -import de.c3ma.ollo.LuaThreadTmr; import de.c3ma.ollo.mockup.ui.WS2812Layout; -import de.c3ma.ollo.mockup.ui.WS2812Layout.Element; /** * created at 28.12.2017 - 23:34:04
@@ -210,15 +207,30 @@ public class ESP8266Ws2812 extends TwoArgFunction { } }); return LuaValue.valueOf(true); - } else { -// for(int i=0; i <= varargs.narg(); i++) { -// System.err.println("[WS2812] write ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); -// } - + } else { System.err.println("[WS2812] set with " + varargs.narg() + " arguments at index="+ index + " and "+ length + " charactes not matching"); return LuaValue.NIL; } + } else if (varargs.narg() == 5) { + final int index = varargs.arg(2).toint(); + final int green = varargs.arg(3).toint(); + final int red = varargs.arg(4).toint(); + final int blue = varargs.arg(5).toint(); + // update buffer + ledList.set(index - 1, new Color(red, green, blue)); + + // update GUI + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ESP8266Ws2812.layout.updateLED(index - 1, red, green, blue); + } + }); + return LuaValue.valueOf(true); } else { + for(int i=0; i <= varargs.narg(); i++) { + System.err.println("[WS2812] write ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); + } System.err.println("[WS2812] set with " + varargs.narg() + " arguments undefined."); return LuaValue.NIL; } From 950854215898dbbbcdfc9ddde27d1217625bda94 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 26 Mar 2021 22:44:18 +0100 Subject: [PATCH 164/204] All MQTT dummy function added --- simulation/config.lua | 2 ++ .../src/de/c3ma/ollo/mockup/ESP8266Mqtt.java | 36 +++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/simulation/config.lua b/simulation/config.lua index c6b8f5e..4b24281 100644 --- a/simulation/config.lua +++ b/simulation/config.lua @@ -11,3 +11,5 @@ color4=string.char(0,0 ,tonumber(blue*0.2)) colorBg=string.char(0,0,0) -- black is the default background color sntpserverhostname="ptbtime1.ptb.de" timezoneoffset=1 +mqttServer="192.168.1.1" +mqttPrefix="test" diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java index 758ab76..cbc752a 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java @@ -6,6 +6,8 @@ import org.luaj.vm2.Varargs; import org.luaj.vm2.lib.TwoArgFunction; import org.luaj.vm2.lib.VarArgFunction; +import de.c3ma.ollo.LuaThreadTmr; + /** * * @author ollo @@ -20,7 +22,7 @@ public class ESP8266Mqtt extends TwoArgFunction { mqtt.set("Client", new MqttClient()); env.set("mqtt", mqtt); env.get("package").get("loaded").set("tmr", mqtt); - + System.out.println("[MQTT] Modlue loaded"); return mqtt; } @@ -28,12 +30,13 @@ public class ESP8266Mqtt extends TwoArgFunction { public LuaValue invoke(Varargs varargs) { final LuaTable dynMqtt = new LuaTable(); if (varargs.narg() == 2) { - final String client = varargs.arg(2).toString().toString(); - final int timeout = varargs.arg(3).toint(); + final String client = varargs.arg(1).toString().toString(); + final int timeout = varargs.arg(2).toint(); dynMqtt.set("on", new OnMqtt(client, timeout)); dynMqtt.set("publish", new PublishMqtt()); dynMqtt.set("subscribe", new SubscribeMqtt()); - System.out.println("[MQTT] New " + client + " client"); + dynMqtt.set("connect", new ConnectMqtt()); + System.out.println("[MQTT] New client: " + client + "(" + timeout+ "s)"); } return dynMqtt; } @@ -51,8 +54,13 @@ public class ESP8266Mqtt extends TwoArgFunction { public LuaValue invoke(Varargs varargs) { final LuaTable onMqtt = new LuaTable(); - if (varargs.narg() == 2) { - System.out.println("[MQTT] On " + this.client); + + if (varargs.narg() == 3) { + final LuaTable table = varargs.arg(1).checktable(); + final String callback = varargs.arg(2).toString().toString(); + final LuaValue code = varargs.arg(3); + System.out.println("[MQTT] On " + this.client + " " + callback); + onMqtt.set("function", code); } else { for(int i=0; i <= varargs.narg(); i++) { System.err.println("[MQTT] On ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); @@ -94,4 +102,20 @@ public class ESP8266Mqtt extends TwoArgFunction { return onMqtt; } } + +private class ConnectMqtt extends VarArgFunction { + + public LuaValue invoke(Varargs varargs) { + final LuaTable onMqtt = new LuaTable(); + if (varargs.narg() == 1) { + System.out.println("[MQTT] connect "); + } else { + for(int i=0; i <= varargs.narg(); i++) { + System.err.println("[MQTT] connect ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); + } + return LuaValue.NIL; + } + return onMqtt; + } + } } From 682201626c9b64669e22005fe83ba255af9991d8 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 1 Apr 2021 18:15:10 +0200 Subject: [PATCH 165/204] Parse MQTT connect function --- simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java index cbc752a..90233fb 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java @@ -107,8 +107,14 @@ private class ConnectMqtt extends VarArgFunction { public LuaValue invoke(Varargs varargs) { final LuaTable onMqtt = new LuaTable(); - if (varargs.narg() == 1) { - System.out.println("[MQTT] connect "); + if (varargs.narg() == 6) { + final LuaTable table = varargs.arg(1).checktable(); + final String targetIP = varargs.arg(2).toString().toString(); + final int portnumber = varargs.arg(3).toint(); + final boolean unkownParameter = varargs.arg(4).toboolean(); + final LuaValue codeOnConnected = varargs.arg(5); + final LuaValue codeOnFailed = varargs.arg(6); + System.out.println("[MQTT] connect to " + targetIP + ":" + portnumber); } else { for(int i=0; i <= varargs.narg(); i++) { System.err.println("[MQTT] connect ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); From 97bf9357f722e5c309347b2ac61a83acec60e111 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 1 Apr 2021 18:22:22 +0200 Subject: [PATCH 166/204] Custom configuration for the simulation can be added --- .gitignore | 1 + simulation/config.lua | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 40db714..18d5539 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ wlancfg.lua config.lua +simulation.config.lua *.swp unit/testTimesMarchOctoberWithAllSeconds.lua diff --git a/simulation/config.lua b/simulation/config.lua index 4b24281..239fe4c 100644 --- a/simulation/config.lua +++ b/simulation/config.lua @@ -13,3 +13,9 @@ sntpserverhostname="ptbtime1.ptb.de" timezoneoffset=1 mqttServer="192.168.1.1" mqttPrefix="test" + +if (file.open("simulation.config.lua")) then + dofile("simulation.config.lua") +else + print("Default configuration, used") +end From e497bbe48e781a947e49b3514c7750675da19d63 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 3 Apr 2021 12:35:09 +0200 Subject: [PATCH 167/204] Added MQTT client in simulation --- simulation/.classpath | 7 +++- simulation/libs/Readme.md | 6 +++ .../org.eclipse.paho.client.mqttv3-1.2.5.jar | Bin 0 -> 241861 bytes .../src/de/c3ma/ollo/mockup/ESP8266Mqtt.java | 36 ++++++++++++++---- 4 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 simulation/libs/org.eclipse.paho.client.mqttv3-1.2.5.jar diff --git a/simulation/.classpath b/simulation/.classpath index 33968ad..6c08763 100644 --- a/simulation/.classpath +++ b/simulation/.classpath @@ -1,8 +1,13 @@ - + + + + + + diff --git a/simulation/libs/Readme.md b/simulation/libs/Readme.md index c76c4af..52fa41b 100644 --- a/simulation/libs/Readme.md +++ b/simulation/libs/Readme.md @@ -1,7 +1,13 @@ # Dependencies +## Lua The following file is expected here: `luaj-3.0.1.zip` It can be downloaded here: https://sourceforge.net/projects/luaj/files/latest/download + +## MQTT + +It can be downloaded here: +https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.eclipse.paho%22%20AND%20a%3A%22org.eclipse.paho.client.mqttv3%22 \ No newline at end of file diff --git a/simulation/libs/org.eclipse.paho.client.mqttv3-1.2.5.jar b/simulation/libs/org.eclipse.paho.client.mqttv3-1.2.5.jar new file mode 100644 index 0000000000000000000000000000000000000000..66f1278e4f4d6b2204b3eca22261e38e76956493 GIT binary patch literal 241861 zcma&tLvSt(uqNQxwr$(V7u&W@Y}+}pZQHhOpV+qT`_E?TuBN6}z3!^Fs=J4N^iuNTjB-NqQsQDNstj`CExKAsg=?*Tx8XmC=#(D< zo|RZ&BfX9U=_c{m==&wX*e1!?e%~Y0mDSZZY)#FxzKf!qJ~urt+Pfbs8`K+~cyF$c z?`ImWx<~$gLA?Qezv9guX&-sd%+8T)Zsfd=zhA1V`Y}G^?Aj{(jQemOk&AkBqju?*#mBcHZ9@Iqr^XN9$k7 z0KmPQ`Q?-O+0=(=|H52P;m70BFPDP9KXp}M6o22xHzxyaRONg1nw@bN>&qjb$6Mm( z%&)qiUa^Av?;}9W)3;^Gzt88Zq;~1n;QhNzp|1D&)Bfr1P;WOc;rBY%d=Ky&)Z1?` z@BjUIxq8~QgLO|%KgcvYq(kbD=O*^b(%2nao|T9D?z{FyTj%j3aAg{LtNpIQ!M1yJ z+^E>@hNGZx`Ey!!TGHuAXA76L%iGU4=fi)!iS;_XWQHW+4lk@Z?Vn0dlAF&(tR{MTSo8HW^^n6PX99kCu zfRWh|^4N9*axK!tveso@T7lymvwRPKxkF1hYYx5;epSMKUPDgw#3OS@LfEilKRkcddv6dmI)zHv6|$Frcw@|pg%O} z`5#cx8@bC;ec3ic4#6A}>fnc57OICk`fz_&h7M(5azRYm5c~*C)ANG@+`G*Rp2~=k;X9w#$M8GDvViqBD?Mts9*M?r*&pqveG6z ztSK(0MmW+;7pjNQMUVej=V7AO14uvoYEu4rKnUIisU_VKBL)!VF(iqlF8f>b>Kt|4 za;WkhzCAr7?vid0-O(<}tC+v=w^3L-WsK{z`$-TgT})s2XiR=_Yt8!_siafa<~a0g z_-e{MF&>cR1tL$UQM$iS;P|xR&7zHhTu!$DLpFYL^%EiU+Cq=dkv>T-u;eu(m!SdT zPO5^zW?e(7o4EYlw`D=ja#)2CwDXh@tSgK;^a4`&h*~3WsJ#cEsa7LAZ}$OldlyIKRwEIQ^iB+}FU!Alb;38X;9v<){>q_Z$hsUsq0wyAOHHUP+RN;v6D3qLQ| zVVlMDO)aI2Q5YihYq5!ya6pa`?TM{FTzZSeC`y!b!6y{dZUrpoJ#POU{`Yy#5$89% zzIueFhwX*EZ5wsved(qe!k@jvY0FhGml#Jq4(;=M2QC`oa{bg7mK2&SK6wQHvBmD| z^TY#Eg)t|quEG*IK`JDST!gXuvUKG=qbghLev8z`II{}yh)rI)XIrM_FlHdxQ}`xL z4J5Tg*kEpw=Yci62dN&csHx8C1yR&s;f9w7{F9=t1b@Ahx_^~#U9c-=Ot!h3v$BPD z)#-fW2dW?Bn0G(X!8YanDt2EGF+g-hJSXE5qf#ks&w8@c7NuxGQjzO zGaP$DLSCO@d}i@v*oJ$qkJ09HSF>c#lsFt^l}vbdYhgQ4|K*Jh>baxq$8~&Oo!iL` zv!uCw!5ARx2o4aB)#{iquD+==qefd{womT&p5qoxMIg%lt%X(4Io}lM3;`){-bS)Y zi`3|*pSXhHuUqxXPI^$kf$%4S-)SiwqOJ#nz1x4EgqVIu2ZG$e)Q#>#2M&C% zES`(<^AlCeHQnNg>f{_18?9JyB&_9pm`zI+B%zq~;c`(1rnCo5@H5$yJ+*4b?>iEz(#gJ?F{~3raAp(okzKo{ zY@S?;{~9^xQUk(dU5vqQ$_2n~V60EPe%JvW-~(pgwq$RAM7!`R8FZcpox9usP@h;c zY;@Xbp%^w?^;}s1#C_{bD5|+Sx0{bmuIIWxr>iHKJpP^FP}ZrQS=|z9G5+A!V4Pv_w{BgtOnoF zu4CWF?K$I?DmZM7jct6oE3Xo!rdl(~gzQgD*t)=Fu9qrYE(3V}QhKS;g$Zi}s_~R) zbu?k7@o_I#Ap?oRx0Ax~-FMc}KFU)GXku(ldupyV39`1pxj-XAdKQmNnZROV@Y{00 zxz4dZ#!*AB zNk)_ynekF)e~l7rF8|7z~EGdtaEWAvL)4f{a z8ZUFPuJxcZ^`_04t&%hVpu|?ZV>|xPQTn0(?CeKR+$6?hc!!$QtssdmK|6Pb^J8af zCks2)8d6PmfUl2zf8VG+HF2+dGAqBHtnlL>bWcV`(jcN)SBWD#~Fx|`z$=p*5`yu|Y7!TCHk7J-UPQPI$cp(8X@$1x-*f&Biq^aRXr zzLH!y5*m!gj!Fl}tSf^r3|X?Yr%*U%VJxnTSp6HS+gV?q7ksuLL(RJA z$N8}*rg4~DU#dFkjw_Q~wd^RqqgXKQVT0jV|8Rg>f$|k@`a-ro&OIAT@#c%-Hjsk$ z+~&P?PFN;4LI~bj$-$R4i<)AZ;tYoaJ0P|NfnIjsR*&Z>yldl z=__gT3_9sR!iR;GN0czYP~%zB7y`?U@W@%XjOSs#$49#c|EF*qm|PuzkVm9t&mwps zRJq=URl9IStX0)tqVSaupmI65bpM-UZ&%~P;NlaJ*;XikotP<9tB8U-h-&gG=O$41 z3A9BDs$FTULkMRL?-J7EJD&Ef^2hjkt82s5gp%_VRL&=YVu&VPO0p-ktT5#~hhziQ z;(0PR+Jz*^v~;U!%U|lvtMHz++&%qkZ)}tJ{H^kgQJSKK!ufvkJaG(C*JX9=*dld$ zmZ|9RAr?nOZxoG|Fa+0Xlg!0VF*Zg3wSPoVk3IH#O|@+-h!-^RstR zU7XBLRYSqL3L$HljMx+u)djT@UL7@DtK2)(b(KphE*|+r(urVfXcRGYWo!p1_d_3=0r(8T~=g&+Gy60!<(1Z zZGIkjM$=}B=0G?Ok}!e}FwSZEk#Gm?l0Kf%on>__IP~+u1fEhngNyxmCSHeUC4sMP zP#=1?FB(U;;ZqvDuM+v1z1x#?o2gcs{^T?#<){D}8ezGuzudnON^1*YR3m2#E;lsW zM0kIrfYaXu=Dn0w5aWyOIkL%pPyuP^=;?sA4D`R92Gcsgd+_PQc56W^JS=DiuUF79HXD-RrW(O<`x1SAXzv~+ zEH%j;^5mn5zrw6?-uJQ`(m5JjOf5aaq<)q%4OT#k78ndZL##lG^h^hiW2hppoe!Cf z?u4gK$B%Ov5O>*26RR&}fl2t_woZbAVa>IN9Z0qmzACo4H@3nUlGSP#P|T`ikIq&D zdEVj$BG=oQxe`xG^k~0%)&An4m?SkPtmvI0O>G`wzEaOWs#SG&lQ;lGtWI2NagBx8 zaN)d(^JQG8#DsaAu{a2jhe?=imTVj(t-H@2a^`a|+Pl$yiF)f4J8mS~(R0R5z+)SG z3Osf%D2zh`U`T&=NIfHP1%KsE^mn%`^JyfNBYp;@9HYjHNQ}CaJDYtN9ay3i9=DZ@ zHk7EWw@moe_9Kt`w;O7+aPq3OqX$iCQ2z~R9V{L}=5kuT1O+r}yIxm*Oiw6Lj~H^K zd28w&U)`bU=`lu17Z=#hMdDvSav6?>A}WHZ`$O+QNCX&~%gkzWZL>_JO@XgKHD@19 zfxiL*^hr*9#c2VJc9hxa8Ls$tT`Jq)C=ir`SXiq=&Ee&CeyUd|C!wQOT}sI9avEpV zAJ4k{(sn{>Gh`x3&hVpJos?!&S1c8hGj)>lV6Oy=?}Twrwds(9*8i46^woIW@@*R< zg9Ywpabrtv$K`QtQ4r;Hj{+gFZLaAY;rGYLufNl1dM2!Uv;x-n$O0!$Vil?2=a9;x zld*fMXsHz`oYm7m$aUXvhh23ZQEcU9#)`0iHQ}bV%&VdbkaUbP)R~;R>B73X+e>=N zMgo1qJAJnN9aLm9zSJaM!$29NQqgl6*I8^V+4)%@PgG@9(^rJhTT!G1NaA}-yKh(a zw2N8g2=bn!^$eNUhfqBiZ75&s>FVxD4W%e(C%{3Y-LG_S4viy2#p$Il4iuX`W?%c5d+lo7hj%ii^#~wRWdL_CZd*W|%b_pc^!ekcd@UB=N8oWg4o% zi%6PPQ*xUU!Z3^!Xxu-P3JSQtpwg1s0E6|Qjn|Qs#*Wy)N3+rE%IkKOddxK$=g7ym zDTF=itVc9sZkky0g{c%`++$AaUcd%7uTcyJD5&@qG60!o{O@p5e=W=oTYZ!~cTIKO z$&7^;=@bv#udQsFhPf^7HErA~{wkc+;p@dT1|?H~s+j+J_tU)YBjIhwliPOp%Nu97 zz4t49^So@I!HPJ;MH-X)NH^3Iv0Zo8{6)}V;dn|HbQ1Y9mk$ZPT8Au%x? z@1$rjSk2MAa~9JW^q{xKR7|L9_LzkG(Z8)%MHdz6xbjrw_?#Zpb$(f^vd3Z!6KQ+J z5e+*3gtS=?6eeZ68`+HB`zQNS=cW!p1QdPr%kiN!la(ur-tAi#&!)ym{-F+^M%{cK zD^Q*<8CWO!@SY_0y$-{ENGFG}LOYJb3X(a+tuAl<`TDDP=4;8BiX;iu4bsq$po5g` z``EQ$H4@vZQwP_zqtQ_0j^4|_m_5-AEMjH|+6`0w4%I)Q?y?gxenF@DLGJyMPwhZ& z7M}Z;>5v2M>OPD1aQ!R|^rxyXhq?YZ&+hTAx@ZNW?Y;$Htpuc_$-{ zW?}q0Dz4CFx(cKbqV8OrrVp8I6m7Slt4re2A@xxHXd{92XK`;0Sg?pAKKu0vnLJxl zU%;FYI0BkFhdz>-;i9d-zv6ABOzui=e04mUZQp0J^G?e8O3z8?hbR80exU60x5X$ClixxA|}yyKk;If}3j_{iO19xWmphom*bY%c^Q z>)!np5sxCFtFG5j(JpPilVtdrTm0~z!K7DW$QJP@?p`+CSfnl0X4LXA?QDl+PS$qn z5(T9f3GS4LbL_S`Z~9(HO&w@ee7UFAY*U;(@)lrVWRZ_j3aHF)fk4QrrA=cv7KuCi z0I2h4_CZ}2m8wl>t8d~%Gc*<0OE{X=ZVvLCh32>?$45*js-X)R=Oerw(?ow3^pSeP z%eHY@U*6|7|M`!z_56!C#W2ZyZ~p;|xL@ zkwG_?A|9zT>|^E0C*lt`{xD$!MBm?#8ydO>#IICja5X`2KZY>qXL^ri;!Sq6W(g!ny4zs$?QJpP4mM=1`Qlh;UBg z?|Ma;;M1{+JzJF|w(4@%ihI~%suGqpv|9hUi$4(tJJ0*i~XQ%OGSetCG$ zUV013YA;P}QhE|~?1>8}(M=PCP*9ZG8m)ZS$+SCfC>B!)R2q`~qkL1Fkqnf9pbWliwTO+!2pQDBJO`&+<*KM)bZXeI!&GVN%*oj|iK`~fUq z?~6f?7^gTuh>)}80=-1@u&BwbA!q`RP?in81H5X|-FRNEB&M^Ix!D=u_L@EBd5-I2 zr3-b%VOwjt^a^)ykz=2Fw1}d+%p=?7;Y#&A?Jyh~{~DIksfE9`aSk3}2SO>4%nLQr zW(-wlJ^t|>q$(h9b65na4cK$Amb1u3o^RlB{Dzs*+cTrV=P z5~$k$j6WO=?be)f82N}i0DBjbFEiC6iIA5LLt4GLdRgvs3--lgI6@*q57W%xyWC zNXbv~z*pgDv;b5NdgA_|ocnfv4_gBFa@dJWW7%)I^T0HZryUb$q=#Sp*TTn7=Svu+ z+oY-gx?gsl+@zy#hEB~P;Dx2hj3;x;R#yE@u zd4Vxv=jK@S$`PltJYC$vs7&0woO~6ck#I3w2l5xm3k(hey4-nVWV|;PUxyDjU+K2L zb=RI~1P~O`WUb+j_vKyruH3t{Ll&48(?+Z*!z{;5KJ##t$3f#LBwxthBD#xDFEmvG zHAr?A82S0Rd}7-=#vyofxZ3z4ND`YMNuRQ%MuYs&8g?IR^I<;*_49@k zmN&G=4mHDj-or&k6>rgT^-=yOnl6gVpyoi4K2^pDlK_F0m{M4j44Ad(S0}%A#m_e2 zdw%bkB59b&YOHrHcWZFRiYBZey%M((CmyNXR%l40u)C+M<<9<>dav}Mm)2LsOsZjx zP77mQECQI4c35k=ph9zG=`X`9#UDY3r*K%m2%ze`)Hb0z1|!?ZkW>bVNZt;MK>bZV zk)iStm96QX-F&R}@P_Eo3q;o;_ zH#22&04jt3I! zQ;;htJ-jV|w3`#GBO?G3>K5AXJ6N@}%1g9DYDStyU6QXmh-3%%4kX z)!g;DZnvLt)Bk7aC>%iK@(P(lt_1iZ_Ey92|E8$=Aqp*+`f?2a@c%Xwu8zr*xGIOr z!mHq<#6%xF4lRvlQTY8DvoDk8pev8^?6<4__`Uf#@&8tT4r`9qd2ZaUz_kjXX3j|a zn6?#fQ>t4f-bc`zaHwpPSTPWBP2d#WCp>xx^7u9Vv`728_Ww5v8+pcAd6U`s82bG9 zbqn~tpYx~E$Ns)->y!zgqG~LS3mBELHvAT-gvhrEGYSIs{1%oF;}F|6UiMV=g@&oS z{f&Gx=(FV6^;Q&UiQW%_nMj|JcU;sjqV(N&YhUx?@%@`FHv91Vxp|wbCh|{BA6Qik zF*zEA-F=j(E zWMpRCd|-H6!mx9%IzG%tL5ef1?9R$?%^JlB*qr=|Vih$IfNvwmOWFDTI-seA?W(O# zZl)Td^!ho~mb!ZSI(T>hWF(434oZW}lnEoRU5)ooOuYnc95-bEQQ1)u=pm8MlSC{B zZ0GKfX@>{875x>t;1L8nozvXc{I@?}Jl>A#q*ajJ`=FoV!lA@ zNl`-$4bG+Y;O%-7P#BMQ$aO(gN9DuV?ybp*9L;5o)^j%uEV(s^(i%nWd+>5^2LW$ zO#AE0X5E~~ZW2g-HSSW^n7N2oJuYA>Yc(x4#o?JtbJL`&=2q`T@@U{ggWHQ%# ziWI{2C8fCuBm(hR0rDyL`~+Deo^jmbfO0JtxESTTOYK=uDpJ`Z_Xu4%8Na_T#$8QEXvo?)O?`unLT zoTEfs*Oq76+5HoKp8R7nLI>^^%ZBJjwMDVHxvz=oSRo?pA%M#*9~aQEF5ukf54_~7 z35rJgT9yewe+Res&YNemEvT8)3=IrmU3cW@>{tq^uw^t|)O$=XLHCuS)P95kyKJ)|3!oT{Rb- z7IPmu`fhAEayUhcJ>ypyO)syQtmCK8?PTkG*h{~AdFor7*pALsM#{U?^ESe^4Oq== ztLYosMM=_`kc-87!j3)&J*M7KZ+y=7xGl%|5mtA;vkNdveL$r9w&0d@z_+K*Cr54s zS%60l#mXfSq}YK0X4=llYzz}VI*`Vr#l8k;A@iR~%R$s_40??|A0n^o7=7MhUZyzf zXJAShcIl&xo2wcL4i2otZH4#exxQYiZ@FGc5*IOshHES}Y&q zF_&WHB8Fa|Fgyhtc;?id6=5B+jGCS#ir~r zH!3hLAT+L&pjDLYph$szOhf<j7BskL6umvtIh27PCGKbW;Lv%&(wP_8mNUO8_-%;kf+p5X z%z)-lzk?n@6G2{*nzMHs{3v45G-8s@S)I2^?67C7X`^fDDewBwe{}We< zlg#@=E`Px-(xQzJ>%MAao;3v#`@NQ3cS#=QsVU~lc^Ng7)05KG^H&z^;IvU>9FK>p zbPC^@wzn>wOr=ix;X2#_kDJ@YqSEMqNpdQA@6>wdJFZ8=~idB@X$ zX|1WX-G?@d!`!-=9m8o#kteTxlBtp2?*-7oCjnD@+4L(8a zepb}0G<>b(upPBCzC~7GJJm;3o$@ceer@6Ps(3=`a>Fd=f&|+9!L5cuo^C;)`D$0F zjL&o$TtwiSCptZ*zJA01%iXJCbeI@n2Z|!deHi??w&f1QI1G9&A&u8jywBO0cs;ET zpT|r)Z5ksoVJc-M>Z=#cDD`l_-;@079nJ?xVhSsL1ddO?^q4>EC;rZvF#*CmoDl-b zH;R7J+Ttg@de?ZrFXZpdWHtz5o zTG77>aSMOAz~y*TOWf9m#i{MGVw~9G6Uoa9Pe(&EONJD3=^(K6i?@c|TD_M0gB*XS z@}rkr2DJyD0p93#dQkHzp)4RoG$c8yLO6(8qQJ``dCy$wNYZov5 zc8ZO`8R>R;H;t4aPlCALKKU0WpSrBxAyx+TJdn@heVnknE~TVPMiLa?`WA94s@T@e zN%fLzdGbiTgWGy|LoXK$$FKkRhy7Q7Vo~?~f+2hdz?bN@yX0A4qh z`b<|Dvqt+2R9@Ne@=Cz@cL5V4-#+sqJlYV3&Q;Ve5N7w}?`sLga6xA}xVob0HWh5z zA4)PUzJ*4s`TjwD40Kl%zD(+U;Pt!jw?3;McBrsU+8(2JLYPqb15rTSN(2*ZlXcfn z{v?dYPT5|s+PRJ^FsVz5bMtew>G$fwoICk_Bb0+V6x)M#yX|ADXol}eCNhEhsp)`S zVDQb!8qc-^alsZG4?la-=Y;TY6F1qqyEFyXx^O$kJeWL6(G@t!qSdAE$bb#KzN5Qz zK7UTkTR-3+viF?si`&;TiPB5t0fEVd*&UlL9>J~Sf&7BkwOU1BL=@6xBc5)R`GGai z%W=BoLqN+A%JT^qqXZVBVDOR}%4hPp4nk&DO{Njv#f`Tn$PNAn$h^1l-zBa8keRZ! z*=lx(E`5vS+QqjWQ=J&d4I_>d*f|Z`xw7-D>iO|p`E(uA&ru{N(DdKYgkGrYCewPk z=1J7f)nmL<8KD^YWK=g`q4U4{tBAU55-*51@^sXsn_yAlUAAsy^HkO1-dd=xHq2)A z7fJoHWt*i^d^gxtALbLEH*gGVW?8LGu|iIj*~GUDFMe~Oo_x1|&|2&p_2Vf4JoXGj zpiFOwVbqS?*vW-7{YP=gh9rr%H;6Or-65b&Q0XT}oaC4)L68FGfL@x(A3Mx)En!?B zw5e$Rwl#@Mmat|k1KyU>tg6xX2TMsq>{zffY$I!>jbJ_=N>`Y5TmpFXwJVdlt?&*j zGB~qHN+0X4RL^8!^wRx9O3dyX{P70S0RG{GC+JR$#8nu4ewS9FbBAj=fLXK*9I-^rI|e(L2n?muB2 z2#ntfZ>~=-PM$r-j7Yn~5>4B#8n#-%#Bdvm{VOxFk$+V+E7gkRQZ zr8cvlr1z-YjAgRtAo9FU#D7_0yvwZf1?6-;@cQY5FHX1u$8%cY;}+!U62R5!mBXTX zhjFPtl22cfa_(c-oq-TEzF>q;%CF;8m)SRv%iJo2MRBNxc?lmxie8!UzzF8S++U!3 zZ&12HLy4K<-M>#jWFL>_nOsSVDM--Fl-;4m4k*q*b&EkZ-vY%Cyw5#%)sRmX`@s+B zc&X0_yl83~qO{#-gVIw#kKp6bSH*9DY&;GB-cLpIgr{30u`{xkbzv?gxS&{!p)Xakm>RY-n*qB=(y{l&^b-PRawc<-J>F^t~NJ+QU!bMBj;6karTuZj-9Rk*a$o zfXeeo=oC+$j}yX1R5bI}n#{O-D|O}|aM(lu8@+EYqwkaP7@uVd49pI< z4wT?K9aqR7z!O{dMi=V$^BLbvS#i-wVBOF;`m59C=(#-@?V}Pl3IAn4)hDeFNt`10 z488fGDZgp_DOD&50IY_loAVt6vAdgIPnfWBcTuD*I++$}55Kf`cigS`KUaMsawzpa z$-Nv?@?C0ubLDaJEH;6KaRN9{mbl5j`!dl1h+mY~-l9PKt+E?bU@sugHfDj3_Cf>}_z7o_NeaBd-9UlJ$^M=3@ zpM;ivl@Qi5V7zW&lj9%=cMqX;BSbCci7`;D~Ht3G4ZN4G^0@~PRBb`xw%qAH7wqr(!pLAc-l@#|@ z;cVV9ESqBOIj>WR+utp|Us$A(G;=W^yH>Lho_f9?9-)LyQ8SN-(Z8cj%5%;8>rC|a z^x=6&ybHe*I|)z2ocM@#ffttj;;MWVN9@^O5kp1r(z2kZS;NC8(z}~R;D^;?zmslB z>u61A5^Lu+X=BEObuq~-0Q`VbJM@!4m$DQydO_vq5OX=S(I&MSe%v>@8urhx7>b{LS6duHivL*)4q&NOJFWLrCs#C*dC{><( zFRU0LxLErli}aSqo1K?S=Vb|byR^n`_=r<>Y(aRrfR`sl`>%|ZfCQz7L*TlbI7xVA zd2#z&_RmjM!*4A*NKth{@WV@I0I1J~&`f@pCr{Cg?YP`bm9Nx#vPwnTTN%b_^8#a| zKo4&kd5^_KV`LxmqWIR9vJ(-U#~hKk;7h-p;CbkcyS`5;VfdFnLGwqZpSy2BIi(Dx zM6no%Noj?6HSO1Y_r_nfijJMpL{Od}M`8JevdU%7zF%+e&)5Q)Ey>4nA(lAL7zZd; z?QO!-`}x}<4s!AWhc~Nv)@P(0f_MPnn%U2RfVKC>jEzbw+=LF+%FHf&-3i4b{*+@{mk%8riDMHhl^U!K4R$Kf3fQe~rPZyfjdOnA65R!9CyzwY-bRL@E`jTsyJ^boA3Mn>#f#h#^fQ>TkV0}ZA z?g6y$Y7}mW1NHJFNTX&ubX^e5`RL^$MG{zNG%AFI*N7{L!eyxW!s5p9B*7uI<0*Vz zy9GB@c+sDfq7I&J?$odc8MVSY$yMCda~zwcD$cSFQ;T>~`fiJRHRQys%sX%=Q!gk~ z%nhNO3r2~CE~eAdAk9j6&G(oT0D3p4al`ac?v$tDw$q`U0a-Ew13q>Sj6z^fS9mAs zN2Z__?V6rwpK8p(Ub3$aNKa1TQ_>LN8r94no#5F^>@DPyH_?&-#<-s)>5WhJol}+!7=IPP87;oV+s+Ef zi&>`H*h1J9d``cUJQnP%*La+~HMZSblOeP&vQ7k3RIMwC=^RNa;t=fMIn3;Z z`A?>`kFMV@{cd5R#>z$K`lM+e=0cPrzJw!%u|&>L12YL7xiR2yA(@a0%Ku#k_!X1Y zWZq@-et5Dzf&;(CbPP<**up4y9@8K+tR% zaN<^r1?BkqQ;r{6Txqx(f7M*n`*~P((|*xIGnJ{A>QYglJ2J&7R=eUq8jBECpIK=0 zQ;I^5N>=&h_1{I&w|UQF@5R)r>=-aX$gDm+24AgsNyRA>AHP>Da&(`#S06Q!FuN06fU?X`0zrwJ6C^%N?e z;WdJtzVbOFZMF54%mP33F!bFB&fCL2ren-T$RX9UL zhJ^=XWD4BwXY;q1H9iX%q8iRnaB0y<5ejW`>ieb6uOO||`TpB(cUT-4zx3_E4~mvb ze$W9J4{D8pD~Paj3WF5tjukTdYio2TcSoEI2Hy5YVmKT~c-oS|Zznz;iQU~H0*avm z`FjG3TQIZ(>=08Ym8n=cn2OB3xr5m&tPcQhYXT(+a}VSJ2LbxuX#;(~$3z?YOV5sl zl#v1fbPf4OP?2trk1`oJupW&F9QQMtBs(fDI;BGn^5Gb*S4om56R`6JUQ=|oH_DHG zPor>$mYVP0qsh!daUzF9`D#>9|Mr)b*Y z7XDkfvaH=#e(f83*KXAk(rBhj2Z!ZuNnpQ5qlHr~T#aC?rB4+zS4A{Mm+z~4aqbOR z=<#WTd+gtu;X{-{Mk?RrZU5)E-(fzX5E#vQdJeA%gy{}6 z-cX)s-+CW}f;2D|HBx><=Y&=dW0L@tog8{BO=IuFj*$?WEHUQPLt?KmK zf-wZ=Bv(~H>fR&bdK0g??QVShwDm>4E3x@Q9C$>B&wMNUy_M&w#fHzu?!ZBON#|)X z)u=0Te#(cD|2#o&AJ0n)loMTb{*@z@iXhA7n_3-Zm4?XvUoPl(eYbB1V zd)NIpzxP2iBZy-C8S5zY{f6zoJRQe8pg(gC68b&F)n+)p;uKU-#Mm%oaWkwpye@rT z=bHAujtWS}ui-93v>J4A4OtfEa(`eO)`I|n zGIV2gIv^M^ueS0M2(^l@ek<6T8(6Z`{#u`QLn;2$Ss4O7gR`Th zk=x9`HPE^;Ke$sC*!J*$cYpKwQ^uBQOAikvSV!`StZBD1oscMG^=6V`UiNbQpzQdc ze_3Be_3!UJR$H0gvqp#`I+ez?SVeTVCjc^Wavqg`U|3X@Ugs5?%w=XYN?hZ#U#2LY zbCUUUkOtFd!;_!)HX}CWY1LKRNl(A;_G9Nja+$|uwbfV~Lt`uR70@Gf@QiK`eir{6 zQ}_V-F0_q+MnN&#&!q)Vjz{kbKwTrSzj2uk6v6<`FYCJv?E<2>in)(9yrN43k7Pbq zU3NJ+oL`Wq$KwsOxhtzx6mgtI$EFf%+nm>2diU5Pocg{XY6;xs#;j63-i(zVw?>u3 z!8HoJFNidq(8u!2UGb?=Q(5TeiN8&r#Ie}%5c4E0K)X&?ji69>pfE=7IzFt7a>4|& z@D3zvDaeMBjRS^)XN$i`P}y*AKu$7$fKceK#EQVrDyu$GD}bwRP?@xMz++alx5UVp z(kiMrDjD@&55%%?S@mYe6=Ng|fL(Z0h^alW>JjJVR^`Vetm*K@?w8-Toqc{8qCS1s zZDrBt9a#I(=EWUYlI)(U8DY^7sv*(Ra*<)QXlMDdVRC<(%&Ty1+e|l{l~7uPGUV0T zUg}P#C$SO!@;hXy=MaGtF$Q?l(@Ed7jiR0nW|i*IS*Et$Kh>fa()K;?Lm_y?l$g)R5_ku z=>s9NW>{HWfAJS+M#Fn5-(6l8UUDEF9>E-25!C496%!^S$ji$iF4o@%lm)gKxg7drh%9X4!`o|R4D zl8lvE(DA8@d(Y&h=Jf2biKH+F2DY6ZO>Ad^iOx_^W>fW^gn1tmBY^s8m1!iSRG(JI{E{g#snsKFQfK-@uZ>Oh zsIKm=&^lmvnMA5Di zic+nHSvMGcii@Z0>8&~Tyx@OVU%>F};BvZpK?D7;f@>1{!WkllrGf+c0-ABr<)P62 z_8-AsjtWpCr+X`;NvOPt$e>)`9cJ^BvAF~Rk^>?Yv@Wg|!&os_~GgUn3WHGgIBXAnyRIS*_# zSOGe_Mu|WZZ3$p&Q0Z0#zyWd=9D>yA4wS^?3@s(Cl$u{TcbSMdzipKB@5vVn~p;b1+@4Yc(qD&pO-EH9KDe@ay*Isl1^m-Y^9acAD!-r08{ z?CV|zDsMfi>bt6`@ahI$e-LJ*mOHuHNT&KE_1?~QngZ#wU~|l}EgU1ZY#MW(_c|VP zCkm{rv?yKO-0;?k8`$G#p#3*Q-)pn4G;UY7DJe3Ea)2?#C?#|OScsD2=bu}2|1gKj z?7N-?wlDQ&;W9q&VL4eh*Dw%_pp$L|#%t_1C)*5^SN2rceNtTcC&KdXZBNPR+Ug94_u%ShuFKoVt&1wj-z6?<^MKC&`0LTrrwk?vSnqC%=D8@qFyXw__YuyK{WK5qx1fzhT9(L9~8ApXZNwVJMglEs{` zYw5OsJIFGfc^A&>3m~-ss7OB114V4LS zAPWS^f>*B)Hx$aJI-A;Rjwm`G^9??y`{+})y@AAv$N(HNohq?l^TG2rBLB#wif*hh4x&3&)FnASwGZ{j z+A10Uc2PFF-Ko`i-8y&|%h-x%rkS@=rusz5ID~1U`7BPZe!4ck=%D^fsAhmRHL*w4 zYRTWRt3ip1ZEaXA3DWCaStg-?%KYAL$S4Si?+2`s0D$sZu{Xv5%mgh&dv`R4_NVO; zZ=RJybjqBkzLeSNl?k1+n%)bAK>-1Y>l(j+TJJn_Zo_Lsamy9DM_6pl_$jgP7YblN z_l|TP=~Sq*b1K5L6!K9Kv-n18qjG;c-Bj)*D;7Gt3QupUh-^m2VA|Btm^FG@!H29= z_gGGtEDL+92!p`tsaVY+*bSzR6SiqJ9bA@O`!KBE{8&>TG<=;I3BU0N29pE@rrk@q zaK4Q7>wblk@Q(psg|ky7o+P=xn@?%OsoN!Mnty~D?CD%2E9N`8Zy4tjIQI0@pDam+@Vw0;201{aYO?@B>R{`1!I;7(LZURF zz4Kc94bFV%;Bb>T8M{d3b)B;o;4$q3GvM-e->~Y<5#+Mt)S?7O)tQpxpc>lydZxvt zwz|3aVX71T5b>CRi$=hCH*tAoRnM_4Q-%+i2s(+O{uP_+lcAA5rzoh$K#kdi696t; z$A6PAEA)frBP@pDMagEgyM zjhk~M6ef>26-4E!@AmD$W$#7aU6Pl{d6qiDWL*o)Hdeev)mOCsUUy{0k_!)GSzg9j z1vlBkp3u3E?o*m#D*fl(+MDmSiH&(nn`(ugYR#X>{l;G5j49t|+gzTfisWWcm495N zPlT8@p^RYX+b%~@u847*V@5GDCGgH}X{_ejT6OtV2pxywVg#xnjpvstz&}<-9Mn}x zJC*o+4wW%bNIiRiXy)G*-F|d|at46fo&ad_J!mqQQbLe7#JKrRY(3fc6@;o4DD)Wj za`!Gyev2r1G7o!SCk!sLe++!A}gujmd&t(b=bh1?AEDIy5HU1J}p z>NbPpBc`J%)g8B~$Ug&<_9o9X?&_yZ|A=eq>Ml76%AH9|sZ1I9AxBqHmtfuOOqGPh zuY9#pP_H*M|9U}))JynS=_O4B|0cD$=GuZe`L4%Se@@dRj)e2QJ!(bbqmupTg<0MQ zU}z@uWSEQAj6tmQ%JSi4BL}75ASYc(FNrbPghhjLKiO1WqY$5m{)S*(eQI7~xP;9^ zD6L5_?Y`#{VoJ!PDnX+RGV@IC7tLzN4|e(~+f*`TF1mmtGqamAnWJ935#>3o)<#=l zH7_m-ADQ!ed6c*BL-Z39Q#3=g5l1yOeQADXOn%Vs2N~2)f?-oo@*w-Icohn<1~XOl zD8)A@RY}4|B+Z;x5gYU2YZLq`Ng_fOz;nUe()R%jFvZB-zN-^YMm3)pv_62hzi@>) zd9V?5I=SJhd(;=?0CxEn)fvbU8p=2UAMnd;BVcg64ijoS6xTcFC@N$~S*s*t<|$aY zRV2-Boiu}F5>A64`7MmA@+Li@_~8IR%S~S z6?FnjP`gt61wbC73^*B7(tq!ip8s1@97q6=|89!&F$w?x{PoM= z5P!7I0s7$ z`ldFtUq2gLJJMR&IXXHs(K^_g(aIV-y4cuT$k-S;SsIJ#8#>z9yD6!PQ%;OaC=8D) zT}#nWOwo-#PRLPANYEUP(n&5!$xMz=lglnpiH{F20oN+sN#5H-OG%DKJTTr#Du&-8 zIou1T1Is(Ml8`3tqpKiQ@Ubt45WOFiNDRD;tdx+r@03XNd`D}TfR>e^rI8#kr~LCy z0XJ?@*nM3EKj1&zDfqu$r zpR(xx_vvhHtY}@WEGN_zY}Qy2yr-(RBLMn*!yMz#Fn~n7G@wz6YjVzl0X@jo!xEDv z^FW&D z9U_xnjbZAeoDG))nUEuHq1xY^*6Mu-5~*TzR|m(>YFvX9s?Sb92{rC<0#K>})nb$y z;_4(Atf3~xaUa|k+4mSqZ%>VI1*b(olaKZ__|5zKGpu;}r{Trnp(D*Q;+r7yPpkQ2 zP!ZMMPxHt}nY!^KMI#+_i);>Y&RN5q6O9d}!sTg-2gj(%az)5fh(=ksjEz{o$8B1C z3$JyEkBf|xP$Hl0^77e<2#zJtNW;?#s?>}chrn>CiLz%fX1kLeqoav<$Tz|i+j?LO zdf*m%g!vh9cwMMA!+<7(s`=3TK6kKJj!prEJqjAw$%T$48*VyAav{c)*wBo%bILK( zLzy2La)UucQHw-%+TfyfF+XR{4w6!wR2$J$N-)`!%-mQ>rV965DS64}VL|6Tr%`C9 zelF=Rwy(Uj`)=`fS9OVW8+H~N{{Suw+vr&d-A1Qi!8wftDn2n^pz9P|yx(vWU1SGP zvZsktREo|m+n#UIRL9fMxsAd3kURd>NPa;lDCCiM4_BOb;#6(OzwQAqJ-ftii_1d2TIttHQ_gz}r>PB>>L$G5D~YtH}OrQ5(K}Ffs6AHm701 zw-!+_O)6T}F>xz!c`j%I$N|LD8QLZ!NfCY6MoLkt3oHUr<5aZ!D_HP1+t1|TqEJ-L z3=Ff*HWs9d=@;sQ`f=n?wqAqmTrA@3)h0y29%8Bu_*B+r(li;v8?UaLuHz$yl$qR{ zbM9xPv6vbC{bIp8M@IbjdN!wJgTAB6+e4YLc8*7qjo4>JvuZV|PU|$pIkSYsx)%MNc{oMU(f^|ahH4ahr3?Z9pn?8RtGLYnKkJyS zy^XE0y`!12gA_I8h_sY6?TvKJ#6M9~%WU|q6m&KD9;Flw<>dHO9m_n^EYktdpA0no z^3y=z>n~IIdi~#X_1DD#d@bq!xNiTQc3}Q<%ztw6zcd!{Z)5-9@qZ}*#{VwBe+Yqp zDGvTW#Q6_F@h^oV|9=i=X6?|nFU6()7vfr5{%b0W=Uus<(i_a!>xu+UsnkaG${e+*>ypF0HWYKVH+wE@5cM^ z9w%y21We6NJt_Y(r?euXUaevVmR8RSnnYB5sYdYENznsRfu`_`m6V^H$WuW-E<3D& zpAvlu27Y8ZZSPvL1NHaN(WoTP&W^>h5LEl9W#tj;m>X%tA!;UNeYfc=`UR5c>Fwg- z!Q-R7{(&C8d9(ZAQvNcr`ZRF+la*adZGX;X*aSbFZG;uQkw*Y$rLiEh(VY_)UKX{0 zL&PsGiYKY-XassK?Haqmtbcs(cczM4Ju=c8Pb0zd;VgUCdu_NALZ7aKHE%)5V$WOw->m z<3nmi-png{{kJrOKLt#T`*JOXH@*9&UFPb%bRRR$t& zy<(w!t0XU3%PZFaRE(31jxxRydF6OU zx(bgo_h6P}mW-u=msgsnTp=POdK{Z3I-w9^Ejq2vt^_z@9U-P5T7iy|);Hk5>5U@P zY*~^Tdi(qwXD@OT_fvV|x4uS|q^I=GS7NBMEC64^~CTW1nsb1WJ9l*Nn zKKlKx5iMeQ!yUH5|Gh}JDu>z=2rgmtTcaR``~|^f5<^>`79 zEic|V{9cdP5B#8LB07;*xCS4|4W~#K41d5Ie03%s(k5QQqQs`5VMw)o;~H3|Wjo8y zplBnk`3T%_cw9_uPKn8S!=asd29-lfhfPdKlN7tEYRp7e% z(kNac94D65jr{}E!Qvv}PI>`k_Cf;u*!PeH$i*M3ktAMx0To#A{ilXYczsYDL%pJh zKQW)EuJiRtuCR)=I!Y^M28p;dnw+*&;sFuY_oSIowVyFwpm??+#^3io6`=Pua8&!e zVM4K5ol^0A?a;C!?s!SZk%uugO~YVA=yiAzu%A!|8>Z}^03ACH zx5)-R<#a|`m7yqAvjf|XWao6RC*_iL4FB6L)6f0-tj#<4JhId5e&r0|-n zN~Ewcj90wg+PDtY@s6n4h$bD`f2UXd-5feuvRYR<5#IRxjD~RsnQ@yf7SFUp$>ScqJRQn!!lI&4?NXm7Ky?A@ttKOU zA0+Q38c+lTQ!AF`2sbE=n(fpyV?2JoaZ+LypU7=-X+5YqZ9S8%kz}4=s| z4}HOWHfjr#VUUSMt2P%%Uh~80Bi(>?{2sj_USBAL4+5tXu@<^qakw?#jY4P&r$&_( zv9*K8_3n8oyu<`#eV%FFy+iYrcs^_>IPWrXbn^#_?z+yCJ&)SRgJY{{i}w(t0iU;| zS=?Mi*Vrv^CFH{?Y!uqk4=OyMQWUbxSnnzJ%A9}4!%C7MF}tLFTB z-v5Wq@Q3F7KlS6E8t^|Q+RXihQd(u=Rvauc_~;*)ly#M<=iV)?kQ3g=2MPami2LtWyIL+ zmvuYrGUiewW8V@CqG@d@65wU6QnSlBWFineL6Herk_hLM@)Xt@g)VJ_7cWFpT?C_> z7xAA~T-Adm@#XmH3ezkyx}*_*R}N&JERK>DM(0OBv6IPMq2pSsSX3^9Ahz^R54Res z=o>po54wH(O=F|RcXe2{aKHBZ@U3sd@%?V-euslsZ?aR5E^+I2=m1FWP9TwPT-Q`Z z_&wm4>Re_<^d9LD3LH3srZ)WKEtN@DwxeN`Jq+)GT5dMj8u2$uQiSrLrwXTmZEn3) z{#?icr&Bh=hQxf9U}Fr=NqpGP(wm>`TqYX?W3*Al(eTi%F3we9%c^0%gQDn0^tOG7 zRcVJ9hXevraK4_cbs~8$aUT(%aFg2ucAcuIl2*vYsMD~{tNyt^!OE@b`xaLyS4c2t z3mVB`%8jz^bDbp>iH9cuVTNs`P(A3JVRX1523o38`w`=L?MuF=qkB$UX8@fYA@YiD zA`EwXERMjP@lXwlj2d;oq`$IqoHVga?kM298~e&RnIQ0`yf_iw)QD{>*(lEcrkQl> zjPk7EX;5L`r^I4khk&%fC&w`l=4v_XzZjqiKU#CV>@lBXS_@e{d=Z;4E1N`mG4?I2k0a69B<{!@v87;Kgx3QPg51h0?8jab zd2pZX03ciW8-YGwNp4k(u%03y*W}fn)s0`|zBf~O98|4mBy!qk!FPCzoJbCNTt2zZ zKy9yepFeC@V>#or(=XrkJLo^bO7MROD?P)%A}dIF#(GW?;Y-s;^g|PfpKEK9$KeZN z%R8-HUkwg+1B3g%2 z7HCe1;_h}{(x6YJydWmB&VG(l;#Eezzb9)V5PG1%;c(CB_WquEaM?uKnN6V?+1y{W z<6_oGyHzuzu!|JeZG;tHD3FgWSE#w5UC}C*~9tR@4Kb9ww1moo4Pkc&(8J__d0d&5xgYm4;K7_mAGF}MV~hD zAWFy6kH;=M#Y78Hg;Td`)y;mA5?l87@I_GO+7^QLTKrQ^k$WNcyHMd_oSUgw9b=Va zeLo16mu^BxO?hs4MgfGTn+eHl6qs8fNC4G+uboG9_XW_Chv{H17~;_Kq!I;rGf~tB zBsdu&5|~iS4(g<9ZNLqAE*Wvn2@^wuTgl6b0M>!lkS`Y-$5R-O zx_aQ3_Z-X!(=v^D77()F?07{LT397jIGw|$oudKIyi{|}+<;HA-AVU1_)FyS-YbuY zJnF@=f(u##0ENPK8B2l7-zi$Bh)mYt$63|8BL-#^M-F7I4`wXD8n0cup6>v++3P!D zxKQO|H%E0W-g!N0dN#LPh!Q(=w}Qi-R($01@^-uXXHs_H+$3;Imc7Wi($d&NQ^Cff z)pj}fs#6l(g*wmzfJLv{2|a#Qcz4k*a<@h;Mxc8F19wVfc*&`dOfiJ2{8RVH+>z&f7ISxaa zu@g_;!XQ5KbE~}AyNsHc-y zi{UxM(tzBnaf|5Vnnly|`4tGV^M45^69thN6MnqXQY>+}KMPb3ucU0GG;F~}XFtJ3 zegAPv7AJDD?ez*cm^bqx<}GTdE^YH1cj^}cdMr!<@zpXC%`AKc;8M~ohg2!1nEx0? zJCtB{Ub$gfP7z%mGK4s&)=wDWR$?%@B1V!JDrW{$@e69kJ^MSxnUoq@fhzIjDZLHS z3U_C$SP?)AFNogl4>P=_e^^oCI%S75~jser)B?WsN`n8<tu7Of){~T1NgA8 zxbi6yX?+Dp*tdpm9p3FJRZHZjO~E+(=|-B5vU^ksSo&ds(uB}xzC4gUz=}jpgC-qy&${0l{Bi8tZ9@wL zPjT-GBX{x1Gvage<;<&)gxkV(m_UT-YbxX8c>Sm){-8(2`PzoFhMBP#Jw^;Y^> zTgz?=geqq{6(>MXA8$pK1QRxPqeCQIofhcJJf;f@nH@;OxQa zbM!cUF1Ol+^%GZ&`4wgBMZdk>=E(S`?QoHlK52raaO=rdHkBKXzemPpr2<|A+2SjY z;pWthq;1oi2eFMf+tQ2F&}uNO+kxplqsrJJ=o!#r2mzMXw)dXoDP``nN_xA@s5-Xi zVNkf*heXCp=@64|DaeVnOqqkUDM?{f{Eb79l-c zppU#Uy+4pO?*K;k2amb^dyw_ND8wM;9_w9tgpNDZZx6Lv4Ke&}Z50W?Qf5KIW-6Mx;RoTLFs=4+x zkea*k=?oSLQ0QUViySNJL*27}8iOG<^0oFLPY;3;fJzkNcYB-{q&0JeF}bEC#2l3d zG%b#sqaqgtGh_;g_?_`N(E~wG3&vGVE0(SE*N%}o4=5G#55~zh3S*KR@4cdoE{0o8+~XjhvHuq{=)mHOK#$GRpX^LN;Qb?Zs3?Kun~5g;!Dhl3C(+jD&cu{)Z>KOT*$# zeQ<|9E6>lvo-d}Ebwz{<>cQFh;k>?c~qE!9XIXSu*jk<@i$jdQB zArj1@msQNpo^_o)vWt6kdba+}5>a zE%MB3@TCf3K5sF!K8G)F?j3ve|6Md=q*?sD-zM5VB%brKW<%e<3?Q zdRal#@$gFa?8?n&$$*fW_DhJ#hNI@Jr=sSvRf7Z{JS{M0p;z&*Lclm`WtFxH)D)cH z*6hibA|59ak?bu`jyabg0#V78If78|z-=;^!LFK7*&){aLpz0~p zq40~6jZIW!w;52n7A(ul|LIRRkSrHMbv5DE)TUd-wLE`f+IB9f&A1}+En2OkUFk*h zvK8Na;oAIcQYp~;%RNgr|G?hC2t>+!4eXi7FVVsdWuctPO~g1gZxi~J8luB^>vY1H zHi=&~c=xhx?`h}d!P4yEiLu^zb7SeslREyjFMlQQa!{knmH&*0WkurKb*jawJb7h> z$R)!WdOV`Mhw>pwdIpLRZaF%}K#YzkmB6A=(SY=lJYI~GB73T4bvE$)Y7x+Q3(xJj z1A|wPGWfBlFkmr&%-Pe_g3zko{i>ZK}8;ktTTe>aiCb&=Yw3XB>+qN8h_ni4vilfcwH9miySi>@l z!EXA3iQ2yhCZo`E(ZY~fCzAEh%*K#13`G=y zBChCuec<|Cov}e$79b3_<=LJh){)xoH$&wLywu8tp|Aj_i|*5H$(hl0;KCZPpx5MS z+FJ9a-2^4Sv|BKBO6DlT`cki;iKB5fs4_`&DnPhk6K-jMJZk;%Fhl|?h=7nK1?F5{ zO!F@g50yAbZx~COW1VGcXbMiLYpYlkF9~d-W zRyA4kjEK-RTp&`ETkq~0<)Iaq1Pw(CXQ)+)dDNdCd>LpCb8mDL3q7&K2Sq!Md2X6F1o5)) z;~tMdn^(>vPRk;7{Q^{0eT9xY*9MNUKCoqFIb<%pqqI!&^FSlV7Uq(NGjG3TwYa*Y zj3S-oOA;{T_}8aAj%zr(fhD-|m6KjlzwsVRu5~!dt2-iL^N=&Nj`|GJ53Zri8-(XU zqg^m}!Ecf)5oYWu2uY!qgh|@N31dP#SlR^Q)|Y>%%$8_iP~AvGvCh3QV-{(^bTyo5 z6He8d;41^B^FYh?998yIR%^EUX7Gf|D05Er!7b-^@?{qxY|NZs><~H1Ai;0DqPhK& zZ0~Mf6teaDw6rHt*8l9I>8862qJxl{(AjXkXq!^MZeZtE6m4n}Koyj%6%r~i^@OB@ zJRZW`O4?#^p}wNrvb4^gF()hS2!(+{WOyX^vwSt7K9k5Inir%~4^bDh@TqT1xJ~eA zi=@JAI7f|dwaxZxK;HEkR%;{?n$*Lzwh33Mp1P|VQn+S0PO-fmR;M}o$e1M+>5&}+ zzU{IbSpZzNP|TkpE*}f;=GzM$J-Gu7eCdm>-UL0 ze)-w6=bM>fjibJi9_*p)@)~oGC)X17@h1?Q9XjJNfdK&A!Tv3Vh1p+=kXFiia$hNw z&s7n7XowZWYJN9s%&oknK&)g5`86|S%VYz`&T{NUer}exNl0T^{ntm9yj*(wT*k%s zP~6LIqYM^))YsGUcqZ|EPbOY6`7Iq1v&H)*^WF$)3ZoMIlTW*Ih1LvaLXzTe<`>H= zz7i-P&rpJVW)+%yvJ)2N-aL{VZOcEritTjO7$m8n>0=jDNcRnDX#TWRrQ=lB3sBD zznZu5-r*lUn6I$U3~98R_+;S&$NKi4_rKZQ-F&cldQ>wxB>2$VmArDHVzmLgNm!fol?V=yM9udG`|tR=2s zOM~6hcYQ4Ueap0`ZGb!dh-nS^Y0O??lw?n~Tg?YK?}T>rKAJYT4H`@x5`BVWU)Y}T zf@q8?*g=79+dOEKO`j_|sGA{aOy_QU2=QDck?L9*TRqV0`bn@>AZyz^p`HlS^EAv7 zrL>PLd%kJu2nR~JIs!Pf;&GF~VNiXhwZ;H@g&J)x`If4UE3STTFBw||dPT8#I<42& zD7_#CzvkA3^~j~rr~wyWO8ZB8{-BFsW!(**ms`DTpld45z|wt@1d_D>7f@Q~|An7^sq}m~3oso=R3PWIuv$bbiI%X#gcfy# z{A;iitxA4^jR*b7hTx6yxjuYh_C#dXZM5KmIpUpSVfkA!ym2#Jx3SvFYek%T6bwY&C3#24Q4OLy&nos;S(H#ZM8_-J#tQ*JVM6x2>SL z=Z&di(u%T_oaU)$lCr z`~g_>@>Ax@h460qJ<6k|ed|S;{M+2Lcm`IAu;?JKxxqK41d0I%|0dJC87d(uKNDK9 zO=tv4A@uoTfP$m-_@C6YBN7BYVa2@+b<32_M*v1KK?t1tc(zc?pi-A-=fuhYImAi6 z#1u!aLB;F#NFDuACV287unl!6OLpjol}c+oKsUKOVRnKq4m`s`-(E#jDekJLkG z=!v}>sH`Aqp<_1YWdAm-;2T(H+hT`I(sO0LGq5?=b4gpnH@@Wj_)EqU(NPm?x(AC# zXXKt)Mw>Gt#447zm6NSF(xgOy?;fEt{%+GgxS+s+|B)#=cLuR0!BX8&DlSu`vdm1 zp5w3~Uu@V6`EP-}h0R}JpYdO^6ydl)tDco26iKBU+-4UIEUy0N8V@S@FrgJRl~yn@ z*KpTXN-PoEW-DweFs|K?P43PYR~EN#qE-Fab}AS6X9gW+0~XIx!itABH_EZS_rNFAGDs%c;|1aB3*#y*m&D)yVh76j}wAO-KtBv~z z8sS{`W{yn5XImM6_DzPQ?oHdR{WKrIcOVbNlob4<0oro!g zfE6V~*JHNQX%^B_ZfhEcppzT19P3GI+~~@Z#>2xK%o+Q_{X;&Cg_dk@r>BdueY;uH z!S!pI`O=Q6(_N;`_0=j~Ky%6V7Qtqyfm;2uEW=y-@vZff@p7<^MJTk6OsV_zEh-M! zw;h@5<~9xQu8c3-N8iC`UD}xFb$&9nU0ofysAW~6yWkh;U7K6#eXXhY%i&wa}XO=)qGUiu1FUaV58^)|@ z#vAy#?;ltcfgmV|F*_?}?jU&%E2JrH`*0HbZW9=?&CLX?6<8@nW!{E15fkHi>P0i{hnBJ;NnGZlzueIv-;#W8vP&xcTnA zJ2wrYYBvd`-#;{@$rbj{EY+vr*N$-vrnRxpNRo>J&dglF7(2ZW>uEr?uc44LNzqY6 zidvWAdKflgNMLbl`xV(HqR#K|H+=A4qWI`ogCZOCE(2wcpTHwu7~NlUfbH^1*3#8n!B4Jmpf$p(3-#hEDXF9cvGl<;h68M!u@Zc zZ(Ga1;P}^nx-dsyE{s$-L1>?vz%3y^zk(1yh&%tUY1a;7>@}`Mcigd$hYXz%eqSgS za4xR5!-+IHpR)`8Bkc2Tj)Mk;yP%+}U2vG!_jny|Fkp-)*Tkm8S_XsV@&y9JXl*f-eN)7S`HIM~HJ-X#2szEH2lodoBXQ(wdEEt+s z?bWP&7Z0VSr=zU0N#pHFqa1}iDMcP-*;`+k>V}bzZ0iAuQo1|zC#@}sz93O-HMk_z zm|O3)^ZMY#t?~~=El17t60sivVG;>xQbS97Lyn9dt#}hZ`pRYwCN>_fKTe*mt*!87 zrfg^j=gO}2IS+mEWD#V4jZ?6xn*~ay8iZD&CL+BmJq82_tYEhH%x4?Gsq>YAa6pSI z9_+e2_Av=THu;8QDCuX|*v6f;I#i&oaZoNl?Kqs zIRzU~v@1Q=q6j(0XI-aCY*Afa75=ue%wfOt6F#)m)s?_KJe2E=JLCO&@w!7F#mryX zc+}stnp}UcI9)lLy(kR%)*caSJM;j{t~H>0#uJ4AbAD0y$Fwb>ZN^-q`w6E1ry>2k zWuDmt6NHajNHj#CU_-@qx0f2ua4}7n%}^QnC+|mnY1+8)p&MK$%4L+4#`4rGuhG@= z!{8zZx1rIgaL+i6Z-?-X=Ev#gIK>a6Iv!`7?Hy~FSp1eoY_Xjc)gnT|_wvJno4Gok z8TvGt_BlJ(r%nUjSefVK)G)78$Yl*;i{0H z#fUu_h%1=~M%_y%jEazLo`8f90?&DJtj!I&oPcYFQkrY5o22+vlorCvfbq5H zG~vb9PoO_&bW;hs4E_s#D*u>Niu_O2v#q0^pyFQ;==8P41d9Q|^GK~cA&J#|JBnBa z`2-Jw5D^IhC5~Gq3~j5o7x2Duotx5Skmw$z)W?AO{iovvkXG!|x~E)VpK+hir0U-qr*IK z{$|3Q*c=R4DSx7G_VL7e%G}cRkV|{$$^Ud^OXoJCiznoR)iisQTzoH&51fRpE@+3{ zgvf)5FW+@9HHxaRW^ISIvrd3KAvf1N`pPe_P!eife$6l>R*5&z)`n70SU9oq?y)&~b(Ux@oHDCNg6LB;dkw9K7B%ny=CnwnN6IrRp63qO zGoQ3WrZMDuiRum3KcV-j0KN@GTZZ-GtbPxDfwH!m`*2$1 z+c)XdW*sr>eU0jWU&Ux{ircLS)L%1bxwnNt69qC8aApeUj#x>UN?6a&LqmEJk>Uk| zrAE22Ecr;cgFgGQr|G^A&G=Or5v8Mj>ExV!ME?UvCK#k33tw4i+`q>qwg0P2+Mp^U zxA#?rJ5p2MtqsqPM1Fz}6+(w91p!r9o|7DwNoQSUE{Us0{q#m&Gt)C4ZKNL4H^uST zOk>+iNoSS|brO^vQK@y6>N}w(+iJh+uesRN&@T}R=DQ3}I>}YAj@Noq5Z+&m$R|QR zk$i@|<%VXe6^}O?JqjG+9Wn8@osv3)#_I~YNf>vdosAJoaqLx6D1RQvM1}vx8w#Q^ z*eQO{Vz9^kO@aU)Oc#ZgQ2;L~p8S4T=Qy<4ReL6whNr?Lhi#2Nh=@uSRr@#n*qm+c zcpouud_>p)4aU^Ljz%UOZR*5>`vwA3QEdL)58^^@^Dq&|&Rl21#Hl=)do_vj-=t>F zglb`37M)1@v^U<+_OiX~1o>-mE6Ho2&bIpe_;`n*Fh-_*F^@^WB-vts#NJ72l$JQ{2Ktf zA2L)AxLo4_B@|$FAp&^ZZ4WA0wGq8oV^~*Mfx&l%pi)+s9y(AmTwi(r`k#n==Fz8& zzXssSxnk7Bi#PGJZ7Q%{8(r$OcGPLUg^x2(32MCWB2-u=EVK3*wQ2ky$KG!p?Ob3T zgT*w!s+msSnFbfBw|-L`DdVJiEuy)>9S%6l2%ti5P!ec_#e1~=?gR!mZKGchU$N{O zJ5fe6q9~L2ae(HQZ`8d@MR*=qj<1Or_|scSLm9+dH^j@;T^6{4ULPl$ahi9W_ zgAGT86R*&2Am*zdzPAa<%4~)xgUQdFaR87)LHHXMn`zl3NrtPeta5OOvaIf$3(Cy) z>H%Oli+z-;L35&ZZ61`}&$OjY;PaA5bAG!=)f&i;K1Dm8Dwizi2}o;c_D4Gpn;t?t zW9uyKsyyr<^>29hgB>NZYjQmPM|ERrxq5jmk zY1RK?IZ7!Mcx@J{M33?!Glp`=j$kz=o7ngD%4N{(h5X!{Lw&^c3-e5L=?_y9wxW|G zDh-}hcPs5ATjwsl6p=pNBkY);?IC0CD}BsaoYYXeO4y2Rg9{c(kHcf!Hp8`*KN>U; zlnV1RxD3iG(4>?)j}9WJrO!^+Q6kA08UngYbc zeL1v8t(+aDnGauWW<eNbAb7kQX>E+dydtGMpQY?Pt+S&2$*^|%H?Ty9r<7YHp zC0^AKd{e+u2m^N{5NmQ}f+LDtP7xJmm}Tp1sNI}OKSM5&HSh-u4FgW58-~81>GnLc zV77_?#7J)o0tSeREmkT({|U?<^8h7W=C=_i0s@XiYSD6dN}AR(Id2MtTy`b(C8C@{ z>KHDGSYJ&}DSmrjB7>ph_@WKgL|u~|!a z8|b#pX^AoiIpPzw*Ub*_$VC>SztuCh#D0>-NLaSE#6qsNb}*pfe997-eybPEN45cd zV#|wJI$~I9AqmtOkk0Rn!ICC*$%h6YRk|Dt#*75hqDF?HL&A`gPD!#-$P>I-RXoQ5 z@tHip|27{W^k#k~GU8UtA|c*3|GXaz|FS&Eu<^K!m0XYZNd7BByAM2Bgb=QK$Fcc| zu-q?4)elwy4|fq!Bf-mCzxM`iu+>KOxoYzRy!-Rpx!aX|2fp3-xHTii>gWvp^Pfd| zLW=vG-7g+x{rBk6FHk9~{S{P7|3Rfse^P1UqVw-qf`{oKe@X!Xlt*Pqj;J}&G*Xqg z#@(%}2w*~fwKfiQY#D z!<=|-GCa-r(S^#@HY0JoB@LNIm6p=+;AA4giB&{HtCp42T@or)BSS1TW6~-w1SO7U z34l5_4eQVI9;g(%n!pWJ&bWF+98DoGZ z*@3hi5NTZ`9iUnFU@R$m0l~u(adf!lzhfuGt&qF`KmibQfV%Vx163~jNf- zh;0~xcmTMG!6Cogo(MM?qmWNOUMz?qfO3rzV$e_E8(FyQNKGW365P4iO#rAQSCl!-UWS!~PQ(=+%=RZsQYK}U?Q1er6LLr)$W zhKi6cD$OT=Elw7C<0n7TDfwPY0)M=u;hM^x+J$ zPh{iq!z+*w%8a7#D9B?S-y|7p{Yt&jFnrL9brnm`7=_-EiSvWlS1(#sNS(R5Pky-( zL(X+8N1POGik`F8dfkR}*w?|4kX5YZBRS`jNRP?3s~|^zIWX?T2f>!fxZg`_d@M2# zrG$O45C0GON|6g)5AwxjM*j=!{(eT4@n1*-U5pJJYz!@o9sluU=G@7OW zQ2KK&C1XP;d*lCIzlyJp3i=KX6{=?r$SNqGG%~d(wJ3_O-$imzViUxYR&ON%O9~2l z>XikH8f*<{Agz>D8LU1r7qS z-}tJ$U(cFTLNOs;tS~eiDNNR4>MY!Z3%HP%$T3+?D22WqUEuhGeTQ9SfVz;Q{4-+j zK0UG~A}>u;fU7%QVh-zyZEppI$~5nXWjaU4|3TV0MrRUs>AI8dSRFg**tR?A*tYS; zw$rg~+qP}nd}G@>neUsKvu4(rS!d1ss8v-z>Q~kC+`IO^_Py1|87e41SjMM?6{t5W zjAO@Z!GaC!3tNBKw@UTtGQhiQ$}llWXvj5lnsWhOeqc}J+%wQzfU`wc6k*V(F5nKz zjZ7Qg#9ggqn{sd*nlSe+1SSId#%G5d08pw4Ot9*JK()xpU9E-QjJBN>$-rvW^x%-e zSn3H+9x-Qvkh(H+igz5`PPL|295MqsP3pqyxP3NB>03<5B6;eZg4S|DRw+&Nm^QP` zP&25DisTh6d3DF z@}tRF zJ3$GiEmuiIU2lf`AEniEtEeTmOFgoZxozk1mPqv!mRUf$&l91Q3UyZYLF8P*L8GcJ zBNmO6@r21gn03tQsTXd9>(9&|;sXAQ7p#RH6(aGJrz zvDZJj8J&8l=8{Tegn2S!Ym&m8!flci7?pQTG0mH0ugb%PxycO3GLvdRQ^PsKM_qn0 zU?L@l{~R;+91k5JBQr1>Y*qc&!Yy8H=oz`k z+J>pHAdqFulksNsq&SnFIfxcJG%8h%YS7KmN)^$ue%YlfafAz;syR*F6}lSayP&U6 z-rf0SPK+qoGsU~SDT>LRRZ0&P->e}fFWIqu!l_L}e!6`(UV64%_ji}Tb{89!%_>{8 zAYpF4-EC2&ik}?;Y=Empn)c^EP@49Lng)0mFiT|8ttbT0WJK`lM+TU8@iOxmnQKbi1sz-bR3|YinOCyw)Bj^A{X= zn(V_ zF{mftt#v)`-lXuv#ne2CX!7#F%xg!6UUVJ8)j}T;g?bH-r8Pa4V^;72PdreiD6{K1 zFqKl)t3tfg_sWJPgoARCDai#gJhq+^&d=$Cz*e0IzvUfch~xoIFh7f0F-TMKf{C{X}+)=B&jZ;*u3Vp z04e5$Bmf*~9yH`m&s=f7v?euHIgF(-!t(pPYD2>qer4rq(s^lF6~5=&vAJV|ckAr* zWx6}&F9LJNijQQ^2M*&b&xhT$*LBxNptFH)I%8?>%<^grH&8B6(9G%lJ|Nb8O zJ-MEGQfCLBwPA|YF6?mg+nCWv&fUjgaXpdQt$DHobS}1%ybGi1!e1!mLXb4g93#5X zY-2<)RoOuTWGy(+i^={s1?@2d4bz{jd^xDHL#H^>7I#Tkz7kxLzrUWj!v7kIW5#8N zL20j!eSg5s^iR0hP4N|UIxTn16m&|fFTBg1vF=AIQ8gHw5aF6|pp8jwqMT|xU@V-W zsurjqg)1XlOqOIs9HB|c?9`qco#4PqMKwESH*vZ-AgPm3B!N4XAZ|01Ja?zoCbqP+ zA?#4B08C7FN)odDG*1X`nX7Jb#T0g2uH12UsP5cn`7zgUv7#fHqE%)=kUD(hQ&j%r?AMejIgd zJbBV%xT1z7bV;?lBMC&9L=$!aOF;v?>)U@a5X?QBXM&m$*q*B=gJ{~TO#k*<4OdOc z{8*w&txSiuVq<>q;?Ik%Jpqe| zoOa_ic+1#WNA;tCy6UpFqF@2Wiuo+YNmH**&QiFt+LUd|Zbh)l#<<_A9OmL=Ib0u? zO19J>ff!D;oCsQKh}FdbrKgMtv?~%z%u49D2oLn0RZe7Cjm*$_v&QH~o&nUwf-TL% z=@SMlu1d}y5ll|U_&kXr`DD914Usrvxw{|LFc8FIqIR;efA}p#XoJ!2AZ#JrNJhYG z{zyCbLg%7-#@4j;GzMr?26P z&cXs3hv+EVN>ez_=YGBk7Q|wk1{-r<%HN5nfQ?Eb z_rWrfBsLBcDKw75jzStRQgJqK$u$6RN7miZbn8@^*&8>}fb5dbtIiP;7h0z2zta}Q~Q5EIAfNPo67bKDcncgADmzTdeyQqQ+?>jMA2rny_HnS#kAk5PW;udUNps0BUNsol}AGK&dUI>KgYJ(-u9 zB=`2MdqT_kkS5eR_O$LIVKyPEV1^ZRZiA-;^%wjeWfQ*%iRyrkqUv?r$MC%M#p+)t znQ0$=-18NUa*xN{Cy=$(WOz11e!HrjtKb^!ze8N2C2jbczVGO&aCfH|Tf8{KGr|C( z)v}}2wtv`Uk3&HUUcu9SqFV)ZsxY8iW=)trZo`UD4M-J-5JSH}eVBmT zjhqrnk=kIy9%#KiL}DBakW6|6WgDhlmRE!3O^fL^JeXvDduP%|++?`TJ5OJ{9|kfU zvav9_gTV!B6LBY0a_1Vb(ib_xW)3|iy_0fYTGUYkfSy8}+bveSt!}Kcl2TQOURh)P zJF`KQ3TX~+vxmauuc0=>Ko$g zdlY7MRt;`vRN9q2_yPJEU6>F=VuL?;6}6L`kXxo{qq zi)D|y%3d-fHm32r5b<+*FD*pweY301vPcmo3Qr#KjeIrkIDbw0CyuFWS(?RpMlT8^ zk*|y^-vUCOs2V;Z9zHX4a6V<7lvX$s;AGP+llJmiXfuIH>2bxl@rjq)DZ}>U+)=pa zBo|`bcYp!0r$2qQ8S^5Bvlo%dfq{V{M(ueQRMVoxXS^$d!Wn8No8x@WiN-@Utc3j4 zp)U|Y#zu5Wb9o7f8oI3Hob5s%6F|_1F!OgxcCH1H1@EI-A(Wbru>hDcH98i7Kawss zM5h41=+Brp6GV`88eeu|=xI6!*bo73;?OI9@<9s3Ueg*#x;kF~AKK)epBpLuJX7hH z!Qk=kWF2y}&X{zlNcxp>^C{+Rw#9tk+0qTj4n{@#B?4bOZMN)qp_*dPfZ0Q6f@Y<# z>ijRlTzl%$VGYHYPmdBCULDPO1_L>%kMEZxnQ`5g>``26WY_cOa^S9@GS&`*Qj@Be z;kFSST^qQVmgY;8qTC6@o7JqVtgntHYw8ePs$tR1h(?5wl(xuuowPcXUcQ%T_4a7J za2|9xZDZN6PUEi3ehRZ8U%&oXZU(Leq{%GOt7R$D@U`&RPhCHj9+oBtf( zO8@Ty-2ae#`M0dgv-4Nh<)cuF^O(MoL_WKjAiFSU;#c;sU$gOx;BkfWvQ(7PaZ64n zsZeoZ=#QRYC^lP zYUGvp6ts>+UV75C8OSQ?Y>~$+4qlS@ zWL8_rDNQ7rZh~3!EPeC(BbmqX!z+O)B%8JMvtEvB+`4;$t-w*hA$gv$NW(>VW)X(Q zq?qW)aHP1Z5=|&txMZq9Y1%}o;7yA1Q7PLgTGf)aNq#aAJ5jJS2g zjIe6iXOR-W`kQ%+4)XWSo9I%25Wl(|4Ch)B6OCD&Pl1dpg>|Fg=+8Jpp6n?@NuG1j z8$geEh*g|#8tMH3H^eUVhTg-WWk!g{oqKHF03MTxIB26nk*F$f13mf&#n|>1 z+NYvdP~nIwtwBdP9AjmSZAJL0p}(O;{0u>!g0LX?u_m2CT{sO=WoS}SBLMj#zM9ml zv!$?4x82P|Z21Jb4$rino{^9`w#s22Y;D-&dtwT5qGd2QZaoLYoO)vDc|(;32xr(} z5+|78Y#T~!3&*cqPYHt3P?H2QDV~?LUtyB)1(psV@Wf@6+EEnbb z0|Sfms>C3u3++GA^&5r~4CrY|5zymPZZ`^m!u7>>c1=11a2Sd+;om728P%DI%-w$#>`RU?n@^kI{_E3ABnP8t~C_#6M=^Hg_T@;HUdVQkx2 zrWlsfTdM<{Pm|H)wB*`9^A?`2jHdvxlD?9($SSYNF`!naAYThtWm3)hI&;aDN@-KA zWN=da-dUNF?WqnIBE#4WUL6~;nd6O+u#LDBn{g-zsQUxH6& zD*ZvqI~bqbw~?#CNoAchZ#4Wszk9x&e!8c^;JKZ;V1xkUYdOTBUR1bV*f^@Qr0QF*o6~NEOsG7`kNS;j^kt`lk(*myD_h^GxEsWWaRA-{~U8PZ;)%c z-9RD_%2=E63?B;Zj{S=lKW~@hR?^Wcp{L9wuzT- zeeVE*PZ5>=K(@5fS7bzxH}gZAe>TEt1}{5Lvu8&IA9wnwP!U*zNMR<&Ps0jyX<6*px~&aZbz!+6 z#Mj6u)Ry*|e0&qvw==fDU$ONtpCV*M$wzb#z;sBkXx z&%&u-`X}Os#;j!F{*~7O`}yC=p7{Sx_C)op4DC(y%>OmFQ=tOoqPXPvQN^71$c*(j z`Zs;KUj)A>R)6O(1~(F@VH8@u4@2Y*gPZ90ycE3yxL-|iouBVP(XK_hy=uiH%s-(W}D+&lu0)y8R^2;e^U&=M$(; z17)c}Bz#t63+Edr+G(@UPz9&eT#clNU!*W@nM3(PjrI^YF1Dk^tZh&vE+=o{?k*>9 z-mX2gEP2@jx#Cyw4tv*Fu3jUa)2`=Q1n0bVr46RicjIXZjSBa=dKS@UbXROdL9Nzd zWgueXZljfLFjv~}w*k8m?0ec`1H||9Q(sG}rUq-xrN&TbC8~=0ml9ojVzipZ=vt*5 z%H_??8LsLsJ`60`WK>BFqHDuFkiO7}X%%GsA)fE2KV@io2cOv6E5$S$x#mA&7d!{5K%LfJg z##xUIZgA+EIw`I)Q8vw<)(YAI}1|cw~PMv8a6#-*a3zhrwly z#H5iUVqKrLCNVv7S`3X@(6)kwgGv=mX0W1+Fr3AJ8A1+s8|b+=KfiK^j!`P6_{CKx zwOQaoTqrkBUE`)6Ma_CNyWbIwjZD2#FyjgutpaU1}}aNWO5eC-6li zTuDtnz?Ioj&@!{*7$Gq2{rjeP{ z5vq76Ocsub?mc#h**Xy)2AUIF4H5J@2w`YD6DNwsWedsU#%gN+(oYfV3sunS$QTiA zFQD-}icVn;dZ~3fu?wHfj6{xA1q?>>-X-(1EV2B5Nohl3TN?xl$cv6hUogr2weY_<5db-iFS6FeJ`} z5Wd1Ep=K418PKexTaG2p&5o>JxOj7NBZb4;qo@+)37Msz7FCGWlaQn0hYnw3f}Kbc zvFI07H2yvvC(CX9T^|5IyRz63%-;^}eW2kA~4SX(reqMDb=>Hx^;bC_*rwNbOqo ztvSWvCBv z;d$)DWWlyAa)Pt*Xt{Jp8V(UIhy`cn=K_5xK_NjULC#KbV18gcxWpgzJ_fiUmh@@* z!W|GezM`E&mh|~6UN{5>o}5{pFeVe_VnJ`h4qlndnlPd%a-1)4Hh(EG)n-m$z|-F! zEXUb|8qDi>QNZiZ(Lt(2&& z{F6dn3rcluO7OHIfEkR@k`(-JsFK;k1Lk;Yg6EPQb8;=A-ZHAI+5z%;S2!WzRgrMR zE^Z?)+;v($bpR_hojzBd4CBVM>-QJM6GfJ1{S4yFf>0TfV?_m>P+A@L`sDFdjUNu+#fsP4}K7VoZt0z!Fl8?}+? zjdH_dW-zN!7lPF?D{Ak)hq$(FN2vmKWa-OgRYF6yl+^Demhm3-ODi46WY`q%h7x>> zX>zM-txB|8=K~Pct6_hhc<45xsI>jBOVOiXnz6l42CQ{6(Ix1&!azVC4gR9{fjSxF zpc7CdU6_M*QfyCk9QEtCTx-7-p!+>h(XD>9kgb#GCi!$cC8EFnSSQ=o0_7#%jsxW- z*`5PU+_r9iLIuG`yQ=o#^;ioNxx%G$yV9a-+;P_q-?r{>Vf&a2)9Kp^8@Y6!`HSyz zz4in_*LoeLy-u~w@HQQ`)x$SZv((WH@p(3Y_ZEhZ-`}MSGd5Rod;r)V$rM{z&q{*Zjf6%}y3>d=&^W1*8E{fl^HQCiT0)=NJ?Kt@^9` zvd7*m)dvft4s0FR(DmJ*i+zf0UDw#yL#)m}71Q4*3;sj1C9c#$>PZ93z z`n_GhuTbe^bp+N?=@fU|@FSVkxBU2&hJy(4%;aRQl)xTZSRE|9HB&RVbzPXoV6Vc$ z_N=@$bKRwWbZw}gQL)u#$v{pUC2j}f+yOM(Kv33z%~dCKZbISvs`|682RbU?UT$KJp;D%<#hWC$s4Q2R z^0sORViaj8Tv50_o4PrbO+s~8fMYr)ROj^DVpZWvvL)45?F(-;eaKS zRyZu>oQO3PRY=t=lNf$t>G-;iJSuBa!5+cofr@;h1x*KBQI`7Qp)P!Gwt&09ON0Fb z$&dG)6Pw#LtGC2F2{RLZ#tkg2j#lX=ddia@PTIC?T$|Bs-*lcn`S5|!hHG#kb?h)7 za)IKWB0NtM7ofhBcSGr9>Z1JTfCgvU#;G$xXYuN-kWKa(4Qsf4P@Zn?im^!+Yp}yf zkEdTAkLrY%;?j3A$o(eonK@Rd51%* zYx7s>1PH%20h^lVOgq53Ml#Y^J3NGSS}x=~*gwf1u0dQ)blUuj9<+NgOLmQRON}&H zn2^yQBgJXz_y}<10c8)t58g|VF_I-%U-DM(G${5Xd4VJX6VZ+NjV;@&rp&Giz zD|4WA22d4WDa}rqP9BEnrQ+vzZgT_d?p--1inRD6P}T}pS1=oP6s7NA)MnIN=9!w zpx!=Y$4i)QPH0uTIPdP@);COfzB&j2wX-)y1x90~@O=8V-YHFKL-zPR_%-EdyRT0q zZE?=GjS#9QRxek?MLlI_-DJTM8Rv_=DQ3)F>thUlJgPOVo;ilus~B~z#G zocEloojpJ*S`M!uqr=`Nu{ijydnDSLPPbM~4e7iRQ+{DbF|&f?WynhtN4D4X{W3LJ z-X`;Ve@@v*9Kg7g`*^W(3-6X9mChW6qE@d& z`1HjXBTmML3Ya76Df1hx`9!BhN5w-~a$gvAArVMxHT+gRUCSavO4r_t1

dgcYMb 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≶}0^eFwJ$J3cF^J@u?47Vs5Gp`ep6jPtw)qx2H+ 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

L<5@27#Vk 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 literal 0 HcmV?d00001 diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java index 90233fb..685de06 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java @@ -1,32 +1,38 @@ package de.c3ma.ollo.mockup; +import java.util.UUID; + +import org.eclipse.paho.client.mqttv3.IMqttClient; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; import org.luaj.vm2.lib.TwoArgFunction; import org.luaj.vm2.lib.VarArgFunction; -import de.c3ma.ollo.LuaThreadTmr; - /** * * @author ollo * */ public class ESP8266Mqtt extends TwoArgFunction { + + private IMqttClient mMqttClient = null; @Override public LuaValue call(LuaValue modname, LuaValue env) { env.checkglobals(); final LuaTable mqtt = new LuaTable(); - mqtt.set("Client", new MqttClient()); + mqtt.set("Client", new LuaMqttClient()); env.set("mqtt", mqtt); env.get("package").get("loaded").set("tmr", mqtt); System.out.println("[MQTT] Modlue loaded"); return mqtt; } - private class MqttClient extends VarArgFunction { + private class LuaMqttClient extends VarArgFunction { public LuaValue invoke(Varargs varargs) { final LuaTable dynMqtt = new LuaTable(); if (varargs.narg() == 2) { @@ -107,14 +113,30 @@ private class ConnectMqtt extends VarArgFunction { public LuaValue invoke(Varargs varargs) { final LuaTable onMqtt = new LuaTable(); - if (varargs.narg() == 6) { + if ((varargs.narg() == 6) && (mMqttClient == null)) { final LuaTable table = varargs.arg(1).checktable(); final String targetIP = varargs.arg(2).toString().toString(); final int portnumber = varargs.arg(3).toint(); - final boolean unkownParameter = varargs.arg(4).toboolean(); + final boolean secureTLS = varargs.arg(4).toboolean(); final LuaValue codeOnConnected = varargs.arg(5); final LuaValue codeOnFailed = varargs.arg(6); - System.out.println("[MQTT] connect to " + targetIP + ":" + portnumber); + String publisherId = "LuaSim" + UUID.randomUUID().toString(); + try { + mMqttClient = new MqttClient("tcp://" + targetIP + ":" + portnumber,publisherId); + MqttConnectOptions options = new MqttConnectOptions(); + options.setAutomaticReconnect(false); + options.setCleanSession(true); + options.setConnectionTimeout(10); + mMqttClient.connect(options); + System.out.println("[MQTT] connected to " + targetIP + ":" + portnumber); + codeOnConnected.call(); + } catch (MqttException e) { + System.err.println("[MQTT] connect failed : " + e.getMessage()); + codeOnFailed.call(); + } + } else if (mMqttClient != null) { + System.err.println("[MQTT] client already exists : " + mMqttClient); + return LuaValue.NIL; } else { for(int i=0; i <= varargs.narg(); i++) { System.err.println("[MQTT] connect ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); From 6fbaec749a52ba25372deafd3ad2b6a1d052f845 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 3 Apr 2021 12:42:23 +0200 Subject: [PATCH 168/204] Removed usage of callback parameter --- mqtt.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 7c9be19..e87fadd 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -121,22 +121,22 @@ function registerMqtt() mqttConnected = false end ) - m:connect(mqttServer, 1883, false, function(client) + m:connect(mqttServer, 1883, false, function(c) print("MQTT is connected") mqttConnected = true -- subscribe topic with qos = 0 - client:subscribe(mqttPrefix .. "/cmd/#", 0) - local mytimer = tmr.create() - mytimer:register(1000, tmr.ALARM_SINGLE, function (t) - -- publish a message with data = hello, QoS = 0, retain = 0 - client:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) + m:subscribe(mqttPrefix .. "/cmd/#", 0) + local tmr1 = tmr.create() + tmr1:register(1000, tmr.ALARM_SINGLE, function (t) + -- publish a message with data = hello, QoS = 0, retain = 0 + m:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) local red = string.byte(colorBg,2) local green = string.byte(colorBg,1) local blue = string.byte(colorBg,3) - client:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) - t:unregister() + m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) + tmr1:unregister() end) - mytimer:start() + tmr1:start() end, function(client, reason) print("failed reason: " .. reason) From 23bcd36a34f03d42d759bc2ecc9376c9b270676d Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 3 Apr 2021 12:55:27 +0200 Subject: [PATCH 169/204] Publishing is simulated, too --- .../src/de/c3ma/ollo/mockup/ESP8266Mqtt.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java index 685de06..b04bd48 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java @@ -6,6 +6,8 @@ import org.eclipse.paho.client.mqttv3.IMqttClient; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.eclipse.paho.client.mqttv3.MqttPersistenceException; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; @@ -81,8 +83,28 @@ public class ESP8266Mqtt extends TwoArgFunction { public LuaValue invoke(Varargs varargs) { final LuaTable onMqtt = new LuaTable(); - if (varargs.narg() == 2) { - System.out.println("[MQTT] publish "); + if (varargs.narg() == 5) { + final String topic = varargs.arg(2).toString().toString(); + final String message = varargs.arg(3).toString().toString(); + final String qos = varargs.arg(4).toString().toString(); + final String retain = varargs.arg(4).toString().toString(); + if ( !mMqttClient.isConnected()) { + return LuaValue.NIL; + } + MqttMessage msg = new MqttMessage(message.getBytes()); + if (qos.equals("0")) { + msg.setQos(0); + } + + msg.setRetained(!retain.contentEquals("0")); + try { + mMqttClient.publish(topic,msg); + System.out.println("[MQTT] publish " + topic); + } catch (MqttPersistenceException e) { + System.err.println("[MQTT] publish " + topic + " failed : " + e.getMessage()); + } catch (MqttException e) { + System.err.println("[MQTT] publish " + topic + " failed : " + e.getMessage()); + } } else { for(int i=0; i <= varargs.narg(); i++) { System.err.println("[MQTT] publish ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); From 8b58d4a39f90a727b5ebdbd922895b32a97ebfdd Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 3 Apr 2021 13:15:37 +0200 Subject: [PATCH 170/204] All colors can be changed via MQTT --- Readme.md | 20 ++++++++++++++++++-- mqtt.lua | 28 ++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Readme.md b/Readme.md index 55e8c3f..0d8df53 100644 --- a/Readme.md +++ b/Readme.md @@ -42,7 +42,8 @@ Mandatory: * GPIO2 LEDs * GPIO0 Bootloader (at start) * GPIO0 factory reset (long during operation) -Optinal: + +Optional: * ADC VT93N2, 48k light resistor * GPIO4 DS18B20 Temperatur sensor @@ -50,6 +51,11 @@ Optinal: ### Status * **basetopic**/brightness **Current brightness in percent** * **basetopic**/background **Current background color** +* **basetopic**/color **Current foreground color** +* **basetopic**/color1 **Current foreground color for first minute** +* **basetopic**/color2 **Current foreground color for second minute** +* **basetopic**/color3 **Current foreground color for third minute** +* **basetopic**/color4 **Current foreground color for fourth minute** * **basetopic**/row1 **Current background color** * **basetopic**/temp **Temperatur** @@ -60,8 +66,18 @@ Optinal: * 0-100 **Set brightness to given value** * #rrggbb **Background color is set to hex representation of red, green and blue** * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** +* **basetopic**/cmd/color + * 0-255,0-255,0-255 **Foreground color is set to decimal representation of red, green an blue** +* **basetopic**/cmd/color1 + * 0-255,0-255,0-255 **Foreground color for first minute is set to decimal representation of red, green an blue** +* **basetopic**/cmd/color2 + * 0-255,0-255,0-255 **Foreground color for second minute is set to decimal representation of red, green an blue** +* **basetopic**/cmd/color3 + * 0-255,0-255,0-255 **Foreground color for third minute is set to decimal representation of red, green an blue** +* **basetopic**/cmd/color4 + * 0-255,0-255,0-255 **Foreground color for fourth minute is set to decimal representation of red, green an blue** * **basetopic**/cmd/telnet - * ignored **Stop MQTT server and start telnetserver at port 23** + * ignored **Stop MQTT server, clock and start telnetserver at port 23** * **basetopic**/cmd/row1 * 0-255,0-255,0-255 **Background color is set to decimal representation of red, green an blue** * **basetopic**/cmd/row1 diff --git a/mqtt.lua b/mqtt.lua index e87fadd..a445bcc 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -39,7 +39,8 @@ end -- Parse MQTT data and extract color -- @param data MQTT information -- @param row string of the row e.g. "row1" used to publish current state -function parseBgColor(data, row) +-- @param per percent the color should be dimmed +function parseBgColor(data, row, per) local red=nil local green=nil local blue=nil @@ -52,7 +53,11 @@ function parseBgColor(data, row) end if ((red ~= nil) and (green ~= nil) and (blue ~= nil) ) then m:publish(mqttPrefix .. "/"..row, tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) - return string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) + if (per ~= nil) then + return string.char(green * per / 100, red * per / 100, blue * per / 100) + else + return string.char(green , red , blue ) + end else return nil end @@ -104,10 +109,25 @@ function registerMqtt() else print("Cannost start Telnet Server!") end - else + elseif (string.match(topic, "color$")) then + color = parseBgColor(data, "color") + print("Updated color" .. tostring(i) ) + elseif (string.match(topic, "color1$")) then + color1 = parseBgColor(data, "color1") + print("Updated color1" .. tostring(i) ) + elseif (string.match(topic, "color2$")) then + color = parseBgColor(data, "color2") + print("Updated color2" .. tostring(i) ) + elseif (string.match(topic, "color3$")) then + color = parseBgColor(data, "color3") + print("Updated color3" .. tostring(i) ) + elseif (string.match(topic, "color4$")) then + color = parseBgColor(data, "color4") + print("Updated color4" .. tostring(i) ) + else for i=1,10,1 do if (string.match(topic, "row".. tostring(i) .."$")) then - rowbgColor[i] = parseBgColor(data, "row" .. tostring(i)) + rowbgColor[i] = parseBgColor(data, "row" .. tostring(i), briPer) print("Updated row" .. tostring(i) ) return end From 379233327c7e7028fdfd68923ee5652b71eaa827 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 3 Apr 2021 13:28:10 +0200 Subject: [PATCH 171/204] Update debug message --- mqtt.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index a445bcc..44c8c87 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -111,19 +111,19 @@ function registerMqtt() end elseif (string.match(topic, "color$")) then color = parseBgColor(data, "color") - print("Updated color" .. tostring(i) ) + print("Updated color" ) elseif (string.match(topic, "color1$")) then color1 = parseBgColor(data, "color1") - print("Updated color1" .. tostring(i) ) + print("Updated color1" ) elseif (string.match(topic, "color2$")) then color = parseBgColor(data, "color2") - print("Updated color2" .. tostring(i) ) + print("Updated color2" ) elseif (string.match(topic, "color3$")) then color = parseBgColor(data, "color3") - print("Updated color3" .. tostring(i) ) + print("Updated color3" ) elseif (string.match(topic, "color4$")) then color = parseBgColor(data, "color4") - print("Updated color4" .. tostring(i) ) + print("Updated color4" ) else for i=1,10,1 do if (string.match(topic, "row".. tostring(i) .."$")) then From 1863ab15b921165c61a3a68e0a3ee9a0372d800f Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 3 Apr 2021 14:03:59 +0200 Subject: [PATCH 172/204] Reconnect to MQTT if necessary (checked every 30 seconds) --- main.lua | 5 +++++ mqtt.lua | 50 +++++++++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/main.lua b/main.lua index 026f881..3b50e51 100644 --- a/main.lua +++ b/main.lua @@ -139,6 +139,11 @@ function normalOperation() if (startMqttClient ~= nil) then if (not connectedMqtt()) then rgbBuffer:set(103, 0, 64,0) + -- check every thirty seconds, if reconnecting is necessary + if (((tmr.now() / 1000000) % 100) == 30) then + print("MQTT reconnecting... ") + reConnectMqtt() + end end end ws2812.write(rgbBuffer) diff --git a/mqtt.lua b/mqtt.lua index 44c8c87..05ebee1 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -78,6 +78,33 @@ function readTemp() end end +-- Connect or reconnect to mqtt server +function reConnectMqtt() + if (not mqttConnected) then + m:connect(mqttServer, 1883, false, function(c) + print("MQTT is connected") + mqttConnected = true + -- subscribe topic with qos = 0 + m:subscribe(mqttPrefix .. "/cmd/#", 0) + local tmr1 = tmr.create() + tmr1:register(1000, tmr.ALARM_SINGLE, function (t) + -- publish a message with data = hello, QoS = 0, retain = 0 + m:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) + local red = string.byte(colorBg,2) + local green = string.byte(colorBg,1) + local blue = string.byte(colorBg,3) + m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) + tmr1:unregister() + end) + tmr1:start() + end, + function(client, reason) + print("failed reason: " .. reason) + mqttConnected = false + end) + end +end + -- MQTT extension function registerMqtt() m = mqtt.Client("wordclock", 120) @@ -141,27 +168,7 @@ function registerMqtt() mqttConnected = false end ) - m:connect(mqttServer, 1883, false, function(c) - print("MQTT is connected") - mqttConnected = true - -- subscribe topic with qos = 0 - m:subscribe(mqttPrefix .. "/cmd/#", 0) - local tmr1 = tmr.create() - tmr1:register(1000, tmr.ALARM_SINGLE, function (t) - -- publish a message with data = hello, QoS = 0, retain = 0 - m:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) - local red = string.byte(colorBg,2) - local green = string.byte(colorBg,1) - local blue = string.byte(colorBg,3) - m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) - tmr1:unregister() - end) - tmr1:start() - end, - function(client, reason) - print("failed reason: " .. reason) - mqttConnected = false - end) + reConnectMqtt() end function connectedMqtt() @@ -201,3 +208,4 @@ function startMqttClient() mqtttimer:start() end end + From e10ad2fafc31c965108949139ff50517c7704a6d Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 3 Apr 2021 14:19:32 +0200 Subject: [PATCH 173/204] Dimm Boot process, and compile all modues --- init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index fba9d65..111f403 100644 --- a/init.lua +++ b/init.lua @@ -9,7 +9,7 @@ local bootledtimer = tmr.create() bootledtimer:register(100, tmr.ALARM_AUTO, function (t) counter1=counter1+1 spaceLeds = math.max(MAXLEDS - (counter1*2), 0) - ws2812.write(string.char(128,0,0):rep(counter1) .. string.char(0,0,0):rep(spaceLeds) .. string.char(0,0,64):rep(counter1)) + ws2812.write(string.char(32,0,0):rep(counter1) .. string.char(0,0,0):rep(spaceLeds) .. string.char(0,0,16):rep(counter1)) if ((counter1*2) > 114) then t:unregister() end @@ -36,7 +36,7 @@ initTimer:register(5000, tmr.ALARM_SINGLE, function (t) initTimer:unregister() initTimer=nil bootledtimer=nil - local modlist = { "timecore" , "displayword", "ds18b20" } + local modlist = { "timecore" , "displayword", "ds18b20", "mqtt", "main" } for i,mod in pairs(modlist) do if (file.open(mod .. "_diet.lua")) then file.remove(mod .. "_diet.lc") From 9b113099aa6da4a795e7d4da52a037c25d045625 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 3 Apr 2021 14:57:39 +0200 Subject: [PATCH 174/204] Fixed minute colors --- mqtt.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 05ebee1..04b884e 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -143,13 +143,13 @@ function registerMqtt() color1 = parseBgColor(data, "color1") print("Updated color1" ) elseif (string.match(topic, "color2$")) then - color = parseBgColor(data, "color2") + color2 = parseBgColor(data, "color2") print("Updated color2" ) elseif (string.match(topic, "color3$")) then - color = parseBgColor(data, "color3") + color3 = parseBgColor(data, "color3") print("Updated color3" ) elseif (string.match(topic, "color4$")) then - color = parseBgColor(data, "color4") + color4 = parseBgColor(data, "color4") print("Updated color4" ) else for i=1,10,1 do From f021012a67b8ecfffb37b4926c5260e7f4eb1aa8 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 4 Apr 2021 19:17:15 +0200 Subject: [PATCH 175/204] Update the time once a second --- main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.lua b/main.lua index 3b50e51..851a463 100644 --- a/main.lua +++ b/main.lua @@ -84,7 +84,7 @@ function normalOperation() -- Define the main loop local setupCounter=5 local alive=0 - mlt:register(2500, tmr.ALARM_AUTO, function (lt) + mlt:register(1000, tmr.ALARM_AUTO, function (lt) if (setupCounter > 4) then if (colorBg ~= nil) then rgbBuffer:fill(string.byte(colorBg,1), string.byte(colorBg,2), string.byte(colorBg,3)) -- disable all LEDs From 19ff6d11c29c47a63183936eb8c785a6ab11cce6 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 28 Oct 2021 21:06:49 +0200 Subject: [PATCH 176/204] Ignore the shrinked LUA scripts, which are uploaded to the ESP --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 18d5539..b9d369b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ config.lua simulation.config.lua *.swp unit/testTimesMarchOctoberWithAllSeconds.lua +diet/* From d5986470fe0397005040ad93f0584ea074b1a7fb Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 28 Oct 2021 21:09:49 +0200 Subject: [PATCH 177/204] Added mqtt library --- simulation/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulation/Readme.md b/simulation/Readme.md index 1c1d3ff..4e711d0 100644 --- a/simulation/Readme.md +++ b/simulation/Readme.md @@ -9,4 +9,4 @@ Compiling: `javac -d bin/ -cp libs/luaj-jme-3.0.1.jar:libs/luaj-jse-3.0.1.jar $(find src -name '*.java')` Running: - `java -cp libs/luaj-jme-3.0.1.jar:libs/luaj-jse-3.0.1.jar:bin de.c3ma.ollo.WS2812Simulation ../init.lua ws28128ClockLayout.txt config.lua` + `java -cp libs/luaj-jme-3.0.1.jar:libs/luaj-jse-3.0.1.jar:libs/org.eclipse.paho.client.mqttv3-1.2.5.jar:bin de.c3ma.ollo.WS2812Simulation ../init.lua ws28128ClockLayout.txt config.lua` From 2790a621754937a451755f849dcfed74b0e16caf Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 28 Oct 2021 21:26:08 +0200 Subject: [PATCH 178/204] buffer is filled with expected color --- simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java index 69a4d75..38da090 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -126,10 +126,11 @@ public class ESP8266Ws2812 extends TwoArgFunction { } public Varargs invoke(Varargs varargs) { - if (varargs.narg() >= 3) { - final int red = varargs.arg(1).toint(); - final int green = varargs.arg(2).toint(); - final int blue = varargs.arg(3).toint(); + if (varargs.narg() == 4) { + /* first argument is the object itself */ + final int red = varargs.arg(2).toint(); + final int green = varargs.arg(3).toint(); + final int blue = varargs.arg(4).toint(); /* update local buffer */ for(int i=0; i < ledList.size(); i++) { ledList.set(i, new Color(red, green, blue)); From eff23d14cfeea3278a94beda17bb951e6efe61a2 Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 29 Oct 2021 22:33:22 +0200 Subject: [PATCH 179/204] compile command updated --- simulation/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulation/Readme.md b/simulation/Readme.md index 4e711d0..b1a7388 100644 --- a/simulation/Readme.md +++ b/simulation/Readme.md @@ -6,7 +6,7 @@ The simualation should be started with the following arguments at this position: # Use it without Eclipse Compiling: - `javac -d bin/ -cp libs/luaj-jme-3.0.1.jar:libs/luaj-jse-3.0.1.jar $(find src -name '*.java')` + `javac -d bin/ -cp libs/luaj-jme-3.0.1.jar:libs/luaj-jse-3.0.1.jar:libs/org.eclipse.paho.client.mqttv3-1.2.5.jar $(find src -name '*.java')` Running: `java -cp libs/luaj-jme-3.0.1.jar:libs/luaj-jse-3.0.1.jar:libs/org.eclipse.paho.client.mqttv3-1.2.5.jar:bin de.c3ma.ollo.WS2812Simulation ../init.lua ws28128ClockLayout.txt config.lua` From a5ddb2994db775f29a19d0e503f67bb02cba6f6b Mon Sep 17 00:00:00 2001 From: Ollo Date: Fri, 29 Oct 2021 23:13:43 +0200 Subject: [PATCH 180/204] Catch failures on loading LUA files --- .../de/c3ma/ollo/mockup/DoFileFunction.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java b/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java index 0d3d741..c88d3ed 100644 --- a/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java +++ b/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java @@ -27,13 +27,18 @@ public class DoFileFunction extends OneArgFunction { String filename = luaFilename.checkjstring(); File f = new File(workingDir.getAbsolutePath() + File.separator + filename); - - if (f.exists()) { - LuaValue chunk = this.globals.loadfile(f.getAbsolutePath()); - chunk.call(); - return LuaValue.valueOf(true); - } else { - return LuaValue.valueOf(false); + try { + if (f.exists()) { + LuaValue chunk = this.globals.loadfile(f.getAbsolutePath()); + chunk.call(); + return LuaValue.valueOf(true); + } else { + return LuaValue.valueOf(false); + } + } catch (Exception e) { + System.err.println("Cannot load " + f.getName()); + e.printStackTrace(); + return LuaValue.valueOf(false); } } From 57de18b37cbec98025dd460e8d6708ad91a1ab38 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 11:53:34 +0100 Subject: [PATCH 181/204] Less different colors --- simulation/config.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/simulation/config.lua b/simulation/config.lua index 239fe4c..e995957 100644 --- a/simulation/config.lua +++ b/simulation/config.lua @@ -1,12 +1,12 @@ green2=200 -red=128 +red=200 blue=200 color=string.char(0, 0, blue) color1=string.char(red, 0, 0) -color2=string.char(tonumber(red*0.8), 0, 0) -color3=string.char(0, tonumber(green2*0.4), 0) -color4=string.char(0,0 ,tonumber(blue*0.2)) +color2=string.char(tonumber(red*0.9), 0, 0) +color3=string.char(tonumber(red*0.8), 0, 0) +color4=string.char(tonumber(red*0.7), 0, 0) colorBg=string.char(0,0,0) -- black is the default background color sntpserverhostname="ptbtime1.ptb.de" From 5d96adb424d640f5a50cb909f58716137b5bf014 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 13:01:40 +0100 Subject: [PATCH 182/204] Only temperature is display; time is killed --- main.lua | 7 +++++++ mqtt.lua | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/main.lua b/main.lua index 851a463..2c28db4 100644 --- a/main.lua +++ b/main.lua @@ -61,6 +61,13 @@ function displayTime() local c = dw.countChars(words) dw.generateLEDs(rgbBuffer, words, colorBg, color, color1, color2, color3, color4, invertRows, c) end + if (mqttDispTemp ~= nil) then + local tw, tcol = mqttDispTemp(dw, rgbBuffer, invertRows) + if ( (tw ~= nil) and (tcol ~= nil) ) then + local c1 = dw.countChars(tw) + dw.generateLEDs(rgbBuffer, tw, nil, tcol, nil, nil, nil, nil, invertRows, c1) + end + end dw = nil collectgarbage() print("dw: " .. tostring(node.heap())) diff --git a/mqtt.lua b/mqtt.lua index 04b884e..27f2da8 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -3,6 +3,7 @@ local m=nil local mqttConnected = false -- Temp: local t=nil +local dispTemp=10 function handleSingleCommand(client, topic, data) if (data == "ON") then @@ -105,16 +106,71 @@ function reConnectMqtt() end end +-- Logic to display Mqtt +function mqttDispTemp(dw, rgbBuffer, invertRows) +if (dispTemp ~= nil) then + -- Values: it, is, 5 minutes, 10 minutes, afer, before, three hour, quarter, dreiviertel, half, s + -- hours: one, one Long, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve + -- Special ones: twenty, clock, minute 1 flag, minute 2 flag, minute 3 flag, minute 4 flag + local ret = { it=0, is=0, m5=0, m10=0, ha=0, hb=0, h3=0, hq=0, h3q=0, half=0, s=0, + h1=0, h1l=0, h2=0, h3=0, h4=0, h5=0, h6=0, h7=0, h8=0, h9=0, h10=0, h11=0, h12=0, + m20=0, cl=0, m1=0, m2=0, m3=0, m4=0 } + + print("Mqtt Display of temperature: " .. tostring(dispTemp) ) + if (dispTemp == 1) or (dispTemp == -1) then + ret.h1=1 + elseif (dispTemp == 2) or (dispTemp == -2) then + ret.h2=1 + elseif (dispTemp == 3) or (dispTemp == -3) then + ret.h3=1 + elseif (dispTemp == 4) or (dispTemp == -4) then + ret.h4=1 + elseif (dispTemp == 5) or (dispTemp == -5) then + ret.h5=1 + elseif (dispTemp == 6) or (dispTemp == -6) then + ret.h6=1 + elseif (dispTemp == 7) or (dispTemp == -7) then + ret.h7=1 + elseif (dispTemp == 8) or (dispTemp == -8) then + ret.h8=1 + elseif (dispTemp == 9) or (dispTemp == -9) then + ret.h9=1 + elseif (dispTemp == 10) or (dispTemp == -10) then + ret.h10=1 + elseif (dispTemp == 11) or (dispTemp == -11) then + ret.h11=1 + elseif (dispTemp == 12) or (dispTemp == -12) then + ret.h12=1 + else + -- over or under temperature + end + local col=string.char(128,0,0) -- red; positive degrees + if (dispTemp < 0) then + col=string.char(0,0,128) -- blue; negative degrees + end + return ret, col +else + return nil, nil +end + +end + -- MQTT extension function registerMqtt() m = mqtt.Client("wordclock", 120) -- on publish message receive event m:on("message", function(client, topic, data) - print(topic .. ":" ) + print("MQTT " .. topic .. ":" ) if data ~= nil then print(data) if (topic == (mqttPrefix .. "/cmd/single")) then handleSingleCommand(client, topic, data) + elseif (topic == (mqttPrefix .. "/cmd/temp")) then + if ( data == "" ) then + dispTemp = nil + else + dispTemp = tonumber(data) + end else -- Handle here the /cmd/# sublevel if (string.match(topic, "telnet$")) then From b0f0481b6f0ae0407bcf834d9de0ee01f49a0fb4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 13:03:07 +0100 Subject: [PATCH 183/204] Only clear background, when a background color is set --- displayword.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/displayword.lua b/displayword.lua index 18d0052..c3c1038 100644 --- a/displayword.lua +++ b/displayword.lua @@ -148,9 +148,6 @@ local generateLEDs = function(rgbBuffer, words, colorBg, colorFg, colorM1, color -- Background color must always be set if (colorBg ~= nil) then rgbBuffer:fill(string.byte(colorBg,1), string.byte(colorBg,2), string.byte(colorBg,3)) -- draw the background - else - -- Space / background has no color by default - rgbBuffer:fill(0, 0, 0) -- draw the background end local lineIdx=1 From 0f2855aafa1c92c409f4d41cd00d8f16082efc64 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 13:06:14 +0100 Subject: [PATCH 184/204] Removed hardcoded testvalue --- mqtt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 27f2da8..534a5b5 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -3,7 +3,7 @@ local m=nil local mqttConnected = false -- Temp: local t=nil -local dispTemp=10 +local dispTemp=nil function handleSingleCommand(client, topic, data) if (data == "ON") then From 7cf761c7a59f6bc8f2c1e6660ecfb3468ee6714c Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 13:38:22 +0100 Subject: [PATCH 185/204] Extracted temperatur functionality into wordclock.lua --- main.lua | 10 ++++---- mqtt.lua | 66 ++++++++------------------------------------------- wordclock.lua | 53 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 61 deletions(-) diff --git a/main.lua b/main.lua index 2c28db4..b7ab043 100644 --- a/main.lua +++ b/main.lua @@ -48,6 +48,11 @@ function displayTime() words.briPer=nil end end + local tw=nil + local tcol=nil + if (mqttDispTemp ~= nil) then + tw, tcol = wc.temp(dw, rgbBuffer, invertRows) + end wc = nil collectgarbage() print("wc: " .. tostring(node.heap())) @@ -61,12 +66,9 @@ function displayTime() local c = dw.countChars(words) dw.generateLEDs(rgbBuffer, words, colorBg, color, color1, color2, color3, color4, invertRows, c) end - if (mqttDispTemp ~= nil) then - local tw, tcol = mqttDispTemp(dw, rgbBuffer, invertRows) - if ( (tw ~= nil) and (tcol ~= nil) ) then + if ( (tw ~= nil) and (tcol ~= nil) ) then local c1 = dw.countChars(tw) dw.generateLEDs(rgbBuffer, tw, nil, tcol, nil, nil, nil, nil, invertRows, c1) - end end dw = nil collectgarbage() diff --git a/mqtt.lua b/mqtt.lua index 534a5b5..a8a9c3b 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -3,7 +3,7 @@ local m=nil local mqttConnected = false -- Temp: local t=nil -local dispTemp=nil +dispTemp=nil function handleSingleCommand(client, topic, data) if (data == "ON") then @@ -106,55 +106,6 @@ function reConnectMqtt() end end --- Logic to display Mqtt -function mqttDispTemp(dw, rgbBuffer, invertRows) -if (dispTemp ~= nil) then - -- Values: it, is, 5 minutes, 10 minutes, afer, before, three hour, quarter, dreiviertel, half, s - -- hours: one, one Long, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve - -- Special ones: twenty, clock, minute 1 flag, minute 2 flag, minute 3 flag, minute 4 flag - local ret = { it=0, is=0, m5=0, m10=0, ha=0, hb=0, h3=0, hq=0, h3q=0, half=0, s=0, - h1=0, h1l=0, h2=0, h3=0, h4=0, h5=0, h6=0, h7=0, h8=0, h9=0, h10=0, h11=0, h12=0, - m20=0, cl=0, m1=0, m2=0, m3=0, m4=0 } - - print("Mqtt Display of temperature: " .. tostring(dispTemp) ) - if (dispTemp == 1) or (dispTemp == -1) then - ret.h1=1 - elseif (dispTemp == 2) or (dispTemp == -2) then - ret.h2=1 - elseif (dispTemp == 3) or (dispTemp == -3) then - ret.h3=1 - elseif (dispTemp == 4) or (dispTemp == -4) then - ret.h4=1 - elseif (dispTemp == 5) or (dispTemp == -5) then - ret.h5=1 - elseif (dispTemp == 6) or (dispTemp == -6) then - ret.h6=1 - elseif (dispTemp == 7) or (dispTemp == -7) then - ret.h7=1 - elseif (dispTemp == 8) or (dispTemp == -8) then - ret.h8=1 - elseif (dispTemp == 9) or (dispTemp == -9) then - ret.h9=1 - elseif (dispTemp == 10) or (dispTemp == -10) then - ret.h10=1 - elseif (dispTemp == 11) or (dispTemp == -11) then - ret.h11=1 - elseif (dispTemp == 12) or (dispTemp == -12) then - ret.h12=1 - else - -- over or under temperature - end - local col=string.char(128,0,0) -- red; positive degrees - if (dispTemp < 0) then - col=string.char(0,0,128) -- blue; negative degrees - end - return ret, col -else - return nil, nil -end - -end - -- MQTT extension function registerMqtt() m = mqtt.Client("wordclock", 120) @@ -235,12 +186,15 @@ function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then registerMqtt() print "Started MQTT client" - if (file.open("ds18b20_diet.lc")) then - t=require("ds18b20_diet") - t.setup(2) -- GPIO4 - readTemp() -- read once, to setup chip - print "Setup temperature" - end + local dstimer = tmr.create() + dstimer:register(123, tmr.ALARM_SINGLE, function (t) + if (file.open("ds18b20_diet.lc")) then + t=require("ds18b20_diet") + t.setup(2) -- GPIO4 + readTemp() -- read once, to setup chip + print "Setup temperature" + end + end) local oldBrightness=0 oldTemp=0 local mqtttimer = tmr.create() diff --git a/wordclock.lua b/wordclock.lua index 11be758..93567c7 100755 --- a/wordclock.lua +++ b/wordclock.lua @@ -140,9 +140,60 @@ local timestat=function (hours, minutes, longmode) collectgarbage() return ret end + + +-- Logic to display Mqtt +function temp(dw, rgbBuffer, invertRows, dispTemp) +if (dispTemp ~= nil) then + -- Values: it, is, 5 minutes, 10 minutes, afer, before, three hour, quarter, dreiviertel, half, s + -- hours: one, one Long, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve + -- Special ones: twenty, clock, minute 1 flag, minute 2 flag, minute 3 flag, minute 4 flag + local ret = { it=0, is=0, m5=0, m10=0, ha=0, hb=0, h3=0, hq=0, h3q=0, half=0, s=0, + h1=0, h1l=0, h2=0, h3=0, h4=0, h5=0, h6=0, h7=0, h8=0, h9=0, h10=0, h11=0, h12=0, + m20=0, cl=0, m1=0, m2=0, m3=0, m4=0 } + + print("Mqtt Display of temperature: " .. tostring(dispTemp) ) + if (dispTemp == 1) or (dispTemp == -1) then + ret.h1=1 + elseif (dispTemp == 2) or (dispTemp == -2) then + ret.h2=1 + elseif (dispTemp == 3) or (dispTemp == -3) then + ret.h3=1 + elseif (dispTemp == 4) or (dispTemp == -4) then + ret.h4=1 + elseif (dispTemp == 5) or (dispTemp == -5) then + ret.h5=1 + elseif (dispTemp == 6) or (dispTemp == -6) then + ret.h6=1 + elseif (dispTemp == 7) or (dispTemp == -7) then + ret.h7=1 + elseif (dispTemp == 8) or (dispTemp == -8) then + ret.h8=1 + elseif (dispTemp == 9) or (dispTemp == -9) then + ret.h9=1 + elseif (dispTemp == 10) or (dispTemp == -10) then + ret.h10=1 + elseif (dispTemp == 11) or (dispTemp == -11) then + ret.h11=1 + elseif (dispTemp == 12) or (dispTemp == -12) then + ret.h12=1 + else + -- over or under temperature + end + local col=string.char(128,0,0) -- red; positive degrees + if (dispTemp < 0) then + col=string.char(0,0,128) -- blue; negative degrees + end + return ret, col +else + return nil, nil +end + +end -- Pack everything into a module M = { - timestat = timestat + timestat = timestat, + temp = temp } end wc = M From d6d305ec7049e371be46cc5162e9e4dce515bc2e Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 19:02:12 +0100 Subject: [PATCH 186/204] Temperature is calcualted, only once --- main.lua | 13 ++++--------- mqtt.lua | 18 +++++++++++++++--- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/main.lua b/main.lua index b7ab043..398c17f 100644 --- a/main.lua +++ b/main.lua @@ -38,20 +38,15 @@ function displayTime() collectgarbage() mydofile("wordclock") if (wc ~= nil) then - words = wc.timestat(time.hour, time.minute) - if ((dim ~= nil) and (dim == "on")) then + words = wc.timestat(time.hour, time.minute) + if ((dim ~= nil) and (dim == "on")) then words.briPer=briPer if (words.briPer ~= nil and words.briPer < 3) then words.briPer=3 end - else + else words.briPer=nil - end - end - local tw=nil - local tcol=nil - if (mqttDispTemp ~= nil) then - tw, tcol = wc.temp(dw, rgbBuffer, invertRows) + end end wc = nil collectgarbage() diff --git a/mqtt.lua b/mqtt.lua index a8a9c3b..665c579 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -3,7 +3,8 @@ local m=nil local mqttConnected = false -- Temp: local t=nil -dispTemp=nil +local tw=nil +local tcol=nil function handleSingleCommand(client, topic, data) if (data == "ON") then @@ -118,9 +119,20 @@ function registerMqtt() handleSingleCommand(client, topic, data) elseif (topic == (mqttPrefix .. "/cmd/temp")) then if ( data == "" ) then - dispTemp = nil + tw=nil + tcol=nil else - dispTemp = tonumber(data) + -- generate the temperatur to display, once as it will not change + local dispTemp = tonumber(data) + collectgarbage() + mydofile("wordclock") + if (wc ~= nil) then + tw, tcol = wc.temp(dw, rgbBuffer, invertRows) + wc = nil + else + print("MQTT | wordclock failed") + end + end else -- Handle here the /cmd/# sublevel From 412db554a02779f890da49fb7c19601ee681516f Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 19:02:34 +0100 Subject: [PATCH 187/204] Simulated threads increased --- simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java index ad2f4b8..116aedd 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java @@ -19,7 +19,7 @@ import de.c3ma.ollo.LuaThreadTmr; */ public class ESP8266Tmr extends TwoArgFunction { - private static final int MAXTHREADS = 7; + private static final int MAXTHREADS = 10; private static LuaThreadTmr[] allThreads = new LuaThreadTmr[MAXTHREADS]; private static LuaThreadTmr[] dynamicThreads = new LuaThreadTmr[MAXTHREADS]; From ba1e93a67c5cf7cf38e2a120cba3ee599811caa4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 19:20:06 +0100 Subject: [PATCH 188/204] Simulation can subscribe to MQTT --- .../src/de/c3ma/ollo/mockup/ESP8266Mqtt.java | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java index b04bd48..757b78c 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java @@ -3,11 +3,13 @@ package de.c3ma.ollo.mockup; import java.util.UUID; import org.eclipse.paho.client.mqttv3.IMqttClient; +import org.eclipse.paho.client.mqttv3.IMqttMessageListener; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttPersistenceException; +import org.eclipse.paho.client.mqttv3.MqttSecurityException; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; @@ -19,7 +21,7 @@ import org.luaj.vm2.lib.VarArgFunction; * @author ollo * */ -public class ESP8266Mqtt extends TwoArgFunction { +public class ESP8266Mqtt extends TwoArgFunction implements IMqttMessageListener { private IMqttClient mMqttClient = null; @@ -68,7 +70,7 @@ public class ESP8266Mqtt extends TwoArgFunction { final String callback = varargs.arg(2).toString().toString(); final LuaValue code = varargs.arg(3); System.out.println("[MQTT] On " + this.client + " " + callback); - onMqtt.set("function", code); + onMqtt.set("on_" + callback, code); } else { for(int i=0; i <= varargs.narg(); i++) { System.err.println("[MQTT] On ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); @@ -119,11 +121,30 @@ public class ESP8266Mqtt extends TwoArgFunction { public LuaValue invoke(Varargs varargs) { final LuaTable onMqtt = new LuaTable(); - if (varargs.narg() == 2) { - System.out.println("[MQTT] subscribe "); + final int numberArg = varargs.narg(); + if (numberArg == 3) { + final String topic = varargs.arg(2).toString().toString(); + final int qos = varargs.arg(3).tonumber().toint(); + + try { + if (mMqttClient != null) { + mMqttClient.subscribe(topic, ESP8266Mqtt.this); + System.out.println("[MQTT] subscribe " + topic + " (QoS " + qos + ")"); + } else { + throw new Exception("Client not instantiated"); + } + } catch (MqttSecurityException e) { + System.err.println("[MQTT] subscribe " + topic + " (QoS " + qos + ") failed: " + e.getMessage()); + e.printStackTrace(); + } catch (MqttException e) { + System.err.println("[MQTT] subscribe " + topic + " (QoS " + qos + ") failed: " + e.getMessage()); + e.printStackTrace(); + } catch (Exception e) { + System.err.println("[MQTT] subscribe " + topic + " (QoS " + qos + ") failed: " + e.getMessage()); + } } else { - for(int i=0; i <= varargs.narg(); i++) { - System.err.println("[MQTT] subscribe ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); + for(int i=0; i <= numberArg; i++) { + System.err.println("[MQTT] subscribe ["+(i) + "/" + numberArg + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); } return LuaValue.NIL; } @@ -131,7 +152,7 @@ public class ESP8266Mqtt extends TwoArgFunction { } } -private class ConnectMqtt extends VarArgFunction { + private class ConnectMqtt extends VarArgFunction { public LuaValue invoke(Varargs varargs) { final LuaTable onMqtt = new LuaTable(); @@ -168,4 +189,9 @@ private class ConnectMqtt extends VarArgFunction { return onMqtt; } } + + @Override + public void messageArrived(String topic, MqttMessage message) throws Exception { + System.err.println("[MQTT] message "+ topic + " : " + message); + } } From e978e440633bfdce30a69e1e7855ab34d927ee25 Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 19:38:01 +0100 Subject: [PATCH 189/204] Mqtt subscription simulated --- .../src/de/c3ma/ollo/mockup/ESP8266Mqtt.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java index 757b78c..194bada 100644 --- a/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Mqtt.java @@ -10,6 +10,7 @@ import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttPersistenceException; import org.eclipse.paho.client.mqttv3.MqttSecurityException; +import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; @@ -23,7 +24,10 @@ import org.luaj.vm2.lib.VarArgFunction; */ public class ESP8266Mqtt extends TwoArgFunction implements IMqttMessageListener { + private static final String ON_PREFIX = "on_"; + private static final String MESSAGE = "message"; private IMqttClient mMqttClient = null; + final LuaTable onMqtt = new LuaTable(); @Override public LuaValue call(LuaValue modname, LuaValue env) { @@ -63,14 +67,13 @@ public class ESP8266Mqtt extends TwoArgFunction implements IMqttMessageListener } public LuaValue invoke(Varargs varargs) { - final LuaTable onMqtt = new LuaTable(); if (varargs.narg() == 3) { final LuaTable table = varargs.arg(1).checktable(); final String callback = varargs.arg(2).toString().toString(); final LuaValue code = varargs.arg(3); System.out.println("[MQTT] On " + this.client + " " + callback); - onMqtt.set("on_" + callback, code); + onMqtt.set(ON_PREFIX + callback, code); } else { for(int i=0; i <= varargs.narg(); i++) { System.err.println("[MQTT] On ["+(i) + "] (" + varargs.arg(i).typename() + ") " + varargs.arg(i).toString() ); @@ -192,6 +195,14 @@ public class ESP8266Mqtt extends TwoArgFunction implements IMqttMessageListener @Override public void messageArrived(String topic, MqttMessage message) throws Exception { - System.err.println("[MQTT] message "+ topic + " : " + message); + LuaValue messageCallback = onMqtt.get(ON_PREFIX + MESSAGE); + if (messageCallback != null) { + LuaValue call2 = messageCallback.call(LuaValue.NIL, + LuaValue.valueOf(topic), + LuaValue.valueOf(message.getPayload())); + //FIXME call the LUA code + } else { + System.err.println("[MQTT] message "+ topic + " : " + message + " without callback"); + } } } From 0bc446fc2af363f67e34ac2371824492c2f550fd Mon Sep 17 00:00:00 2001 From: Ollo Date: Mon, 1 Nov 2021 19:49:56 +0100 Subject: [PATCH 190/204] More debug messages when receiving a temperature --- mqtt.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 665c579..d86dc79 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -117,10 +117,11 @@ function registerMqtt() print(data) if (topic == (mqttPrefix .. "/cmd/single")) then handleSingleCommand(client, topic, data) - elseif (topic == (mqttPrefix .. "/cmd/temp")) then - if ( data == "" ) then - tw=nil - tcol=nil + elseif (topic == (mqttPrefix .. "/cmd/temp")) then + if (( data == "" ) or (data == nil)) then + tw=nil + tcol=nil + print("MQTT | wordclock failed") else -- generate the temperatur to display, once as it will not change local dispTemp = tonumber(data) @@ -129,10 +130,10 @@ function registerMqtt() if (wc ~= nil) then tw, tcol = wc.temp(dw, rgbBuffer, invertRows) wc = nil + print("MQTT | generated words for: " + tostring(dispTemp)) else print("MQTT | wordclock failed") end - end else -- Handle here the /cmd/# sublevel From 96b690d90b8dc1fe475123cd5ec76752c2483ad4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 28 Nov 2021 09:49:12 +0100 Subject: [PATCH 191/204] Start DS18B20 initialization; uniq names before creating _diet files --- main.lua | 1 - mqtt.lua | 24 ++++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/main.lua b/main.lua index 398c17f..7f7f839 100644 --- a/main.lua +++ b/main.lua @@ -67,7 +67,6 @@ function displayTime() end dw = nil collectgarbage() - print("dw: " .. tostring(node.heap())) -- cleanup i=nil diff --git a/mqtt.lua b/mqtt.lua index d86dc79..bebb84f 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -73,9 +73,12 @@ function readTemp() local temp1=0 if (sensors >= 1) then temp1=t.read(addrs[0]) + else + print("No sensor DS18B20 found") end return temp1 else + print("No DS18B20 lib") return nil end end @@ -200,7 +203,7 @@ function startMqttClient() registerMqtt() print "Started MQTT client" local dstimer = tmr.create() - dstimer:register(123, tmr.ALARM_SINGLE, function (t) + dstimer:register(123, tmr.ALARM_SINGLE, function (kTemp) if (file.open("ds18b20_diet.lc")) then t=require("ds18b20_diet") t.setup(2) -- GPIO4 @@ -208,24 +211,25 @@ function startMqttClient() print "Setup temperature" end end) - local oldBrightness=0 - oldTemp=0 + dstimer:start() + local oldBrightness=0 + oldTemp=0 local mqtttimer = tmr.create() - mqtttimer:register(5001, tmr.ALARM_AUTO, function (t) + mqtttimer:register(5001, tmr.ALARM_AUTO, function (kTemp) if (mqttConnected) then - local temp = nil + local temperatur = nil if (t ~= nil) then - temp=readTemp() + temperatur=readTemp() end if (oldBrightness ~= briPer) then m:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) - elseif (temp ~= nil and temp ~= oldTemp) then - oldTemp = temp - m:publish(mqttPrefix .. "/temp", tostring(temp/100).."."..tostring(temp%100), 0, 0) + oldBrightness = briPer + elseif (temperatur ~= nil and temperatur ~= oldTemp) then + oldTemp = temperatur + m:publish(mqttPrefix .. "/temp", tostring(temperatur/100).."."..tostring(temperatur%100), 0, 0) else m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) end - oldBrightness = briPer end end) mqtttimer:start() From ffa3bb69de9a8e43d39bc62dea5f848d56c85939 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 28 Nov 2021 12:19:19 +0100 Subject: [PATCH 192/204] Load DS18B20 library only, when needed --- mqtt.lua | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index bebb84f..52c7c46 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -65,14 +65,14 @@ function parseBgColor(data, row, per) end end -function readTemp() - if (t ~= nil) then - addrs=t.addrs() +function readTemp(ds18b20) + if (ds18b20 ~= nil) then + addrs=ds18b20.addrs() -- Total DS18B20 numbers sensors=table.getn(addrs) local temp1=0 if (sensors >= 1) then - temp1=t.read(addrs[0]) + temp1=ds18b20.read(addrs[0]) else print("No sensor DS18B20 found") end @@ -92,7 +92,7 @@ function reConnectMqtt() -- subscribe topic with qos = 0 m:subscribe(mqttPrefix .. "/cmd/#", 0) local tmr1 = tmr.create() - tmr1:register(1000, tmr.ALARM_SINGLE, function (t) + tmr1:register(1000, tmr.ALARM_SINGLE, function (dummyTemp) -- publish a message with data = hello, QoS = 0, retain = 0 m:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) local red = string.byte(colorBg,2) @@ -205,9 +205,7 @@ function startMqttClient() local dstimer = tmr.create() dstimer:register(123, tmr.ALARM_SINGLE, function (kTemp) if (file.open("ds18b20_diet.lc")) then - t=require("ds18b20_diet") - t.setup(2) -- GPIO4 - readTemp() -- read once, to setup chip + t=true print "Setup temperature" end end) @@ -215,20 +213,29 @@ function startMqttClient() local oldBrightness=0 oldTemp=0 local mqtttimer = tmr.create() - mqtttimer:register(5001, tmr.ALARM_AUTO, function (kTemp) + mqtttimer:register(6001, tmr.ALARM_AUTO, function (kTemp) if (mqttConnected) then local temperatur = nil - if (t ~= nil) then - temperatur=readTemp() - end if (oldBrightness ~= briPer) then m:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) oldBrightness = briPer - elseif (temperatur ~= nil and temperatur ~= oldTemp) then - oldTemp = temperatur - m:publish(mqttPrefix .. "/temp", tostring(temperatur/100).."."..tostring(temperatur%100), 0, 0) else - m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) + if (t ~= nil) then + local ds18b20=require("ds18b20_diet") + ds18b20.setup(2) -- GPIO4 + readTemp(ds18b20) -- read once, to setup chip + temperatur=readTemp(ds18b20) + if (temperatur == 85) then + temperatur=nil + end + ds18b20=nil + end + if (temperatur ~= nil and temperatur ~= oldTemp) then + oldTemp = temperatur + m:publish(mqttPrefix .. "/temp", tostring(temperatur/100).."."..tostring(temperatur%100), 0, 0) + else + m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) + end end end end) From 8bc3b0cb666faf9a576001f257070efb717af8c9 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sun, 28 Nov 2021 19:02:29 +0100 Subject: [PATCH 193/204] Read temperatur, when more than 12k RAM is free --- mqtt.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 52c7c46..8d90add 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -215,12 +215,13 @@ function startMqttClient() local mqtttimer = tmr.create() mqtttimer:register(6001, tmr.ALARM_AUTO, function (kTemp) if (mqttConnected) then + local heapusage = node.heap() local temperatur = nil if (oldBrightness ~= briPer) then m:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) oldBrightness = briPer else - if (t ~= nil) then + if ((t ~= nil) and (heapusage > 12000)) then local ds18b20=require("ds18b20_diet") ds18b20.setup(2) -- GPIO4 readTemp(ds18b20) -- read once, to setup chip @@ -234,7 +235,7 @@ function startMqttClient() oldTemp = temperatur m:publish(mqttPrefix .. "/temp", tostring(temperatur/100).."."..tostring(temperatur%100), 0, 0) else - m:publish(mqttPrefix .. "/heap", tostring(node.heap()), 0, 0) + m:publish(mqttPrefix .. "/heap", tostring(heapusage), 0, 0) end end end From b8f037d61c18e243bee0e4a3e7baf0575509683f Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 2 Dec 2021 22:53:38 +0100 Subject: [PATCH 194/204] Clear Memory, and try next time again --- mqtt.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index 8d90add..c34a928 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -206,7 +206,7 @@ function startMqttClient() dstimer:register(123, tmr.ALARM_SINGLE, function (kTemp) if (file.open("ds18b20_diet.lc")) then t=true - print "Setup temperature" + print "Setup temperatur" end end) dstimer:start() @@ -224,16 +224,18 @@ function startMqttClient() if ((t ~= nil) and (heapusage > 12000)) then local ds18b20=require("ds18b20_diet") ds18b20.setup(2) -- GPIO4 - readTemp(ds18b20) -- read once, to setup chip + readTemp(ds18b20) -- read once, to setup chip temperatur=readTemp(ds18b20) - if (temperatur == 85) then + if (temperatur == 8500) then temperatur=nil end ds18b20=nil + else + collectgarbage() end if (temperatur ~= nil and temperatur ~= oldTemp) then oldTemp = temperatur - m:publish(mqttPrefix .. "/temp", tostring(temperatur/100).."."..tostring(temperatur%100), 0, 0) + m:publish(mqttPrefix .. "/temp", tostring(temperatur/100)..".".. tostring(temperatur%100), 0, 0) else m:publish(mqttPrefix .. "/heap", tostring(heapusage), 0, 0) end From fd85314d3703f0ca3312e34671a4e082763d34df Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 4 Dec 2021 13:04:12 +0100 Subject: [PATCH 195/204] No actions on low memory --- main.lua | 11 ++++-- mqtt.lua | 113 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 72 insertions(+), 52 deletions(-) diff --git a/main.lua b/main.lua index 7f7f839..323479d 100644 --- a/main.lua +++ b/main.lua @@ -11,7 +11,6 @@ function syncTimeFromInternet() syncRunning=true sntp.sync(sntpserverhostname, function(sec,usec,server) - print('sync', sec, usec, server) syncRunning=nil end, function() @@ -129,10 +128,13 @@ function normalOperation() end setupCounter=setupCounter-1 elseif ( (alive % 120) == 0) then - -- sync the time every 5 minutes - syncTimeFromInternet() + -- sync the time every 5 minutes + local heapusage = node.heap() + if (heapusage > 12000) then + syncTimeFromInternet() + end + heapusage=nil alive = alive + 1 - collectgarbage() else displayTime() alive = alive + 1 @@ -158,6 +160,7 @@ function normalOperation() ws2812.write(rgbBuffer) print("Fallback no time displayed") end + collectgarbage() -- Feed the system watchdog. tmr.wdclr() end) diff --git a/mqtt.lua b/mqtt.lua index c34a928..e426b8f 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -1,18 +1,21 @@ --- Global variable -local m=nil -local mqttConnected = false --- Temp: -local t=nil -local tw=nil -local tcol=nil +-- Global Variables +-- Display Temp +tw=nil +tcol=nil +-- Module Variables +-- Mqtt variable +local mMqttClient=nil +local mMqttConnected = false +-- Read Temp +local mOldTemp=nil function handleSingleCommand(client, topic, data) if (data == "ON") then briPer=100 - m:publish(mqttPrefix .. "/clock", "ON", 0, 0) + mMqttClient:publish(mqttPrefix .. "/clock", "ON", 0, 0) elseif (data == "OFF") then briPer=0 - m:publish(mqttPrefix .. "/clock", "OFF", 0, 0) + mMqttClient:publish(mqttPrefix .. "/clock", "OFF", 0, 0) elseif ((data:sub(1,1) == "#" and data:len() == 7) or (string.match(data, "%d+,%d+,%d+"))) then local red=0 local green=0 @@ -26,11 +29,11 @@ function handleSingleCommand(client, topic, data) end colorBg=string.char(green * briPer / 100, red * briPer / 100, blue * briPer / 100) print("Updated BG: " .. tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue) ) - m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) + mMqttClient:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) else if (tonumber(data) >= 0 and tonumber(data) <= 100) then briPer=tonumber(data) - m:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) + mMqttClient:publish(mqttPrefix .. "/clock", tostring(data), 0, 0) else print "Unknown MQTT command" end @@ -54,7 +57,7 @@ function parseBgColor(data, row, per) red, green, blue = string.match(data, "(%d+),(%d+),(%d+)") end if ((red ~= nil) and (green ~= nil) and (blue ~= nil) ) then - m:publish(mqttPrefix .. "/"..row, tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) + mMqttClient:publish(mqttPrefix .. "/"..row, tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) if (per ~= nil) then return string.char(green * per / 100, red * per / 100, blue * per / 100) else @@ -67,9 +70,9 @@ end function readTemp(ds18b20) if (ds18b20 ~= nil) then - addrs=ds18b20.addrs() + local addrs=ds18b20.addrs() -- Total DS18B20 numbers - sensors=table.getn(addrs) + local sensors=table.getn(addrs) local temp1=0 if (sensors >= 1) then temp1=ds18b20.read(addrs[0]) @@ -85,39 +88,47 @@ end -- Connect or reconnect to mqtt server function reConnectMqtt() - if (not mqttConnected) then - m:connect(mqttServer, 1883, false, function(c) + if (not mMqttConnected) then + mMqttClient:connect(mqttServer, 1883, false, function(c) print("MQTT is connected") - mqttConnected = true + mMqttConnected = true -- subscribe topic with qos = 0 - m:subscribe(mqttPrefix .. "/cmd/#", 0) + mMqttClient:subscribe(mqttPrefix .. "/cmd/#", 0) local tmr1 = tmr.create() tmr1:register(1000, tmr.ALARM_SINGLE, function (dummyTemp) -- publish a message with data = hello, QoS = 0, retain = 0 - m:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) + mMqttClient:publish(mqttPrefix .. "/ip", tostring(wifi.sta.getip()), 0, 0) local red = string.byte(colorBg,2) local green = string.byte(colorBg,1) local blue = string.byte(colorBg,3) - m:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) + mMqttClient:publish(mqttPrefix .. "/background", tostring(red) .. "," .. tostring(green) .. "," .. tostring(blue), 0, 0) tmr1:unregister() + tmr1=nil end) tmr1:start() end, function(client, reason) print("failed reason: " .. reason) - mqttConnected = false + mMqttConnected = false end) end end -- MQTT extension function registerMqtt() - m = mqtt.Client("wordclock", 120) + mMqttClient = mqtt.Client("wordclock", 120) -- on publish message receive event - m:on("message", function(client, topic, data) - print("MQTT " .. topic .. ":" ) + mMqttClient:on("message", function(client, topic, data) + collectgarbage() if data ~= nil then - print(data) + local heapusage = node.heap() + if (heapusage < 12000) then + print("Skip " .. topic .. ":" .. data .. "; heap:" .. heapusage) + heapusage=nil + return + end + heapusage=nil + print("MQTT " .. topic .. ":" .. data) if (topic == (mqttPrefix .. "/cmd/single")) then handleSingleCommand(client, topic, data) elseif (topic == (mqttPrefix .. "/cmd/temp")) then @@ -146,7 +157,7 @@ function registerMqtt() print("Stop Mqtt and Temp") m=nil t=nil - mqttConnected = false + mMqttConnected = false if (mlt ~= nil) then mlt:unregister() else @@ -178,7 +189,6 @@ function registerMqtt() for i=1,10,1 do if (string.match(topic, "row".. tostring(i) .."$")) then rowbgColor[i] = parseBgColor(data, "row" .. tostring(i), briPer) - print("Updated row" .. tostring(i) ) return end end @@ -186,40 +196,45 @@ function registerMqtt() end end end) - m:on("offline", function(client) + -- do something + mMqttClient:on("offline", function(client) print("MQTT Disconnected") - mqttConnected = false - end - ) + mMqttConnected = false + collectgarbage() + end) reConnectMqtt() end function connectedMqtt() - return mqttConnected + return mMqttConnected end function startMqttClient() if (mqttServer ~= nil and mqttPrefix ~= nil) then registerMqtt() print "Started MQTT client" - local dstimer = tmr.create() - dstimer:register(123, tmr.ALARM_SINGLE, function (kTemp) + local lSetupTimer = tmr.create() + lSetupTimer:register(123, tmr.ALARM_SINGLE, function (kTemp) if (file.open("ds18b20_diet.lc")) then t=true print "Setup temperatur" end end) - dstimer:start() - local oldBrightness=0 - oldTemp=0 - local mqtttimer = tmr.create() - mqtttimer:register(6001, tmr.ALARM_AUTO, function (kTemp) - if (mqttConnected) then + lSetupTimer:start() + local loldBrightness=0 + mOldTemp=0 + local lMqttTimer = tmr.create() + -- Check every 12 seconds + lMqttTimer:register(12321, tmr.ALARM_AUTO, function (kTemp) + if (mMqttConnected) then + -- Cleanup the initialization stuff + lSetupTimer=nil + -- Do the action local heapusage = node.heap() local temperatur = nil - if (oldBrightness ~= briPer) then - m:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) - oldBrightness = briPer + if (loldBrightness ~= briPer) then + mMqttClient:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) + loldBrightness = briPer else if ((t ~= nil) and (heapusage > 12000)) then local ds18b20=require("ds18b20_diet") @@ -233,16 +248,18 @@ function startMqttClient() else collectgarbage() end - if (temperatur ~= nil and temperatur ~= oldTemp) then - oldTemp = temperatur - m:publish(mqttPrefix .. "/temp", tostring(temperatur/100)..".".. tostring(temperatur%100), 0, 0) + if (temperatur ~= nil and temperatur ~= mOldTemp) then + mOldTemp = temperatur + mMqttClient:publish(mqttPrefix .. "/temp", tostring(temperatur/100)..".".. tostring(temperatur%100), 0, 0) else - m:publish(mqttPrefix .. "/heap", tostring(heapusage), 0, 0) + mMqttClient:publish(mqttPrefix .. "/heap", tostring(heapusage), 0, 0) end end + heapusage=nil + temperatur=nil end end) - mqtttimer:start() + lMqttTimer:start() end end From 3b2554ee53aff5f6b237cffee84d09622e9bd134 Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 4 Dec 2021 13:07:29 +0100 Subject: [PATCH 196/204] Lower brightness at start --- init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index 111f403..68aff81 100644 --- a/init.lua +++ b/init.lua @@ -6,10 +6,10 @@ local MAXLEDS=110 local counter1=0 ws2812.write(string.char(0,0,0):rep(114)) local bootledtimer = tmr.create() -bootledtimer:register(100, tmr.ALARM_AUTO, function (t) +bootledtimer:register(75, tmr.ALARM_AUTO, function (t) counter1=counter1+1 spaceLeds = math.max(MAXLEDS - (counter1*2), 0) - ws2812.write(string.char(32,0,0):rep(counter1) .. string.char(0,0,0):rep(spaceLeds) .. string.char(0,0,16):rep(counter1)) + ws2812.write(string.char(16,0,0):rep(counter1) .. string.char(0,0,0):rep(spaceLeds) .. string.char(0,0,8):rep(counter1)) if ((counter1*2) > 114) then t:unregister() end From 5703c2757648e92d22326396a28eada5998174bf Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 6 Jan 2022 16:01:27 +0100 Subject: [PATCH 197/204] Reduced necessary memory --- mqtt.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index e426b8f..5cc4106 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -122,7 +122,7 @@ function registerMqtt() collectgarbage() if data ~= nil then local heapusage = node.heap() - if (heapusage < 12000) then + if (heapusage < 11000) then print("Skip " .. topic .. ":" .. data .. "; heap:" .. heapusage) heapusage=nil return @@ -236,7 +236,7 @@ function startMqttClient() mMqttClient:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) loldBrightness = briPer else - if ((t ~= nil) and (heapusage > 12000)) then + if ((t ~= nil) and (heapusage > 11900)) then local ds18b20=require("ds18b20_diet") ds18b20.setup(2) -- GPIO4 readTemp(ds18b20) -- read once, to setup chip @@ -245,7 +245,7 @@ function startMqttClient() temperatur=nil end ds18b20=nil - else + else collectgarbage() end if (temperatur ~= nil and temperatur ~= mOldTemp) then From 40fce7763e1b190b056568e597019a06b3dee6d6 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 6 Jan 2022 16:35:41 +0100 Subject: [PATCH 198/204] Use a timeout to activate Telnet server --- tools/remoteFlash.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/remoteFlash.sh b/tools/remoteFlash.sh index 2bdeb47..a46fd35 100755 --- a/tools/remoteFlash.sh +++ b/tools/remoteFlash.sh @@ -62,9 +62,14 @@ if [ $? -ne 0 ]; then echo "Entered Wordclock address: $MQTTPREFIX on $MQTTSERVER is NOT online" exit 2 fi -echo "Activate Telnet server" -mosquitto_pub -h $MQTTSERVER -t "$MQTTPREFIX/cmd/telnet" -m "a" -TELNETIP=$(mosquitto_sub -h $MQTTSERVER -t "$MQTTPREFIX/telnet" -C 1) +echo "Activate Telnet server ..." +TELNETIP="empty" +while [ "$TELNETIP" = "empty" ]; do + date + mosquitto_pub -h $MQTTSERVER -t "$MQTTPREFIX/cmd/telnet" -m "a" + TELNETIP=$(mosquitto_sub -h $MQTTSERVER -t "$MQTTPREFIX/telnet" -C 1 -W 30) +done + echo "Upgrading $MQTTPREFIX via telenet on $TELNETIP ..." sleep 1 echo "if (mlt ~= nil) then mlt:unregister() end" > $UPGRADEPREP From f35da0a3c807f8dae9a056057f2162fcc01b9935 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 6 Jan 2022 16:46:33 +0100 Subject: [PATCH 199/204] Upload into temporary file; Rename it after upload was finished --- tools/tcpFlash.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/tcpFlash.py b/tools/tcpFlash.py index b2a2be1..f66ab57 100755 --- a/tools/tcpFlash.py +++ b/tools/tcpFlash.py @@ -78,9 +78,8 @@ def main(nodeip, luafile, volatile=None, outfile=None): outfile=luafile else: print "Flashing " + luafile + " as " + outfile - sendCmd(s, "file.remove(\"" + outfile +"\");", True) sendCmd(s, "w= file.writeline", True) - sendCmd(s, "file.open(\"" + outfile + "\",\"w+\");", True) + sendCmd(s, "file.open(\"temp.lua\",\"w+\");", True) else: print "Executing " + luafile + " on nodemcu" @@ -114,6 +113,11 @@ def main(nodeip, luafile, volatile=None, outfile=None): if (not sendCmd(s, "file.close();")): print "Cannot close the file" sys.exit(4) + + sendCmd(s, "file.remove(\"" + outfile +"\");", True) + if (not sendCmd(s, "file.rename(\"temp.lua\",\""+ outfile + "\")")): + print "Cannot move temporary file to " + outfile + # Check if the file exists: if (not sendRecv(s, "=file.exists(\"" + outfile + "\")", "true")): From 7f6c9689ea259329bac1bf494f10a754c25129a4 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 6 Jan 2022 16:50:19 +0100 Subject: [PATCH 200/204] Temperatur measurement needs these amount of resources --- mqtt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 5cc4106..f20eb10 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -236,7 +236,7 @@ function startMqttClient() mMqttClient:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) loldBrightness = briPer else - if ((t ~= nil) and (heapusage > 11900)) then + if ((t ~= nil) and (heapusage > 12000)) then local ds18b20=require("ds18b20_diet") ds18b20.setup(2) -- GPIO4 readTemp(ds18b20) -- read once, to setup chip From a98a30c06b55bf70714cbfd2012938d7a070f12b Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 20 Jan 2022 21:12:54 +0100 Subject: [PATCH 201/204] Measure temperature every minute --- mqtt.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index f20eb10..2f69f3d 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -224,6 +224,7 @@ function startMqttClient() local loldBrightness=0 mOldTemp=0 local lMqttTimer = tmr.create() + local tempCounter=0 -- Check every 12 seconds lMqttTimer:register(12321, tmr.ALARM_AUTO, function (kTemp) if (mMqttConnected) then @@ -236,7 +237,7 @@ function startMqttClient() mMqttClient:publish(mqttPrefix .. "/brightness", tostring(briPer), 0, 0) loldBrightness = briPer else - if ((t ~= nil) and (heapusage > 12000)) then + if ((t ~= nil) and (heapusage > 11900) and (tempCounter > 10)) then local ds18b20=require("ds18b20_diet") ds18b20.setup(2) -- GPIO4 readTemp(ds18b20) -- read once, to setup chip @@ -245,14 +246,17 @@ function startMqttClient() temperatur=nil end ds18b20=nil - else - collectgarbage() - end + tempCounter = 0 + else + tempCounter = tempCounter + 1 + end + collectgarbage() if (temperatur ~= nil and temperatur ~= mOldTemp) then mOldTemp = temperatur mMqttClient:publish(mqttPrefix .. "/temp", tostring(temperatur/100)..".".. tostring(temperatur%100), 0, 0) else mMqttClient:publish(mqttPrefix .. "/heap", tostring(heapusage), 0, 0) + collectgarbage() end end heapusage=nil From 042bef0bf7b0c8fc4acb9377be23dc58d653a965 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 20 Jan 2022 21:49:35 +0100 Subject: [PATCH 202/204] Unload temperatur sensor module, after usage --- mqtt.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mqtt.lua b/mqtt.lua index 2f69f3d..39b8aa8 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -246,6 +246,8 @@ function startMqttClient() temperatur=nil end ds18b20=nil + ds18b20_diet=nil + package.loaded["ds18b20_diet"]=nil tempCounter = 0 else tempCounter = tempCounter + 1 From 2322276745a91c6d95ebd484c1408601c7dac156 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 20 Jan 2022 21:58:10 +0100 Subject: [PATCH 203/204] Increase mqtt cycle time --- mqtt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt.lua b/mqtt.lua index 39b8aa8..bcb38b5 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -226,7 +226,7 @@ function startMqttClient() local lMqttTimer = tmr.create() local tempCounter=0 -- Check every 12 seconds - lMqttTimer:register(12321, tmr.ALARM_AUTO, function (kTemp) + lMqttTimer:register(6321, tmr.ALARM_AUTO, function (kTemp) if (mMqttConnected) then -- Cleanup the initialization stuff lSetupTimer=nil From aba8e214061b6b89ad19e69dcd6982291bb393a1 Mon Sep 17 00:00:00 2001 From: Ollo Date: Thu, 20 Jan 2022 22:06:03 +0100 Subject: [PATCH 204/204] Always publish the temperatur --- mqtt.lua | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mqtt.lua b/mqtt.lua index bcb38b5..330488e 100644 --- a/mqtt.lua +++ b/mqtt.lua @@ -6,8 +6,6 @@ tcol=nil -- Mqtt variable local mMqttClient=nil local mMqttConnected = false --- Read Temp -local mOldTemp=nil function handleSingleCommand(client, topic, data) if (data == "ON") then @@ -222,7 +220,6 @@ function startMqttClient() end) lSetupTimer:start() local loldBrightness=0 - mOldTemp=0 local lMqttTimer = tmr.create() local tempCounter=0 -- Check every 12 seconds @@ -253,8 +250,7 @@ function startMqttClient() tempCounter = tempCounter + 1 end collectgarbage() - if (temperatur ~= nil and temperatur ~= mOldTemp) then - mOldTemp = temperatur + if (temperatur ~= nil) then mMqttClient:publish(mqttPrefix .. "/temp", tostring(temperatur/100)..".".. tostring(temperatur%100), 0, 0) else mMqttClient:publish(mqttPrefix .. "/heap", tostring(heapusage), 0, 0)