Files
Leo-ElixirLights/main/watchMain.cpp
T

315 lines
10 KiB
C++

/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* eth2ap (Ethernet to Wi-Fi AP packet forwarding) Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <stdlib.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_eth_driver.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "esp_private/wifi.h"
#include "ethernet_init.h"
#include "esp_netif.h"
#include "esp_eth.h"
// Component header
#include "Task.hpp"
#include "PwmExpanderPca9685.hpp"
#include "StepperDrv8833.hpp"
#include "stepperMotor.hpp"
#include "cliWrapper.hpp"
#include "udpSockets.hpp"
#include "tcpSockets.hpp"
static const char *TAG = "Watch";
static esp_eth_handle_t s_eth_handle = NULL;
static bool s_ethernet_is_connected = false;
extern "C" { // This switch allows the ROS C-implementation to find this main
void app_main(void);
}
std::unique_ptr<Cli> shellPtr;
/// @brief Callback for update start
/// @param args callback arguments
void startUpdate(Cli::CArgs args) {
ESP_LOGI(TAG, "Invoking Update");
if (args.size() != 1) {
shellPtr->write("Need URL to application'\n");
return;
}
// @ToDo: Start Update here
}
/// @brief Callback for commands that are not directly wired
/// @param name command name
/// @param args callback arguments
void onCommand(std::string name, Cli::CArgs args) {
ESP_LOGI(TAG, "Invoking: %s", name.c_str());
}
void showLogServerConfig(Cli::CArgs args) {
ESP_LOGI(TAG, "on showLogServerConfig:");
// auto &store = NvsApi::getInstance();
// auto logger = store.getValue("syslogDst");
// shellPtr->write(std::string{"syslog destination = '"} + logger + "'\n");
}
void setLogServerConfig(Cli::CArgs args) {
ESP_LOGI(TAG, "on showLogServerConfig:");
if (args.size() != 1) {
shellPtr->write("Need IP address to syslog server'\n");
return;
}
// auto &store = NvsApi::getInstance();
// shellPtr->write(std::string{"setting syslog destination to = '"} + args[0] + "'\n");
// store.setValue("syslogDst", args[0]);
}
/**
* @brief Telnet socket via TCP/IP
*
* @details The ini-file for TeraTerm only changes CRReceive and CRSend values both to "=CR"
* @param arg ignored task argument
*/
static void telnetSocketTask(int addrFamily) {
ESP_LOGI(TAG, "Starting Telnet task");
try {
TelnetServer telnet(addrFamily);
telnet.run(
[](TcpSession &session) {
shellPtr = std::make_unique<Cli>(session, [](std::string n, Cli::CArgs a) { onCommand(n, a); });
shellPtr->addBinding(
{"update", "Start OTA-Update-Process",
[](Cli::CArgs a) { startUpdate(a); }});
shellPtr->addBinding(
{"logserver_show", "Shows log server config ip",
[](Cli::CArgs a) { showLogServerConfig(a); }});
shellPtr->addBinding(
{"logserver_set", "Set log server config ip",
[](Cli::CArgs a) { setLogServerConfig(a); }});
},
[](TcpSession &session) {
shellPtr->process();
Syslog::setupTask(session.getOther());
});
} catch (const std::exception &e) {
ESP_LOGE("TCP", "%s", e.what());
}
vTaskDelete(NULL);
}
void startServerTasks() {
static int ipVersion = AF_INET;
static fos::TaskT<int> telnetSocket(telnetSocketTask, ipVersion, "tcpServer", 4096);
// static TaskT<int> dmxNode(dmxSocketTask, ipVersion, "dmxNode", 4096);
// static Task otaUpdate(SystemFunctions::OtaTaskEntry, "otaTask", 8192);
// initialise_mdns();
// netbiosns_init();
// netbiosns_set_name(CONFIG_EXAMPLE_MDNS_HOST_NAME);
// WebServer::init(FileSystem::getInstance());
// WebServer::getInstance(FileSystem::getInstance()).registerCallback(printSysState);
// auto &store = NvsApi::getInstance();
// auto broker = store.getValue("mqttBroker");
// if (broker != "") {
// MqttClient::init(broker);
// }
// auto logger = store.getValue("syslogDst");
// if (logger != "") {
// Syslog::setupTask(IpAdr{logger, 0});
// }
}
/** Event handler for IP_EVENT_ETH_GOT_IP */
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
const esp_netif_ip_info_t *ip_info = &event->ip_info;
ESP_LOGI(TAG, "Ethernet Got IP Address");
ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
ESP_LOGI(TAG, "~~~~~~~~~~~");
startServerTasks();
}
// Event handler for Ethernet
static void eth_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
uint8_t mac_addr[6] = {0};
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
ESP_LOGI(TAG, "Ethernet Link Up");
s_ethernet_is_connected = true;
ESP_LOGI(TAG, "Ethernet Link Up");
ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "Ethernet Link Down");
s_ethernet_is_connected = false;
break;
case ETHERNET_EVENT_START:
ESP_LOGI(TAG, "Ethernet Started");
break;
case ETHERNET_EVENT_STOP:
ESP_LOGI(TAG, "Ethernet Stopped");
break;
default:
break;
}
}
static void initialize_ethernet(void)
{
uint8_t eth_port_cnt = 0;
esp_eth_handle_t *eth_handles;
ESP_ERROR_CHECK(example_eth_init(&eth_handles, &eth_port_cnt));
if (eth_port_cnt > 1) {
ESP_LOGW(TAG, "multiple Ethernet devices detected, the first initialized is to be used!");
}
s_eth_handle = eth_handles[0];
free(eth_handles);
// Initialize TCP/IP network interface aka the esp-netif (should be called only once in application)
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and you don't need to modify
// default esp-netif configuration parameters.
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
// Attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(s_eth_handle)));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_eth_start(s_eth_handle));
}
void LightingTask() {
ESP_LOGI(TAG, "Start Lighting");
static I2cMaster master(I2C_NUM_0,
/*sda=*/ GPIO_NUM_10,
/*scl=*/ GPIO_NUM_11);
// static PmwExpanderPca9685 pca9685(master);
static PmwExpanderPca9685 ledDriver1(master, /*iverted=*/ false);
static PmwExpanderPca9685 ledDriver2(master, /*iverted=*/ false, 0x41);
PmwExpanderPca9685::GrayValues values[2];
OutputPort pwmEnable(GPIO_NUM_5, GpioPort::Logic::Inverted);
pwmEnable.write(true);
int idx = 0;
while (true) {
values[0].fill(0);
values[1].fill(0);
// values[x][4] = 0x200; // Actually first
values[0][idx] = 0x200;
ledDriver1.sendImage(values[0]);
// values[1][4] = 0x100; // Actually first
values[1][idx] = 0x400;
ledDriver2.sendImage(values[1]);
if (++idx >= 16 ) {
idx = 0;
}
fos::Task::delayMs(100);
}
}
void MovementTask() {
ESP_LOGI(TAG, "Start Stepper");
constexpr int MicroSteps = 32;
StepperDriverDrv8833::Pins stepperPins{
LEDC_TIMER_0,
{LEDC_CHANNEL_0, LEDC_CHANNEL_1, LEDC_CHANNEL_2, LEDC_CHANNEL_3},
{GPIO_NUM_23, GPIO_NUM_22, GPIO_NUM_21, GPIO_NUM_20},
};
StepperDriverDrv8833 stepperDriver(stepperPins, MicroSteps);
stepperDriver.setPos(0);
StepperMotor::Config stepperCfg{1.8F, MicroSteps};
InputPort initSens(GPIO_NUM_18);
InputPort motorFault(GPIO_NUM_8);
motorFault.setLogic(GpioPort::Logic::Inverted);
OutputPort motorSleep(GPIO_NUM_15, GpioPort::Logic::Inverted);
motorSleep.write(false);
StepperMotor stepper(stepperCfg, stepperDriver, initSens);
int i = 0;
while (i++ < 80) {
stepperDriver.step(1);
stepperDriver.getSubPos();
fos::Task::delayMs(100);
}
ESP_LOGI("Stepper", "Find Home");
stepper.findRef();
ESP_LOGI(TAG, "Fist Position is %f.2", stepper.getScaledPos() * 6);
fos::Task::delayMs(1000);
while (true) {
fos::Task::delayMs(100);
}
}
void IoTest()
{
ESP_LOGI(TAG, "Start IO");
InputPort in2(GPIO_NUM_19);
OutputPort nReset(GPIO_NUM_9);
while (true) {
nReset.write(in2.read());
fos::Task::delayMs(100);
}
}
void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
initialize_ethernet();
static fos::Task lightingTask(LightingTask, "Lights", 0x4000uL);
static fos::Task movementTask(MovementTask, "Motor", 0x4000uL);
static fos::Task ioTask(IoTest, "IO", 0x4000uL);
}