├── firmware ├── lib │ ├── AsyncTCP │ │ ├── .gitignore │ │ ├── component.mk │ │ ├── library.properties │ │ ├── CMakeLists.txt │ │ ├── library.json │ │ ├── Kconfig.projbuild │ │ ├── .travis.yml │ │ └── README.md │ ├── ESPAsyncWebServer │ │ ├── _config.yml │ │ ├── .gitignore │ │ ├── keywords.txt │ │ ├── component.mk │ │ ├── library.properties │ │ ├── CMakeLists.txt │ │ ├── src │ │ │ ├── SPIFFSEditor.h │ │ │ ├── WebAuthentication.h │ │ │ └── AsyncWebSynchronization.h │ │ ├── library.json │ │ └── .travis.yml │ └── README ├── src │ ├── mooncake │ │ ├── .gitignore │ │ ├── README.md │ │ ├── src │ │ │ ├── spdlog │ │ │ │ ├── include │ │ │ │ │ └── spdlog │ │ │ │ │ │ ├── fmt │ │ │ │ │ │ ├── bundled │ │ │ │ │ │ │ ├── locale.h │ │ │ │ │ │ │ └── fmt.license.rst │ │ │ │ │ │ ├── xchar.h │ │ │ │ │ │ ├── chrono.h │ │ │ │ │ │ ├── ostr.h │ │ │ │ │ │ ├── ranges.h │ │ │ │ │ │ ├── compile.h │ │ │ │ │ │ ├── std.h │ │ │ │ │ │ └── fmt.h │ │ │ │ │ │ ├── details │ │ │ │ │ │ ├── windows_include.h │ │ │ │ │ │ ├── periodic_worker-inl.h │ │ │ │ │ │ ├── console_globals.h │ │ │ │ │ │ ├── synchronous_factory.h │ │ │ │ │ │ ├── log_msg_buffer.h │ │ │ │ │ │ ├── null_mutex.h │ │ │ │ │ │ ├── log_msg-inl.h │ │ │ │ │ │ ├── log_msg.h │ │ │ │ │ │ ├── backtracer.h │ │ │ │ │ │ ├── log_msg_buffer-inl.h │ │ │ │ │ │ ├── file_helper.h │ │ │ │ │ │ ├── periodic_worker.h │ │ │ │ │ │ ├── backtracer-inl.h │ │ │ │ │ │ ├── udp_client.h │ │ │ │ │ │ ├── udp_client-windows.h │ │ │ │ │ │ ├── thread_pool.h │ │ │ │ │ │ ├── thread_pool-inl.h │ │ │ │ │ │ ├── circular_q.h │ │ │ │ │ │ └── os.h │ │ │ │ │ │ ├── fwd.h │ │ │ │ │ │ ├── version.h │ │ │ │ │ │ ├── formatter.h │ │ │ │ │ │ ├── sinks │ │ │ │ │ │ ├── sink-inl.h │ │ │ │ │ │ ├── sink.h │ │ │ │ │ │ ├── basic_file_sink-inl.h │ │ │ │ │ │ ├── stdout_color_sinks-inl.h │ │ │ │ │ │ ├── null_sink.h │ │ │ │ │ │ ├── ostream_sink.h │ │ │ │ │ │ ├── base_sink.h │ │ │ │ │ │ ├── stdout_color_sinks.h │ │ │ │ │ │ ├── callback_sink.h │ │ │ │ │ │ ├── base_sink-inl.h │ │ │ │ │ │ ├── basic_file_sink.h │ │ │ │ │ │ ├── udp_sink.h │ │ │ │ │ │ ├── msvc_sink.h │ │ │ │ │ │ ├── ringbuffer_sink.h │ │ │ │ │ │ ├── tcp_sink.h │ │ │ │ │ │ ├── stdout_sinks.h │ │ │ │ │ │ ├── dist_sink.h │ │ │ │ │ │ ├── rotating_file_sink.h │ │ │ │ │ │ ├── wincolor_sink.h │ │ │ │ │ │ ├── dup_filter_sink.h │ │ │ │ │ │ ├── mongo_sink.h │ │ │ │ │ │ └── syslog_sink.h │ │ │ │ │ │ ├── cfg │ │ │ │ │ │ ├── helpers.h │ │ │ │ │ │ ├── env.h │ │ │ │ │ │ ├── argv.h │ │ │ │ │ │ └── helpers-inl.h │ │ │ │ │ │ ├── stopwatch.h │ │ │ │ │ │ ├── common-inl.h │ │ │ │ │ │ ├── async_logger.h │ │ │ │ │ │ ├── async_logger-inl.h │ │ │ │ │ │ ├── spdlog-inl.h │ │ │ │ │ │ ├── async.h │ │ │ │ │ │ └── pattern_formatter.h │ │ │ │ └── LICENSE │ │ │ └── mooncake.h │ │ ├── CMakeLists.txt │ │ └── LICENSE │ ├── apis │ │ ├── poster │ │ │ └── api_poster.h │ │ ├── shooter │ │ │ └── api_shooter.h │ │ ├── mic │ │ │ └── api_mic.h │ │ ├── utils │ │ │ └── led_status │ │ │ │ ├── status_led.h │ │ │ │ └── status_led.cpp │ │ ├── system │ │ │ └── api_system.h │ │ └── camera │ │ │ └── api_cam.h │ ├── servers │ │ ├── servers.h │ │ ├── server_ap.cpp │ │ └── server_shooter.cpp │ ├── main.cpp │ └── hal │ │ ├── hal.cpp │ │ ├── hal.h │ │ └── cam │ │ └── hal_cam.cpp ├── data │ ├── m5.jpg │ ├── index.html.gz │ └── config.json ├── .gitignore ├── .vscode │ └── extensions.json ├── custom.csv ├── test │ └── README ├── platformio.ini └── include │ └── README ├── web ├── src │ ├── vite-env.d.ts │ ├── index.css │ ├── error-page.tsx │ ├── routes │ │ ├── page-poster.tsx │ │ ├── page-shooter.tsx │ │ ├── page-shooter-start.tsx │ │ ├── page-poster-start.tsx │ │ └── page-root.tsx │ ├── assets │ │ ├── poster-interval-list.ts │ │ └── time-zone-list.ts │ ├── components │ │ ├── shooter │ │ │ ├── card-shooter-start.tsx │ │ │ ├── card-shooter.tsx │ │ │ └── card-shooter-notice.tsx │ │ ├── poster │ │ │ ├── card-poster.tsx │ │ │ ├── card-poster-notice.tsx │ │ │ └── card-poster-start-and-link.tsx │ │ ├── hardware-test │ │ │ ├── card-led-test.tsx │ │ │ ├── card-sd-card-test.tsx │ │ │ ├── card-camera-test.tsx │ │ │ └── card-mic-test.tsx │ │ └── title-bar.tsx │ └── main.tsx ├── public │ └── m5.jpg ├── postcss.config.js ├── tsconfig.node.json ├── .gitignore ├── tailwind.config.js ├── index.html ├── vite.config.ts ├── .eslintrc.cjs ├── tsconfig.json ├── json_server │ └── unitcams3.json ├── package.json └── README.md ├── README.md └── LICENSE /firmware/lib/AsyncTCP/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /firmware/src/mooncake/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .vscode 3 | .cache 4 | -------------------------------------------------------------------------------- /web/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /web/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /web/public/m5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m5stack/UnitCamS3-UserDemo/HEAD/web/public/m5.jpg -------------------------------------------------------------------------------- /firmware/data/m5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m5stack/UnitCamS3-UserDemo/HEAD/firmware/data/m5.jpg -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/keywords.txt: -------------------------------------------------------------------------------- 1 | JsonArray KEYWORD1 2 | add KEYWORD2 3 | createArray KEYWORD3 4 | -------------------------------------------------------------------------------- /firmware/data/index.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m5stack/UnitCamS3-UserDemo/HEAD/firmware/data/index.html.gz -------------------------------------------------------------------------------- /firmware/lib/AsyncTCP/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_INCLUDEDIRS := src 2 | COMPONENT_SRCDIRS := src 3 | CXXFLAGS += -fno-rtti 4 | -------------------------------------------------------------------------------- /web/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_INCLUDEDIRS := src 2 | COMPONENT_SRCDIRS := src 3 | CXXFLAGS += -fno-rtti 4 | -------------------------------------------------------------------------------- /firmware/.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | # src/mooncake -------------------------------------------------------------------------------- /firmware/src/mooncake/README.md: -------------------------------------------------------------------------------- 1 | # Mooncake 2 | 3 | Monica 请切换 Monica 分支 4 | 5 | ![](https://github.com/Forairaaaaa/mooncake/blob/main/pics/note_shit.jpg?raw=true) 6 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/bundled/locale.h: -------------------------------------------------------------------------------- 1 | #include "xchar.h" 2 | #warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead 3 | -------------------------------------------------------------------------------- /firmware/data/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "wifiSsid": "", 3 | "wifiPass": "", 4 | "startPoster": "no", 5 | "waitApFirst": "no", 6 | "nickname": "UnitCamS3", 7 | "postInterval": 5, 8 | "timeZone": "GMT+0", 9 | "startShooter": "no" 10 | } 11 | -------------------------------------------------------------------------------- /web/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /firmware/lib/AsyncTCP/library.properties: -------------------------------------------------------------------------------- 1 | name=AsyncTCP 2 | version=1.1.1 3 | author=Me-No-Dev 4 | maintainer=Me-No-Dev 5 | sentence=Async TCP Library for ESP32 6 | paragraph=Async TCP Library for ESP32 7 | category=Other 8 | url=https://github.com/me-no-dev/AsyncTCP 9 | architectures=* 10 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/windows_include.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef NOMINMAX 4 | # define NOMINMAX // prevent windows redefining min/max 5 | #endif 6 | 7 | #ifndef WIN32_LEAN_AND_MEAN 8 | # define WIN32_LEAN_AND_MEAN 9 | #endif 10 | 11 | #include 12 | -------------------------------------------------------------------------------- /firmware/lib/AsyncTCP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCDIRS 2 | "src" 3 | ) 4 | 5 | set(COMPONENT_ADD_INCLUDEDIRS 6 | "src" 7 | ) 8 | 9 | set(COMPONENT_REQUIRES 10 | "arduino-esp32" 11 | ) 12 | 13 | register_component() 14 | 15 | target_compile_options(${COMPONENT_TARGET} PRIVATE -fno-rtti) 16 | -------------------------------------------------------------------------------- /firmware/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "platformio.platformio-ide" 6 | ], 7 | "unwantedRecommendations": [ 8 | "ms-vscode.cpptools-extension-pack" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /firmware/src/mooncake/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeLists.txt 2 | cmake_minimum_required(VERSION 3.5) 3 | 4 | set(MOONCAKE_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) 5 | 6 | 7 | if (ESP_PLATFORM) 8 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/esp_idf.cmake) 9 | else() 10 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/basic.cmake) 11 | endif() 12 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/library.properties: -------------------------------------------------------------------------------- 1 | name=ESP Async WebServer 2 | version=1.2.3 3 | author=Me-No-Dev 4 | maintainer=Me-No-Dev 5 | sentence=Async Web Server for ESP8266 and ESP31B 6 | paragraph=Async Web Server for ESP8266 and ESP31B 7 | category=Other 8 | url=https://github.com/me-no-dev/ESPAsyncWebServer 9 | architectures=* 10 | -------------------------------------------------------------------------------- /firmware/src/apis/poster/api_poster.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file api_poster.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-11-03 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include 12 | 13 | void load_poster_apis(AsyncWebServer& server); 14 | void start_poster_task(); 15 | 16 | -------------------------------------------------------------------------------- /firmware/src/apis/shooter/api_shooter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file api_shooter.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-12-06 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | 14 | void load_shooter_apis(AsyncWebServer& server); 15 | void start_shooter_task(); 16 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCDIRS 2 | "src" 3 | ) 4 | 5 | set(COMPONENT_ADD_INCLUDEDIRS 6 | "src" 7 | ) 8 | 9 | set(COMPONENT_REQUIRES 10 | "arduino-esp32" 11 | "AsyncTCP" 12 | ) 13 | 14 | register_component() 15 | 16 | target_compile_definitions(${COMPONENT_TARGET} PUBLIC -DESP32) 17 | target_compile_options(${COMPONENT_TARGET} PRIVATE -fno-rtti) 18 | -------------------------------------------------------------------------------- /web/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { nextui } = require("@nextui-org/react"); 2 | 3 | /** @type {import('tailwindcss').Config} */ 4 | export default { 5 | content: [ 6 | "./index.html", 7 | "./src/**/*.{js,ts,jsx,tsx}", 8 | "./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}", 9 | ], 10 | theme: { 11 | extend: {}, 12 | }, 13 | darkMode: "class", 14 | plugins: [nextui()], 15 | }; 16 | -------------------------------------------------------------------------------- /firmware/src/servers/servers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file servers.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-11-20 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #pragma once 12 | 13 | namespace UserDemoServers 14 | { 15 | void start_ap_server(); 16 | void stop_ap_server(); 17 | void start_poster_server(); 18 | void start_shooter_server(); 19 | } 20 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/mooncake.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mooncake.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.2 6 | * @date 2023-08-19 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #pragma once 12 | 13 | /* Disable some features */ 14 | #ifdef ESP_PLATFORM 15 | #define SPDLOG_NO_EXCEPTIONS 16 | #define SPDLOG_NO_THREAD_ID 17 | #endif 18 | #include "spdlog/include/spdlog/spdlog.h" 19 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | UnitCamS3 | User Demo 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fwd.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | namespace spdlog { 7 | class logger; 8 | class formatter; 9 | 10 | namespace sinks { 11 | class sink; 12 | } 13 | 14 | namespace level { 15 | enum level_enum : int; 16 | } 17 | 18 | } // namespace spdlog 19 | -------------------------------------------------------------------------------- /web/src/error-page.tsx: -------------------------------------------------------------------------------- 1 | import { useRouteError } from "react-router-dom"; 2 | 3 | export default function ErrorPage() { 4 | const error = useRouteError() as any; 5 | console.error(error); 6 | 7 | return ( 8 |
9 |

Oops!

10 |

Sorry, an unexpected error has occurred.

11 |

12 | {error.statusText || error.message} 13 |

