This commit is contained in:
TheJoKlLa 2024-11-06 08:54:31 -05:00
commit cf395f9c86
12 changed files with 745 additions and 0 deletions

47
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,47 @@
FROM espressif/idf
ARG DEBIAN_FRONTEND=nointeractive
ARG CONTAINER_USER=esp
ARG USER_UID=1050
ARG USER_GID=$USER_UID
RUN apt-get update \
&& apt install -y -q \
cmake \
git \
libglib2.0-0 \
libnuma1 \
libpixman-1-0 \
&& rm -rf /var/lib/apt/lists/*
# QEMU
ENV QEMU_REL=esp_develop_8.2.0_20240122
ENV QEMU_SHA256=e7c72ef5705ad1444d391711088c8717fc89f42e9bf6d1487f9c2a326b8cfa83
ENV QEMU_DIST=qemu-xtensa-softmmu-${QEMU_REL}-x86_64-linux-gnu.tar.xz
ENV QEMU_URL=https://github.com/espressif/qemu/releases/download/esp-develop-8.2.0-20240122/${QEMU_DIST}
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN wget --no-verbose ${QEMU_URL} \
&& echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - \
&& tar -xf $QEMU_DIST -C /opt \
&& rm ${QEMU_DIST}
ENV PATH=/opt/qemu/bin:${PATH}
RUN groupadd --gid $USER_GID $CONTAINER_USER \
&& adduser --uid $USER_UID --gid $USER_GID --disabled-password --gecos "" ${CONTAINER_USER} \
&& usermod -a -G root $CONTAINER_USER && usermod -a -G dialout $CONTAINER_USER
RUN chmod -R 775 /opt/esp/python_env/
USER ${CONTAINER_USER}
ENV USER=${CONTAINER_USER}
WORKDIR /home/${CONTAINER_USER}
RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc
ENTRYPOINT [ "/opt/esp/entrypoint.sh" ]
CMD ["/bin/bash", "-c"]

View File

@ -0,0 +1,36 @@
{
"name": "ESP-IDF QEMU",
"build": {
"dockerfile": "Dockerfile"
},
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "bash",
"idf.espIdfPath": "/opt/esp/idf",
"idf.customExtraPaths": "",
"idf.pythonBinPath": "/opt/esp/python_env/idf5.4_py3.12_env/bin/python",
"idf.toolsPath": "/opt/esp",
"idf.gitPath": "/usr/bin/git"
},
"extensions": [
"espressif.esp-idf-extension"
]
},
"codespaces": {
"settings": {
"terminal.integrated.defaultProfile.linux": "bash",
"idf.espIdfPath": "/opt/esp/idf",
"idf.customExtraPaths": "",
"idf.pythonBinPath": "/opt/esp/python_env/idf5.4_py3.12_env/bin/python",
"idf.toolsPath": "/opt/esp",
"idf.gitPath": "/usr/bin/git"
},
"extensions": [
"espressif.esp-idf-extension",
"espressif.esp-idf-web"
]
}
},
"runArgs": ["--privileged"]
}

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
build/
sdkconfig
sdkconfig.old

23
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,23 @@
{
"configurations": [
{
"name": "ESP-IDF",
"compilerPath": "${config:idf.toolsPath}/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin/xtensa-esp32-elf-gcc",
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
"includePath": [
"${config:idf.espIdfPath}/components/**",
"${config:idf.espIdfPathWin}/components/**",
"${workspaceFolder}/**"
],
"browse": {
"path": [
"${config:idf.espIdfPath}/components",
"${config:idf.espIdfPathWin}/components",
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
}
}
],
"version": 4
}

15
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "gdbtarget",
"request": "attach",
"name": "Eclipse CDT GDB Adapter"
},
{
"type": "espidf",
"name": "Launch",
"request": "launch"
}
]
}

20
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
"C_Cpp.intelliSenseEngine": "default",
"idf.adapterTargetName": "esp32",
"idf.customExtraPaths": "/home/user/.espressif/tools/xtensa-esp-elf-gdb/14.2_20240403/xtensa-esp-elf-gdb/bin:/home/user/.espressif/tools/riscv32-esp-elf-gdb/14.2_20240403/riscv32-esp-elf-gdb/bin:/home/user/.espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin:/home/user/.espressif/tools/riscv32-esp-elf/esp-13.2.0_20240530/riscv32-esp-elf/bin:/home/user/.espressif/tools/esp32ulp-elf/2.38_20240113/esp32ulp-elf/bin:/home/user/.espressif/tools/cmake/3.24.0/bin:/home/user/.espressif/tools/openocd-esp32/v0.12.0-esp32-20240318/openocd-esp32/bin:/home/user/.espressif/tools/ninja/1.11.1:/home/user/.espressif/tools/esp-rom-elfs/20240305",
"idf.customExtraVars": {
"OPENOCD_SCRIPTS": "/home/user/.espressif/tools/openocd-esp32/v0.12.0-esp32-20240318/openocd-esp32/share/openocd/scripts",
"ESP_ROM_ELF_DIR": "/home/user/.espressif/tools/esp-rom-elfs/20240305/"
},
"idf.espIdfPath": "/home/user/esp/v5.3.1/esp-idf",
"idf.openOcdConfigs": [
"board/esp32-wrover-kit-3.3v.cfg"
],
"idf.port": "/dev/ttyUSB1",
"idf.pythonBinPath": "/home/user/.espressif/python_env/idf5.3_py3.12_env/bin/python",
"idf.toolsPath": "/home/user/.espressif",
"idf.flashType": "UART",
"files.associations": {
"stdio.h": "c"
}
}

259
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,259 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build - Build project",
"type": "shell",
"command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py build",
"windows": {
"command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py build",
"options": {
"env": {
"PATH": "${env:PATH};${config:idf.customExtraPaths}"
}
}
},
"options": {
"env": {
"PATH": "${env:PATH}:${config:idf.customExtraPaths}"
}
},
"problemMatcher": [
{
"owner": "cpp",
"fileLocation": [
"autoDetect",
"${workspaceFolder}"
],
"pattern": {
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Set ESP-IDF Target",
"type": "shell",
"command": "${command:espIdf.setTarget}",
"problemMatcher": {
"owner": "cpp",
"fileLocation": [
"autoDetect",
"${workspaceFolder}"
],
"pattern": {
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
},
{
"label": "Clean - Clean the project",
"type": "shell",
"command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py fullclean",
"windows": {
"command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py fullclean",
"options": {
"env": {
"PATH": "${env:PATH};${config:idf.customExtraPaths}"
}
}
},
"options": {
"env": {
"PATH": "${env:PATH}:${config:idf.customExtraPaths}"
}
},
"problemMatcher": [
{
"owner": "cpp",
"fileLocation": [
"autoDetect",
"${workspaceFolder}"
],
"pattern": {
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
]
},
{
"label": "Flash - Flash the device",
"type": "shell",
"command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py -p ${config:idf.port} -b ${config:idf.flashBaudRate} flash",
"windows": {
"command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py flash -p ${config:idf.portWin} -b ${config:idf.flashBaudRate}",
"options": {
"env": {
"PATH": "${env:PATH};${config:idf.customExtraPaths}"
}
}
},
"options": {
"env": {
"PATH": "${env:PATH}:${config:idf.customExtraPaths}"
}
},
"problemMatcher": [
{
"owner": "cpp",
"fileLocation": [
"autoDetect",
"${workspaceFolder}"
],
"pattern": {
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
]
},
{
"label": "Monitor: Start the monitor",
"type": "shell",
"command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py -p ${config:idf.port} monitor",
"windows": {
"command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py -p ${config:idf.portWin} monitor",
"options": {
"env": {
"PATH": "${env:PATH};${config:idf.customExtraPaths}"
}
}
},
"options": {
"env": {
"PATH": "${env:PATH}:${config:idf.customExtraPaths}"
}
},
"problemMatcher": [
{
"owner": "cpp",
"fileLocation": [
"autoDetect",
"${workspaceFolder}"
],
"pattern": {
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
],
"dependsOn": "Flash - Flash the device"
},
{
"label": "OpenOCD: Start openOCD",
"type": "shell",
"presentation": {
"echo": true,
"reveal": "never",
"focus": false,
"panel": "new"
},
"command": "openocd -s ${command:espIdf.getOpenOcdScriptValue} ${command:espIdf.getOpenOcdConfigs}",
"windows": {
"command": "openocd.exe -s ${command:espIdf.getOpenOcdScriptValue} ${command:espIdf.getOpenOcdConfigs}",
"options": {
"env": {
"PATH": "${env:PATH};${config:idf.customExtraPaths}"
}
}
},
"options": {
"env": {
"PATH": "${env:PATH}:${config:idf.customExtraPaths}"
}
},
"problemMatcher": {
"owner": "cpp",
"fileLocation": [
"autoDetect",
"${workspaceFolder}"
],
"pattern": {
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
},
{
"label": "adapter",
"type": "shell",
"command": "${config:idf.pythonBinPath}",
"isBackground": true,
"options": {
"env": {
"PATH": "${env:PATH}:${config:idf.customExtraPaths}",
"PYTHONPATH": "${command:espIdf.getExtensionPath}/esp_debug_adapter/debug_adapter"
}
},
"problemMatcher": {
"background": {
"beginsPattern": "\bDEBUG_ADAPTER_STARTED\b",
"endsPattern": "DEBUG_ADAPTER_READY2CONNECT",
"activeOnStart": true
},
"pattern": {
"regexp": "(\\d+)-(\\d+)-(\\d+)\\s(\\d+):(\\d+):(\\d+),(\\d+)\\s-(.+)\\s(ERROR)",
"file": 8,
"line": 2,
"column": 3,
"severity": 4,
"message": 9
}
},
"args": [
"${command:espIdf.getExtensionPath}/esp_debug_adapter/debug_adapter_main.py",
"-e",
"${workspaceFolder}/build/${command:espIdf.getProjectName}.elf",
"-s",
"$OPENOCD_SCRIPTS",
"-dn",
"esp32",
"-om",
"connect_to_instance",
"-t",
"xtensa-esp32-elf-"
],
"windows": {
"command": "${config:idf.pythonBinPathWin}",
"options": {
"env": {
"PATH": "${env:PATH};${config:idf.customExtraPaths}",
"PYTHONPATH": "${command:espIdf.getExtensionPath}/esp_debug_adapter/debug_adapter"
}
}
}
}
]
}

8
CMakeLists.txt Normal file
View File

@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(FabLock Kallax)

69
README.md Normal file
View File

@ -0,0 +1,69 @@
# FabLock Kallax
FabLock Code for ANTS MAKE AM-022 Module
Connection for 16-Relais Board:
```
1 NC
1 COM
1 NO
2 NC
2 COM
2 NO
3 NC
3 COM
3 NO
4 NC
4 COM
4 NO
5 NC
5 COM
5 NO
6 NC
6 COM
6 NO
7 NC
7 COM
7 NO
8 NC
8 COM
8 NO
9 NC
9 COM
9 NO
10 NC
10 COM
10 NO
11 NC
11 COM
11 NO
12 NC
12 COM
12 NO
13 NC
13 COM
13 NO
14 NC
14 COM
14 NO
15 NC
15 COM
15 NO
16 NC
16 COM
16 NO
```

2
main/CMakeLists.txt Normal file
View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "main.c"
INCLUDE_DIRS ".")

20
main/Kconfig.projbuild Executable file
View File

@ -0,0 +1,20 @@
menu "FabLock"
config FABLOCK_ID
int "FabLock ID"
config FABLOCK_MQTT_HOST
string "MQTT Host"
default "mqtt.fab-access.org"
config FABLOCK_MQTT_USERNAME
string "MQTT Username"
config FABLOCK_MQTT_PASSWORD
string "MQTT Password"
config FABLOCK_WIFI_SSID
string "Wifi SSID"
config FABLOCK_WIFI_PSK
string "Wifi PSK"
endmenu

243
main/main.c Normal file
View File

@ -0,0 +1,243 @@
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "mqtt_client.h"
#include "driver/gpio.h"
#include "nvs_flash.h"
static const char *TAG = "MAIN";
static const char *TAG_WIFI = "WIFI";
static const char *TAG_MQTT = "MQTT";
esp_netif_t* sta_netif;
esp_event_handler_instance_t event_wifi;
esp_mqtt_client_handle_t client;
int PIN_GND[] = {25, 33, 27, 26, 12};
int PIN_LED[] = {17, 13, 4, 16, 18};
int PIN_LOCK[] = {19, 23, 5, 21, 22};
static void wifi_eventhandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
{
ESP_LOGI(TAG_WIFI, "Started");
esp_wifi_connect();
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
{
ESP_LOGI(TAG_WIFI, "Disconnected");
esp_wifi_connect();
}
else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED)
{
ESP_LOGI(TAG_WIFI, "Connected");
}
else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
ESP_LOGI(TAG_WIFI, "IPv4 recived");
}
}
void init()
{
gpio_config_t config;
config.pin_bit_mask = 0;
config.pull_down_en = GPIO_PULLDOWN_DISABLE;
config.pull_up_en = GPIO_PULLUP_DISABLE;
config.mode = GPIO_MODE_OUTPUT;
config.intr_type = GPIO_INTR_DISABLE;
config.pin_bit_mask |= 1ULL << 14;
for(int i = 0; i < 5; i++)
{
config.pin_bit_mask |= 1ULL << PIN_LED[i];
config.pin_bit_mask |= 1ULL << PIN_LOCK[i];
config.pin_bit_mask |= 1ULL << PIN_GND[i];
}
gpio_config(&config);
for(int i = 0; i < 5; i++)
{
gpio_set_level(PIN_LED[i], 0);
gpio_set_level(PIN_LOCK[i], 0);
gpio_set_level(PIN_GND[i], 0);
}
gpio_set_level(14, 0);
}
void trigger(int id)
{
ESP_LOGI(TAG, "Trigger: %d", id);
if(id >= 25)
{
ESP_LOGW(TAG, "Invalid ID: %d", id);
return;
}
for(int i = 0; i < 5; i++)
{
gpio_set_level(PIN_GND[i], 0);
}
gpio_set_level(PIN_LOCK[id/5], 1);
gpio_set_level(PIN_GND[id%5], 1);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(PIN_LOCK[id/5], 0);
gpio_set_level(PIN_GND[id%5], 0);
}
void identify(int id)
{
ESP_LOGI(TAG, "Identify: %d", id);
if(id >= 25)
{
ESP_LOGW(TAG, "Invalid ID: %d", id);
return;
}
for(int i = 0; i < 5; i++)
{
gpio_set_level(PIN_GND[i], 1);
}
gpio_set_level(PIN_LED[id/5], 1);
gpio_set_level(PIN_GND[id%5], 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(PIN_LED[id/5], 0);
gpio_set_level(PIN_GND[id%5], 1);
}
static void mqtt_eventhandler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
char topic_subscribe1[] = "fablock/00000/+/trigger\0";
snprintf(topic_subscribe1, strlen(topic_subscribe1)+1, "fablock/%05d/+/trigger", CONFIG_FABLOCK_ID);
char topic_subscribe2[] = "fablock/00000/+/identify\0";
snprintf(topic_subscribe2, strlen(topic_subscribe2)+1, "fablock/%05d/+/identify", CONFIG_FABLOCK_ID);
char* topic_trigger = "fablock/00000/00000/trigger";
char* topic_identify = "fablock/00000/00000/identify";
char str_id[6] = {0};
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG_MQTT, "Connected");
ESP_LOGI(TAG_MQTT, "Subscribe: %s", topic_subscribe1);
esp_mqtt_client_subscribe(client, topic_subscribe1, 1);
ESP_LOGI(TAG_MQTT, "Subscribe: %s", topic_subscribe2);
esp_mqtt_client_subscribe(client, topic_subscribe2, 1);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG_MQTT, "Disconnected");
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG_MQTT, "Data recieved");
ESP_LOGI(TAG_MQTT, "TOPIC=%.*s", event->topic_len, event->topic);
if(strlen(topic_trigger) == event->topic_len)
{
if(!strncmp(event->topic + strlen("fablock/00000/00000"), "/trigger", 8))
{
strncpy(str_id, event->topic + 14, 5);
int id = atoi(str_id);
trigger(id);
}
}
if(strlen(topic_identify) == event->topic_len)
{
if(!strncmp(event->topic + strlen("fablock/00000/00000"), "/identify", 9))
{
strncpy(str_id, event->topic + 14, 5);
int id = atoi(str_id);
identify(id);
}
}
break;
default:
break;
}
}
void app_main(void)
{
if(CONFIG_FABLOCK_ID > 99999 || CONFIG_FABLOCK_ID < 0)
{
ESP_LOGE(TAG, "Invalid FabLock ID");
}
init();
ESP_LOGI(TAG, "GPIO initied");
nvs_flash_init();
esp_event_loop_create_default();
esp_netif_init();
sta_netif = esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_eventhandler,
NULL,
&event_wifi);
esp_event_handler_instance_register(IP_EVENT,
ESP_EVENT_ANY_ID,
&wifi_eventhandler,
NULL,
&event_wifi);
wifi_config_t wifi_config = {
.sta = {
.ssid = CONFIG_FABLOCK_WIFI_SSID,
.password = CONFIG_FABLOCK_WIFI_PSK,
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
},
};
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
esp_wifi_start();
ESP_LOGI(TAG, "WIFI started");
esp_mqtt_client_config_t mqtt_cfg =
{
.broker.address.uri = "mqtt://" CONFIG_FABLOCK_MQTT_HOST,
.broker.address.port = 1883,
.credentials.username = CONFIG_FABLOCK_MQTT_USERNAME,
.credentials.authentication.password = CONFIG_FABLOCK_MQTT_PASSWORD
};
client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_eventhandler, NULL);
esp_mqtt_client_start(client);
ESP_LOGI(TAG, "MQTT started");
}