Compare commits
3 Commits
18710fa443
...
bbed68cff2
Author | SHA1 | Date | |
---|---|---|---|
bbed68cff2 | |||
60ba2c59e7 | |||
a8e26be242 |
5
code/C/.clang-format
Normal file
5
code/C/.clang-format
Normal file
@ -0,0 +1,5 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 2
|
||||
ColumnLimit: 132
|
||||
SortIncludes: Never
|
18
code/C/System/check-root-user.c
Normal file
18
code/C/System/check-root-user.c
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* https://man.openbsd.org/getuid
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void main(int argc, char const *argv[]) {
|
||||
uid_t user = getuid();
|
||||
uid_t privs = geteuid();
|
||||
printf("User: %u\n", user);
|
||||
printf("Privs: %u\n", privs);
|
||||
|
||||
puts("::");
|
||||
|
||||
char *login = getlogin();
|
||||
printf("%s\n", login);
|
||||
}
|
@ -3,10 +3,8 @@ atomic_bool running = true;
|
||||
#define PORT 8000
|
||||
#define PREFIX "/api"
|
||||
|
||||
int callback_default(const struct _u_request *request,
|
||||
struct _u_response *response, void *user_data);
|
||||
int callback_all_test_foo(const struct _u_request *request,
|
||||
struct _u_response *response, void *user_data);
|
||||
int callback_default(const struct _u_request *request, struct _u_response *response, void *user_data);
|
||||
int callback_all_test_foo(const struct _u_request *request, struct _u_response *response, void *user_data);
|
||||
|
||||
void *thread_server(void *vargp) {
|
||||
int ret;
|
||||
@ -18,10 +16,8 @@ void *thread_server(void *vargp) {
|
||||
|
||||
instance.max_post_body_size = 1024;
|
||||
|
||||
ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, "/param/:name", 0,
|
||||
&callback_all_test_foo, "user data 1");
|
||||
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/param/:name", 0,
|
||||
&callback_all_test_foo, "user data 2");
|
||||
ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, "/param/:name", 0, &callback_all_test_foo, "user data 1");
|
||||
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/param/:name", 0, &callback_all_test_foo, "user data 2");
|
||||
|
||||
ulfius_set_default_endpoint(&instance, &callback_default, NULL);
|
||||
|
||||
@ -41,18 +37,15 @@ void *thread_server(void *vargp) {
|
||||
ulfius_clean_instance(&instance);
|
||||
}
|
||||
|
||||
int callback_default(const struct _u_request *request,
|
||||
struct _u_response *response, void *user_data) {
|
||||
int callback_default(const struct _u_request *request, struct _u_response *response, void *user_data) {
|
||||
(void)(request);
|
||||
(void)(user_data);
|
||||
ulfius_set_string_body_response(response, 404,
|
||||
"Page not found, do what you want");
|
||||
ulfius_set_string_body_response(response, 404, "Page not found, do what you want");
|
||||
|
||||
return U_CALLBACK_CONTINUE;
|
||||
}
|
||||
|
||||
int callback_all_test_foo(const struct _u_request *request,
|
||||
struct _u_response *response, void *user_data) {
|
||||
int callback_all_test_foo(const struct _u_request *request, struct _u_response *response, void *user_data) {
|
||||
// url_params = request->map_url
|
||||
// post_params = request->map_post_body
|
||||
|
||||
|
@ -2,128 +2,125 @@
|
||||
|
||||
#include "webui.h"
|
||||
|
||||
void my_function_string(webui_event_t* e) {
|
||||
void my_function_string(webui_event_t *e) {
|
||||
|
||||
// JavaScript:
|
||||
// webui_fn('MyID_One', 'Hello');
|
||||
// JavaScript:
|
||||
// webui_fn('MyID_One', 'Hello');
|
||||
|
||||
const char* str = webui_get_string(e);
|
||||
printf("my_function_string: %s\n", str); // Hello
|
||||
const char *str = webui_get_string(e);
|
||||
printf("my_function_string: %s\n", str); // Hello
|
||||
|
||||
// Need Multiple Arguments?
|
||||
//
|
||||
// WebUI support only one argument. To get multiple arguments
|
||||
// you can send a JSON string from JavaScript then decode it.
|
||||
// Example:
|
||||
//
|
||||
// my_json = my_json_decoder(str);
|
||||
// foo = my_json[0];
|
||||
// bar = my_json[1];
|
||||
// Need Multiple Arguments?
|
||||
//
|
||||
// WebUI support only one argument. To get multiple arguments
|
||||
// you can send a JSON string from JavaScript then decode it.
|
||||
// Example:
|
||||
//
|
||||
// my_json = my_json_decoder(str);
|
||||
// foo = my_json[0];
|
||||
// bar = my_json[1];
|
||||
}
|
||||
|
||||
void my_function_integer(webui_event_t* e) {
|
||||
void my_function_integer(webui_event_t *e) {
|
||||
|
||||
// JavaScript:
|
||||
// webui_fn('MyID_Two', 123456789);
|
||||
// JavaScript:
|
||||
// webui_fn('MyID_Two', 123456789);
|
||||
|
||||
long long number = webui_get_int(e);
|
||||
printf("my_function_integer: %lld\n", number); // 123456789
|
||||
long long number = webui_get_int(e);
|
||||
printf("my_function_integer: %lld\n", number); // 123456789
|
||||
}
|
||||
|
||||
void my_function_boolean(webui_event_t* e) {
|
||||
void my_function_boolean(webui_event_t *e) {
|
||||
|
||||
// JavaScript:
|
||||
// webui_fn('MyID_Three', true);
|
||||
// JavaScript:
|
||||
// webui_fn('MyID_Three', true);
|
||||
|
||||
bool status = webui_get_bool(e); // True
|
||||
if(status)
|
||||
printf("my_function_boolean: True\n");
|
||||
else
|
||||
printf("my_function_boolean: False\n");
|
||||
bool status = webui_get_bool(e); // True
|
||||
if (status)
|
||||
printf("my_function_boolean: True\n");
|
||||
else
|
||||
printf("my_function_boolean: False\n");
|
||||
}
|
||||
|
||||
void my_function_with_response(webui_event_t* e) {
|
||||
void my_function_with_response(webui_event_t *e) {
|
||||
|
||||
// JavaScript:
|
||||
// const result = webui_fn('MyID_Four', number);
|
||||
// JavaScript:
|
||||
// const result = webui_fn('MyID_Four', number);
|
||||
|
||||
long long number = webui_get_int(e);
|
||||
number = number * 2;
|
||||
printf("my_function_with_response: %lld\n", number);
|
||||
long long number = webui_get_int(e);
|
||||
number = number * 2;
|
||||
printf("my_function_with_response: %lld\n", number);
|
||||
|
||||
// Send back the response to JavaScript
|
||||
webui_return_int(e, number);
|
||||
// Send back the response to JavaScript
|
||||
webui_return_int(e, number);
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
// HTML
|
||||
const char* my_html =
|
||||
"<html>"
|
||||
" <head>"
|
||||
" <title>Call C from JavaScript Example</title>"
|
||||
" <style>"
|
||||
" body {"
|
||||
" color: white;"
|
||||
" background: #0F2027;"
|
||||
" text-align: center;"
|
||||
" font-size: 16px;"
|
||||
" font-family: sans-serif;"
|
||||
" }"
|
||||
" </style>"
|
||||
" </head>"
|
||||
" <body>"
|
||||
" <h2>WebUI - Call C from JavaScript Example</h2>"
|
||||
" <p>Call C function with argument (<em>See the logs in your terminal</em>)</p>"
|
||||
" <br>"
|
||||
" <button onclick=\"webui_fn('MyID_One', 'Hello');\">Call my_function_string()</button>"
|
||||
" <br>"
|
||||
" <br>"
|
||||
" <button onclick=\"webui_fn('MyID_Two', 123456789);\">Call my_function_integer()</button>"
|
||||
" <br>"
|
||||
" <br>"
|
||||
" <button onclick=\"webui_fn('MyID_Three', true);\">Call my_function_boolean()</button>"
|
||||
" <br>"
|
||||
" <br>"
|
||||
" <p>Call C function and wait for the response</p>"
|
||||
" <br>"
|
||||
" <button onclick=\"MyJS();\">Call my_function_with_response()</button>"
|
||||
" <br>"
|
||||
" <br>"
|
||||
" <input type=\"text\" id=\"MyInputID\" value=\"2\">"
|
||||
" <script>"
|
||||
" function MyJS() {"
|
||||
" const MyInput = document.getElementById('MyInputID');"
|
||||
" const number = MyInput.value;"
|
||||
" webui_fn('MyID_Four', number).then((response) => {"
|
||||
" MyInput.value = response;"
|
||||
" });"
|
||||
" }"
|
||||
" </script>"
|
||||
" <script src=\"/webui.js\"></script>"
|
||||
" </body>"
|
||||
"</html>";
|
||||
// HTML
|
||||
const char *my_html = "<html>"
|
||||
" <head>"
|
||||
" <title>Call C from JavaScript Example</title>"
|
||||
" <style>"
|
||||
" body {"
|
||||
" color: white;"
|
||||
" background: #0F2027;"
|
||||
" text-align: center;"
|
||||
" font-size: 16px;"
|
||||
" font-family: sans-serif;"
|
||||
" }"
|
||||
" </style>"
|
||||
" </head>"
|
||||
" <body>"
|
||||
" <h2>WebUI - Call C from JavaScript Example</h2>"
|
||||
" <p>Call C function with argument (<em>See the logs in your terminal</em>)</p>"
|
||||
" <br>"
|
||||
" <button onclick=\"webui_fn('MyID_One', 'Hello');\">Call my_function_string()</button>"
|
||||
" <br>"
|
||||
" <br>"
|
||||
" <button onclick=\"webui_fn('MyID_Two', 123456789);\">Call my_function_integer()</button>"
|
||||
" <br>"
|
||||
" <br>"
|
||||
" <button onclick=\"webui_fn('MyID_Three', true);\">Call my_function_boolean()</button>"
|
||||
" <br>"
|
||||
" <br>"
|
||||
" <p>Call C function and wait for the response</p>"
|
||||
" <br>"
|
||||
" <button onclick=\"MyJS();\">Call my_function_with_response()</button>"
|
||||
" <br>"
|
||||
" <br>"
|
||||
" <input type=\"text\" id=\"MyInputID\" value=\"2\">"
|
||||
" <script>"
|
||||
" function MyJS() {"
|
||||
" const MyInput = document.getElementById('MyInputID');"
|
||||
" const number = MyInput.value;"
|
||||
" webui_fn('MyID_Four', number).then((response) => {"
|
||||
" MyInput.value = response;"
|
||||
" });"
|
||||
" }"
|
||||
" </script>"
|
||||
" <script src=\"/webui.js\"></script>"
|
||||
" </body>"
|
||||
"</html>";
|
||||
|
||||
// Create a window
|
||||
size_t my_window = webui_new_window();
|
||||
// Create a window
|
||||
size_t my_window = webui_new_window();
|
||||
|
||||
// Bind HTML elements with C functions
|
||||
webui_bind(my_window, "MyID_One", my_function_string);
|
||||
webui_bind(my_window, "MyID_Two", my_function_integer);
|
||||
webui_bind(my_window, "MyID_Three", my_function_boolean);
|
||||
webui_bind(my_window, "MyID_Four", my_function_with_response);
|
||||
// Bind HTML elements with C functions
|
||||
webui_bind(my_window, "MyID_One", my_function_string);
|
||||
webui_bind(my_window, "MyID_Two", my_function_integer);
|
||||
webui_bind(my_window, "MyID_Three", my_function_boolean);
|
||||
webui_bind(my_window, "MyID_Four", my_function_with_response);
|
||||
|
||||
// Show the window
|
||||
webui_show(my_window, my_html); // webui_show_browser(my_window, my_html, Chrome);
|
||||
// Show the window
|
||||
webui_show(my_window, my_html); // webui_show_browser(my_window, my_html, Chrome);
|
||||
|
||||
// Wait until all windows get closed
|
||||
webui_wait();
|
||||
// Wait until all windows get closed
|
||||
webui_wait();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) {
|
||||
return main();
|
||||
}
|
||||
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { return main(); }
|
||||
#endif
|
||||
|
2
code/MicroPython/.gitignore
vendored
Normal file
2
code/MicroPython/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
microdot/
|
||||
utemplate/
|
37
code/MicroPython/README.md
Normal file
37
code/MicroPython/README.md
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
|
||||
##
|
||||
|
||||
```shell
|
||||
# ...
|
||||
esptool.py --port /dev/ttyACM0 erase_flash
|
||||
# ...
|
||||
esptool.py --chip esp32s2 --port /dev/ttyACM0 write_flash -z 0x1000 ~/Downloads/LOLIN_S2_MINI-20240222-v1.22.2.bin
|
||||
```
|
||||
|
||||
```shell
|
||||
pip3 install rshell #
|
||||
pip3 install mpremote #
|
||||
```
|
||||
|
||||
### Выполнение кода
|
||||
|
||||
```shell
|
||||
rshell --port /dev/ttyACM0 cat blink.py
|
||||
```
|
||||
|
||||
```python
|
||||
import machine
|
||||
import time
|
||||
|
||||
led = machine.Pin(15, machine.Pin.OUT)
|
||||
|
||||
led.on()
|
||||
time.sleep(1)
|
||||
led.off()
|
||||
time.sleep(1)
|
||||
```
|
||||
|
||||
```shell
|
||||
mpremote exec 'exec(open("blink.py").read())'
|
||||
```
|
9
code/MicroPython/blink.py
Normal file
9
code/MicroPython/blink.py
Normal file
@ -0,0 +1,9 @@
|
||||
import machine
|
||||
import time
|
||||
|
||||
led = machine.Pin(15, machine.Pin.OUT)
|
||||
|
||||
led.on()
|
||||
time.sleep(1)
|
||||
led.off()
|
||||
time.sleep(1)
|
4
code/MicroPython/boot.py
Normal file
4
code/MicroPython/boot.py
Normal file
@ -0,0 +1,4 @@
|
||||
"""
|
||||
Скрипт, который выполняется при старте EPS32.
|
||||
После него выполняется скрипт `main.py`.
|
||||
"""
|
163
code/MicroPython/ftp.py
Normal file
163
code/MicroPython/ftp.py
Normal file
@ -0,0 +1,163 @@
|
||||
import socket
|
||||
import network
|
||||
import os
|
||||
import _thread
|
||||
|
||||
DATA_PORT = 13333
|
||||
|
||||
ftpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
datasocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
ftpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
datasocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
ftpsocket.bind(socket.getaddrinfo("0.0.0.0", 21)[0][4])
|
||||
datasocket.bind(socket.getaddrinfo("0.0.0.0", DATA_PORT)[0][4])
|
||||
|
||||
ftpsocket.listen(1)
|
||||
datasocket.listen(1)
|
||||
datasocket.settimeout(10)
|
||||
|
||||
dataclient = None
|
||||
|
||||
|
||||
def send_list_data(cwd, dataclient):
|
||||
for file in os.listdir(cwd):
|
||||
stat = os.stat(get_absolute_path(cwd, file))
|
||||
file_permissions = "drwxr-xr-x" if (stat[0] & 0o170000 == 0o040000) else "-rw-r--r--"
|
||||
file_size = stat[6]
|
||||
description = "{} 1 owner group {:>13} Jan 1 1980 {}\r\n".format(
|
||||
file_permissions, file_size, file
|
||||
)
|
||||
dataclient.sendall(description)
|
||||
|
||||
|
||||
def send_file_data(path, dataclient):
|
||||
with open(path) as file:
|
||||
chunk = file.read(128)
|
||||
while len(chunk) > 0:
|
||||
dataclient.sendall(chunk)
|
||||
chunk = file.read(128)
|
||||
|
||||
|
||||
def save_file_data(path, dataclient):
|
||||
with open(path, "w") as file:
|
||||
chunk = dataclient.read(128)
|
||||
while len(chunk) > 0:
|
||||
file.write(chunk)
|
||||
chunk = dataclient.read(128)
|
||||
|
||||
|
||||
def get_absolute_path(cwd, payload):
|
||||
# if it doesn't start with / consider
|
||||
# it a relative path
|
||||
if not payload.startswith("/"):
|
||||
payload = cwd + "/" + payload
|
||||
# and don't leave any trailing /
|
||||
return payload.rstrip("/")
|
||||
|
||||
|
||||
def ftp():
|
||||
try:
|
||||
dataclient = None
|
||||
while True:
|
||||
cwd = "/"
|
||||
cl, remote_addr = ftpsocket.accept()
|
||||
cl.settimeout(300)
|
||||
try:
|
||||
print("FTP connection from:", remote_addr)
|
||||
cl.sendall("220 Hello, this is the ESP8266.\r\n")
|
||||
while True:
|
||||
data = cl.readline().decode("utf-8").replace("\r\n", "")
|
||||
if len(data) <= 0:
|
||||
print("Client is dead")
|
||||
break
|
||||
|
||||
command, payload = (data.split(" ") + [""])[:2]
|
||||
command = command.upper()
|
||||
|
||||
print("Command={}, Payload={}".format(command, payload))
|
||||
|
||||
if command == "USER":
|
||||
cl.sendall("230 Logged in.\r\n")
|
||||
elif command == "SYST":
|
||||
cl.sendall("215 ESP8266 MicroPython\r\n")
|
||||
elif command == "SYST":
|
||||
cl.sendall("502\r\n")
|
||||
elif command == "PWD":
|
||||
cl.sendall('257 "{}"\r\n'.format(cwd))
|
||||
elif command == "CWD":
|
||||
path = get_absolute_path(cwd, payload)
|
||||
try:
|
||||
files = os.listdir(path)
|
||||
cwd = path
|
||||
cl.sendall('250 Directory changed successfully\r\n')
|
||||
except:
|
||||
cl.sendall('550 Failed to change directory\r\n')
|
||||
elif command == "EPSV":
|
||||
cl.sendall('502\r\n')
|
||||
elif command == "TYPE":
|
||||
# probably should switch between binary and not
|
||||
cl.sendall('200 Transfer mode set\r\n')
|
||||
elif command == "SIZE":
|
||||
path = get_absolute_path(cwd, payload)
|
||||
try:
|
||||
size = os.stat(path)[6]
|
||||
cl.sendall('213 {}\r\n'.format(size))
|
||||
except:
|
||||
cl.sendall('550 Could not get file size\r\n')
|
||||
elif command == "QUIT":
|
||||
cl.sendall('221 Bye.\r\n')
|
||||
elif command == "PASV":
|
||||
addr = network.WLAN().ifconfig()[0]
|
||||
cl.sendall(
|
||||
'227 Entering Passive Mode ({},{},{}).\r\n'.format(
|
||||
addr.replace('.', ','), DATA_PORT >> 8, DATA_PORT % 256
|
||||
)
|
||||
)
|
||||
dataclient, data_addr = datasocket.accept()
|
||||
print("FTP Data connection from:", data_addr)
|
||||
elif command == "LIST":
|
||||
try:
|
||||
send_list_data(cwd, dataclient)
|
||||
dataclient.close()
|
||||
cl.sendall("150 Here comes the directory listing.\r\n")
|
||||
cl.sendall("226 Listed.\r\n")
|
||||
except:
|
||||
cl.sendall('550 Failed to list directory\r\n')
|
||||
finally:
|
||||
dataclient.close()
|
||||
elif command == "RETR":
|
||||
try:
|
||||
send_file_data(get_absolute_path(cwd, payload), dataclient)
|
||||
dataclient.close()
|
||||
cl.sendall("150 Opening data connection.\r\n")
|
||||
cl.sendall("226 Transfer complete.\r\n")
|
||||
except:
|
||||
cl.sendall('550 Failed to send file\r\n')
|
||||
finally:
|
||||
dataclient.close()
|
||||
elif command == "STOR":
|
||||
try:
|
||||
cl.sendall("150 Ok to send data.\r\n")
|
||||
save_file_data(get_absolute_path(cwd, payload), dataclient)
|
||||
dataclient.close()
|
||||
cl.sendall("226 Transfer complete.\r\n")
|
||||
except:
|
||||
cl.sendall('550 Failed to send file\r\n')
|
||||
finally:
|
||||
dataclient.close()
|
||||
else:
|
||||
cl.sendall("502 Unsupported command.\r\n")
|
||||
print("Unsupported command {} with payload {}".format(command, payload))
|
||||
|
||||
finally:
|
||||
cl.close()
|
||||
finally:
|
||||
datasocket.close()
|
||||
ftpsocket.close()
|
||||
if dataclient is not None:
|
||||
dataclient.close()
|
||||
|
||||
|
||||
_thread.start_new_thread(ftp, ())
|
13
code/MicroPython/get_mac.py
Normal file
13
code/MicroPython/get_mac.py
Normal file
@ -0,0 +1,13 @@
|
||||
"""
|
||||
Скрипт, который возвращает MAC адрес
|
||||
|
||||
https://git.a2s.su/iiiypuk/snipplets.dev/src/branch/master/code/MicroPython
|
||||
Update: May 14 2024
|
||||
"""
|
||||
|
||||
import network
|
||||
import ubinascii
|
||||
|
||||
mac = ubinascii.hexlify(network.WLAN().config('mac'), ':').decode()
|
||||
|
||||
print(mac)
|
79
code/MicroPython/http.py
Normal file
79
code/MicroPython/http.py
Normal file
@ -0,0 +1,79 @@
|
||||
import machine
|
||||
import time
|
||||
import gc
|
||||
|
||||
from microdot import Microdot, send_file, Request, Response
|
||||
|
||||
from microdot.utemplate import Template
|
||||
|
||||
led = machine.Pin(15, machine.Pin.OUT)
|
||||
|
||||
app = Microdot()
|
||||
Response.default_content_type = 'text/html'
|
||||
Request.max_content_length = 1024 * 1024
|
||||
|
||||
|
||||
def cmd_parse(method, args):
|
||||
if method == 'GET':
|
||||
if 'cmd' in args:
|
||||
cmd = args['cmd']
|
||||
|
||||
if 'reboot' == cmd:
|
||||
for x in range(2):
|
||||
led.on()
|
||||
time.sleep_ms(200)
|
||||
led.off()
|
||||
time.sleep_ms(200)
|
||||
|
||||
machine.reset()
|
||||
|
||||
if 'ftp' == cmd:
|
||||
exec(open('ftp.py').read())
|
||||
|
||||
|
||||
@app.route('/static/<path:path>')
|
||||
async def static(request, path):
|
||||
if '..' in path:
|
||||
# directory traversal is not allowed
|
||||
return 'Not found', 404
|
||||
return send_file('static/' + path)
|
||||
|
||||
|
||||
@app.get('/file')
|
||||
async def file(request):
|
||||
return send_file('templates/upload.html')
|
||||
|
||||
|
||||
@app.post('/upload')
|
||||
async def upload(request):
|
||||
filename = request.headers['Content-Disposition'].split('filename=')[1].strip('"')
|
||||
size = int(request.headers['Content-Length'])
|
||||
|
||||
filename = filename.replace('/', '_')
|
||||
|
||||
with open('/' + filename, 'wb') as f:
|
||||
while size > 0:
|
||||
chunk = await request.stream.read(min(size, 1024))
|
||||
f.write(chunk)
|
||||
size -= len(chunk)
|
||||
|
||||
print('Successfully saved file: ' + filename)
|
||||
return ''
|
||||
|
||||
|
||||
@app.route('/')
|
||||
async def index(request):
|
||||
# print(request.args, request.path, request.method, sep='\n')
|
||||
# print(request.url, request.query_string, request.url_args, sep='\n')
|
||||
print(request.args)
|
||||
|
||||
cmd_parse(request.method, request.args)
|
||||
|
||||
ram_f = gc.mem_free()
|
||||
ram_a = gc.mem_alloc()
|
||||
ram_t = ram_a + ram_f
|
||||
return Template('index.html').render(ram_free=int(ram_f / 1024), ram_total=int(ram_t / 1024))
|
||||
|
||||
|
||||
print('HTTP server started')
|
||||
app.run(port=80)
|
17
code/MicroPython/main.py
Normal file
17
code/MicroPython/main.py
Normal file
@ -0,0 +1,17 @@
|
||||
"""
|
||||
Скрипт, который выполняется при старте EPS32.
|
||||
После выполнения скрипта `boot.py`.
|
||||
"""
|
||||
|
||||
import time
|
||||
import network_ap
|
||||
import network_sta
|
||||
|
||||
# Connecting to Wifi
|
||||
wifi_connect = network_sta.connect('Keenetic-8647', 'sFJZi7U51')
|
||||
if wifi_connect == False:
|
||||
wifi_connect = network_ap.connect(essid='SkyNet', clients=2)
|
||||
|
||||
# If WiFi connected run HTTP server
|
||||
if wifi_connect == True:
|
||||
exec(open('http.py').read())
|
21
code/MicroPython/network_ap.py
Normal file
21
code/MicroPython/network_ap.py
Normal file
@ -0,0 +1,21 @@
|
||||
import time
|
||||
import network
|
||||
|
||||
|
||||
def connect(essid='ESP', clients=3) -> bool:
|
||||
print('Starting AP: {0}...'.format(essid))
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.active(True)
|
||||
ap.config(essid=essid)
|
||||
ap.config(max_clients=clients)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
if ap.isconnected():
|
||||
print('AP "{0}" started'.format(essid))
|
||||
|
||||
return True
|
||||
else:
|
||||
print('Starting AP failed!')
|
||||
|
||||
return False
|
38
code/MicroPython/network_sta.py
Normal file
38
code/MicroPython/network_sta.py
Normal file
@ -0,0 +1,38 @@
|
||||
import time
|
||||
import network
|
||||
|
||||
|
||||
def connect(ssid: str, password: str) -> bool:
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
wlan.config(reconnects=2)
|
||||
|
||||
if not wlan.isconnected():
|
||||
print('Scanning networks...')
|
||||
wlan.scan()
|
||||
print('Connecting to {0}...'.format(ssid))
|
||||
# try:
|
||||
wlan.connect(ssid, password)
|
||||
|
||||
while not wlan.isconnected():
|
||||
status = wlan.status()
|
||||
if status in (network.STAT_IDLE, network.STAT_WRONG_PASSWORD, network.STAT_NO_AP_FOUND):
|
||||
print('\nConnection to "{0}" failed!'.format(ssid))
|
||||
wlan.active(False)
|
||||
|
||||
return False
|
||||
|
||||
print('.', end='')
|
||||
time.sleep(0.1)
|
||||
|
||||
print('\nConnection success!')
|
||||
ifconfig = wlan.ifconfig()
|
||||
print('IP: {0}'.format(ifconfig[0]))
|
||||
|
||||
return True
|
||||
else:
|
||||
print('Already connected!')
|
||||
ifconfig = wlan.ifconfig()
|
||||
print('IP: {0}'.format(ifconfig[0]))
|
||||
|
||||
return True
|
3
code/MicroPython/pyproject.toml
Normal file
3
code/MicroPython/pyproject.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[tool.black]
|
||||
skip-string-normalization = true
|
||||
line-length = 100
|
13
code/MicroPython/read_write_file.py
Normal file
13
code/MicroPython/read_write_file.py
Normal file
@ -0,0 +1,13 @@
|
||||
import os
|
||||
|
||||
print('Listing filesystem...')
|
||||
print(os.listdir(), '\n')
|
||||
|
||||
print('Write data...')
|
||||
with open('data.txt', 'w') as f:
|
||||
count = f.write('ololo\n')
|
||||
print('Write', count, 'bytes')
|
||||
|
||||
print('Read data...')
|
||||
with open('data.txt', 'r') as f:
|
||||
print('Data:', f.read())
|
3
code/MicroPython/static/styles.css
Normal file
3
code/MicroPython/static/styles.css
Normal file
@ -0,0 +1,3 @@
|
||||
body {
|
||||
background-color: #ccc;
|
||||
}
|
18
code/MicroPython/templates/index.html
Normal file
18
code/MicroPython/templates/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
{% args ram_free, ram_total %}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>S2F Terminal</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link href="/static/styles.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<h1>by Alexander Popov</h1>
|
||||
<p>Free RAM: {{ ram_free }} of {{ ram_total }}</p>
|
||||
<div>
|
||||
<a href="/?cmd=ftp">Поднять FTP сервер</a><br>
|
||||
<a href="/?cmd=reboot">Перезапустить</a><br>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
code/MicroPython/templates/index_html.py
Normal file
23
code/MicroPython/templates/index_html.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Autogenerated file
|
||||
def render(ram_free, ram_total):
|
||||
yield """<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>S2F Terminal</title>
|
||||
<meta charset=\"utf-8\">
|
||||
<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">
|
||||
<link href=\"/static/styles.css\" rel=\"stylesheet\">
|
||||
</head>
|
||||
<body>
|
||||
<h1>by Alexander Popov</h1>
|
||||
<p>Free RAM: """
|
||||
yield str(ram_free)
|
||||
yield """ of """
|
||||
yield str(ram_total)
|
||||
yield """</p>
|
||||
<div>
|
||||
<a href=\"/?cmd=ftp\">Поднять FTP сервер</a><br>
|
||||
<a href=\"/?cmd=reboot\">Перезапустить</a><br>
|
||||
</div>
|
||||
</body>
|
||||
</html>"""
|
35
code/MicroPython/templates/upload.html
Normal file
35
code/MicroPython/templates/upload.html
Normal file
@ -0,0 +1,35 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Microdot Upload Example</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Microdot Upload Example</h1>
|
||||
<form id="form">
|
||||
<input type="file" id="file" name="file" />
|
||||
<input type="submit" value="Upload" />
|
||||
</form>
|
||||
<script>
|
||||
async function upload(ev) {
|
||||
ev.preventDefault();
|
||||
const file = document.getElementById('file').files[0];
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
await fetch('/upload', {
|
||||
method: 'POST',
|
||||
body: file,
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-Disposition': `attachment; filename="${file.name}"`,
|
||||
},
|
||||
}).then(res => {
|
||||
console.log('Upload accepted');
|
||||
window.location.href = '/';
|
||||
});
|
||||
}
|
||||
document.getElementById('form').addEventListener('submit', upload);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
0
code/MicroPython/webrepl_cfg.py
Normal file
0
code/MicroPython/webrepl_cfg.py
Normal file
@ -1,4 +0,0 @@
|
||||
* draw rect
|
||||
* draw text
|
||||
* draw image
|
||||
* key event
|
1
projects/V/Game/.gitignore
vendored
Normal file
1
projects/V/Game/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
Game
|
82
projects/V/Game/README.md
Normal file
82
projects/V/Game/README.md
Normal file
@ -0,0 +1,82 @@
|
||||
* draw rect
|
||||
* draw text
|
||||
* draw image
|
||||
* key event
|
||||
|
||||
## Build
|
||||
|
||||
### Linux
|
||||
|
||||
`...`
|
||||
|
||||
### Android
|
||||
|
||||
**Подготовка Android окружения**.
|
||||
|
||||
Необходимо выполнить следующие шаги:
|
||||
|
||||
1. Установка модуля `vab` для **V**
|
||||
2. Установка **Android NDK**
|
||||
3. Установка **android-tools**
|
||||
4. Получение идентификатора устройства для деплоя
|
||||
|
||||
**Установка модуля `vab` для V**
|
||||
|
||||
```sh
|
||||
v install vab
|
||||
# Installed `vab` in ~/.vmodules/vab .
|
||||
vab install "platforms;android-33" # Silent output... wait!
|
||||
```
|
||||
|
||||
**Получение идентификатора устройства**
|
||||
|
||||
```sh
|
||||
adb devices -l
|
||||
```
|
||||
|
||||
https://developer.android.com/ndk
|
||||
https://dl.google.com/android/repository/android-ndk-r26d-linux.zip
|
||||
https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
|
||||
|
||||
Сборка `debug` пакета.
|
||||
|
||||
```sh
|
||||
ANDROID_NDK_ROOT="/home/user/.android/android-ndk-r26d"
|
||||
VAB_FLAGS="-v 3 --name 'V App' --api 33 --build-tools 29.0.0" ~/.vmodules/vab/vab .
|
||||
|
||||
~/.vmodules/vab/vab --device ca4fcde6 run /home/user/Develop/snipplets.dev/projects/V/Game/v_app.apk
|
||||
```
|
||||
|
||||
Сборка `release` пакета:
|
||||
|
||||
```sh
|
||||
# Генерация sign.keystore
|
||||
|
||||
keytool -genkey -v -keystore sign.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
|
||||
```
|
||||
|
||||
```sh
|
||||
KEYSTORE_PASSWORD="Mix9BEAH" \
|
||||
KEYSTORE_ALIAS_PASSWORD="Mix9BEAH" \
|
||||
VAB_FLAGS="-v 3 --name 'V App' --api 33 --build-tools 29.0.0" \
|
||||
~/.vmodules/vab/vab -prod --name "V App" --package-id "me.a2s.example" --icon ./assets/vlang.png --version-code 1 \
|
||||
--keystore ./sign.keystore --keystore-alias "alias_name" .
|
||||
```
|
||||
|
||||
### HTML (WASM)
|
||||
|
||||
Guide: https://github.com/vlang/v/tree/master/examples/2048#compiling-to-wasm
|
||||
|
||||
## OTHER
|
||||
|
||||
```sh
|
||||
VCROSS_COMPILER_NAME=/home/user/.android/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-17 /home/user/.local/bin/vlang/v -os android .
|
||||
|
||||
VCROSS_COMPILER_NAME=/home/user/.android/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-17 /home/user/.local/bin/vlang/v -os android -nocache -cc clang .
|
||||
|
||||
ANDROID_SDK_ROOT="/home/user/.android/sdk/cmdline-tools/33" ANDROID_NDK_ROOT="/home/user/.android/android-ndk-r26d" ANDROID_PACKAGE_NAME="test app" ANDROID_PACKAGE_ID="me.a2s.example" VAB_FLAGS="-v 3 --name $ANDROID_PACKAGE_NAME --package-id $ANDROID_PACKAGE_ID --api 33 --build-tools 26.0.2" /home/user/.vmodules/vab/vab .
|
||||
|
||||
VCROSS_COMPILER_NAME=/home/user/.android/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-17 /home/user/.local/bin/vlang/v -os android -nocache -cc clang -DSOKOL_GLES3 -dump-modules "/tmp/vab/v/v.modules" -dump-c-flags "/tmp/vab/v/v.cflags" .
|
||||
|
||||
VCROSS_COMPILER_NAME=/home/user/.android/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang /home/user/.local/bin/vlang/v -os android android.v
|
||||
```
|
BIN
projects/V/Game/android
Executable file
BIN
projects/V/Game/android
Executable file
Binary file not shown.
3
projects/V/Game/android.v
Normal file
3
projects/V/Game/android.v
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
print('Loading... ')
|
||||
}
|
1
projects/V/Game/assets/monogram-extended.ttf
Symbolic link
1
projects/V/Game/assets/monogram-extended.ttf
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../assets/monogram-extended.ttf
|
1
projects/V/Game/assets/tiled_bg.png
Symbolic link
1
projects/V/Game/assets/tiled_bg.png
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../assets/tiled_bg.png
|
1
projects/V/Game/assets/vlang.png
Symbolic link
1
projects/V/Game/assets/vlang.png
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../assets/languages/vlang.png
|
30
projects/V/Game/build.sh
Executable file
30
projects/V/Game/build.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Обновление PATH
|
||||
PATH="~/.local/bin/vlang:~/.vmodules/vab:$PATH"
|
||||
|
||||
# Настройки Android
|
||||
export ANDROID_SDK_ROOT="/home/user/.android/sdk/cmdline-tools/33"
|
||||
export ANDROID_NDK_ROOT="/home/user/.android/android-ndk-r26d"
|
||||
ANDROID_DEVICE_ID="ca4fcde6"
|
||||
ANDROID_PACKAGE_NAME="test app"
|
||||
ANDROID_PACKAGE_ID="me.a2s.example"
|
||||
|
||||
VAB_FLAGS_DEBUG="-v 3 --name $ANDROID_PACKAGE_NAME --package-id $ANDROID_PACKAGE_ID --api 33 --build-tools 29.0.0"
|
||||
VAB_FLAGS_RELEASE="-v 3 --name $ANDROID_PACKAGE_NAME --package-id $ANDROID_PACKAGE_ID --api 33 --build-tools 29.0.0 --icon ./assets/vlang.png --version-code 1 --keystore ./sign.keystore --keystore-alias \"alias_name\""
|
||||
|
||||
debug() {
|
||||
VAB_FLAGS=$VAB_FLAGS_DEBUG vab $(pwd)
|
||||
|
||||
# vab --device $ANDROID_DEVICE_ID run ./v_app.apk
|
||||
}
|
||||
|
||||
release() {
|
||||
echo "WIP"
|
||||
}
|
||||
|
||||
test() {
|
||||
VAB_FLAGS="-v 3 --name $ANDROID_PACKAGE_NAME --package-id $ANDROID_PACKAGE_ID --api 33 --build-tools 26.0.2" vab android.v
|
||||
}
|
||||
|
||||
test
|
@ -12,7 +12,7 @@ fn (game &Game) draw() {
|
||||
gx.white, 'right', 'top', true)
|
||||
|
||||
// draw image
|
||||
game.gg.draw_image(0, game.gg.window_size().height - game.player.image.height, game.player.image.width,
|
||||
game.gg.draw_image(game.player.pos_x, game.player.pos_y, game.player.image.width,
|
||||
game.player.image.height, game.player.image)
|
||||
|
||||
game.gg.end()
|
@ -3,10 +3,8 @@ import gg
|
||||
import gx
|
||||
import sokol.sapp
|
||||
|
||||
const (
|
||||
win_width = 512
|
||||
win_height = 512
|
||||
)
|
||||
const win_width = 768
|
||||
const win_height = 768
|
||||
|
||||
struct Game {
|
||||
mut:
|
||||
@ -39,7 +37,7 @@ fn main() {
|
||||
print('Loading... ')
|
||||
mut game := &Game{}
|
||||
|
||||
mut font_path := os.resource_abs_path(os.join_path('..', '..', '.assets', 'monogram-extended.ttf'))
|
||||
mut font_path := os.resource_abs_path(os.join_path('assets', 'monogram-extended.ttf'))
|
||||
|
||||
game.gg = gg.new_context(
|
||||
bg_color: gx.hex(0x2A2A3AFF)
|
||||
@ -55,8 +53,8 @@ fn main() {
|
||||
)
|
||||
|
||||
game.player = &Player{
|
||||
pos_x: 10
|
||||
pos_y: 10
|
||||
pos_x: 50
|
||||
pos_y: 50
|
||||
lives: 3
|
||||
}
|
||||
|
||||
@ -65,10 +63,10 @@ fn main() {
|
||||
pos_y: 0
|
||||
}
|
||||
|
||||
game.bg_texture.image = game.gg.create_image(os.resource_abs_path(os.join_path('..',
|
||||
'..', '.assets', 'fondo para itchio.png'))) or { panic(err) }
|
||||
game.player.image = game.gg.create_image(os.resource_abs_path(os.join_path('..', '..',
|
||||
'.assets', 'v-logo.png'))) or { panic(err) }
|
||||
game.bg_texture.image = game.gg.create_image(os.resource_abs_path(os.join_path('assets',
|
||||
'tiled_bg.png'))) or { panic(err) }
|
||||
game.player.image = game.gg.create_image(os.resource_abs_path(os.join_path('assets',
|
||||
'vlang.png'))) or { panic(err) }
|
||||
|
||||
println('OK!\n')
|
||||
println('High DPI: ${gg.high_dpi()}')
|
7
projects/V/Game/v.mod
Normal file
7
projects/V/Game/v.mod
Normal file
@ -0,0 +1,7 @@
|
||||
Module {
|
||||
name: 'game',
|
||||
description: '...',
|
||||
version: '0.0.0',
|
||||
repo_url: '...',
|
||||
dependencies: []
|
||||
}
|
Loading…
Reference in New Issue
Block a user