14 |
15 | ); 16 | } -------------------------------------------------------------------------------- /firmware/src/apis/mic/api_mic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file api_mic.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-11-02 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include 12 | // #include 13 | 14 | void startMicRecording(AsyncWebServerRequest* request); 15 | void isMicRecording(AsyncWebServerRequest* request); 16 | 17 | void load_mic_apis(AsyncWebServer& server); 18 | -------------------------------------------------------------------------------- /firmware/custom.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | nvs, data, nvs, 0x9000, 0x5000, 3 | # otadata, data, ota, 0xe000, 0x2000, 4 | phy_init, data, phy, , 0x1000, 5 | app0, app, ota_0, 0x10000, 2M, 6 | # app1, app, ota_1, 0x650000,0x640000, 7 | # spiffs, data, spiffs, 0xc90000,0x360000, 8 | #spiffs, data, spiffs, , 4M 9 | spiffs, data, spiffs, , 2M 10 | # ffat, data, fat, , 4M, 11 | coredump, data, coredump,0xFF0000,0x10000, -------------------------------------------------------------------------------- /web/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | import { viteSingleFile } from "vite-plugin-singlefile"; 4 | import viteCompression from "vite-plugin-compression"; 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [react(), viteSingleFile(), viteCompression()], 9 | server: { 10 | proxy: { 11 | // string shorthand 12 | "/api": "http://localhost:3000", 13 | }, 14 | }, 15 | }); 16 | -------------------------------------------------------------------------------- /web/src/routes/page-poster.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import TitleBar from "../components/title-bar"; 4 | import CardPosterConfig from "../components/poster/card-poster-config"; 5 | 6 | export default function PagePoster() { 7 | return ( 8 |
9 | 10 | 11 |
12 | 13 |
14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/version.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #define SPDLOG_VER_MAJOR 1 7 | #define SPDLOG_VER_MINOR 12 8 | #define SPDLOG_VER_PATCH 0 9 | 10 | #define SPDLOG_TO_VERSION(major, minor, patch) (major * 10000 + minor * 100 + patch) 11 | #define SPDLOG_VERSION SPDLOG_TO_VERSION(SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH) 12 | -------------------------------------------------------------------------------- /web/src/routes/page-shooter.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import TitleBar from "../components/title-bar"; 4 | import CardShooterConfig from "../components/shooter/card-shooter-config"; 5 | 6 | export default function PageShooter() { 7 | return ( 8 |
9 | 10 | 11 |
12 | 13 |
14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /web/src/routes/page-shooter-start.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import TitleBar from "../components/title-bar"; 4 | import CardShooterStart from "../components/shooter/card-shooter-start"; 5 | 6 | export default function PageShooterStart() { 7 | return ( 8 |
9 | 10 | 11 |
12 | 13 |
14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /web/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /firmware/src/apis/utils/led_status/status_led.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file status_led.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-12-06 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | 14 | 15 | enum LedState_t 16 | { 17 | led_state_waiting = 0, 18 | led_state_posting, 19 | }; 20 | 21 | 22 | namespace StatusLed 23 | { 24 | void start(); 25 | LedState_t getState(); 26 | void setState(LedState_t state); 27 | }; 28 | -------------------------------------------------------------------------------- /firmware/src/apis/system/api_system.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file api_system.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-11-01 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include 12 | // #include 13 | 14 | void getMac(AsyncWebServerRequest* request); 15 | void getSdCardInfo(AsyncWebServerRequest* request); 16 | void ledOn(AsyncWebServerRequest* request); 17 | void ledOff(AsyncWebServerRequest* request); 18 | 19 | void load_system_apis(AsyncWebServer& server); 20 | -------------------------------------------------------------------------------- /firmware/lib/AsyncTCP/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"AsyncTCP", 3 | "description":"Asynchronous TCP Library for ESP32", 4 | "keywords":"async,tcp", 5 | "authors": 6 | { 7 | "name": "Hristo Gochkov", 8 | "maintainer": true 9 | }, 10 | "repository": 11 | { 12 | "type": "git", 13 | "url": "https://github.com/me-no-dev/AsyncTCP.git" 14 | }, 15 | "version": "1.1.1", 16 | "license": "LGPL-3.0", 17 | "frameworks": "arduino", 18 | "platforms": "espressif32", 19 | "build": { 20 | "libCompatMode": 2 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /firmware/test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PlatformIO Test Runner and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PlatformIO Unit Testing: 11 | - https://docs.platformio.org/en/latest/advanced/unit-testing/index.html 12 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/formatter.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | 11 | class formatter 12 | { 13 | public: 14 | virtual ~formatter() = default; 15 | virtual void format(const details::log_msg &msg, memory_buf_t &dest) = 0; 16 | virtual std::unique_ptr clone() const = 0; 17 | }; 18 | } // namespace spdlog 19 | -------------------------------------------------------------------------------- /firmware/src/apis/camera/api_cam.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file api_cam.h 3 | * @author Forairaaaaa 4 | * @brief https://gist.github.com/me-no-dev/d34fba51a8f059ac559bf62002e61aa3 5 | * @version 0.1 6 | * @date 2023-11-01 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include 12 | // #include 13 | 14 | void sendBMP(AsyncWebServerRequest *request); 15 | void sendJpg(AsyncWebServerRequest *request); 16 | void streamJpg(AsyncWebServerRequest *request); 17 | void getCameraStatus(AsyncWebServerRequest *request); 18 | void setCameraVar(AsyncWebServerRequest *request); 19 | 20 | void load_cam_apis(AsyncWebServer& server); 21 | -------------------------------------------------------------------------------- /web/src/routes/page-poster-start.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import TitleBar from "../components/title-bar"; 4 | import CardPosterStartAndLink from "../components/poster/card-poster-start-and-link"; 5 | import CardPosterNotice from "../components/poster/card-poster-notice"; 6 | 7 | export default function PagePosterStart() { 8 | return ( 9 |
10 | 11 | 12 |
13 | 14 | 15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/xchar.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's xchar support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/chrono.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's chrono support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/ostr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's ostream support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/ranges.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's ranges support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/compile.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's compile-time support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnitCamS3-UserDemo 2 | UnitCamS3 user demo for hardware evaluation. 3 | 4 | If you looking UnitCAM S3 5MP, please check this branch: [unitcams3-5mp](https://github.com/m5stack/UnitCamS3-UserDemo/tree/unitcams3-5mp) 5 | 6 | # Firmware 7 | 8 | ## Tool Chains 9 | 10 | [PlatformIO](https://platformio.org/) 11 | 12 | ## Build 13 | 14 | - Upload firmware 15 | - Upload filesystem image 16 | 17 | # Web 18 | 19 | ## Tool Chains 20 | 21 | [Vite](https://vitejs.dev/) 22 | 23 | ## Dev 24 | 25 | Local Host 26 | 27 | ```shell 28 | npm run dev 29 | ``` 30 | 31 | JsonServer 32 | 33 | ```shell 34 | json-server --watch .\json_server\unitcams3.json 35 | ``` 36 | 37 | ## Build 38 | 39 | ```shell 40 | npm run build 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2021", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/std.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's std support (for formatting e.g. std::filesystem::path, std::thread::id, std::monostate, 9 | // std::variant, ...) 10 | // 11 | 12 | #if !defined(SPDLOG_USE_STD_FORMAT) 13 | # if !defined(SPDLOG_FMT_EXTERNAL) 14 | # ifdef SPDLOG_HEADER_ONLY 15 | # ifndef FMT_HEADER_ONLY 16 | # define FMT_HEADER_ONLY 17 | # endif 18 | # endif 19 | # include 20 | # else 21 | # include 22 | # endif 23 | #endif 24 | -------------------------------------------------------------------------------- /firmware/src/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-10-31 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include 12 | #include 13 | #include "hal/hal.h" 14 | #include "servers/servers.h" 15 | 16 | 17 | void setup() 18 | { 19 | // Init 20 | HAL::hal::GetHal()->init(); 21 | 22 | // Start server 23 | if (HAL::hal::GetHal()->getConfig().start_poster == "yes") 24 | UserDemoServers::start_poster_server(); 25 | else if (HAL::hal::GetHal()->getConfig().start_shooter == "yes") 26 | UserDemoServers::start_shooter_server(); 27 | else 28 | UserDemoServers::start_ap_server(); 29 | } 30 | 31 | 32 | void loop() 33 | { 34 | delay(5000); 35 | } 36 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/periodic_worker-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | namespace spdlog { 11 | namespace details { 12 | 13 | // stop the worker thread and join it 14 | SPDLOG_INLINE periodic_worker::~periodic_worker() 15 | { 16 | if (worker_thread_.joinable()) 17 | { 18 | { 19 | std::lock_guard lock(mutex_); 20 | active_ = false; 21 | } 22 | cv_.notify_one(); 23 | worker_thread_.join(); 24 | } 25 | } 26 | 27 | } // namespace details 28 | } // namespace spdlog 29 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/console_globals.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | 12 | struct console_mutex 13 | { 14 | using mutex_t = std::mutex; 15 | static mutex_t &mutex() 16 | { 17 | static mutex_t s_mutex; 18 | return s_mutex; 19 | } 20 | }; 21 | 22 | struct console_nullmutex 23 | { 24 | using mutex_t = null_mutex; 25 | static mutex_t &mutex() 26 | { 27 | static mutex_t s_mutex; 28 | return s_mutex; 29 | } 30 | }; 31 | } // namespace details 32 | } // namespace spdlog 33 | -------------------------------------------------------------------------------- /web/src/assets/poster-interval-list.ts: -------------------------------------------------------------------------------- 1 | interface PosterInterval { 2 | label: string; 3 | value: number; 4 | } 5 | export const posterIntervalList: PosterInterval[] = [ 6 | { 7 | label: "5 seconds", 8 | value: 5, 9 | }, 10 | { 11 | label: "10 seconds", 12 | value: 10, 13 | }, 14 | { 15 | label: "30 seconds", 16 | value: 30, 17 | }, 18 | { 19 | label: "1 minute", 20 | value: 60, 21 | }, 22 | { 23 | label: "5 minutes", 24 | value: 300, 25 | }, 26 | { 27 | label: "10 minutes", 28 | value: 600, 29 | }, 30 | { 31 | label: "30 minutes", 32 | value: 1800, 33 | }, 34 | { 35 | label: "1 hour", 36 | value: 3600, 37 | }, 38 | { 39 | label: "12 hours", 40 | value: 43200, 41 | }, 42 | { 43 | label: "24 hours", 44 | value: 86400, 45 | }, 46 | ]; 47 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | 12 | SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const 13 | { 14 | return msg_level >= level_.load(std::memory_order_relaxed); 15 | } 16 | 17 | SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) 18 | { 19 | level_.store(log_level, std::memory_order_relaxed); 20 | } 21 | 22 | SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const 23 | { 24 | return static_cast(level_.load(std::memory_order_relaxed)); 25 | } 26 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/cfg/helpers.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | namespace cfg { 11 | namespace helpers { 12 | // 13 | // Init levels from given string 14 | // 15 | // Examples: 16 | // 17 | // set global level to debug: "debug" 18 | // turn off all logging except for logger1: "off,logger1=debug" 19 | // turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info" 20 | // 21 | SPDLOG_API void load_levels(const std::string &txt); 22 | } // namespace helpers 23 | 24 | } // namespace cfg 25 | } // namespace spdlog 26 | 27 | #ifdef SPDLOG_HEADER_ONLY 28 | # include "helpers-inl.h" 29 | #endif // SPDLOG_HEADER_ONLY 30 | -------------------------------------------------------------------------------- /firmware/lib/AsyncTCP/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "AsyncTCP Configuration" 2 | 3 | choice ASYNC_TCP_RUNNING_CORE 4 | bool "Core on which AsyncTCP's thread is running" 5 | default ASYNC_TCP_RUN_CORE1 6 | help 7 | Select on which core AsyncTCP is running 8 | 9 | config ASYNC_TCP_RUN_CORE0 10 | bool "CORE 0" 11 | config ASYNC_TCP_RUN_CORE1 12 | bool "CORE 1" 13 | config ASYNC_TCP_RUN_NO_AFFINITY 14 | bool "BOTH" 15 | 16 | endchoice 17 | 18 | config ASYNC_TCP_RUNNING_CORE 19 | int 20 | default 0 if ASYNC_TCP_RUN_CORE0 21 | default 1 if ASYNC_TCP_RUN_CORE1 22 | default -1 if ASYNC_TCP_RUN_NO_AFFINITY 23 | 24 | config ASYNC_TCP_USE_WDT 25 | bool "Enable WDT for the AsyncTCP task" 26 | default "y" 27 | help 28 | Enable WDT for the AsyncTCP task, so it will trigger if a handler is locking the thread. 29 | 30 | endmenu 31 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/synchronous_factory.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "registry.h" 7 | 8 | namespace spdlog { 9 | 10 | // Default logger factory- creates synchronous loggers 11 | class logger; 12 | 13 | struct synchronous_factory 14 | { 15 | template 16 | static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) 17 | { 18 | auto sink = std::make_shared(std::forward(args)...); 19 | auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); 20 | details::registry::instance().initialize_logger(new_logger); 21 | return new_logger; 22 | } 23 | }; 24 | } // namespace spdlog 25 | -------------------------------------------------------------------------------- /web/src/components/shooter/card-shooter-start.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { useEffect } from "react"; 4 | import CardShooterNotice from "../../components/shooter/card-shooter-notice"; 5 | 6 | export default function CardShooterStart() { 7 | function handleStartShooter() { 8 | console.log("start shooter"); 9 | fetch("/api/v1/start_shooter") 10 | .then((response) => response.json()) 11 | .then((data) => { 12 | console.log(data); 13 | }) 14 | .catch((error) => { 15 | if (error instanceof TypeError && error.message.includes("API key")) { 16 | console.error("Invalid API key:", error); 17 | } else { 18 | console.error("There was a problem with the Fetch operation:", error); 19 | } 20 | }); 21 | } 22 | useEffect(() => { 23 | handleStartShooter(); 24 | }, []); 25 | 26 | return ; 27 | } 28 | -------------------------------------------------------------------------------- /web/src/components/poster/card-poster.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { Button } from "@nextui-org/react"; 4 | import { useNavigate } from "react-router-dom"; 5 | 6 | export default function CardPoster() { 7 | const navigate = useNavigate(); 8 | 9 | return ( 10 |
11 |
12 |

Image Poster

13 | 21 |
22 | 23 |
24 |

25 | Posting captured image to 26 | EzData 27 | regularly 28 |

29 |
30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /web/src/components/shooter/card-shooter.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { Button } from "@nextui-org/react"; 4 | import { useNavigate } from "react-router-dom"; 5 | 6 | export default function CardShooter() { 7 | const navigate = useNavigate(); 8 | 9 | return ( 10 |
11 |
12 |

Interval Shooting

13 | 21 |
22 | 23 |
24 |

25 | Save captured image to 26 | SD Card 27 | regularly 28 |

29 |
30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /firmware/lib/AsyncTCP/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: python 3 | os: 4 | - linux 5 | 6 | git: 7 | depth: false 8 | 9 | stages: 10 | - build 11 | 12 | jobs: 13 | include: 14 | 15 | - name: "Arduino Build" 16 | if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) 17 | stage: build 18 | script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 19 | 20 | - name: "PlatformIO Build" 21 | if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) 22 | stage: build 23 | script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1 24 | 25 | notifications: 26 | email: 27 | on_success: change 28 | on_failure: change 29 | webhooks: 30 | urls: 31 | - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 32 | on_success: change # options: [always|never|change] default: always 33 | on_failure: always # options: [always|never|change] default: always 34 | on_start: false # default: false 35 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/src/SPIFFSEditor.h: -------------------------------------------------------------------------------- 1 | #ifndef SPIFFSEditor_H_ 2 | #define SPIFFSEditor_H_ 3 | #include 4 | 5 | class SPIFFSEditor: public AsyncWebHandler { 6 | private: 7 | fs::FS _fs; 8 | String _username; 9 | String _password; 10 | bool _authenticated; 11 | uint32_t _startTime; 12 | public: 13 | #ifdef ESP32 14 | SPIFFSEditor(const fs::FS& fs, const String& username=String(), const String& password=String()); 15 | #else 16 | SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS); 17 | #endif 18 | virtual bool canHandle(AsyncWebServerRequest *request) override final; 19 | virtual void handleRequest(AsyncWebServerRequest *request) override final; 20 | virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final; 21 | virtual bool isRequestHandlerTrivial() override final {return false;} 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"ESP Async WebServer", 3 | "description":"Asynchronous HTTP and WebSocket Server Library for ESP8266 and ESP32", 4 | "keywords":"http,async,websocket,webserver", 5 | "authors": 6 | { 7 | "name": "Hristo Gochkov", 8 | "maintainer": true 9 | }, 10 | "repository": 11 | { 12 | "type": "git", 13 | "url": "https://github.com/me-no-dev/ESPAsyncWebServer.git" 14 | }, 15 | "version": "1.2.3", 16 | "license": "LGPL-3.0", 17 | "frameworks": "arduino", 18 | "platforms": ["espressif8266", "espressif32"], 19 | "dependencies": [ 20 | { 21 | "owner": "me-no-dev", 22 | "name": "ESPAsyncTCP", 23 | "version": "^1.2.2", 24 | "platforms": "espressif8266" 25 | }, 26 | { 27 | "owner": "me-no-dev", 28 | "name": "AsyncTCP", 29 | "version": "^1.1.1", 30 | "platforms": "espressif32" 31 | }, 32 | { 33 | "name": "Hash", 34 | "platforms": "espressif8266" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | 11 | namespace sinks { 12 | class SPDLOG_API sink 13 | { 14 | public: 15 | virtual ~sink() = default; 16 | virtual void log(const details::log_msg &msg) = 0; 17 | virtual void flush() = 0; 18 | virtual void set_pattern(const std::string &pattern) = 0; 19 | virtual void set_formatter(std::unique_ptr sink_formatter) = 0; 20 | 21 | void set_level(level::level_enum log_level); 22 | level::level_enum level() const; 23 | bool should_log(level::level_enum msg_level) const; 24 | 25 | protected: 26 | // sink log level - default is all 27 | level_t level_{level::trace}; 28 | }; 29 | 30 | } // namespace sinks 31 | } // namespace spdlog 32 | 33 | #ifdef SPDLOG_HEADER_ONLY 34 | # include "sink-inl.h" 35 | #endif 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 M5Stack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/src/components/hardware-test/card-led-test.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { Switch } from "@nextui-org/react"; 4 | import { useState } from "react"; 5 | 6 | type LedState = "ON" | "OFF"; 7 | 8 | export default function CardLedTest() { 9 | const [ledState, setLedState] = useState("ON" as LedState); 10 | 11 | function handleLedStateSwitch(params: boolean) { 12 | console.log("change led state: " + params); 13 | 14 | if (params) { 15 | fetch("/api/v1/led_on"); 16 | } else { 17 | fetch("/api/v1/led_off"); 18 | } 19 | 20 | setLedState(params ? "ON" : "OFF"); 21 | } 22 | 23 | return ( 24 |
25 |
26 |

LED

27 | 32 |
33 | 34 |
35 |

{"LED is " + ledState}

36 |
37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/log_msg_buffer.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace spdlog { 9 | namespace details { 10 | 11 | // Extend log_msg with internal buffer to store its payload. 12 | // This is needed since log_msg holds string_views that points to stack data. 13 | 14 | class SPDLOG_API log_msg_buffer : public log_msg 15 | { 16 | memory_buf_t buffer; 17 | void update_string_views(); 18 | 19 | public: 20 | log_msg_buffer() = default; 21 | explicit log_msg_buffer(const log_msg &orig_msg); 22 | log_msg_buffer(const log_msg_buffer &other); 23 | log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT; 24 | log_msg_buffer &operator=(const log_msg_buffer &other); 25 | log_msg_buffer &operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT; 26 | }; 27 | 28 | } // namespace details 29 | } // namespace spdlog 30 | 31 | #ifdef SPDLOG_HEADER_ONLY 32 | # include "log_msg_buffer-inl.h" 33 | #endif 34 | -------------------------------------------------------------------------------- /firmware/src/mooncake/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Forairaaaaa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/fmt.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016-2018 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // 9 | // Include a bundled header-only copy of fmtlib or an external one. 10 | // By default spdlog include its own copy. 11 | // 12 | 13 | #if defined(SPDLOG_USE_STD_FORMAT) // SPDLOG_USE_STD_FORMAT is defined - use std::format 14 | # include 15 | #elif !defined(SPDLOG_FMT_EXTERNAL) 16 | # if !defined(SPDLOG_COMPILED_LIB) && !defined(FMT_HEADER_ONLY) 17 | # define FMT_HEADER_ONLY 18 | # endif 19 | # ifndef FMT_USE_WINDOWS_H 20 | # define FMT_USE_WINDOWS_H 0 21 | # endif 22 | // enable the 'n' flag in for backward compatibility with fmt 6.x 23 | # define FMT_DEPRECATED_N_SPECIFIER 24 | // enable ostream formatting for backward compatibility with fmt 8.x 25 | # define FMT_DEPRECATED_OSTREAM 26 | 27 | # include 28 | # include 29 | 30 | #else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib 31 | # include 32 | # include 33 | #endif 34 | -------------------------------------------------------------------------------- /firmware/lib/AsyncTCP/README.md: -------------------------------------------------------------------------------- 1 | # AsyncTCP 2 | [![Build Status](https://travis-ci.org/me-no-dev/AsyncTCP.svg?branch=master)](https://travis-ci.org/me-no-dev/AsyncTCP) ![](https://github.com/me-no-dev/AsyncTCP/workflows/Async%20TCP%20CI/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2f7e4d1df8b446d192cbfec6dc174d2d)](https://www.codacy.com/manual/me-no-dev/AsyncTCP?utm_source=github.com&utm_medium=referral&utm_content=me-no-dev/AsyncTCP&utm_campaign=Badge_Grade) 3 | 4 | ### Async TCP Library for ESP32 Arduino 5 | 6 | [![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 7 | 8 | This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. 9 | 10 | This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) 11 | 12 | ## AsyncClient and AsyncServer 13 | The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. 14 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/cfg/env.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | #include 6 | #include 7 | #include 8 | 9 | // 10 | // Init levels and patterns from env variables SPDLOG_LEVEL 11 | // Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger). 12 | // Note - fallback to "info" level on unrecognized levels 13 | // 14 | // Examples: 15 | // 16 | // set global level to debug: 17 | // export SPDLOG_LEVEL=debug 18 | // 19 | // turn off all logging except for logger1: 20 | // export SPDLOG_LEVEL="*=off,logger1=debug" 21 | // 22 | 23 | // turn off all logging except for logger1 and logger2: 24 | // export SPDLOG_LEVEL="off,logger1=debug,logger2=info" 25 | 26 | namespace spdlog { 27 | namespace cfg { 28 | inline void load_env_levels() 29 | { 30 | auto env_val = details::os::getenv("SPDLOG_LEVEL"); 31 | if (!env_val.empty()) 32 | { 33 | helpers::load_levels(env_val); 34 | } 35 | } 36 | 37 | } // namespace cfg 38 | } // namespace spdlog 39 | -------------------------------------------------------------------------------- /web/json_server/unitcams3.json: -------------------------------------------------------------------------------- 1 | { 2 | "get_mac": { 3 | "msg": "ok", 4 | "mac": "12:34:56:78:90:12" 5 | }, 6 | "check_sdcard": { 7 | "msg": "ok", 8 | "info": "SD Card Not Valid" 9 | }, 10 | "led_on": { 11 | "msg": "ok" 12 | }, 13 | "led_off": { 14 | "msg": "ok" 15 | }, 16 | "get_config": { 17 | "wifiSsid": "qwerqwerqwer", 18 | "wifiPass": "dfdfdf", 19 | "startPoster": "no", 20 | "waitApFirst": "no", 21 | "nickname": "UnitCamS3", 22 | "postInterval": 5, 23 | "timeZone": "GMT+0" 24 | }, 25 | "set_config": { 26 | "wifiSsid": "qwerqwerqwer", 27 | "wifiPass": "dfdfdf", 28 | "startPoster": "no", 29 | "nickname": "UnitCamS3", 30 | "postInterval": 5, 31 | "timeZone": "GMT+0", 32 | "apiId": "v1" 33 | }, 34 | "reset_config": { 35 | "msg": "ok" 36 | }, 37 | "get_wifi_list": { 38 | "wifiList": [ 39 | "tjrtjrtjrtjj", 40 | "啊??", 41 | " 小米共享WiFi_12341234", 42 | "$%^%$^%$#^", 43 | "0987098790-LLLdgfsdg", 44 | "gggdgdgd", 45 | "R s s s ss s", 46 | "C**99986___dfidung???" 47 | ] 48 | }, 49 | "start_poster": { 50 | "msg": "ok" 51 | }, 52 | "start_shooter": { 53 | "msg": "ok" 54 | } 55 | } -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/null_mutex.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | // null, no cost dummy "mutex" and dummy "atomic" int 9 | 10 | namespace spdlog { 11 | namespace details { 12 | struct null_mutex 13 | { 14 | void lock() const {} 15 | void unlock() const {} 16 | }; 17 | 18 | struct null_atomic_int 19 | { 20 | int value; 21 | null_atomic_int() = default; 22 | 23 | explicit null_atomic_int(int new_value) 24 | : value(new_value) 25 | {} 26 | 27 | int load(std::memory_order = std::memory_order_relaxed) const 28 | { 29 | return value; 30 | } 31 | 32 | void store(int new_value, std::memory_order = std::memory_order_relaxed) 33 | { 34 | value = new_value; 35 | } 36 | 37 | int exchange(int new_value, std::memory_order = std::memory_order_relaxed) 38 | { 39 | std::swap(new_value, value); 40 | return new_value; // return value before the call 41 | } 42 | }; 43 | 44 | } // namespace details 45 | } // namespace spdlog 46 | -------------------------------------------------------------------------------- /web/src/components/title-bar.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | // import { Link } from "@nextui-org/react"; 4 | 5 | export default function TitleBar() { 6 | // const docLink: string = "https://www.github.com"; 7 | // const githubLink: string = "https://www.github.com"; 8 | 9 | return ( 10 |
11 |
12 |

UNIT-CAM-S3

13 | 14 |
15 |

User Demo

16 | 17 |
18 | 19 | {/* 25 | Document 26 | 27 | 28 | 34 | Github 35 | */} 36 | 37 |
38 |
39 |
40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /firmware/lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/log_msg-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | 12 | namespace spdlog { 13 | namespace details { 14 | 15 | SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, spdlog::source_loc loc, string_view_t a_logger_name, 16 | spdlog::level::level_enum lvl, spdlog::string_view_t msg) 17 | : logger_name(a_logger_name) 18 | , level(lvl) 19 | , time(log_time) 20 | #ifndef SPDLOG_NO_THREAD_ID 21 | , thread_id(os::thread_id()) 22 | #endif 23 | , source(loc) 24 | , payload(msg) 25 | {} 26 | 27 | SPDLOG_INLINE log_msg::log_msg( 28 | spdlog::source_loc loc, string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg) 29 | : log_msg(os::now(), loc, a_logger_name, lvl, msg) 30 | {} 31 | 32 | SPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg) 33 | : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg) 34 | {} 35 | 36 | } // namespace details 37 | } // namespace spdlog 38 | -------------------------------------------------------------------------------- /firmware/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:m5stack-unitcams3] 12 | platform = espressif32@6.4.0 13 | 14 | ; UnitCamS3 and esp32s3box use the same module 15 | board = esp32s3box 16 | framework = arduino 17 | 18 | board_build.f_cpu = 240000000L 19 | board_build.f_flash = 80000000L 20 | board_build.flash_mode = qio 21 | board_build.flash_size = 16MB 22 | 23 | build_flags = 24 | -DCORE_DEBUG_LEVEL=3 25 | -DBOARD_HAS_PSRAM 26 | ; -mfix-esp32-psram-cache-issue 27 | -DCONFIG_ARDUINO_LOOP_STACK_SIZE=16384 28 | -DCONFIG_SPIRAM_MODE_OCT=y 29 | -I./src/mooncake/src/spdlog/include 30 | -I./src/mooncake/src/ 31 | -DARDUINO_USB_CDC_ON_BOOT=0 32 | -DARDUINO_USB_MODE=0 33 | 34 | 35 | ; board_build.partitions = huge_app.csv 36 | board_build.partitions = custom.csv 37 | board_build.filesystem = littlefs 38 | 39 | monitor_filters = esp32_exception_decoder 40 | monitor_speed = 115200 41 | 42 | lib_deps = 43 | bblanchon/ArduinoJson @ ~6.21.3 44 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/log_msg.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | struct SPDLOG_API log_msg 12 | { 13 | log_msg() = default; 14 | log_msg(log_clock::time_point log_time, source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); 15 | log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); 16 | log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg); 17 | log_msg(const log_msg &other) = default; 18 | log_msg &operator=(const log_msg &other) = default; 19 | 20 | string_view_t logger_name; 21 | level::level_enum level{level::off}; 22 | log_clock::time_point time; 23 | size_t thread_id{0}; 24 | 25 | // wrapping the formatted text with color (updated by pattern_formatter). 26 | mutable size_t color_range_start{0}; 27 | mutable size_t color_range_end{0}; 28 | 29 | source_loc source; 30 | string_view_t payload; 31 | }; 32 | } // namespace details 33 | } // namespace spdlog 34 | 35 | #ifdef SPDLOG_HEADER_ONLY 36 | # include "log_msg-inl.h" 37 | #endif 38 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/basic_file_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | namespace sinks { 15 | 16 | template 17 | SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, bool truncate, const file_event_handlers &event_handlers) 18 | : file_helper_{event_handlers} 19 | { 20 | file_helper_.open(filename, truncate); 21 | } 22 | 23 | template 24 | SPDLOG_INLINE const filename_t &basic_file_sink::filename() const 25 | { 26 | return file_helper_.filename(); 27 | } 28 | 29 | template 30 | SPDLOG_INLINE void basic_file_sink::sink_it_(const details::log_msg &msg) 31 | { 32 | memory_buf_t formatted; 33 | base_sink::formatter_->format(msg, formatted); 34 | file_helper_.write(formatted); 35 | } 36 | 37 | template 38 | SPDLOG_INLINE void basic_file_sink::flush_() 39 | { 40 | file_helper_.flush(); 41 | } 42 | 43 | } // namespace sinks 44 | } // namespace spdlog 45 | -------------------------------------------------------------------------------- /web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unitcams3-user-demo-vite", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@nextui-org/react": "^2.2.9", 14 | "framer-motion": "^10.16.5", 15 | "json-server": "^0.17.4", 16 | "localforage": "^1.10.0", 17 | "match-sorter": "^6.3.1", 18 | "qrcode.react": "^3.1.0", 19 | "react": "^18.2.0", 20 | "react-dom": "^18.2.0", 21 | "react-router-dom": "^6.19.0", 22 | "sort-by": "^0.0.2" 23 | }, 24 | "devDependencies": { 25 | "@types/react": "^18.2.37", 26 | "@types/react-dom": "^18.2.15", 27 | "@typescript-eslint/eslint-plugin": "^6.10.0", 28 | "@typescript-eslint/parser": "^6.10.0", 29 | "@vitejs/plugin-react": "^4.2.0", 30 | "autoprefixer": "^10.4.16", 31 | "eslint": "^8.53.0", 32 | "eslint-plugin-react-hooks": "^4.6.0", 33 | "eslint-plugin-react-refresh": "^0.4.4", 34 | "postcss": "^8.4.31", 35 | "tailwindcss": "^3.3.5", 36 | "typescript": "^5.2.2", 37 | "vite": "^5.0.0", 38 | "vite-plugin-compression": "^0.5.1", 39 | "vite-plugin-singlefile": "^0.13.5" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | # React + TypeScript + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | 10 | ## Expanding the ESLint configuration 11 | 12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: 13 | 14 | - Configure the top-level `parserOptions` property like this: 15 | 16 | ```js 17 | export default { 18 | // other rules... 19 | parserOptions: { 20 | ecmaVersion: 'latest', 21 | sourceType: 'module', 22 | project: ['./tsconfig.json', './tsconfig.node.json'], 23 | tsconfigRootDir: __dirname, 24 | }, 25 | } 26 | ``` 27 | 28 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` 29 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked` 30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list 31 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/backtracer.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | // Store log messages in circular buffer. 14 | // Useful for storing debug data in case of error/warning happens. 15 | 16 | namespace spdlog { 17 | namespace details { 18 | class SPDLOG_API backtracer 19 | { 20 | mutable std::mutex mutex_; 21 | std::atomic enabled_{false}; 22 | circular_q messages_; 23 | 24 | public: 25 | backtracer() = default; 26 | backtracer(const backtracer &other); 27 | 28 | backtracer(backtracer &&other) SPDLOG_NOEXCEPT; 29 | backtracer &operator=(backtracer other); 30 | 31 | void enable(size_t size); 32 | void disable(); 33 | bool enabled() const; 34 | void push_back(const log_msg &msg); 35 | bool empty() const; 36 | 37 | // pop all items in the q and apply the given fun on each of them. 38 | void foreach_pop(std::function fun); 39 | }; 40 | 41 | } // namespace details 42 | } // namespace spdlog 43 | 44 | #ifdef SPDLOG_HEADER_ONLY 45 | # include "backtracer-inl.h" 46 | #endif 47 | -------------------------------------------------------------------------------- /web/src/routes/page-root.tsx: -------------------------------------------------------------------------------- 1 | import { Card, Divider } from "@nextui-org/react"; 2 | import TitleBar from "../components/title-bar"; 3 | import CardCameraTest from "../components/hardware-test/card-camera-test"; 4 | import CardSdCardTest from "../components/hardware-test/card-sd-card-test"; 5 | import CardMicTest from "../components/hardware-test/card-mic-test"; 6 | import CardLedTest from "../components/hardware-test/card-led-test"; 7 | import CardPoster from "../components/poster/card-poster"; 8 | import CardShooter from "../components/shooter/card-shooter"; 9 | 10 | function PageRoot() { 11 | return ( 12 |
13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 | ); 42 | } 43 | 44 | export default PageRoot; 45 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Gabi Melman. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -- NOTE: Third party dependency used by this software -- 24 | This software depends on the fmt lib (MIT License), 25 | and users must comply to its license: https://github.com/fmtlib/fmt/blob/master/LICENSE.rst 26 | 27 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/stdout_color_sinks-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | 15 | template 16 | SPDLOG_INLINE std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode) 17 | { 18 | return Factory::template create(logger_name, mode); 19 | } 20 | 21 | template 22 | SPDLOG_INLINE std::shared_ptr stdout_color_st(const std::string &logger_name, color_mode mode) 23 | { 24 | return Factory::template create(logger_name, mode); 25 | } 26 | 27 | template 28 | SPDLOG_INLINE std::shared_ptr stderr_color_mt(const std::string &logger_name, color_mode mode) 29 | { 30 | return Factory::template create(logger_name, mode); 31 | } 32 | 33 | template 34 | SPDLOG_INLINE std::shared_ptr stderr_color_st(const std::string &logger_name, color_mode mode) 35 | { 36 | return Factory::template create(logger_name, mode); 37 | } 38 | } // namespace spdlog 39 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/cfg/argv.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | #include 6 | #include 7 | 8 | // 9 | // Init log levels using each argv entry that starts with "SPDLOG_LEVEL=" 10 | // 11 | // set all loggers to debug level: 12 | // example.exe "SPDLOG_LEVEL=debug" 13 | 14 | // set logger1 to trace level 15 | // example.exe "SPDLOG_LEVEL=logger1=trace" 16 | 17 | // turn off all logging except for logger1 and logger2: 18 | // example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info" 19 | 20 | namespace spdlog { 21 | namespace cfg { 22 | 23 | // search for SPDLOG_LEVEL= in the args and use it to init the levels 24 | inline void load_argv_levels(int argc, const char **argv) 25 | { 26 | const std::string spdlog_level_prefix = "SPDLOG_LEVEL="; 27 | for (int i = 1; i < argc; i++) 28 | { 29 | std::string arg = argv[i]; 30 | if (arg.find(spdlog_level_prefix) == 0) 31 | { 32 | auto levels_string = arg.substr(spdlog_level_prefix.size()); 33 | helpers::load_levels(levels_string); 34 | } 35 | } 36 | } 37 | 38 | inline void load_argv_levels(int argc, char **argv) 39 | { 40 | load_argv_levels(argc, const_cast(argv)); 41 | } 42 | 43 | } // namespace cfg 44 | } // namespace spdlog 45 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/null_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace spdlog { 13 | namespace sinks { 14 | 15 | template 16 | class null_sink : public base_sink 17 | { 18 | protected: 19 | void sink_it_(const details::log_msg &) override {} 20 | void flush_() override {} 21 | }; 22 | 23 | using null_sink_mt = null_sink; 24 | using null_sink_st = null_sink; 25 | 26 | } // namespace sinks 27 | 28 | template 29 | inline std::shared_ptr null_logger_mt(const std::string &logger_name) 30 | { 31 | auto null_logger = Factory::template create(logger_name); 32 | null_logger->set_level(level::off); 33 | return null_logger; 34 | } 35 | 36 | template 37 | inline std::shared_ptr null_logger_st(const std::string &logger_name) 38 | { 39 | auto null_logger = Factory::template create(logger_name); 40 | null_logger->set_level(level::off); 41 | return null_logger; 42 | } 43 | 44 | } // namespace spdlog 45 | -------------------------------------------------------------------------------- /firmware/src/hal/hal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hal.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-09-13 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include 12 | #include 13 | #include "hal.h" 14 | 15 | 16 | using namespace HAL; 17 | 18 | 19 | void hal::init() 20 | { 21 | spdlog::set_pattern("[%M:%S] [%^%L%$] %v"); 22 | spdlog::info("hal init"); 23 | 24 | 25 | // Cam 26 | _cam_init(); 27 | 28 | 29 | // Mic 30 | mic = new m5::Mic_Class; 31 | auto mic_config = mic->config(); 32 | mic_config.pin_data_in = HAL_PIN_MIC_DATA; 33 | mic_config.pin_ws = HAL_PIN_MIC_CLK; 34 | mic_config.task_priority = 5; 35 | mic_config.magnification = 1; 36 | // mic_config.noise_filter_level = 1; 37 | // mic_config.over_sampling = 4; 38 | // mic_config.over_sampling = 1; 39 | // mic_config.sample_rate = 48000; 40 | mic->config(mic_config); 41 | mic->begin(); 42 | 43 | 44 | // Led 45 | gpio_reset_pin(GPIO_NUM_14); 46 | pinMode(14, OUTPUT); 47 | setLed(false); 48 | 49 | // Config 50 | _config_init(); 51 | } 52 | 53 | 54 | void hal::setLed(bool state) 55 | { 56 | if (state) 57 | digitalWrite(14, 0); 58 | else 59 | digitalWrite(14, 1); 60 | } 61 | 62 | 63 | hal* hal::_hal = nullptr; 64 | 65 | hal* hal::GetHal() 66 | { 67 | if (_hal == nullptr) 68 | { 69 | _hal = new hal; 70 | } 71 | return _hal; 72 | } 73 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/ostream_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace spdlog { 13 | namespace sinks { 14 | template 15 | class ostream_sink final : public base_sink 16 | { 17 | public: 18 | explicit ostream_sink(std::ostream &os, bool force_flush = false) 19 | : ostream_(os) 20 | , force_flush_(force_flush) 21 | {} 22 | ostream_sink(const ostream_sink &) = delete; 23 | ostream_sink &operator=(const ostream_sink &) = delete; 24 | 25 | protected: 26 | void sink_it_(const details::log_msg &msg) override 27 | { 28 | memory_buf_t formatted; 29 | base_sink::formatter_->format(msg, formatted); 30 | ostream_.write(formatted.data(), static_cast(formatted.size())); 31 | if (force_flush_) 32 | { 33 | ostream_.flush(); 34 | } 35 | } 36 | 37 | void flush_() override 38 | { 39 | ostream_.flush(); 40 | } 41 | 42 | std::ostream &ostream_; 43 | bool force_flush_; 44 | }; 45 | 46 | using ostream_sink_mt = ostream_sink; 47 | using ostream_sink_st = ostream_sink; 48 | 49 | } // namespace sinks 50 | } // namespace spdlog 51 | -------------------------------------------------------------------------------- /firmware/include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/fmt/bundled/fmt.license.rst: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - present, Victor Zverovich 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | --- Optional exception to the license --- 23 | 24 | As an exception, if, as a result of your compiling your source code, portions 25 | of this Software are embedded into a machine-executable object form of such 26 | source code, you may redistribute such embedded portions in such object form 27 | without including the above copyright and permission notices. 28 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: python 4 | 5 | os: 6 | - linux 7 | 8 | git: 9 | depth: false 10 | 11 | stages: 12 | - build 13 | 14 | jobs: 15 | include: 16 | 17 | - name: "Build Arduino ESP32" 18 | if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) 19 | stage: build 20 | script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp32 21 | 22 | - name: "Build Arduino ESP8266" 23 | if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) 24 | stage: build 25 | script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp8266 26 | 27 | - name: "Build Platformio ESP32" 28 | if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) 29 | stage: build 30 | script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp32 1 1 31 | 32 | - name: "Build Platformio ESP8266" 33 | if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) 34 | stage: build 35 | script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp8266 1 1 36 | 37 | notifications: 38 | email: 39 | on_success: change 40 | on_failure: change 41 | webhooks: 42 | urls: 43 | - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 44 | on_success: change # options: [always|never|change] default: always 45 | on_failure: always # options: [always|never|change] default: always 46 | on_start: never # options: [always|never|change] default: always 47 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/src/WebAuthentication.h: -------------------------------------------------------------------------------- 1 | /* 2 | Asynchronous WebServer library for Espressif MCUs 3 | 4 | Copyright (c) 2016 Hristo Gochkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef WEB_AUTHENTICATION_H_ 23 | #define WEB_AUTHENTICATION_H_ 24 | 25 | #include "Arduino.h" 26 | 27 | bool checkBasicAuthentication(const char * header, const char * username, const char * password); 28 | String requestDigestAuthentication(const char * realm); 29 | bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri); 30 | 31 | //for storing hashed versions on the device that can be authenticated against 32 | String generateDigestHash(const char * username, const char * password, const char * realm); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /web/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { createBrowserRouter, RouterProvider } from "react-router-dom"; 4 | import { NextUIProvider } from "@nextui-org/react"; 5 | import "./index.css"; 6 | import ErrorPage from "./error-page"; 7 | import PageRoot from "./routes/page-root"; 8 | import PagePoster from "./routes/page-poster"; 9 | import PagePosterStart from "./routes/page-poster-start"; 10 | import PageShooter from "./routes/page-shooter"; 11 | import PageShooterStart from "./routes/page-shooter-start"; 12 | 13 | const router = createBrowserRouter([ 14 | { 15 | path: "/", 16 | element: ( 17 | 18 | 19 | 20 | ), 21 | errorElement: , 22 | }, 23 | { 24 | path: "/poster", 25 | element: ( 26 | 27 | 28 | 29 | ), 30 | }, 31 | { 32 | path: "/poster_start", 33 | element: ( 34 | 35 | 36 | 37 | ), 38 | }, 39 | { 40 | path: "/shooter", 41 | element: ( 42 | 43 | 44 | 45 | ), 46 | }, 47 | { 48 | path: "/shooter_start", 49 | element: ( 50 | 51 | 52 | 53 | ), 54 | }, 55 | ]); 56 | 57 | ReactDOM.createRoot(document.getElementById("root")!).render( 58 | 59 | 60 | 61 | ); 62 | -------------------------------------------------------------------------------- /web/src/components/hardware-test/card-sd-card-test.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { useState } from "react"; 4 | import { Button } from "@nextui-org/react"; 5 | 6 | export default function CardSdCardTest() { 7 | const [sdCardInfo, setSdCardInfo] = useState( 8 | "Click the button to get SD card info" 9 | ); 10 | 11 | function handleUpdateSdCardInfo() { 12 | console.log("handle update sd card info"); 13 | 14 | setSdCardInfo("Updating..."); 15 | 16 | fetch("/api/v1/check_sdcard") 17 | .then((response) => response.json()) 18 | .then((data) => { 19 | console.log(data.info); 20 | setSdCardInfo(data.info); 21 | }) 22 | .catch((error) => { 23 | if (error instanceof TypeError && error.message.includes("API key")) { 24 | console.error("Invalid API key:", error); 25 | } else { 26 | console.error("There was a problem with the Fetch operation:", error); 27 | } 28 | setSdCardInfo("😓 Failed :("); 29 | }); 30 | } 31 | 32 | return ( 33 |
34 |
35 |

SD Card

36 | 37 | 46 |
47 | 48 |
49 |

{sdCardInfo}

50 |
51 |
52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /web/src/assets/time-zone-list.ts: -------------------------------------------------------------------------------- 1 | interface TimeZoneObject { 2 | label: string; 3 | value: string; 4 | } 5 | 6 | export const timeZoneList: TimeZoneObject[] = [ 7 | // GMT-... 8 | { label: "(GMT-12) Pacific/Wake", value: "GMT-12" }, 9 | { label: "(GMT-11) Pacific/Midway", value: "GMT-11" }, 10 | { label: "(GMT-10) Pacific/Honolulu", value: "GMT-10" }, 11 | { label: "(GMT-9) America/Adak", value: "GMT-9" }, 12 | { label: "(GMT-8) America/Anchorage", value: "GMT-8" }, 13 | { label: "(GMT-7) America/Los_Angeles", value: "GMT-7" }, 14 | { label: "(GMT-6) America/Denver", value: "GMT-6" }, 15 | { label: "(GMT-5) America/Chicago", value: "GMT-5" }, 16 | { label: "(GMT-4) America/New_York", value: "GMT-4" }, 17 | { label: "(GMT-3) America/Buenos_Aires", value: "GMT-3" }, 18 | { label: "(GMT-2) America/Noronha", value: "GMT-2" }, 19 | { label: "(GMT-1) Atlantic/Azores", value: "GMT-1" }, 20 | 21 | // GMT+... 22 | { label: "(GMT+0) Europe/London", value: "GMT+0" }, 23 | { label: "(GMT+1) Europe/Berlin", value: "GMT+1" }, 24 | { label: "(GMT+2) Europe/Athens", value: "GMT+2" }, 25 | { label: "(GMT+3) Europe/Moscow", value: "GMT+3" }, 26 | { label: "(GMT+4) Asia/Dubai", value: "GMT+4" }, 27 | { label: "(GMT+5) Asia/Karachi", value: "GMT+5" }, 28 | { label: "(GMT+5:30) Asia/Kolkata", value: "GMT+5:30" }, 29 | { label: "(GMT+6) Asia/Dhaka", value: "GMT+6" }, 30 | { label: "(GMT+7) Asia/Bangkok", value: "GMT+7" }, 31 | { label: "(GMT+8) Asia/Shanghai", value: "GMT+8" }, 32 | { label: "(GMT+9) Asia/Tokyo", value: "GMT+9" }, 33 | { label: "(GMT+9:30) Australia/Adelaide", value: "GMT+9:30" }, 34 | { label: "(GMT+10) Australia/Sydney", value: "GMT+10" }, 35 | { label: "(GMT+11) Pacific/Noumea", value: "GMT+11" }, 36 | { label: "(GMT+12) Pacific/Auckland", value: "GMT+12" }, 37 | ]; 38 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/base_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | // 6 | // base sink templated over a mutex (either dummy or real) 7 | // concrete implementation should override the sink_it_() and flush_() methods. 8 | // locking is taken care of in this class - no locking needed by the 9 | // implementers.. 10 | // 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace spdlog { 17 | namespace sinks { 18 | template 19 | class SPDLOG_API base_sink : public sink 20 | { 21 | public: 22 | base_sink(); 23 | explicit base_sink(std::unique_ptr formatter); 24 | ~base_sink() override = default; 25 | 26 | base_sink(const base_sink &) = delete; 27 | base_sink(base_sink &&) = delete; 28 | 29 | base_sink &operator=(const base_sink &) = delete; 30 | base_sink &operator=(base_sink &&) = delete; 31 | 32 | void log(const details::log_msg &msg) final; 33 | void flush() final; 34 | void set_pattern(const std::string &pattern) final; 35 | void set_formatter(std::unique_ptr sink_formatter) final; 36 | 37 | protected: 38 | // sink formatter 39 | std::unique_ptr formatter_; 40 | Mutex mutex_; 41 | 42 | virtual void sink_it_(const details::log_msg &msg) = 0; 43 | virtual void flush_() = 0; 44 | virtual void set_pattern_(const std::string &pattern); 45 | virtual void set_formatter_(std::unique_ptr sink_formatter); 46 | }; 47 | } // namespace sinks 48 | } // namespace spdlog 49 | 50 | #ifdef SPDLOG_HEADER_ONLY 51 | # include "base_sink-inl.h" 52 | #endif 53 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/stdout_color_sinks.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifdef _WIN32 7 | # include 8 | #else 9 | # include 10 | #endif 11 | 12 | #include 13 | 14 | namespace spdlog { 15 | namespace sinks { 16 | #ifdef _WIN32 17 | using stdout_color_sink_mt = wincolor_stdout_sink_mt; 18 | using stdout_color_sink_st = wincolor_stdout_sink_st; 19 | using stderr_color_sink_mt = wincolor_stderr_sink_mt; 20 | using stderr_color_sink_st = wincolor_stderr_sink_st; 21 | #else 22 | using stdout_color_sink_mt = ansicolor_stdout_sink_mt; 23 | using stdout_color_sink_st = ansicolor_stdout_sink_st; 24 | using stderr_color_sink_mt = ansicolor_stderr_sink_mt; 25 | using stderr_color_sink_st = ansicolor_stderr_sink_st; 26 | #endif 27 | } // namespace sinks 28 | 29 | template 30 | std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); 31 | 32 | template 33 | std::shared_ptr stdout_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic); 34 | 35 | template 36 | std::shared_ptr stderr_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); 37 | 38 | template 39 | std::shared_ptr stderr_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic); 40 | 41 | } // namespace spdlog 42 | 43 | #ifdef SPDLOG_HEADER_ONLY 44 | # include "stdout_color_sinks-inl.h" 45 | #endif 46 | -------------------------------------------------------------------------------- /firmware/lib/ESPAsyncWebServer/src/AsyncWebSynchronization.h: -------------------------------------------------------------------------------- 1 | #ifndef ASYNCWEBSYNCHRONIZATION_H_ 2 | #define ASYNCWEBSYNCHRONIZATION_H_ 3 | 4 | // Synchronisation is only available on ESP32, as the ESP8266 isn't using FreeRTOS by default 5 | 6 | #include 7 | 8 | #ifdef ESP32 9 | 10 | // This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore 11 | class AsyncWebLock 12 | { 13 | private: 14 | SemaphoreHandle_t _lock; 15 | mutable void *_lockedBy; 16 | 17 | public: 18 | AsyncWebLock() { 19 | _lock = xSemaphoreCreateBinary(); 20 | _lockedBy = NULL; 21 | xSemaphoreGive(_lock); 22 | } 23 | 24 | ~AsyncWebLock() { 25 | vSemaphoreDelete(_lock); 26 | } 27 | 28 | bool lock() const { 29 | extern void *pxCurrentTCB; 30 | if (_lockedBy != pxCurrentTCB) { 31 | xSemaphoreTake(_lock, portMAX_DELAY); 32 | _lockedBy = pxCurrentTCB; 33 | return true; 34 | } 35 | return false; 36 | } 37 | 38 | void unlock() const { 39 | _lockedBy = NULL; 40 | xSemaphoreGive(_lock); 41 | } 42 | }; 43 | 44 | #else 45 | 46 | // This is the 8266 version of the Sync Lock which is currently unimplemented 47 | class AsyncWebLock 48 | { 49 | 50 | public: 51 | AsyncWebLock() { 52 | } 53 | 54 | ~AsyncWebLock() { 55 | } 56 | 57 | bool lock() const { 58 | return false; 59 | } 60 | 61 | void unlock() const { 62 | } 63 | }; 64 | #endif 65 | 66 | class AsyncWebLockGuard 67 | { 68 | private: 69 | const AsyncWebLock *_lock; 70 | 71 | public: 72 | AsyncWebLockGuard(const AsyncWebLock &l) { 73 | if (l.lock()) { 74 | _lock = &l; 75 | } else { 76 | _lock = NULL; 77 | } 78 | } 79 | 80 | ~AsyncWebLockGuard() { 81 | if (_lock) { 82 | _lock->unlock(); 83 | } 84 | } 85 | }; 86 | 87 | #endif // ASYNCWEBSYNCHRONIZATION_H_ -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/callback_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | 15 | // callbacks type 16 | typedef std::function custom_log_callback; 17 | 18 | namespace sinks { 19 | /* 20 | * Trivial callback sink, gets a callback function and calls it on each log 21 | */ 22 | template 23 | class callback_sink final : public base_sink 24 | { 25 | public: 26 | explicit callback_sink(const custom_log_callback &callback) 27 | : callback_{callback} 28 | {} 29 | 30 | protected: 31 | void sink_it_(const details::log_msg &msg) override 32 | { 33 | callback_(msg); 34 | } 35 | void flush_() override{}; 36 | 37 | private: 38 | custom_log_callback callback_; 39 | }; 40 | 41 | using callback_sink_mt = callback_sink; 42 | using callback_sink_st = callback_sink; 43 | 44 | } // namespace sinks 45 | 46 | // 47 | // factory functions 48 | // 49 | template 50 | inline std::shared_ptr callback_logger_mt(const std::string &logger_name, const custom_log_callback &callback) 51 | { 52 | return Factory::template create(logger_name, callback); 53 | } 54 | 55 | template 56 | inline std::shared_ptr callback_logger_st(const std::string &logger_name, const custom_log_callback &callback) 57 | { 58 | return Factory::template create(logger_name, callback); 59 | } 60 | 61 | } // namespace spdlog 62 | -------------------------------------------------------------------------------- /web/src/components/hardware-test/card-camera-test.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { useState } from "react"; 4 | import { Button, Image, Link } from "@nextui-org/react"; 5 | // import Link from "next/link"; 6 | 7 | export default function CardCameraTest() { 8 | const [camCapturePath, setCamCapturePath] = useState(""); 9 | 10 | function handleCamCapture() { 11 | console.log("handle cam capture"); 12 | setCamCapturePath("/api/v1/capture?" + new Date().getTime().toString()); 13 | } 14 | 15 | // function handleCamStream() { 16 | // console.log("handle cam stream"); 17 | // setCamCapturePath("/stream"); 18 | // } 19 | 20 | return ( 21 |
22 |

23 | Camera 24 |

25 | 26 |
27 | Captured Image 33 |
34 | 35 |
36 | 45 | 46 | 47 | 56 | 57 |
58 |
59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/log_msg_buffer-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | namespace spdlog { 11 | namespace details { 12 | 13 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg &orig_msg) 14 | : log_msg{orig_msg} 15 | { 16 | buffer.append(logger_name.begin(), logger_name.end()); 17 | buffer.append(payload.begin(), payload.end()); 18 | update_string_views(); 19 | } 20 | 21 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other) 22 | : log_msg{other} 23 | { 24 | buffer.append(logger_name.begin(), logger_name.end()); 25 | buffer.append(payload.begin(), payload.end()); 26 | update_string_views(); 27 | } 28 | 29 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT : log_msg{other}, buffer{std::move(other.buffer)} 30 | { 31 | update_string_views(); 32 | } 33 | 34 | SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other) 35 | { 36 | log_msg::operator=(other); 37 | buffer.clear(); 38 | buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size()); 39 | update_string_views(); 40 | return *this; 41 | } 42 | 43 | SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT 44 | { 45 | log_msg::operator=(other); 46 | buffer = std::move(other.buffer); 47 | update_string_views(); 48 | return *this; 49 | } 50 | 51 | SPDLOG_INLINE void log_msg_buffer::update_string_views() 52 | { 53 | logger_name = string_view_t{buffer.data(), logger_name.size()}; 54 | payload = string_view_t{buffer.data() + logger_name.size(), payload.size()}; 55 | } 56 | 57 | } // namespace details 58 | } // namespace spdlog 59 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/file_helper.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | 12 | // Helper class for file sinks. 13 | // When failing to open a file, retry several times(5) with a delay interval(10 ms). 14 | // Throw spdlog_ex exception on errors. 15 | 16 | class SPDLOG_API file_helper 17 | { 18 | public: 19 | file_helper() = default; 20 | explicit file_helper(const file_event_handlers &event_handlers); 21 | 22 | file_helper(const file_helper &) = delete; 23 | file_helper &operator=(const file_helper &) = delete; 24 | ~file_helper(); 25 | 26 | void open(const filename_t &fname, bool truncate = false); 27 | void reopen(bool truncate); 28 | void flush(); 29 | void sync(); 30 | void close(); 31 | void write(const memory_buf_t &buf); 32 | size_t size() const; 33 | const filename_t &filename() const; 34 | 35 | // 36 | // return file path and its extension: 37 | // 38 | // "mylog.txt" => ("mylog", ".txt") 39 | // "mylog" => ("mylog", "") 40 | // "mylog." => ("mylog.", "") 41 | // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") 42 | // 43 | // the starting dot in filenames is ignored (hidden files): 44 | // 45 | // ".mylog" => (".mylog". "") 46 | // "my_folder/.mylog" => ("my_folder/.mylog", "") 47 | // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") 48 | static std::tuple split_by_extension(const filename_t &fname); 49 | 50 | private: 51 | const int open_tries_ = 5; 52 | const unsigned int open_interval_ = 10; 53 | std::FILE *fd_{nullptr}; 54 | filename_t filename_; 55 | file_event_handlers event_handlers_; 56 | }; 57 | } // namespace details 58 | } // namespace spdlog 59 | 60 | #ifdef SPDLOG_HEADER_ONLY 61 | # include "file_helper-inl.h" 62 | #endif 63 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/periodic_worker.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // periodic worker thread - periodically executes the given callback function. 7 | // 8 | // RAII over the owned thread: 9 | // creates the thread on construction. 10 | // stops and joins the thread on destruction (if the thread is executing a callback, wait for it to finish first). 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | namespace spdlog { 18 | namespace details { 19 | 20 | class SPDLOG_API periodic_worker 21 | { 22 | public: 23 | template 24 | periodic_worker(const std::function &callback_fun, std::chrono::duration interval) 25 | { 26 | active_ = (interval > std::chrono::duration::zero()); 27 | if (!active_) 28 | { 29 | return; 30 | } 31 | 32 | worker_thread_ = std::thread([this, callback_fun, interval]() { 33 | for (;;) 34 | { 35 | std::unique_lock lock(this->mutex_); 36 | if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) 37 | { 38 | return; // active_ == false, so exit this thread 39 | } 40 | callback_fun(); 41 | } 42 | }); 43 | } 44 | periodic_worker(const periodic_worker &) = delete; 45 | periodic_worker &operator=(const periodic_worker &) = delete; 46 | // stop the worker thread and join it 47 | ~periodic_worker(); 48 | 49 | private: 50 | bool active_; 51 | std::thread worker_thread_; 52 | std::mutex mutex_; 53 | std::condition_variable cv_; 54 | }; 55 | } // namespace details 56 | } // namespace spdlog 57 | 58 | #ifdef SPDLOG_HEADER_ONLY 59 | # include "periodic_worker-inl.h" 60 | #endif 61 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/stopwatch.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | // Stopwatch support for spdlog (using std::chrono::steady_clock). 10 | // Displays elapsed seconds since construction as double. 11 | // 12 | // Usage: 13 | // 14 | // spdlog::stopwatch sw; 15 | // ... 16 | // spdlog::debug("Elapsed: {} seconds", sw); => "Elapsed 0.005116733 seconds" 17 | // spdlog::info("Elapsed: {:.6} seconds", sw); => "Elapsed 0.005163 seconds" 18 | // 19 | // 20 | // If other units are needed (e.g. millis instead of double), include "fmt/chrono.h" and use "duration_cast<..>(sw.elapsed())": 21 | // 22 | // #include 23 | //.. 24 | // using std::chrono::duration_cast; 25 | // using std::chrono::milliseconds; 26 | // spdlog::info("Elapsed {}", duration_cast(sw.elapsed())); => "Elapsed 5ms" 27 | 28 | namespace spdlog { 29 | class stopwatch 30 | { 31 | using clock = std::chrono::steady_clock; 32 | std::chrono::time_point start_tp_; 33 | 34 | public: 35 | stopwatch() 36 | : start_tp_{clock::now()} 37 | {} 38 | 39 | std::chrono::duration elapsed() const 40 | { 41 | return std::chrono::duration(clock::now() - start_tp_); 42 | } 43 | 44 | void reset() 45 | { 46 | start_tp_ = clock::now(); 47 | } 48 | }; 49 | } // namespace spdlog 50 | 51 | // Support for fmt formatting (e.g. "{:012.9}" or just "{}") 52 | namespace 53 | #ifdef SPDLOG_USE_STD_FORMAT 54 | std 55 | #else 56 | fmt 57 | #endif 58 | { 59 | 60 | template<> 61 | struct formatter : formatter 62 | { 63 | template 64 | auto format(const spdlog::stopwatch &sw, FormatContext &ctx) const -> decltype(ctx.out()) 65 | { 66 | return formatter::format(sw.elapsed().count(), ctx); 67 | } 68 | }; 69 | } // namespace std 70 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/base_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | template 16 | SPDLOG_INLINE spdlog::sinks::base_sink::base_sink() 17 | : formatter_{details::make_unique()} 18 | {} 19 | 20 | template 21 | SPDLOG_INLINE spdlog::sinks::base_sink::base_sink(std::unique_ptr formatter) 22 | : formatter_{std::move(formatter)} 23 | {} 24 | 25 | template 26 | void SPDLOG_INLINE spdlog::sinks::base_sink::log(const details::log_msg &msg) 27 | { 28 | std::lock_guard lock(mutex_); 29 | sink_it_(msg); 30 | } 31 | 32 | template 33 | void SPDLOG_INLINE spdlog::sinks::base_sink::flush() 34 | { 35 | std::lock_guard lock(mutex_); 36 | flush_(); 37 | } 38 | 39 | template 40 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern(const std::string &pattern) 41 | { 42 | std::lock_guard lock(mutex_); 43 | set_pattern_(pattern); 44 | } 45 | 46 | template 47 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_formatter(std::unique_ptr sink_formatter) 48 | { 49 | std::lock_guard lock(mutex_); 50 | set_formatter_(std::move(sink_formatter)); 51 | } 52 | 53 | template 54 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern_(const std::string &pattern) 55 | { 56 | set_formatter_(details::make_unique(pattern)); 57 | } 58 | 59 | template 60 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_formatter_(std::unique_ptr sink_formatter) 61 | { 62 | formatter_ = std::move(sink_formatter); 63 | } 64 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/basic_file_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace spdlog { 15 | namespace sinks { 16 | /* 17 | * Trivial file sink with single file as target 18 | */ 19 | template 20 | class basic_file_sink final : public base_sink 21 | { 22 | public: 23 | explicit basic_file_sink(const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}); 24 | const filename_t &filename() const; 25 | 26 | protected: 27 | void sink_it_(const details::log_msg &msg) override; 28 | void flush_() override; 29 | 30 | private: 31 | details::file_helper file_helper_; 32 | }; 33 | 34 | using basic_file_sink_mt = basic_file_sink; 35 | using basic_file_sink_st = basic_file_sink; 36 | 37 | } // namespace sinks 38 | 39 | // 40 | // factory functions 41 | // 42 | template 43 | inline std::shared_ptr basic_logger_mt( 44 | const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}) 45 | { 46 | return Factory::template create(logger_name, filename, truncate, event_handlers); 47 | } 48 | 49 | template 50 | inline std::shared_ptr basic_logger_st( 51 | const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}) 52 | { 53 | return Factory::template create(logger_name, filename, truncate, event_handlers); 54 | } 55 | 56 | } // namespace spdlog 57 | 58 | #ifdef SPDLOG_HEADER_ONLY 59 | # include "basic_file_sink-inl.h" 60 | #endif 61 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/udp_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #ifdef _WIN32 10 | # include 11 | #else 12 | # include 13 | #endif 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // Simple udp client sink 21 | // Sends formatted log via udp 22 | 23 | namespace spdlog { 24 | namespace sinks { 25 | 26 | struct udp_sink_config 27 | { 28 | std::string server_host; 29 | uint16_t server_port; 30 | 31 | udp_sink_config(std::string host, uint16_t port) 32 | : server_host{std::move(host)} 33 | , server_port{port} 34 | {} 35 | }; 36 | 37 | template 38 | class udp_sink : public spdlog::sinks::base_sink 39 | { 40 | public: 41 | // host can be hostname or ip address 42 | explicit udp_sink(udp_sink_config sink_config) 43 | : client_{sink_config.server_host, sink_config.server_port} 44 | {} 45 | 46 | ~udp_sink() override = default; 47 | 48 | protected: 49 | void sink_it_(const spdlog::details::log_msg &msg) override 50 | { 51 | spdlog::memory_buf_t formatted; 52 | spdlog::sinks::base_sink::formatter_->format(msg, formatted); 53 | client_.send(formatted.data(), formatted.size()); 54 | } 55 | 56 | void flush_() override {} 57 | details::udp_client client_; 58 | }; 59 | 60 | using udp_sink_mt = udp_sink; 61 | using udp_sink_st = udp_sink; 62 | 63 | } // namespace sinks 64 | 65 | // 66 | // factory functions 67 | // 68 | template 69 | inline std::shared_ptr udp_logger_mt(const std::string &logger_name, sinks::udp_sink_config skin_config) 70 | { 71 | return Factory::template create(logger_name, skin_config); 72 | } 73 | 74 | } // namespace spdlog 75 | -------------------------------------------------------------------------------- /firmware/src/servers/server_ap.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file server_ap.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-12-06 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "servers.h" 12 | #include 13 | #include 14 | #include "hal/hal.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | #include "apis/camera/api_cam.h" 27 | #include "apis/system/api_system.h" 28 | #include "apis/mic/api_mic.h" 29 | #include "apis/poster/api_poster.h" 30 | #include "apis/shooter/api_shooter.h" 31 | 32 | 33 | static AsyncWebServer* _server = nullptr; 34 | 35 | void UserDemoServers::start_ap_server() 36 | { 37 | delay(200); 38 | Serial.begin(115200); 39 | Serial.printf("start ap server\n"); 40 | 41 | 42 | // Create web server 43 | _server = new AsyncWebServer(80); 44 | 45 | 46 | // Start open ap 47 | // uint64_t chipid = ESP.getEfuseMac(); 48 | // String ap_ssid = "UNIT-CAM-S3-" + String((uint32_t)(chipid >> 32), HEX); 49 | String ap_ssid = "UnitCamS3-WiFi"; 50 | // String ap_pass = "12345678"; 51 | 52 | // WiFi.softAP(ap_ssid); 53 | WiFi.softAP(ap_ssid, emptyString, 1, 0, 1, false); 54 | // WiFi.softAP(ap_ssid, ap_pass); 55 | IPAddress IP = WiFi.softAPIP(); 56 | Serial.print("AP IP address: "); 57 | Serial.println(IP); 58 | 59 | 60 | // Load apis 61 | load_cam_apis(*_server); 62 | load_system_apis(*_server); 63 | load_mic_apis(*_server); 64 | load_poster_apis(*_server); 65 | load_shooter_apis(*_server); 66 | 67 | // Set file system support 68 | _server->serveStatic("/", LittleFS, "/").setDefaultFile("index.html"); 69 | _server->onNotFound([](AsyncWebServerRequest* request) { 70 | request->send(LittleFS, "/404.html"); 71 | }); 72 | 73 | 74 | // Start server 75 | _server->begin(); 76 | 77 | // Light up 78 | HAL::hal::GetHal()->setLed(true); 79 | } 80 | 81 | 82 | void UserDemoServers::stop_ap_server() 83 | { 84 | spdlog::info("stop ap server"); 85 | 86 | delete _server; 87 | delay(200); 88 | 89 | WiFi.softAPdisconnect(); 90 | WiFi.disconnect(); 91 | } 92 | -------------------------------------------------------------------------------- /firmware/src/apis/utils/led_status/status_led.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file status_led.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-12-06 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "status_led.h" 12 | #include "../../hal/hal.h" 13 | 14 | 15 | static SemaphoreHandle_t _semaphore_led_state = NULL; 16 | static LedState_t _led_state = led_state_waiting; 17 | 18 | 19 | LedState_t StatusLed::getState() 20 | { 21 | LedState_t ret = led_state_waiting; 22 | xSemaphoreTake(_semaphore_led_state, portMAX_DELAY); 23 | ret = _led_state; 24 | xSemaphoreGive(_semaphore_led_state); 25 | return ret; 26 | } 27 | 28 | 29 | void StatusLed::setState(LedState_t state) 30 | { 31 | xSemaphoreTake(_semaphore_led_state, portMAX_DELAY); 32 | _led_state = state; 33 | xSemaphoreGive(_semaphore_led_state); 34 | } 35 | 36 | 37 | static void _led_blink() 38 | { 39 | HAL::hal::GetHal()->setLed(true); 40 | delay(50); 41 | HAL::hal::GetHal()->setLed(false); 42 | } 43 | 44 | 45 | static void _task_led(void* param) 46 | { 47 | LedState_t led_state = led_state_waiting; 48 | uint32_t state_time_count = 0; 49 | uint32_t led_time_count = 0; 50 | 51 | while (1) 52 | { 53 | // Update state 54 | if (millis() - state_time_count > 1000) 55 | { 56 | led_state = StatusLed::getState(); 57 | state_time_count = millis(); 58 | } 59 | 60 | // Update led 61 | if (led_state == led_state_waiting) 62 | { 63 | if (millis() - led_time_count > 2000) 64 | { 65 | _led_blink(); 66 | led_time_count = millis(); 67 | } 68 | } 69 | else 70 | { 71 | if (millis() - led_time_count > 500) 72 | { 73 | _led_blink(); 74 | delay(50); 75 | _led_blink(); 76 | led_time_count = millis(); 77 | } 78 | } 79 | 80 | delay(100); 81 | } 82 | 83 | vTaskDelete(NULL); 84 | } 85 | 86 | 87 | void StatusLed::start() 88 | { 89 | /* Create a mutex type semaphore. */ 90 | _semaphore_led_state = xSemaphoreCreateMutex(); 91 | // Create led task 92 | xTaskCreate(_task_led, "led", 2000, NULL, 4, NULL); 93 | } 94 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/backtracer-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | namespace spdlog { 10 | namespace details { 11 | SPDLOG_INLINE backtracer::backtracer(const backtracer &other) 12 | { 13 | std::lock_guard lock(other.mutex_); 14 | enabled_ = other.enabled(); 15 | messages_ = other.messages_; 16 | } 17 | 18 | SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT 19 | { 20 | std::lock_guard lock(other.mutex_); 21 | enabled_ = other.enabled(); 22 | messages_ = std::move(other.messages_); 23 | } 24 | 25 | SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other) 26 | { 27 | std::lock_guard lock(mutex_); 28 | enabled_ = other.enabled(); 29 | messages_ = std::move(other.messages_); 30 | return *this; 31 | } 32 | 33 | SPDLOG_INLINE void backtracer::enable(size_t size) 34 | { 35 | std::lock_guard lock{mutex_}; 36 | enabled_.store(true, std::memory_order_relaxed); 37 | messages_ = circular_q{size}; 38 | } 39 | 40 | SPDLOG_INLINE void backtracer::disable() 41 | { 42 | std::lock_guard lock{mutex_}; 43 | enabled_.store(false, std::memory_order_relaxed); 44 | } 45 | 46 | SPDLOG_INLINE bool backtracer::enabled() const 47 | { 48 | return enabled_.load(std::memory_order_relaxed); 49 | } 50 | 51 | SPDLOG_INLINE void backtracer::push_back(const log_msg &msg) 52 | { 53 | std::lock_guard lock{mutex_}; 54 | messages_.push_back(log_msg_buffer{msg}); 55 | } 56 | 57 | SPDLOG_INLINE bool backtracer::empty() const 58 | { 59 | std::lock_guard lock{mutex_}; 60 | return messages_.empty(); 61 | } 62 | 63 | // pop all items in the q and apply the given fun on each of them. 64 | SPDLOG_INLINE void backtracer::foreach_pop(std::function fun) 65 | { 66 | std::lock_guard lock{mutex_}; 67 | while (!messages_.empty()) 68 | { 69 | auto &front_msg = messages_.front(); 70 | fun(front_msg); 71 | messages_.pop_front(); 72 | } 73 | } 74 | } // namespace details 75 | } // namespace spdlog 76 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/msvc_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2016 Alexander Dalshov & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #if defined(_WIN32) 7 | 8 | # include 9 | # if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) 10 | # include 11 | # endif 12 | # include 13 | 14 | # include 15 | # include 16 | 17 | // Avoid including windows.h (https://stackoverflow.com/a/30741042) 18 | # if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) 19 | extern "C" __declspec(dllimport) void __stdcall OutputDebugStringW(const wchar_t *lpOutputString); 20 | # else 21 | extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char *lpOutputString); 22 | # endif 23 | extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 24 | 25 | namespace spdlog { 26 | namespace sinks { 27 | /* 28 | * MSVC sink (logging using OutputDebugStringA) 29 | */ 30 | template 31 | class msvc_sink : public base_sink 32 | { 33 | public: 34 | msvc_sink() = default; 35 | msvc_sink(bool check_debugger_present) 36 | : check_debugger_present_{check_debugger_present} {}; 37 | 38 | protected: 39 | void sink_it_(const details::log_msg &msg) override 40 | { 41 | if (check_debugger_present_ && !IsDebuggerPresent()) 42 | { 43 | return; 44 | } 45 | memory_buf_t formatted; 46 | base_sink::formatter_->format(msg, formatted); 47 | formatted.push_back('\0'); // add a null terminator for OutputDebugString 48 | # if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) 49 | wmemory_buf_t wformatted; 50 | details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), wformatted); 51 | OutputDebugStringW(wformatted.data()); 52 | # else 53 | OutputDebugStringA(formatted.data()); 54 | # endif 55 | } 56 | 57 | void flush_() override {} 58 | 59 | bool check_debugger_present_ = true; 60 | }; 61 | 62 | using msvc_sink_mt = msvc_sink; 63 | using msvc_sink_st = msvc_sink; 64 | 65 | using windebug_sink_mt = msvc_sink_mt; 66 | using windebug_sink_st = msvc_sink_st; 67 | 68 | } // namespace sinks 69 | } // namespace spdlog 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/common-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | namespace level { 15 | 16 | #if __cplusplus >= 201703L 17 | constexpr 18 | #endif 19 | static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES; 20 | 21 | static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES; 22 | 23 | SPDLOG_INLINE const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT 24 | { 25 | return level_string_views[l]; 26 | } 27 | 28 | SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT 29 | { 30 | return short_level_names[l]; 31 | } 32 | 33 | SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT 34 | { 35 | auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name); 36 | if (it != std::end(level_string_views)) 37 | return static_cast(std::distance(std::begin(level_string_views), it)); 38 | 39 | // check also for "warn" and "err" before giving up.. 40 | if (name == "warn") 41 | { 42 | return level::warn; 43 | } 44 | if (name == "err") 45 | { 46 | return level::err; 47 | } 48 | return level::off; 49 | } 50 | } // namespace level 51 | 52 | SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg) 53 | : msg_(std::move(msg)) 54 | {} 55 | 56 | SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno) 57 | { 58 | #ifdef SPDLOG_USE_STD_FORMAT 59 | msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what(); 60 | #else 61 | memory_buf_t outbuf; 62 | fmt::format_system_error(outbuf, last_errno, msg.c_str()); 63 | msg_ = fmt::to_string(outbuf); 64 | #endif 65 | } 66 | 67 | SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT 68 | { 69 | return msg_.c_str(); 70 | } 71 | 72 | SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno) 73 | { 74 | SPDLOG_THROW(spdlog_ex(msg, last_errno)); 75 | } 76 | 77 | SPDLOG_INLINE void throw_spdlog_ex(std::string msg) 78 | { 79 | SPDLOG_THROW(spdlog_ex(std::move(msg))); 80 | } 81 | 82 | } // namespace spdlog 83 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/ringbuffer_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/sinks/base_sink.h" 7 | #include "spdlog/details/circular_q.h" 8 | #include "spdlog/details/log_msg_buffer.h" 9 | #include "spdlog/details/null_mutex.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace spdlog { 16 | namespace sinks { 17 | /* 18 | * Ring buffer sink 19 | */ 20 | template 21 | class ringbuffer_sink final : public base_sink 22 | { 23 | public: 24 | explicit ringbuffer_sink(size_t n_items) 25 | : q_{n_items} 26 | {} 27 | 28 | std::vector last_raw(size_t lim = 0) 29 | { 30 | std::lock_guard lock(base_sink::mutex_); 31 | auto items_available = q_.size(); 32 | auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; 33 | std::vector ret; 34 | ret.reserve(n_items); 35 | for (size_t i = (items_available - n_items); i < items_available; i++) 36 | { 37 | ret.push_back(q_.at(i)); 38 | } 39 | return ret; 40 | } 41 | 42 | std::vector last_formatted(size_t lim = 0) 43 | { 44 | std::lock_guard lock(base_sink::mutex_); 45 | auto items_available = q_.size(); 46 | auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; 47 | std::vector ret; 48 | ret.reserve(n_items); 49 | for (size_t i = (items_available - n_items); i < items_available; i++) 50 | { 51 | memory_buf_t formatted; 52 | base_sink::formatter_->format(q_.at(i), formatted); 53 | ret.push_back(SPDLOG_BUF_TO_STRING(formatted)); 54 | } 55 | return ret; 56 | } 57 | 58 | protected: 59 | void sink_it_(const details::log_msg &msg) override 60 | { 61 | q_.push_back(details::log_msg_buffer{msg}); 62 | } 63 | void flush_() override {} 64 | 65 | private: 66 | details::circular_q q_; 67 | }; 68 | 69 | using ringbuffer_sink_mt = ringbuffer_sink; 70 | using ringbuffer_sink_st = ringbuffer_sink; 71 | 72 | } // namespace sinks 73 | 74 | } // namespace spdlog 75 | -------------------------------------------------------------------------------- /web/src/components/shooter/card-shooter-notice.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { 4 | Card, 5 | Table, 6 | TableHeader, 7 | TableColumn, 8 | TableBody, 9 | TableRow, 10 | TableCell, 11 | Divider, 12 | } from "@nextui-org/react"; 13 | 14 | export default function CardShooterNotice() { 15 | return ( 16 | 17 |
18 |

19 | Notice 20 |

21 |
22 |
23 |

24 | UnitCamS3 is now try to start interval shooting. 25 |

26 | 27 | 28 | 29 |

30 | The LED Status shows the current 31 | state: 32 |

33 | 34 | 35 | LED STATUS 36 | STATE 37 | 38 | 39 | 40 | Fast Blinking 41 | Capturing image 42 | 43 | 44 | Slow Blinking 45 | Wait next capture 46 | 47 | 48 | Constantly on 49 | 50 | Wait config (default) 51 | 52 | 53 | 54 |
55 | 56 | 57 | 58 |

59 | Reset 60 |

61 | 62 |

63 | If your SD card is valid, there will be 10 seconds of waiting on every 64 | reboot, before start shooting. 65 |

66 |

67 | You can connect to UnitCamS3-WiFi{" "} 68 | and reconfigure your settings. 69 |

70 |
71 |
72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/tcp_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #ifdef _WIN32 10 | # include 11 | #else 12 | # include 13 | #endif 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #pragma once 21 | 22 | // Simple tcp client sink 23 | // Connects to remote address and send the formatted log. 24 | // Will attempt to reconnect if connection drops. 25 | // If more complicated behaviour is needed (i.e get responses), you can inherit it and override the sink_it_ method. 26 | 27 | namespace spdlog { 28 | namespace sinks { 29 | 30 | struct tcp_sink_config 31 | { 32 | std::string server_host; 33 | int server_port; 34 | bool lazy_connect = false; // if true connect on first log call instead of on construction 35 | 36 | tcp_sink_config(std::string host, int port) 37 | : server_host{std::move(host)} 38 | , server_port{port} 39 | {} 40 | }; 41 | 42 | template 43 | class tcp_sink : public spdlog::sinks::base_sink 44 | { 45 | public: 46 | // connect to tcp host/port or throw if failed 47 | // host can be hostname or ip address 48 | 49 | explicit tcp_sink(tcp_sink_config sink_config) 50 | : config_{std::move(sink_config)} 51 | { 52 | if (!config_.lazy_connect) 53 | { 54 | this->client_.connect(config_.server_host, config_.server_port); 55 | } 56 | } 57 | 58 | ~tcp_sink() override = default; 59 | 60 | protected: 61 | void sink_it_(const spdlog::details::log_msg &msg) override 62 | { 63 | spdlog::memory_buf_t formatted; 64 | spdlog::sinks::base_sink::formatter_->format(msg, formatted); 65 | if (!client_.is_connected()) 66 | { 67 | client_.connect(config_.server_host, config_.server_port); 68 | } 69 | client_.send(formatted.data(), formatted.size()); 70 | } 71 | 72 | void flush_() override {} 73 | tcp_sink_config config_; 74 | details::tcp_client client_; 75 | }; 76 | 77 | using tcp_sink_mt = tcp_sink; 78 | using tcp_sink_st = tcp_sink; 79 | 80 | } // namespace sinks 81 | } // namespace spdlog 82 | -------------------------------------------------------------------------------- /web/src/components/hardware-test/card-mic-test.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { Button, Link } from "@nextui-org/react"; 4 | import { useState } from "react"; 5 | 6 | type MicState = "waitFirst" | "recording" | "waitNext"; 7 | 8 | export default function CardMicTest() { 9 | let nIntervId: number; 10 | const [micState, setMicState] = useState("waitFirst" as MicState); 11 | 12 | function handleButtonRecord() { 13 | console.log("start recording"); 14 | 15 | // Start recording 16 | fetch("/api/v1/mic_start"); 17 | 18 | setMicState("recording"); 19 | nIntervId = setInterval(handleCheckIsRecording, 2000); 20 | } 21 | 22 | function handleCheckIsRecording() { 23 | console.log("check record state"); 24 | 25 | fetch("/api/v1/mic_is_recording") 26 | .then((response) => response.json()) 27 | .then((data) => { 28 | console.log(data.msg); 29 | // Done recording 30 | if (data.msg === "no") { 31 | clearInterval(nIntervId); 32 | setMicState("waitNext"); 33 | } 34 | }); 35 | } 36 | 37 | return ( 38 |
39 |
40 |

Mic

41 | 42 | 51 |
52 | 53 |
54 | {micState === "waitFirst" &&

Click the button to record audio

} 55 | 56 | {micState === "recording" && ( 57 |
58 |

Recording, please wait...

59 | {/* */} 60 |
61 | )} 62 | 63 | {micState === "waitNext" && ( 64 |
65 | 69 | 70 | 73 | 74 |
75 | )} 76 |
77 |
78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/async_logger.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // Fast asynchronous logger. 7 | // Uses pre allocated queue. 8 | // Creates a single back thread to pop messages from the queue and log them. 9 | // 10 | // Upon each log write the logger: 11 | // 1. Checks if its log level is enough to log the message 12 | // 2. Push a new copy of the message to a queue (or block the caller until 13 | // space is available in the queue) 14 | // Upon destruction, logs all remaining messages in the queue before 15 | // destructing.. 16 | 17 | #include 18 | 19 | namespace spdlog { 20 | 21 | // Async overflow policy - block by default. 22 | enum class async_overflow_policy 23 | { 24 | block, // Block until message can be enqueued 25 | overrun_oldest // Discard oldest message in the queue if full when trying to 26 | // add new item. 27 | }; 28 | 29 | namespace details { 30 | class thread_pool; 31 | } 32 | 33 | class SPDLOG_API async_logger final : public std::enable_shared_from_this, public logger 34 | { 35 | friend class details::thread_pool; 36 | 37 | public: 38 | template 39 | async_logger(std::string logger_name, It begin, It end, std::weak_ptr tp, 40 | async_overflow_policy overflow_policy = async_overflow_policy::block) 41 | : logger(std::move(logger_name), begin, end) 42 | , thread_pool_(std::move(tp)) 43 | , overflow_policy_(overflow_policy) 44 | {} 45 | 46 | async_logger(std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, 47 | async_overflow_policy overflow_policy = async_overflow_policy::block); 48 | 49 | async_logger(std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, 50 | async_overflow_policy overflow_policy = async_overflow_policy::block); 51 | 52 | std::shared_ptr clone(std::string new_name) override; 53 | 54 | protected: 55 | void sink_it_(const details::log_msg &msg) override; 56 | void flush_() override; 57 | void backend_sink_it_(const details::log_msg &incoming_log_msg); 58 | void backend_flush_(); 59 | 60 | private: 61 | std::weak_ptr thread_pool_; 62 | async_overflow_policy overflow_policy_; 63 | }; 64 | } // namespace spdlog 65 | 66 | #ifdef SPDLOG_HEADER_ONLY 67 | # include "async_logger-inl.h" 68 | #endif 69 | -------------------------------------------------------------------------------- /firmware/src/servers/server_shooter.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file server_interval_shooting.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-12-06 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "servers.h" 12 | #include 13 | #include 14 | #include "hal/hal.h" 15 | #include 16 | #include "../apis/shooter/api_shooter.h" 17 | 18 | 19 | void UserDemoServers::start_shooter_server() 20 | { 21 | spdlog::info("start interval shooting server"); 22 | auto config = HAL::hal::GetHal()->getConfig(); 23 | 24 | 25 | // If need to wait ap connection for 10s 26 | if (config.wait_ap_first == "yes") 27 | { 28 | spdlog::info("start wait ap"); 29 | start_ap_server(); 30 | 31 | uint32_t ap_wait_time_cout = millis(); 32 | bool led_state = true; 33 | while (millis() - ap_wait_time_cout < 10000) 34 | { 35 | // If get client 36 | if (WiFi.softAPgetStationNum() != 0) 37 | { 38 | // Hold Ap mode 39 | spdlog::info("get client, hold ap mode"); 40 | HAL::hal::GetHal()->setLed(true); 41 | while (WiFi.softAPgetStationNum() != 0) 42 | delay(2000); 43 | 44 | // If no config setting, reset counting 45 | ap_wait_time_cout = millis(); 46 | } 47 | 48 | delay(500); 49 | led_state = !led_state; 50 | HAL::hal::GetHal()->setLed(led_state); 51 | } 52 | 53 | spdlog::info("no client, go on poster mode"); 54 | stop_ap_server(); 55 | } 56 | 57 | // Try init sd card 58 | for (int i = 0; i < 5; i++) 59 | { 60 | // Init sd card 61 | if (HAL::hal::GetHal()->sdCardInit()) 62 | break; 63 | delay(200); 64 | } 65 | 66 | // If not valid 67 | if (!HAL::hal::GetHal()->isSdCardValid()) 68 | { 69 | spdlog::error("sd card init failed, return back to ap mode"); 70 | config.start_shooter = "no"; 71 | HAL::hal::GetHal()->setConfig(config); 72 | 73 | // Reboot 74 | delay(300); 75 | esp_restart(); 76 | delay(10000); 77 | } 78 | 79 | 80 | // Mark to wait at next time 81 | if (config.wait_ap_first != "yes") 82 | { 83 | spdlog::info("start 10s ap waiting from next reboot"); 84 | config.wait_ap_first = "yes"; 85 | HAL::hal::GetHal()->setConfig(config); 86 | } 87 | 88 | 89 | // Start shooter 90 | start_shooter_task(); 91 | } 92 | -------------------------------------------------------------------------------- /web/src/components/poster/card-poster-notice.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { 4 | Card, 5 | Table, 6 | TableHeader, 7 | TableColumn, 8 | TableBody, 9 | TableRow, 10 | TableCell, 11 | Divider, 12 | } from "@nextui-org/react"; 13 | 14 | export default function CardPosterNotice() { 15 | return ( 16 | 17 |
18 |

19 | Notice 20 |

21 |
22 |
23 |

24 | UnitCamS3 will try to connect the wifi and start posting images. 25 |

26 | 27 | 28 | 29 |

30 | The LED Status shows the current 31 | state: 32 |

33 | 34 | 35 | LED STATUS 36 | STATE 37 | 38 | 39 | 40 | Breathing 41 | Connecting WiFi 42 | 43 | 44 | Fast Blinking 45 | Posting image 46 | 47 | 48 | Slow Blinking 49 | Wait next post 50 | 51 | 52 | Constantly on 53 | 54 | Wait config (default) 55 | 56 | 57 | 58 |
59 | 60 | 61 | 62 |

63 | Reset 64 |

65 | 66 |

67 | If the configed WiFi is valid, there will be 10 seconds of waiting on 68 | every reboot, before starting image poster. 69 |

70 |

71 | You can connect to UnitCamS3-WiFi{" "} 72 | and reconfigure your settings. 73 |

74 |
75 |
76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /firmware/src/hal/hal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hal.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-09-13 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #pragma once 12 | #include "mic/Mic_Class.hpp" 13 | 14 | 15 | /** 16 | * @brief 17 | * 18 | */ 19 | #define HAL_PIN_BTN_A 0 20 | 21 | #define HAL_PIN_GROVE_SCL 19 22 | #define HAL_PIN_GROVE_SDA 20 23 | 24 | #define HAL_PIN_MIC_CLK 47 25 | #define HAL_PIN_MIC_DATA 48 26 | 27 | #define HAL_PIN_SD_CS 9 28 | #define HAL_PIN_SD_MOSI 38 29 | #define HAL_PIN_SD_CLK 39 30 | #define HAL_PIN_SD_MISO 40 31 | 32 | 33 | namespace HAL 34 | { 35 | class hal 36 | { 37 | public: 38 | struct Config_t 39 | { 40 | String wifi_ssid; 41 | String wifi_password; 42 | String start_poster = "no"; 43 | String wait_ap_first = "no"; 44 | String nickname = "UnitCamS3"; 45 | String time_zone = "GMT+0"; 46 | String start_shooter = "no"; 47 | int post_interval = 5; 48 | }; 49 | 50 | private: 51 | struct Data_t 52 | { 53 | Config_t config; 54 | bool is_wifi_config_vaild = false; 55 | bool is_sd_card_valid = false; 56 | }; 57 | Data_t _data; 58 | 59 | void _cam_init(); 60 | void _config_init(); 61 | bool _check_sd_card_config_hijack(); 62 | 63 | public: 64 | void init(); 65 | 66 | // Mic 67 | m5::Mic_Class* mic; 68 | 69 | // Sd card 70 | struct SdCardPin_t 71 | { 72 | int cs = HAL_PIN_SD_CS; 73 | int mosi = HAL_PIN_SD_MOSI; 74 | int clk = HAL_PIN_SD_CLK; 75 | int miso = HAL_PIN_SD_MISO; 76 | }; 77 | inline SdCardPin_t getSdCardPin() { 78 | SdCardPin_t pin; 79 | return pin; 80 | } 81 | 82 | void setLed(bool state); 83 | 84 | void setConfig(Config_t& cfg); 85 | Config_t getConfig(); 86 | Config_t getDefaultConfig(); 87 | void printConfig(); 88 | 89 | // For poster mode usage 90 | bool sdCardInit(bool passImagePath = false); 91 | void sdCardDeinit(); 92 | inline bool isSdCardValid() { return _data.is_sd_card_valid; } 93 | bool saveImage(uint8_t* img, size_t size); 94 | 95 | 96 | private: 97 | static hal* _hal; 98 | public: 99 | static hal* GetHal(); 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/udp_client.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // Helper RAII over unix udp client socket. 7 | // Will throw on construction if the socket creation failed. 8 | 9 | #ifdef _WIN32 10 | # error "include udp_client-windows.h instead" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | namespace spdlog { 26 | namespace details { 27 | 28 | class udp_client 29 | { 30 | static constexpr int TX_BUFFER_SIZE = 1024 * 10; 31 | int socket_ = -1; 32 | struct sockaddr_in sockAddr_; 33 | 34 | void cleanup_() 35 | { 36 | if (socket_ != -1) 37 | { 38 | ::close(socket_); 39 | socket_ = -1; 40 | } 41 | } 42 | 43 | public: 44 | udp_client(const std::string &host, uint16_t port) 45 | { 46 | socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); 47 | if (socket_ < 0) 48 | { 49 | throw_spdlog_ex("error: Create Socket Failed!"); 50 | } 51 | 52 | int option_value = TX_BUFFER_SIZE; 53 | if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&option_value), sizeof(option_value)) < 0) 54 | { 55 | cleanup_(); 56 | throw_spdlog_ex("error: setsockopt(SO_SNDBUF) Failed!"); 57 | } 58 | 59 | sockAddr_.sin_family = AF_INET; 60 | sockAddr_.sin_port = htons(port); 61 | 62 | if (::inet_aton(host.c_str(), &sockAddr_.sin_addr) == 0) 63 | { 64 | cleanup_(); 65 | throw_spdlog_ex("error: Invalid address!"); 66 | } 67 | 68 | ::memset(sockAddr_.sin_zero, 0x00, sizeof(sockAddr_.sin_zero)); 69 | } 70 | 71 | ~udp_client() 72 | { 73 | cleanup_(); 74 | } 75 | 76 | int fd() const 77 | { 78 | return socket_; 79 | } 80 | 81 | // Send exactly n_bytes of the given data. 82 | // On error close the connection and throw. 83 | void send(const char *data, size_t n_bytes) 84 | { 85 | ssize_t toslen = 0; 86 | socklen_t tolen = sizeof(struct sockaddr); 87 | if ((toslen = ::sendto(socket_, data, n_bytes, 0, (struct sockaddr *)&sockAddr_, tolen)) == -1) 88 | { 89 | throw_spdlog_ex("sendto(2) failed", errno); 90 | } 91 | } 92 | }; 93 | } // namespace details 94 | } // namespace spdlog 95 | -------------------------------------------------------------------------------- /web/src/components/poster/card-poster-start-and-link.tsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | 3 | import { Card, Link } from "@nextui-org/react"; 4 | import { useState, useEffect } from "react"; 5 | import { QRCodeSVG } from "qrcode.react"; 6 | 7 | export default function CardPosterStartAndLink() { 8 | const [imageLink, setImageLink] = useState(""); 9 | // const [imageLink, setImageLink] = useState( 10 | // "https://ezdata-dev-bucket.oss-cn-shenzhen.aliyuncs.com/asdasdasdasdasd/asdasdasdasd/asdasdasda" 11 | // ); 12 | 13 | function handleStartPoster() { 14 | console.log("start poster"); 15 | fetch("/api/v1/start_poster") 16 | .then((response) => response.json()) 17 | .then((data) => { 18 | console.log(data); 19 | }) 20 | .catch((error) => { 21 | if (error instanceof TypeError && error.message.includes("API key")) { 22 | console.error("Invalid API key:", error); 23 | } else { 24 | console.error("There was a problem with the Fetch operation:", error); 25 | } 26 | }); 27 | } 28 | 29 | function handleUpdateImageLink(mac: string) { 30 | // Remove ":" 31 | let newMac = mac.replaceAll(":", ""); 32 | console.log("get mac:", newMac); 33 | 34 | // Merge link 35 | let newLink = 36 | "https://ezdata2.m5stack.com/" + 37 | newMac + 38 | "/captured.jpg"; 39 | console.log("new link:", newLink); 40 | 41 | setImageLink(newLink); 42 | handleStartPoster(); 43 | } 44 | 45 | useEffect(() => { 46 | // Get mac 47 | fetch("/api/v1/get_mac") 48 | .then((response) => response.json()) 49 | .then((data) => { 50 | console.log(data); 51 | handleUpdateImageLink(data.mac); 52 | }) 53 | .catch((error) => { 54 | if (error instanceof TypeError && error.message.includes("API key")) { 55 | console.error("Invalid API key:", error); 56 | } else { 57 | console.error("There was a problem with the Fetch operation:", error); 58 | } 59 | }); 60 | }, []); 61 | 62 | return ( 63 | 64 |
65 | 74 | 75 | 81 | Image Link 82 | 83 | 84 |

85 | {imageLink} 86 |

87 |
88 |
89 | ); 90 | } 91 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/stdout_sinks.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #ifdef _WIN32 12 | # include 13 | #endif 14 | 15 | namespace spdlog { 16 | 17 | namespace sinks { 18 | 19 | template 20 | class stdout_sink_base : public sink 21 | { 22 | public: 23 | using mutex_t = typename ConsoleMutex::mutex_t; 24 | explicit stdout_sink_base(FILE *file); 25 | ~stdout_sink_base() override = default; 26 | 27 | stdout_sink_base(const stdout_sink_base &other) = delete; 28 | stdout_sink_base(stdout_sink_base &&other) = delete; 29 | 30 | stdout_sink_base &operator=(const stdout_sink_base &other) = delete; 31 | stdout_sink_base &operator=(stdout_sink_base &&other) = delete; 32 | 33 | void log(const details::log_msg &msg) override; 34 | void flush() override; 35 | void set_pattern(const std::string &pattern) override; 36 | 37 | void set_formatter(std::unique_ptr sink_formatter) override; 38 | 39 | protected: 40 | mutex_t &mutex_; 41 | FILE *file_; 42 | std::unique_ptr formatter_; 43 | #ifdef _WIN32 44 | HANDLE handle_; 45 | #endif // WIN32 46 | }; 47 | 48 | template 49 | class stdout_sink : public stdout_sink_base 50 | { 51 | public: 52 | stdout_sink(); 53 | }; 54 | 55 | template 56 | class stderr_sink : public stdout_sink_base 57 | { 58 | public: 59 | stderr_sink(); 60 | }; 61 | 62 | using stdout_sink_mt = stdout_sink; 63 | using stdout_sink_st = stdout_sink; 64 | 65 | using stderr_sink_mt = stderr_sink; 66 | using stderr_sink_st = stderr_sink; 67 | 68 | } // namespace sinks 69 | 70 | // factory methods 71 | template 72 | std::shared_ptr stdout_logger_mt(const std::string &logger_name); 73 | 74 | template 75 | std::shared_ptr stdout_logger_st(const std::string &logger_name); 76 | 77 | template 78 | std::shared_ptr stderr_logger_mt(const std::string &logger_name); 79 | 80 | template 81 | std::shared_ptr stderr_logger_st(const std::string &logger_name); 82 | 83 | } // namespace spdlog 84 | 85 | #ifdef SPDLOG_HEADER_ONLY 86 | # include "stdout_sinks-inl.h" 87 | #endif 88 | -------------------------------------------------------------------------------- /firmware/src/hal/cam/hal_cam.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hal_cam.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-11-01 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include 12 | #include 13 | #include "../hal.h" 14 | 15 | using namespace HAL; 16 | 17 | 18 | 19 | #include 20 | // 21 | // WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality 22 | // Ensure ESP32 Wrover Module or other board with PSRAM is selected 23 | // Partial images will be transmitted if image exceeds buffer size 24 | // 25 | // You must select partition scheme from the board menu that has at least 3MB APP space. 26 | // Face Recognition is DISABLED for ESP32 and ESP32-S2, because it takes up from 15 27 | // seconds to process single frame. Face Detection is ENABLED if PSRAM is enabled as well 28 | 29 | #define CAMERA_MODEL_ESP_EYE 30 | #include "camera_pins.h" 31 | 32 | 33 | 34 | void hal::_cam_init() 35 | { 36 | spdlog::info("cam init"); 37 | 38 | 39 | camera_config_t config; 40 | config.ledc_channel = LEDC_CHANNEL_0; 41 | config.ledc_timer = LEDC_TIMER_0; 42 | config.pin_d0 = Y2_GPIO_NUM; 43 | config.pin_d1 = Y3_GPIO_NUM; 44 | config.pin_d2 = Y4_GPIO_NUM; 45 | config.pin_d3 = Y5_GPIO_NUM; 46 | config.pin_d4 = Y6_GPIO_NUM; 47 | config.pin_d5 = Y7_GPIO_NUM; 48 | config.pin_d6 = Y8_GPIO_NUM; 49 | config.pin_d7 = Y9_GPIO_NUM; 50 | config.pin_xclk = XCLK_GPIO_NUM; 51 | config.pin_pclk = PCLK_GPIO_NUM; 52 | config.pin_vsync = VSYNC_GPIO_NUM; 53 | config.pin_href = HREF_GPIO_NUM; 54 | config.pin_sccb_sda = SIOD_GPIO_NUM; 55 | config.pin_sccb_scl = SIOC_GPIO_NUM; 56 | config.pin_pwdn = PWDN_GPIO_NUM; 57 | config.pin_reset = RESET_GPIO_NUM; 58 | config.xclk_freq_hz = 20000000; 59 | 60 | // config.frame_size = FRAMESIZE_UXGA; 61 | config.frame_size = FRAMESIZE_VGA; 62 | // config.frame_size = FRAMESIZE_QVGA; 63 | 64 | config.pixel_format = PIXFORMAT_JPEG; // for streaming 65 | // config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition 66 | config.grab_mode = CAMERA_GRAB_LATEST; 67 | config.fb_location = CAMERA_FB_IN_PSRAM; 68 | config.jpeg_quality = 16; 69 | config.fb_count = 2; 70 | 71 | 72 | esp_err_t err = esp_camera_init(&config); 73 | if (err != ESP_OK) 74 | { 75 | // Serial.printf("Camera init failed with error 0x%x", err); 76 | printf("Camera init failed with error 0x%x\n", err); 77 | 78 | // Retry 79 | spdlog::info("reboot.."); 80 | delay(1000); 81 | esp_restart(); 82 | } 83 | 84 | 85 | sensor_t* s = esp_camera_sensor_get(); 86 | s->set_vflip(s, 1); 87 | s->set_hmirror(s, 1); 88 | 89 | spdlog::info("cam init ok"); 90 | delay(100); 91 | } 92 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/dist_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "base_sink.h" 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | // Distribution sink (mux). Stores a vector of sinks which get called when log 17 | // is called 18 | 19 | namespace spdlog { 20 | namespace sinks { 21 | 22 | template 23 | class dist_sink : public base_sink 24 | { 25 | public: 26 | dist_sink() = default; 27 | explicit dist_sink(std::vector> sinks) 28 | : sinks_(sinks) 29 | {} 30 | 31 | dist_sink(const dist_sink &) = delete; 32 | dist_sink &operator=(const dist_sink &) = delete; 33 | 34 | void add_sink(std::shared_ptr sub_sink) 35 | { 36 | std::lock_guard lock(base_sink::mutex_); 37 | sinks_.push_back(sub_sink); 38 | } 39 | 40 | void remove_sink(std::shared_ptr sub_sink) 41 | { 42 | std::lock_guard lock(base_sink::mutex_); 43 | sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sub_sink), sinks_.end()); 44 | } 45 | 46 | void set_sinks(std::vector> sinks) 47 | { 48 | std::lock_guard lock(base_sink::mutex_); 49 | sinks_ = std::move(sinks); 50 | } 51 | 52 | std::vector> &sinks() 53 | { 54 | return sinks_; 55 | } 56 | 57 | protected: 58 | void sink_it_(const details::log_msg &msg) override 59 | { 60 | for (auto &sub_sink : sinks_) 61 | { 62 | if (sub_sink->should_log(msg.level)) 63 | { 64 | sub_sink->log(msg); 65 | } 66 | } 67 | } 68 | 69 | void flush_() override 70 | { 71 | for (auto &sub_sink : sinks_) 72 | { 73 | sub_sink->flush(); 74 | } 75 | } 76 | 77 | void set_pattern_(const std::string &pattern) override 78 | { 79 | set_formatter_(details::make_unique(pattern)); 80 | } 81 | 82 | void set_formatter_(std::unique_ptr sink_formatter) override 83 | { 84 | base_sink::formatter_ = std::move(sink_formatter); 85 | for (auto &sub_sink : sinks_) 86 | { 87 | sub_sink->set_formatter(base_sink::formatter_->clone()); 88 | } 89 | } 90 | std::vector> sinks_; 91 | }; 92 | 93 | using dist_sink_mt = dist_sink; 94 | using dist_sink_st = dist_sink; 95 | 96 | } // namespace sinks 97 | } // namespace spdlog 98 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/async_logger-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | SPDLOG_INLINE spdlog::async_logger::async_logger( 17 | std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, async_overflow_policy overflow_policy) 18 | : async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy) 19 | {} 20 | 21 | SPDLOG_INLINE spdlog::async_logger::async_logger( 22 | std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, async_overflow_policy overflow_policy) 23 | : async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) 24 | {} 25 | 26 | // send the log message to the thread pool 27 | SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg){ 28 | SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){pool_ptr->post_log(shared_from_this(), msg, overflow_policy_); 29 | } 30 | else 31 | { 32 | throw_spdlog_ex("async log: thread pool doesn't exist anymore"); 33 | } 34 | } 35 | SPDLOG_LOGGER_CATCH(msg.source) 36 | } 37 | 38 | // send flush request to the thread pool 39 | SPDLOG_INLINE void spdlog::async_logger::flush_(){ 40 | SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){pool_ptr->post_flush(shared_from_this(), overflow_policy_); 41 | } 42 | else 43 | { 44 | throw_spdlog_ex("async flush: thread pool doesn't exist anymore"); 45 | } 46 | } 47 | SPDLOG_LOGGER_CATCH(source_loc()) 48 | } 49 | 50 | // 51 | // backend functions - called from the thread pool to do the actual job 52 | // 53 | SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg) 54 | { 55 | for (auto &sink : sinks_) 56 | { 57 | if (sink->should_log(msg.level)) 58 | { 59 | SPDLOG_TRY 60 | { 61 | sink->log(msg); 62 | } 63 | SPDLOG_LOGGER_CATCH(msg.source) 64 | } 65 | } 66 | 67 | if (should_flush_(msg)) 68 | { 69 | backend_flush_(); 70 | } 71 | } 72 | 73 | SPDLOG_INLINE void spdlog::async_logger::backend_flush_() 74 | { 75 | for (auto &sink : sinks_) 76 | { 77 | SPDLOG_TRY 78 | { 79 | sink->flush(); 80 | } 81 | SPDLOG_LOGGER_CATCH(source_loc()) 82 | } 83 | } 84 | 85 | SPDLOG_INLINE std::shared_ptr spdlog::async_logger::clone(std::string new_name) 86 | { 87 | auto cloned = std::make_shared(*this); 88 | cloned->name_ = std::move(new_name); 89 | return cloned; 90 | } 91 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/rotating_file_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace spdlog { 16 | namespace sinks { 17 | 18 | // 19 | // Rotating file sink based on size 20 | // 21 | template 22 | class rotating_file_sink final : public base_sink 23 | { 24 | public: 25 | rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false, 26 | const file_event_handlers &event_handlers = {}); 27 | static filename_t calc_filename(const filename_t &filename, std::size_t index); 28 | filename_t filename(); 29 | 30 | protected: 31 | void sink_it_(const details::log_msg &msg) override; 32 | void flush_() override; 33 | 34 | private: 35 | // Rotate files: 36 | // log.txt -> log.1.txt 37 | // log.1.txt -> log.2.txt 38 | // log.2.txt -> log.3.txt 39 | // log.3.txt -> delete 40 | void rotate_(); 41 | 42 | // delete the target if exists, and rename the src file to target 43 | // return true on success, false otherwise. 44 | bool rename_file_(const filename_t &src_filename, const filename_t &target_filename); 45 | 46 | filename_t base_filename_; 47 | std::size_t max_size_; 48 | std::size_t max_files_; 49 | std::size_t current_size_; 50 | details::file_helper file_helper_; 51 | }; 52 | 53 | using rotating_file_sink_mt = rotating_file_sink; 54 | using rotating_file_sink_st = rotating_file_sink; 55 | 56 | } // namespace sinks 57 | 58 | // 59 | // factory functions 60 | // 61 | 62 | template 63 | inline std::shared_ptr rotating_logger_mt(const std::string &logger_name, const filename_t &filename, size_t max_file_size, 64 | size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {}) 65 | { 66 | return Factory::template create( 67 | logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); 68 | } 69 | 70 | template 71 | inline std::shared_ptr rotating_logger_st(const std::string &logger_name, const filename_t &filename, size_t max_file_size, 72 | size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {}) 73 | { 74 | return Factory::template create( 75 | logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); 76 | } 77 | } // namespace spdlog 78 | 79 | #ifdef SPDLOG_HEADER_ONLY 80 | # include "rotating_file_sink-inl.h" 81 | #endif 82 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/wincolor_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace spdlog { 18 | namespace sinks { 19 | /* 20 | * Windows color console sink. Uses WriteConsoleA to write to the console with 21 | * colors 22 | */ 23 | template 24 | class wincolor_sink : public sink 25 | { 26 | public: 27 | wincolor_sink(void *out_handle, color_mode mode); 28 | ~wincolor_sink() override; 29 | 30 | wincolor_sink(const wincolor_sink &other) = delete; 31 | wincolor_sink &operator=(const wincolor_sink &other) = delete; 32 | 33 | // change the color for the given level 34 | void set_color(level::level_enum level, std::uint16_t color); 35 | void log(const details::log_msg &msg) final override; 36 | void flush() final override; 37 | void set_pattern(const std::string &pattern) override final; 38 | void set_formatter(std::unique_ptr sink_formatter) override final; 39 | void set_color_mode(color_mode mode); 40 | 41 | protected: 42 | using mutex_t = typename ConsoleMutex::mutex_t; 43 | void *out_handle_; 44 | mutex_t &mutex_; 45 | bool should_do_colors_; 46 | std::unique_ptr formatter_; 47 | std::array colors_; 48 | 49 | // set foreground color and return the orig console attributes (for resetting later) 50 | std::uint16_t set_foreground_color_(std::uint16_t attribs); 51 | 52 | // print a range of formatted message to console 53 | void print_range_(const memory_buf_t &formatted, size_t start, size_t end); 54 | 55 | // in case we are redirected to file (not in console mode) 56 | void write_to_file_(const memory_buf_t &formatted); 57 | 58 | void set_color_mode_impl(color_mode mode); 59 | }; 60 | 61 | template 62 | class wincolor_stdout_sink : public wincolor_sink 63 | { 64 | public: 65 | explicit wincolor_stdout_sink(color_mode mode = color_mode::automatic); 66 | }; 67 | 68 | template 69 | class wincolor_stderr_sink : public wincolor_sink 70 | { 71 | public: 72 | explicit wincolor_stderr_sink(color_mode mode = color_mode::automatic); 73 | }; 74 | 75 | using wincolor_stdout_sink_mt = wincolor_stdout_sink; 76 | using wincolor_stdout_sink_st = wincolor_stdout_sink; 77 | 78 | using wincolor_stderr_sink_mt = wincolor_stderr_sink; 79 | using wincolor_stderr_sink_st = wincolor_stderr_sink; 80 | } // namespace sinks 81 | } // namespace spdlog 82 | 83 | #ifdef SPDLOG_HEADER_ONLY 84 | # include "wincolor_sink-inl.h" 85 | #endif 86 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/dup_filter_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "dist_sink.h" 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // Duplicate message removal sink. 16 | // Skip the message if previous one is identical and less than "max_skip_duration" have passed 17 | // 18 | // Example: 19 | // 20 | // #include 21 | // 22 | // int main() { 23 | // auto dup_filter = std::make_shared(std::chrono::seconds(5), level::info); 24 | // dup_filter->add_sink(std::make_shared()); 25 | // spdlog::logger l("logger", dup_filter); 26 | // l.info("Hello"); 27 | // l.info("Hello"); 28 | // l.info("Hello"); 29 | // l.info("Different Hello"); 30 | // } 31 | // 32 | // Will produce: 33 | // [2019-06-25 17:50:56.511] [logger] [info] Hello 34 | // [2019-06-25 17:50:56.512] [logger] [info] Skipped 3 duplicate messages.. 35 | // [2019-06-25 17:50:56.512] [logger] [info] Different Hello 36 | 37 | namespace spdlog { 38 | namespace sinks { 39 | template 40 | class dup_filter_sink : public dist_sink 41 | { 42 | public: 43 | template 44 | explicit dup_filter_sink(std::chrono::duration max_skip_duration, level::level_enum notification_level = level::info) 45 | : max_skip_duration_{max_skip_duration} 46 | , log_level_{notification_level} 47 | {} 48 | 49 | protected: 50 | std::chrono::microseconds max_skip_duration_; 51 | log_clock::time_point last_msg_time_; 52 | std::string last_msg_payload_; 53 | size_t skip_counter_ = 0; 54 | level::level_enum log_level_; 55 | 56 | void sink_it_(const details::log_msg &msg) override 57 | { 58 | bool filtered = filter_(msg); 59 | if (!filtered) 60 | { 61 | skip_counter_ += 1; 62 | return; 63 | } 64 | 65 | // log the "skipped.." message 66 | if (skip_counter_ > 0) 67 | { 68 | char buf[64]; 69 | auto msg_size = ::snprintf(buf, sizeof(buf), "Skipped %u duplicate messages..", static_cast(skip_counter_)); 70 | if (msg_size > 0 && static_cast(msg_size) < sizeof(buf)) 71 | { 72 | details::log_msg skipped_msg{msg.source, msg.logger_name, log_level_, string_view_t{buf, static_cast(msg_size)}}; 73 | dist_sink::sink_it_(skipped_msg); 74 | } 75 | } 76 | 77 | // log current message 78 | dist_sink::sink_it_(msg); 79 | last_msg_time_ = msg.time; 80 | skip_counter_ = 0; 81 | last_msg_payload_.assign(msg.payload.data(), msg.payload.data() + msg.payload.size()); 82 | } 83 | 84 | // return whether the log msg should be displayed (true) or skipped (false) 85 | bool filter_(const details::log_msg &msg) 86 | { 87 | auto filter_duration = msg.time - last_msg_time_; 88 | return (filter_duration > max_skip_duration_) || (msg.payload != last_msg_payload_); 89 | } 90 | }; 91 | 92 | using dup_filter_sink_mt = dup_filter_sink; 93 | using dup_filter_sink_st = dup_filter_sink; 94 | 95 | } // namespace sinks 96 | } // namespace spdlog 97 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/udp_client-windows.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // Helper RAII over winsock udp client socket. 7 | // Will throw on construction if socket creation failed. 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #if defined(_MSC_VER) 19 | # pragma comment(lib, "Ws2_32.lib") 20 | # pragma comment(lib, "Mswsock.lib") 21 | # pragma comment(lib, "AdvApi32.lib") 22 | #endif 23 | 24 | namespace spdlog { 25 | namespace details { 26 | class udp_client 27 | { 28 | static constexpr int TX_BUFFER_SIZE = 1024 * 10; 29 | SOCKET socket_ = INVALID_SOCKET; 30 | sockaddr_in addr_ = {}; 31 | 32 | static void init_winsock_() 33 | { 34 | WSADATA wsaData; 35 | auto rv = ::WSAStartup(MAKEWORD(2, 2), &wsaData); 36 | if (rv != 0) 37 | { 38 | throw_winsock_error_("WSAStartup failed", ::WSAGetLastError()); 39 | } 40 | } 41 | 42 | static void throw_winsock_error_(const std::string &msg, int last_error) 43 | { 44 | char buf[512]; 45 | ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error, 46 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(char)), NULL); 47 | 48 | throw_spdlog_ex(fmt_lib::format("udp_sink - {}: {}", msg, buf)); 49 | } 50 | 51 | void cleanup_() 52 | { 53 | if (socket_ != INVALID_SOCKET) 54 | { 55 | ::closesocket(socket_); 56 | } 57 | socket_ = INVALID_SOCKET; 58 | ::WSACleanup(); 59 | } 60 | 61 | public: 62 | udp_client(const std::string &host, uint16_t port) 63 | { 64 | init_winsock_(); 65 | 66 | addr_.sin_family = PF_INET; 67 | addr_.sin_port = htons(port); 68 | addr_.sin_addr.s_addr = INADDR_ANY; 69 | if (InetPtonA(PF_INET, host.c_str(), &addr_.sin_addr.s_addr) != 1) 70 | { 71 | int last_error = ::WSAGetLastError(); 72 | ::WSACleanup(); 73 | throw_winsock_error_("error: Invalid address!", last_error); 74 | } 75 | 76 | socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); 77 | if (socket_ == INVALID_SOCKET) 78 | { 79 | int last_error = ::WSAGetLastError(); 80 | ::WSACleanup(); 81 | throw_winsock_error_("error: Create Socket failed", last_error); 82 | } 83 | 84 | int option_value = TX_BUFFER_SIZE; 85 | if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&option_value), sizeof(option_value)) < 0) 86 | { 87 | int last_error = ::WSAGetLastError(); 88 | cleanup_(); 89 | throw_winsock_error_("error: setsockopt(SO_SNDBUF) Failed!", last_error); 90 | } 91 | } 92 | 93 | ~udp_client() 94 | { 95 | cleanup_(); 96 | } 97 | 98 | SOCKET fd() const 99 | { 100 | return socket_; 101 | } 102 | 103 | void send(const char *data, size_t n_bytes) 104 | { 105 | socklen_t tolen = sizeof(struct sockaddr); 106 | if (::sendto(socket_, data, static_cast(n_bytes), 0, (struct sockaddr *)&addr_, tolen) == -1) 107 | { 108 | throw_spdlog_ex("sendto(2) failed", errno); 109 | } 110 | } 111 | }; 112 | } // namespace details 113 | } // namespace spdlog 114 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/spdlog-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | 15 | SPDLOG_INLINE void initialize_logger(std::shared_ptr logger) 16 | { 17 | details::registry::instance().initialize_logger(std::move(logger)); 18 | } 19 | 20 | SPDLOG_INLINE std::shared_ptr get(const std::string &name) 21 | { 22 | return details::registry::instance().get(name); 23 | } 24 | 25 | SPDLOG_INLINE void set_formatter(std::unique_ptr formatter) 26 | { 27 | details::registry::instance().set_formatter(std::move(formatter)); 28 | } 29 | 30 | SPDLOG_INLINE void set_pattern(std::string pattern, pattern_time_type time_type) 31 | { 32 | set_formatter(std::unique_ptr(new pattern_formatter(std::move(pattern), time_type))); 33 | } 34 | 35 | SPDLOG_INLINE void enable_backtrace(size_t n_messages) 36 | { 37 | details::registry::instance().enable_backtrace(n_messages); 38 | } 39 | 40 | SPDLOG_INLINE void disable_backtrace() 41 | { 42 | details::registry::instance().disable_backtrace(); 43 | } 44 | 45 | SPDLOG_INLINE void dump_backtrace() 46 | { 47 | default_logger_raw()->dump_backtrace(); 48 | } 49 | 50 | SPDLOG_INLINE level::level_enum get_level() 51 | { 52 | return default_logger_raw()->level(); 53 | } 54 | 55 | SPDLOG_INLINE bool should_log(level::level_enum log_level) 56 | { 57 | return default_logger_raw()->should_log(log_level); 58 | } 59 | 60 | SPDLOG_INLINE void set_level(level::level_enum log_level) 61 | { 62 | details::registry::instance().set_level(log_level); 63 | } 64 | 65 | SPDLOG_INLINE void flush_on(level::level_enum log_level) 66 | { 67 | details::registry::instance().flush_on(log_level); 68 | } 69 | 70 | SPDLOG_INLINE void set_error_handler(void (*handler)(const std::string &msg)) 71 | { 72 | details::registry::instance().set_error_handler(handler); 73 | } 74 | 75 | SPDLOG_INLINE void register_logger(std::shared_ptr logger) 76 | { 77 | details::registry::instance().register_logger(std::move(logger)); 78 | } 79 | 80 | SPDLOG_INLINE void apply_all(const std::function)> &fun) 81 | { 82 | details::registry::instance().apply_all(fun); 83 | } 84 | 85 | SPDLOG_INLINE void drop(const std::string &name) 86 | { 87 | details::registry::instance().drop(name); 88 | } 89 | 90 | SPDLOG_INLINE void drop_all() 91 | { 92 | details::registry::instance().drop_all(); 93 | } 94 | 95 | SPDLOG_INLINE void shutdown() 96 | { 97 | details::registry::instance().shutdown(); 98 | } 99 | 100 | SPDLOG_INLINE void set_automatic_registration(bool automatic_registration) 101 | { 102 | details::registry::instance().set_automatic_registration(automatic_registration); 103 | } 104 | 105 | SPDLOG_INLINE std::shared_ptr default_logger() 106 | { 107 | return details::registry::instance().default_logger(); 108 | } 109 | 110 | SPDLOG_INLINE spdlog::logger *default_logger_raw() 111 | { 112 | return details::registry::instance().get_default_raw(); 113 | } 114 | 115 | SPDLOG_INLINE void set_default_logger(std::shared_ptr default_logger) 116 | { 117 | details::registry::instance().set_default_logger(std::move(default_logger)); 118 | } 119 | 120 | SPDLOG_INLINE void apply_logger_env_levels(std::shared_ptr logger) 121 | { 122 | details::registry::instance().apply_logger_env_levels(std::move(logger)); 123 | } 124 | 125 | } // namespace spdlog 126 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/cfg/helpers-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace spdlog { 20 | namespace cfg { 21 | namespace helpers { 22 | 23 | // inplace convert to lowercase 24 | inline std::string &to_lower_(std::string &str) 25 | { 26 | std::transform( 27 | str.begin(), str.end(), str.begin(), [](char ch) { return static_cast((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch); }); 28 | return str; 29 | } 30 | 31 | // inplace trim spaces 32 | inline std::string &trim_(std::string &str) 33 | { 34 | const char *spaces = " \n\r\t"; 35 | str.erase(str.find_last_not_of(spaces) + 1); 36 | str.erase(0, str.find_first_not_of(spaces)); 37 | return str; 38 | } 39 | 40 | // return (name,value) trimmed pair from given "name=value" string. 41 | // return empty string on missing parts 42 | // "key=val" => ("key", "val") 43 | // " key = val " => ("key", "val") 44 | // "key=" => ("key", "") 45 | // "val" => ("", "val") 46 | 47 | inline std::pair extract_kv_(char sep, const std::string &str) 48 | { 49 | auto n = str.find(sep); 50 | std::string k, v; 51 | if (n == std::string::npos) 52 | { 53 | v = str; 54 | } 55 | else 56 | { 57 | k = str.substr(0, n); 58 | v = str.substr(n + 1); 59 | } 60 | return std::make_pair(trim_(k), trim_(v)); 61 | } 62 | 63 | // return vector of key/value pairs from sequence of "K1=V1,K2=V2,.." 64 | // "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...} 65 | inline std::unordered_map extract_key_vals_(const std::string &str) 66 | { 67 | std::string token; 68 | std::istringstream token_stream(str); 69 | std::unordered_map rv{}; 70 | while (std::getline(token_stream, token, ',')) 71 | { 72 | if (token.empty()) 73 | { 74 | continue; 75 | } 76 | auto kv = extract_kv_('=', token); 77 | rv[kv.first] = kv.second; 78 | } 79 | return rv; 80 | } 81 | 82 | SPDLOG_INLINE void load_levels(const std::string &input) 83 | { 84 | if (input.empty() || input.size() > 512) 85 | { 86 | return; 87 | } 88 | 89 | auto key_vals = extract_key_vals_(input); 90 | std::unordered_map levels; 91 | level::level_enum global_level = level::info; 92 | bool global_level_found = false; 93 | 94 | for (auto &name_level : key_vals) 95 | { 96 | auto &logger_name = name_level.first; 97 | auto level_name = to_lower_(name_level.second); 98 | auto level = level::from_str(level_name); 99 | // ignore unrecognized level names 100 | if (level == level::off && level_name != "off") 101 | { 102 | continue; 103 | } 104 | if (logger_name.empty()) // no logger name indicate global level 105 | { 106 | global_level_found = true; 107 | global_level = level; 108 | } 109 | else 110 | { 111 | levels[logger_name] = level; 112 | } 113 | } 114 | 115 | details::registry::instance().set_levels(std::move(levels), global_level_found ? &global_level : nullptr); 116 | } 117 | 118 | } // namespace helpers 119 | } // namespace cfg 120 | } // namespace spdlog 121 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/thread_pool.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace spdlog { 17 | class async_logger; 18 | 19 | namespace details { 20 | 21 | using async_logger_ptr = std::shared_ptr; 22 | 23 | enum class async_msg_type 24 | { 25 | log, 26 | flush, 27 | terminate 28 | }; 29 | 30 | // Async msg to move to/from the queue 31 | // Movable only. should never be copied 32 | struct async_msg : log_msg_buffer 33 | { 34 | async_msg_type msg_type{async_msg_type::log}; 35 | async_logger_ptr worker_ptr; 36 | 37 | async_msg() = default; 38 | ~async_msg() = default; 39 | 40 | // should only be moved in or out of the queue.. 41 | async_msg(const async_msg &) = delete; 42 | 43 | // support for vs2013 move 44 | #if defined(_MSC_VER) && _MSC_VER <= 1800 45 | async_msg(async_msg &&other) 46 | : log_msg_buffer(std::move(other)) 47 | , msg_type(other.msg_type) 48 | , worker_ptr(std::move(other.worker_ptr)) 49 | {} 50 | 51 | async_msg &operator=(async_msg &&other) 52 | { 53 | *static_cast(this) = std::move(other); 54 | msg_type = other.msg_type; 55 | worker_ptr = std::move(other.worker_ptr); 56 | return *this; 57 | } 58 | #else // (_MSC_VER) && _MSC_VER <= 1800 59 | async_msg(async_msg &&) = default; 60 | async_msg &operator=(async_msg &&) = default; 61 | #endif 62 | 63 | // construct from log_msg with given type 64 | async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m) 65 | : log_msg_buffer{m} 66 | , msg_type{the_type} 67 | , worker_ptr{std::move(worker)} 68 | {} 69 | 70 | async_msg(async_logger_ptr &&worker, async_msg_type the_type) 71 | : log_msg_buffer{} 72 | , msg_type{the_type} 73 | , worker_ptr{std::move(worker)} 74 | {} 75 | 76 | explicit async_msg(async_msg_type the_type) 77 | : async_msg{nullptr, the_type} 78 | {} 79 | }; 80 | 81 | class SPDLOG_API thread_pool 82 | { 83 | public: 84 | using item_type = async_msg; 85 | using q_type = details::mpmc_blocking_queue; 86 | 87 | thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start, std::function on_thread_stop); 88 | thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start); 89 | thread_pool(size_t q_max_items, size_t threads_n); 90 | 91 | // message all threads to terminate gracefully and join them 92 | ~thread_pool(); 93 | 94 | thread_pool(const thread_pool &) = delete; 95 | thread_pool &operator=(thread_pool &&) = delete; 96 | 97 | void post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy); 98 | void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy); 99 | size_t overrun_counter(); 100 | void reset_overrun_counter(); 101 | size_t queue_size(); 102 | 103 | private: 104 | q_type q_; 105 | 106 | std::vector threads_; 107 | 108 | void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy); 109 | void worker_loop_(); 110 | 111 | // process next message in the queue 112 | // return true if this thread should still be active (while no terminate msg 113 | // was received) 114 | bool process_next_msg_(); 115 | }; 116 | 117 | } // namespace details 118 | } // namespace spdlog 119 | 120 | #ifdef SPDLOG_HEADER_ONLY 121 | # include "thread_pool-inl.h" 122 | #endif 123 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/async.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // 7 | // Async logging using global thread pool 8 | // All loggers created here share same global thread pool. 9 | // Each log message is pushed to a queue along with a shared pointer to the 10 | // logger. 11 | // If a logger deleted while having pending messages in the queue, it's actual 12 | // destruction will defer 13 | // until all its messages are processed by the thread pool. 14 | // This is because each message in the queue holds a shared_ptr to the 15 | // originating logger. 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace spdlog { 26 | 27 | namespace details { 28 | static const size_t default_async_q_size = 8192; 29 | } 30 | 31 | // async logger factory - creates async loggers backed with thread pool. 32 | // if a global thread pool doesn't already exist, create it with default queue 33 | // size of 8192 items and single thread. 34 | template 35 | struct async_factory_impl 36 | { 37 | template 38 | static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) 39 | { 40 | auto ®istry_inst = details::registry::instance(); 41 | 42 | // create global thread pool if not already exists.. 43 | 44 | auto &mutex = registry_inst.tp_mutex(); 45 | std::lock_guard tp_lock(mutex); 46 | auto tp = registry_inst.get_tp(); 47 | if (tp == nullptr) 48 | { 49 | tp = std::make_shared(details::default_async_q_size, 1U); 50 | registry_inst.set_tp(tp); 51 | } 52 | 53 | auto sink = std::make_shared(std::forward(args)...); 54 | auto new_logger = std::make_shared(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy); 55 | registry_inst.initialize_logger(new_logger); 56 | return new_logger; 57 | } 58 | }; 59 | 60 | using async_factory = async_factory_impl; 61 | using async_factory_nonblock = async_factory_impl; 62 | 63 | template 64 | inline std::shared_ptr create_async(std::string logger_name, SinkArgs &&...sink_args) 65 | { 66 | return async_factory::create(std::move(logger_name), std::forward(sink_args)...); 67 | } 68 | 69 | template 70 | inline std::shared_ptr create_async_nb(std::string logger_name, SinkArgs &&...sink_args) 71 | { 72 | return async_factory_nonblock::create(std::move(logger_name), std::forward(sink_args)...); 73 | } 74 | 75 | // set global thread pool. 76 | inline void init_thread_pool( 77 | size_t q_size, size_t thread_count, std::function on_thread_start, std::function on_thread_stop) 78 | { 79 | auto tp = std::make_shared(q_size, thread_count, on_thread_start, on_thread_stop); 80 | details::registry::instance().set_tp(std::move(tp)); 81 | } 82 | 83 | inline void init_thread_pool(size_t q_size, size_t thread_count, std::function on_thread_start) 84 | { 85 | init_thread_pool(q_size, thread_count, on_thread_start, [] {}); 86 | } 87 | 88 | inline void init_thread_pool(size_t q_size, size_t thread_count) 89 | { 90 | init_thread_pool( 91 | q_size, thread_count, [] {}, [] {}); 92 | } 93 | 94 | // get the global thread pool. 95 | inline std::shared_ptr thread_pool() 96 | { 97 | return details::registry::instance().get_tp(); 98 | } 99 | } // namespace spdlog 100 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/mongo_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // 7 | // Custom sink for mongodb 8 | // Building and using requires mongocxx library. 9 | // For building mongocxx library check the url below 10 | // http://mongocxx.org/mongocxx-v3/installation/ 11 | // 12 | 13 | #include "spdlog/common.h" 14 | #include "spdlog/details/log_msg.h" 15 | #include "spdlog/sinks/base_sink.h" 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace spdlog { 27 | namespace sinks { 28 | template 29 | class mongo_sink : public base_sink 30 | { 31 | public: 32 | mongo_sink(const std::string &db_name, const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017") 33 | try : mongo_sink(std::make_shared(), db_name, collection_name, uri) 34 | {} 35 | catch (const std::exception &e) 36 | { 37 | throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what())); 38 | } 39 | 40 | mongo_sink(std::shared_ptr instance, const std::string &db_name, const std::string &collection_name, 41 | const std::string &uri = "mongodb://localhost:27017") 42 | : instance_(std::move(instance)) 43 | , db_name_(db_name) 44 | , coll_name_(collection_name) 45 | { 46 | try 47 | { 48 | client_ = spdlog::details::make_unique(mongocxx::uri{uri}); 49 | } 50 | catch (const std::exception &e) 51 | { 52 | throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what())); 53 | } 54 | } 55 | 56 | ~mongo_sink() 57 | { 58 | flush_(); 59 | } 60 | 61 | protected: 62 | void sink_it_(const details::log_msg &msg) override 63 | { 64 | using bsoncxx::builder::stream::document; 65 | using bsoncxx::builder::stream::finalize; 66 | 67 | if (client_ != nullptr) 68 | { 69 | auto doc = document{} << "timestamp" << bsoncxx::types::b_date(msg.time) << "level" << level::to_string_view(msg.level).data() 70 | << "level_num" << msg.level << "message" << std::string(msg.payload.begin(), msg.payload.end()) 71 | << "logger_name" << std::string(msg.logger_name.begin(), msg.logger_name.end()) << "thread_id" 72 | << static_cast(msg.thread_id) << finalize; 73 | client_->database(db_name_).collection(coll_name_).insert_one(doc.view()); 74 | } 75 | } 76 | 77 | void flush_() override {} 78 | 79 | private: 80 | std::shared_ptr instance_; 81 | std::string db_name_; 82 | std::string coll_name_; 83 | std::unique_ptr client_ = nullptr; 84 | }; 85 | 86 | #include "spdlog/details/null_mutex.h" 87 | #include 88 | using mongo_sink_mt = mongo_sink; 89 | using mongo_sink_st = mongo_sink; 90 | 91 | } // namespace sinks 92 | 93 | template 94 | inline std::shared_ptr mongo_logger_mt(const std::string &logger_name, const std::string &db_name, 95 | const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017") 96 | { 97 | return Factory::template create(logger_name, db_name, collection_name, uri); 98 | } 99 | 100 | template 101 | inline std::shared_ptr mongo_logger_st(const std::string &logger_name, const std::string &db_name, 102 | const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017") 103 | { 104 | return Factory::template create(logger_name, db_name, collection_name, uri); 105 | } 106 | 107 | } // namespace spdlog 108 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/sinks/syslog_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace spdlog { 15 | namespace sinks { 16 | /** 17 | * Sink that write to syslog using the `syscall()` library call. 18 | */ 19 | template 20 | class syslog_sink : public base_sink 21 | { 22 | 23 | public: 24 | syslog_sink(std::string ident, int syslog_option, int syslog_facility, bool enable_formatting) 25 | : enable_formatting_{enable_formatting} 26 | , syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, 27 | /* spdlog::level::debug */ LOG_DEBUG, 28 | /* spdlog::level::info */ LOG_INFO, 29 | /* spdlog::level::warn */ LOG_WARNING, 30 | /* spdlog::level::err */ LOG_ERR, 31 | /* spdlog::level::critical */ LOG_CRIT, 32 | /* spdlog::level::off */ LOG_INFO}} 33 | , ident_{std::move(ident)} 34 | { 35 | // set ident to be program name if empty 36 | ::openlog(ident_.empty() ? nullptr : ident_.c_str(), syslog_option, syslog_facility); 37 | } 38 | 39 | ~syslog_sink() override 40 | { 41 | ::closelog(); 42 | } 43 | 44 | syslog_sink(const syslog_sink &) = delete; 45 | syslog_sink &operator=(const syslog_sink &) = delete; 46 | 47 | protected: 48 | void sink_it_(const details::log_msg &msg) override 49 | { 50 | string_view_t payload; 51 | memory_buf_t formatted; 52 | if (enable_formatting_) 53 | { 54 | base_sink::formatter_->format(msg, formatted); 55 | payload = string_view_t(formatted.data(), formatted.size()); 56 | } 57 | else 58 | { 59 | payload = msg.payload; 60 | } 61 | 62 | size_t length = payload.size(); 63 | // limit to max int 64 | if (length > static_cast(std::numeric_limits::max())) 65 | { 66 | length = static_cast(std::numeric_limits::max()); 67 | } 68 | 69 | ::syslog(syslog_prio_from_level(msg), "%.*s", static_cast(length), payload.data()); 70 | } 71 | 72 | void flush_() override {} 73 | bool enable_formatting_ = false; 74 | 75 | private: 76 | using levels_array = std::array; 77 | levels_array syslog_levels_; 78 | // must store the ident because the man says openlog might use the pointer as 79 | // is and not a string copy 80 | const std::string ident_; 81 | 82 | // 83 | // Simply maps spdlog's log level to syslog priority level. 84 | // 85 | int syslog_prio_from_level(const details::log_msg &msg) const 86 | { 87 | return syslog_levels_.at(static_cast(msg.level)); 88 | } 89 | }; 90 | 91 | using syslog_sink_mt = syslog_sink; 92 | using syslog_sink_st = syslog_sink; 93 | } // namespace sinks 94 | 95 | // Create and register a syslog logger 96 | template 97 | inline std::shared_ptr syslog_logger_mt(const std::string &logger_name, const std::string &syslog_ident = "", int syslog_option = 0, 98 | int syslog_facility = LOG_USER, bool enable_formatting = false) 99 | { 100 | return Factory::template create(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting); 101 | } 102 | 103 | template 104 | inline std::shared_ptr syslog_logger_st(const std::string &logger_name, const std::string &syslog_ident = "", int syslog_option = 0, 105 | int syslog_facility = LOG_USER, bool enable_formatting = false) 106 | { 107 | return Factory::template create(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting); 108 | } 109 | } // namespace spdlog 110 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/thread_pool-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | namespace details { 15 | 16 | SPDLOG_INLINE thread_pool::thread_pool( 17 | size_t q_max_items, size_t threads_n, std::function on_thread_start, std::function on_thread_stop) 18 | : q_(q_max_items) 19 | { 20 | if (threads_n == 0 || threads_n > 1000) 21 | { 22 | throw_spdlog_ex("spdlog::thread_pool(): invalid threads_n param (valid " 23 | "range is 1-1000)"); 24 | } 25 | for (size_t i = 0; i < threads_n; i++) 26 | { 27 | threads_.emplace_back([this, on_thread_start, on_thread_stop] { 28 | on_thread_start(); 29 | this->thread_pool::worker_loop_(); 30 | on_thread_stop(); 31 | }); 32 | } 33 | } 34 | 35 | SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start) 36 | : thread_pool(q_max_items, threads_n, on_thread_start, [] {}) 37 | {} 38 | 39 | SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n) 40 | : thread_pool( 41 | q_max_items, threads_n, [] {}, [] {}) 42 | {} 43 | 44 | // message all threads to terminate gracefully join them 45 | SPDLOG_INLINE thread_pool::~thread_pool() 46 | { 47 | SPDLOG_TRY 48 | { 49 | for (size_t i = 0; i < threads_.size(); i++) 50 | { 51 | post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block); 52 | } 53 | 54 | for (auto &t : threads_) 55 | { 56 | t.join(); 57 | } 58 | } 59 | SPDLOG_CATCH_STD 60 | } 61 | 62 | void SPDLOG_INLINE thread_pool::post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy) 63 | { 64 | async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg); 65 | post_async_msg_(std::move(async_m), overflow_policy); 66 | } 67 | 68 | void SPDLOG_INLINE thread_pool::post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy) 69 | { 70 | post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy); 71 | } 72 | 73 | size_t SPDLOG_INLINE thread_pool::overrun_counter() 74 | { 75 | return q_.overrun_counter(); 76 | } 77 | 78 | void SPDLOG_INLINE thread_pool::reset_overrun_counter() 79 | { 80 | q_.reset_overrun_counter(); 81 | } 82 | 83 | size_t SPDLOG_INLINE thread_pool::queue_size() 84 | { 85 | return q_.size(); 86 | } 87 | 88 | void SPDLOG_INLINE thread_pool::post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy) 89 | { 90 | if (overflow_policy == async_overflow_policy::block) 91 | { 92 | q_.enqueue(std::move(new_msg)); 93 | } 94 | else 95 | { 96 | q_.enqueue_nowait(std::move(new_msg)); 97 | } 98 | } 99 | 100 | void SPDLOG_INLINE thread_pool::worker_loop_() 101 | { 102 | while (process_next_msg_()) {} 103 | } 104 | 105 | // process next message in the queue 106 | // return true if this thread should still be active (while no terminate msg 107 | // was received) 108 | bool SPDLOG_INLINE thread_pool::process_next_msg_() 109 | { 110 | async_msg incoming_async_msg; 111 | q_.dequeue(incoming_async_msg); 112 | 113 | switch (incoming_async_msg.msg_type) 114 | { 115 | case async_msg_type::log: { 116 | incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg); 117 | return true; 118 | } 119 | case async_msg_type::flush: { 120 | incoming_async_msg.worker_ptr->backend_flush_(); 121 | return true; 122 | } 123 | 124 | case async_msg_type::terminate: { 125 | return false; 126 | } 127 | 128 | default: { 129 | assert(false); 130 | } 131 | } 132 | 133 | return true; 134 | } 135 | 136 | } // namespace details 137 | } // namespace spdlog 138 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/pattern_formatter.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | namespace spdlog { 20 | namespace details { 21 | 22 | // padding information. 23 | struct padding_info 24 | { 25 | enum class pad_side 26 | { 27 | left, 28 | right, 29 | center 30 | }; 31 | 32 | padding_info() = default; 33 | padding_info(size_t width, padding_info::pad_side side, bool truncate) 34 | : width_(width) 35 | , side_(side) 36 | , truncate_(truncate) 37 | , enabled_(true) 38 | {} 39 | 40 | bool enabled() const 41 | { 42 | return enabled_; 43 | } 44 | size_t width_ = 0; 45 | pad_side side_ = pad_side::left; 46 | bool truncate_ = false; 47 | bool enabled_ = false; 48 | }; 49 | 50 | class SPDLOG_API flag_formatter 51 | { 52 | public: 53 | explicit flag_formatter(padding_info padinfo) 54 | : padinfo_(padinfo) 55 | {} 56 | flag_formatter() = default; 57 | virtual ~flag_formatter() = default; 58 | virtual void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) = 0; 59 | 60 | protected: 61 | padding_info padinfo_; 62 | }; 63 | 64 | } // namespace details 65 | 66 | class SPDLOG_API custom_flag_formatter : public details::flag_formatter 67 | { 68 | public: 69 | virtual std::unique_ptr clone() const = 0; 70 | 71 | void set_padding_info(const details::padding_info &padding) 72 | { 73 | flag_formatter::padinfo_ = padding; 74 | } 75 | }; 76 | 77 | class SPDLOG_API pattern_formatter final : public formatter 78 | { 79 | public: 80 | using custom_flags = std::unordered_map>; 81 | 82 | explicit pattern_formatter(std::string pattern, pattern_time_type time_type = pattern_time_type::local, 83 | std::string eol = spdlog::details::os::default_eol, custom_flags custom_user_flags = custom_flags()); 84 | 85 | // use default pattern is not given 86 | explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol); 87 | 88 | pattern_formatter(const pattern_formatter &other) = delete; 89 | pattern_formatter &operator=(const pattern_formatter &other) = delete; 90 | 91 | std::unique_ptr clone() const override; 92 | void format(const details::log_msg &msg, memory_buf_t &dest) override; 93 | 94 | template 95 | pattern_formatter &add_flag(char flag, Args &&...args) 96 | { 97 | custom_handlers_[flag] = details::make_unique(std::forward(args)...); 98 | return *this; 99 | } 100 | void set_pattern(std::string pattern); 101 | void need_localtime(bool need = true); 102 | 103 | private: 104 | std::string pattern_; 105 | std::string eol_; 106 | pattern_time_type pattern_time_type_; 107 | bool need_localtime_; 108 | std::tm cached_tm_; 109 | std::chrono::seconds last_log_secs_; 110 | std::vector> formatters_; 111 | custom_flags custom_handlers_; 112 | 113 | std::tm get_time_(const details::log_msg &msg); 114 | template 115 | void handle_flag_(char flag, details::padding_info padding); 116 | 117 | // Extract given pad spec (e.g. %8X) 118 | // Advance the given it pass the end of the padding spec found (if any) 119 | // Return padding. 120 | static details::padding_info handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end); 121 | 122 | void compile_pattern_(const std::string &pattern); 123 | }; 124 | } // namespace spdlog 125 | 126 | #ifdef SPDLOG_HEADER_ONLY 127 | # include "pattern_formatter-inl.h" 128 | #endif 129 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/circular_q.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | // circular q view of std::vector. 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace spdlog { 11 | namespace details { 12 | template 13 | class circular_q 14 | { 15 | size_t max_items_ = 0; 16 | typename std::vector::size_type head_ = 0; 17 | typename std::vector::size_type tail_ = 0; 18 | size_t overrun_counter_ = 0; 19 | std::vector v_; 20 | 21 | public: 22 | using value_type = T; 23 | 24 | // empty ctor - create a disabled queue with no elements allocated at all 25 | circular_q() = default; 26 | 27 | explicit circular_q(size_t max_items) 28 | : max_items_(max_items + 1) // one item is reserved as marker for full q 29 | , v_(max_items_) 30 | {} 31 | 32 | circular_q(const circular_q &) = default; 33 | circular_q &operator=(const circular_q &) = default; 34 | 35 | // move cannot be default, 36 | // since we need to reset head_, tail_, etc to zero in the moved object 37 | circular_q(circular_q &&other) SPDLOG_NOEXCEPT 38 | { 39 | copy_moveable(std::move(other)); 40 | } 41 | 42 | circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT 43 | { 44 | copy_moveable(std::move(other)); 45 | return *this; 46 | } 47 | 48 | // push back, overrun (oldest) item if no room left 49 | void push_back(T &&item) 50 | { 51 | if (max_items_ > 0) 52 | { 53 | v_[tail_] = std::move(item); 54 | tail_ = (tail_ + 1) % max_items_; 55 | 56 | if (tail_ == head_) // overrun last item if full 57 | { 58 | head_ = (head_ + 1) % max_items_; 59 | ++overrun_counter_; 60 | } 61 | } 62 | } 63 | 64 | // Return reference to the front item. 65 | // If there are no elements in the container, the behavior is undefined. 66 | const T &front() const 67 | { 68 | return v_[head_]; 69 | } 70 | 71 | T &front() 72 | { 73 | return v_[head_]; 74 | } 75 | 76 | // Return number of elements actually stored 77 | size_t size() const 78 | { 79 | if (tail_ >= head_) 80 | { 81 | return tail_ - head_; 82 | } 83 | else 84 | { 85 | return max_items_ - (head_ - tail_); 86 | } 87 | } 88 | 89 | // Return const reference to item by index. 90 | // If index is out of range 0…size()-1, the behavior is undefined. 91 | const T &at(size_t i) const 92 | { 93 | assert(i < size()); 94 | return v_[(head_ + i) % max_items_]; 95 | } 96 | 97 | // Pop item from front. 98 | // If there are no elements in the container, the behavior is undefined. 99 | void pop_front() 100 | { 101 | head_ = (head_ + 1) % max_items_; 102 | } 103 | 104 | bool empty() const 105 | { 106 | return tail_ == head_; 107 | } 108 | 109 | bool full() const 110 | { 111 | // head is ahead of the tail by 1 112 | if (max_items_ > 0) 113 | { 114 | return ((tail_ + 1) % max_items_) == head_; 115 | } 116 | return false; 117 | } 118 | 119 | size_t overrun_counter() const 120 | { 121 | return overrun_counter_; 122 | } 123 | 124 | void reset_overrun_counter() 125 | { 126 | overrun_counter_ = 0; 127 | } 128 | 129 | private: 130 | // copy from other&& and reset it to disabled state 131 | void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT 132 | { 133 | max_items_ = other.max_items_; 134 | head_ = other.head_; 135 | tail_ = other.tail_; 136 | overrun_counter_ = other.overrun_counter_; 137 | v_ = std::move(other.v_); 138 | 139 | // put &&other in disabled, but valid state 140 | other.max_items_ = 0; 141 | other.head_ = other.tail_ = 0; 142 | other.overrun_counter_ = 0; 143 | } 144 | }; 145 | } // namespace details 146 | } // namespace spdlog 147 | -------------------------------------------------------------------------------- /firmware/src/mooncake/src/spdlog/include/spdlog/details/os.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include // std::time_t 8 | 9 | namespace spdlog { 10 | namespace details { 11 | namespace os { 12 | 13 | SPDLOG_API spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT; 14 | 15 | SPDLOG_API std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; 16 | 17 | SPDLOG_API std::tm localtime() SPDLOG_NOEXCEPT; 18 | 19 | SPDLOG_API std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; 20 | 21 | SPDLOG_API std::tm gmtime() SPDLOG_NOEXCEPT; 22 | 23 | // eol definition 24 | #if !defined(SPDLOG_EOL) 25 | # ifdef _WIN32 26 | # define SPDLOG_EOL "\r\n" 27 | # else 28 | # define SPDLOG_EOL "\n" 29 | # endif 30 | #endif 31 | 32 | SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL; 33 | 34 | // folder separator 35 | #if !defined(SPDLOG_FOLDER_SEPS) 36 | # ifdef _WIN32 37 | # define SPDLOG_FOLDER_SEPS "\\/" 38 | # else 39 | # define SPDLOG_FOLDER_SEPS "/" 40 | # endif 41 | #endif 42 | 43 | SPDLOG_CONSTEXPR static const char folder_seps[] = SPDLOG_FOLDER_SEPS; 44 | SPDLOG_CONSTEXPR static const filename_t::value_type folder_seps_filename[] = SPDLOG_FILENAME_T(SPDLOG_FOLDER_SEPS); 45 | 46 | // fopen_s on non windows for writing 47 | SPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode); 48 | 49 | // Remove filename. return 0 on success 50 | SPDLOG_API int remove(const filename_t &filename) SPDLOG_NOEXCEPT; 51 | 52 | // Remove file if exists. return 0 on success 53 | // Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread) 54 | SPDLOG_API int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT; 55 | 56 | SPDLOG_API int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT; 57 | 58 | // Return if file exists. 59 | SPDLOG_API bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT; 60 | 61 | // Return file size according to open FILE* object 62 | SPDLOG_API size_t filesize(FILE *f); 63 | 64 | // Return utc offset in minutes or throw spdlog_ex on failure 65 | SPDLOG_API int utc_minutes_offset(const std::tm &tm = details::os::localtime()); 66 | 67 | // Return current thread id as size_t 68 | // It exists because the std::this_thread::get_id() is much slower(especially 69 | // under VS 2013) 70 | SPDLOG_API size_t _thread_id() SPDLOG_NOEXCEPT; 71 | 72 | // Return current thread id as size_t (from thread local storage) 73 | SPDLOG_API size_t thread_id() SPDLOG_NOEXCEPT; 74 | 75 | // This is avoid msvc issue in sleep_for that happens if the clock changes. 76 | // See https://github.com/gabime/spdlog/issues/609 77 | SPDLOG_API void sleep_for_millis(unsigned int milliseconds) SPDLOG_NOEXCEPT; 78 | 79 | SPDLOG_API std::string filename_to_str(const filename_t &filename); 80 | 81 | SPDLOG_API int pid() SPDLOG_NOEXCEPT; 82 | 83 | // Determine if the terminal supports colors 84 | // Source: https://github.com/agauniyal/rang/ 85 | SPDLOG_API bool is_color_terminal() SPDLOG_NOEXCEPT; 86 | 87 | // Determine if the terminal attached 88 | // Source: https://github.com/agauniyal/rang/ 89 | SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; 90 | 91 | #if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) 92 | SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); 93 | 94 | SPDLOG_API void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target); 95 | #endif 96 | 97 | // Return directory name from given path or empty string 98 | // "abc/file" => "abc" 99 | // "abc/" => "abc" 100 | // "abc" => "" 101 | // "abc///" => "abc//" 102 | SPDLOG_API filename_t dir_name(const filename_t &path); 103 | 104 | // Create a dir from the given path. 105 | // Return true if succeeded or if this dir already exists. 106 | SPDLOG_API bool create_dir(const filename_t &path); 107 | 108 | // non thread safe, cross platform getenv/getenv_s 109 | // return empty string if field not found 110 | SPDLOG_API std::string getenv(const char *field); 111 | 112 | // Do fsync by FILE objectpointer. 113 | // Return true on success. 114 | SPDLOG_API bool fsync(FILE *fp); 115 | 116 | } // namespace os 117 | } // namespace details 118 | } // namespace spdlog 119 | 120 | #ifdef SPDLOG_HEADER_ONLY 121 | # include "os-inl.h" 122 | #endif 123 | --------------------------------------------------------------------------------