Pracovni prvni odevzdani - zatim nefunkcni!
This commit is contained in:
parent
76eae4e788
commit
691ecffe39
43
.gitignore
vendored
43
.gitignore
vendored
@ -1,34 +1,9 @@
|
||||
# ---> C++
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
|
55
.travis.yml
Normal file
55
.travis.yml
Normal file
@ -0,0 +1,55 @@
|
||||
# Continuous Integration (CI) is the practice, in software
|
||||
# engineering, of merging all developer working copies with a shared mainline
|
||||
# several times a day < http://docs.platformio.org/page/ci/index.html >
|
||||
#
|
||||
# Documentation:
|
||||
#
|
||||
# * Travis CI Embedded Builds with PlatformIO
|
||||
# < https://docs.travis-ci.com/user/integration/platformio/ >
|
||||
#
|
||||
# * PlatformIO integration with Travis CI
|
||||
# < http://docs.platformio.org/page/ci/travis.html >
|
||||
#
|
||||
# * User Guide for `platformio ci` command
|
||||
# < http://docs.platformio.org/page/userguide/cmd_ci.html >
|
||||
#
|
||||
#
|
||||
# Please choice one of the following templates (proposed below) and uncomment
|
||||
# it (remove "# " before each line) or use own configuration according to the
|
||||
# Travis CI documentation (see above).
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# Template #1: General project. Test it using existing `platformio.ini`.
|
||||
#
|
||||
|
||||
# language: python
|
||||
# python:
|
||||
# - "2.7"
|
||||
#
|
||||
# install:
|
||||
# - pip install -U platformio
|
||||
#
|
||||
# script:
|
||||
# - platformio run
|
||||
|
||||
|
||||
#
|
||||
# Template #2: The project is intended to by used as a library with examples
|
||||
#
|
||||
|
||||
# language: python
|
||||
# python:
|
||||
# - "2.7"
|
||||
#
|
||||
# env:
|
||||
# - PLATFORMIO_CI_SRC=path/to/test/file.c
|
||||
# - PLATFORMIO_CI_SRC=examples/file.ino
|
||||
# - PLATFORMIO_CI_SRC=path/to/test/directory
|
||||
#
|
||||
# install:
|
||||
# - pip install -U platformio
|
||||
#
|
||||
# script:
|
||||
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
|
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"terminal.integrated.env.windows": {
|
||||
"PATH": "C:\\Users\\PBRY\\.platformio\\penv\\Scripts;C:\\Users\\PBRY\\.platformio\\penv;C:\\ProgramData\\Oracle\\Java\\javapath;C:\\Python27\\;C:\\Python27\\Scripts;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;c:\\python27;C:\\Program Files\\TortoiseSVN\\bin\\;%USERPROFILE%\\.dnx\\bin;C:\\Program Files\\Microsoft DNX\\Dnvm\\;C:\\Users\\PBRY\\AppData\\Local\\Programs\\Git\\cmd;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\;C:\\Python27\\;C:\\Python27\\Scripts;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;c:\\python27;C:\\Program Files\\TortoiseSVN\\bin\\;C:\\Users\\PBRY\\.dnx\\bin;C:\\Program Files\\Microsoft DNX\\Dnvm\\;C:\\Users\\PBRY\\AppData\\Local\\Programs\\Git\\cmd;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C:\\Users\\PBRY\\.dnx\\bin;C:\\Program Files (x86)\\Atmel\\sam-ba_2.12\\drv\\;C:\\Program Files (x86)\\Atmel\\sam-ba_2.12;C:\\Program Files\\Intel\\WiFi\\bin\\;C:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;i:\\MyProjects\\Kicad\\BOM\";C:\\Users\\PBRY\\AppData\\Local\\Programs\\Fiddler;C:\\Users\\PBRY\\AppData\\Local\\atom\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\ProgramData\\Oracle\\Java\\javapath;C:\\Python27\\;C:\\Python27\\Scripts;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;c:\\python27;C:\\Program Files\\TortoiseSVN\\bin\\;%USERPROFILE%\\.dnx\\bin;C:\\Program Files\\Microsoft DNX\\Dnvm\\;C:\\Users\\PBRY\\AppData\\Local\\Programs\\Git\\cmd;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\;C:\\Python27\\;C:\\Python27\\Scripts;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;c:\\python27;C:\\Program Files\\TortoiseSVN\\bin\\;C:\\Users\\PBRY\\.dnx\\bin;C:\\Program Files\\Microsoft DNX\\Dnvm\\;C:\\Users\\PBRY\\AppData\\Local\\Programs\\Git\\cmd;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C:\\Users\\PBRY\\.dnx\\bin;C:\\Program Files (x86)\\Atmel\\sam-ba_2.12\\drv\\;C:\\Program Files (x86)\\Atmel\\sam-ba_2.12;C:\\Program Files\\Intel\\WiFi\\bin\\;C:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;i:\\MyProjects\\Kicad\\BOM\";C:\\Users\\PBRY\\AppData\\Local\\Programs\\Fiddler;C:\\Users\\PBRY\\AppData\\Local\\atom\\bin;C:\\Program Files\\Microsoft VS Code\\bin",
|
||||
"PLATFORMIO_CALLER": "vscode"
|
||||
}
|
||||
}
|
20
eagle.flash.4m2m.ld
Normal file
20
eagle.flash.4m2m.ld
Normal file
@ -0,0 +1,20 @@
|
||||
/* Flash Split for 4M chips */
|
||||
/* sketch 1019KB */
|
||||
/* empty 1024KB */
|
||||
/* spiffs 2028KB */
|
||||
/* eeprom 20KB */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
dport0_0_seg : org = 0x3FF00000, len = 0x10
|
||||
dram0_0_seg : org = 0x3FFE8000, len = 0x14000
|
||||
iram1_0_seg : org = 0x40100000, len = 0x8000
|
||||
irom0_0_seg : org = 0x40201010, len = 0xfeff0
|
||||
}
|
||||
|
||||
PROVIDE ( _SPIFFS_start = 0x40400000 );
|
||||
PROVIDE ( _SPIFFS_end = 0x405FB000 );
|
||||
PROVIDE ( _SPIFFS_page = 0x100 );
|
||||
PROVIDE ( _SPIFFS_block = 0x2000 );
|
||||
|
||||
INCLUDE "../ld/eagle.app.v6.common.ld"
|
117
lib/led/led.cpp
Normal file
117
lib/led/led.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
// Obsluha LED signalizace
|
||||
#include <Arduino.h>
|
||||
#include "led.h"
|
||||
|
||||
LED::LED(int pin, int ledon, int ledoff)
|
||||
{
|
||||
_pin = pin;
|
||||
_ledon = ledon;
|
||||
_ledoff = ledoff;
|
||||
}
|
||||
|
||||
void LED::rtLed(void)
|
||||
{
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case LS_RUN:
|
||||
{
|
||||
uint8_t instr;
|
||||
|
||||
if (NULL != _signal)
|
||||
instr = *_ptr; // instrukce
|
||||
else if (NULL != _psignal)
|
||||
instr = pgm_read_byte(_pptr);
|
||||
else
|
||||
instr = LEDS_STOP;
|
||||
switch (instr & 0xc0)
|
||||
{
|
||||
case LEDS_ONFOR:
|
||||
digitalWrite(_pin, _ledon);
|
||||
_timer = 10ul * ((instr & 0x3F) + 1);
|
||||
_state = LS_WAIT;
|
||||
break;
|
||||
|
||||
case LEDS_OFFFOR:
|
||||
digitalWrite(_pin, _ledoff);
|
||||
_timer = 10ul * ((instr & 0x3F) + 1);
|
||||
_state = LS_WAIT;
|
||||
break;
|
||||
|
||||
case LEDS_STOP:
|
||||
_state = LS_IDLE;
|
||||
break;
|
||||
|
||||
case LEDS_RESTART:
|
||||
_ptr = _signal;
|
||||
_pptr = _psignal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_WAIT:
|
||||
--_timer;
|
||||
if (0 == _timer)
|
||||
{
|
||||
_state = LS_RUN;
|
||||
++_ptr;
|
||||
++_pptr;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LED::begin(void)
|
||||
{
|
||||
|
||||
pinMode(_pin, OUTPUT);
|
||||
digitalWrite(_pin, _ledoff);
|
||||
_state - LS_IDLE;
|
||||
// _handler.attach_ms(10, lh, static_cast<void *>(this));
|
||||
_handler.attach_ms(10, lh, this);
|
||||
}
|
||||
|
||||
void LED::set(const uint8_t *signal)
|
||||
{
|
||||
|
||||
noInterrupts();
|
||||
_signal = signal;
|
||||
_ptr = _signal;
|
||||
_psignal = NULL;
|
||||
_state = LS_RUN;
|
||||
interrupts();
|
||||
}
|
||||
|
||||
//void LED::set(const __FlashStringHelper *signal)
|
||||
void LED::set(PGM_P signal)
|
||||
{
|
||||
noInterrupts();
|
||||
// _psignal = reinterpret_cast<PGM_P>(signal);
|
||||
_psignal = signal;
|
||||
_pptr = _psignal;
|
||||
_signal = NULL;
|
||||
_state = LS_RUN;
|
||||
interrupts();
|
||||
}
|
||||
|
||||
void LED::start()
|
||||
{
|
||||
|
||||
noInterrupts();
|
||||
_ptr = _signal;
|
||||
_pptr = _psignal;
|
||||
_state = LS_RUN;
|
||||
interrupts();
|
||||
}
|
||||
|
||||
//void LED::lh(void *ptr)
|
||||
void LED::lh(LED *ptr)
|
||||
{
|
||||
// LED *pled = static_cast<LED *>(ptr);
|
||||
LED *pled = ptr;
|
||||
pled->rtLed();
|
||||
}
|
72
lib/led/led.h
Normal file
72
lib/led/led.h
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file led.h
|
||||
* @author Pavel Brychta, http://www.xpablo.cz
|
||||
*
|
||||
* Copyright (c) 2015,16 Pavel Brychta. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#ifndef _led_h_
|
||||
#define _led_h_
|
||||
|
||||
#include <Ticker.h>
|
||||
#include <pgmspace.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
}ledsignal_t;
|
||||
|
||||
enum
|
||||
{
|
||||
LEDS_ONFOR = 0x00, // rozsviti LED na delku, ktera je uvedena v nizsich 6-ti bitech (+1) [100ms], 0 znamena, ze se rozsviti na 100ms
|
||||
LEDS_OFFFOR = 0x40,
|
||||
LEDS_STOP = 0x80,
|
||||
LEDS_RESTART = 0xc0
|
||||
};
|
||||
|
||||
class LED
|
||||
{
|
||||
// typedef void (LED::*runtime)(void);
|
||||
|
||||
protected:
|
||||
int _pin; // pin, na kterem je LED pripojena
|
||||
Ticker _handler; // obsluha LED signalizace
|
||||
const uint8_t *_signal; // ukazatel na vzor signalizace
|
||||
PGM_P _psignal;
|
||||
const uint8_t *_ptr; // ukazatel na aktualne zpracovavane misto v signalizaci
|
||||
PGM_P _pptr;
|
||||
uint32_t _timer; // casovani
|
||||
int _ledon;
|
||||
int _ledoff;
|
||||
enum
|
||||
{
|
||||
LS_IDLE, // klid, cekame na zmenu (zavolani set, nebo start)
|
||||
LS_RUN, // bezi automat
|
||||
LS_WAIT, // cekame v automatu
|
||||
}_state; // stav automatu
|
||||
public:
|
||||
LED(int pin, int ledon, int ledoff);
|
||||
void begin(void);
|
||||
void set(const uint8_t *signal);
|
||||
// void set(const __FlashStringHelper *signal);
|
||||
void set(PGM_P signal);
|
||||
void start();
|
||||
// static void lh(void *ptr);
|
||||
static void lh(LED *ptr);
|
||||
void rtLed(void); // vykonna metoda
|
||||
};
|
||||
#endif
|
41
lib/readme.txt
Normal file
41
lib/readme.txt
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
This directory is intended for the project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link to executable file.
|
||||
|
||||
The source code of each library should be placed in separate directory, like
|
||||
"lib/private_lib/[here are source files]".
|
||||
|
||||
For example, see how can be organized `Foo` and `Bar` libraries:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) http://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- readme.txt --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
Then in `src/main.c` you should use:
|
||||
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
// rest H/C/CPP code
|
||||
|
||||
PlatformIO will find your libraries automatically, configure preprocessor's
|
||||
include paths and build them.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- http://docs.platformio.org/page/librarymanager/ldf.html
|
36
lib/uinterval/uinterval.cpp
Normal file
36
lib/uinterval/uinterval.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
}
|
||||
#include <Arduino.h>
|
||||
#include "uinterval.h"
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
uint32_t uInterval::remains(void)
|
||||
{
|
||||
|
||||
return _timeout - (micros() - _timefrom);
|
||||
}
|
||||
|
||||
uint32_t uInterval::elapsed(void)
|
||||
{
|
||||
|
||||
return micros() - _timefrom;
|
||||
}
|
||||
|
||||
bool uInterval::expired(void)
|
||||
{
|
||||
|
||||
if ((micros() - _timefrom) >= _timeout)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void uInterval::set(uint32_t tmout)
|
||||
{
|
||||
|
||||
_timefrom = micros();
|
||||
_timeout = tmout;
|
||||
}
|
30
lib/uinterval/uinterval.h
Normal file
30
lib/uinterval/uinterval.h
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
#ifndef uinterval_h
|
||||
#define uinterval_h
|
||||
|
||||
/* uInterval
|
||||
* Copyright (C) 2014, 2016 Pavel Brychta http://www.xpablo.cz
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
class uInterval
|
||||
{
|
||||
protected:
|
||||
uint32_t _timefrom;
|
||||
uint32_t _timeout;
|
||||
public:
|
||||
bool expired(void);
|
||||
void set(uint32_t tmout);
|
||||
uint32_t elapsed(void);
|
||||
uint32_t remains(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
// EOF
|
24
platformio.ini
Normal file
24
platformio.ini
Normal file
@ -0,0 +1,24 @@
|
||||
[env:esp12e]
|
||||
; platform = https://github.com/platformio/platform-espressif8266.git#feature/stage
|
||||
; platform = https://github.com/platformio/platform-espressif8266.git
|
||||
platform = espressif8266
|
||||
; platform = espressif8266@1.6 - odladena na verzi @1.7 diky workaroundu
|
||||
board = esp12e
|
||||
framework = arduino
|
||||
board_build.flash_mode = dio
|
||||
upload_port = com25
|
||||
;upload_port = bwrpn5325.local
|
||||
;upload_port = bwrt00.local
|
||||
; upload_port = 192.168.1.197
|
||||
; upload_port = /dev/ttyUSB0
|
||||
upload_speed = 230400
|
||||
lib_deps =
|
||||
http://git.xpablo.cz/pablo2048/Interval.git
|
||||
http://git.xpablo.cz/pablo2048/WiFiConfig.git
|
||||
https://github.com/me-no-dev/AsyncTCP.git
|
||||
https://github.com/me-no-dev/ESPAsyncUDP.git
|
||||
https://github.com/me-no-dev/ESPAsyncWebServer.git
|
||||
http://git.xpablo.cz/pablo2048/Trace.git
|
||||
build_flags =
|
||||
-Wl,-Teagle.flash.4m2m.ld
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
73
src/configuration.h
Normal file
73
src/configuration.h
Normal file
@ -0,0 +1,73 @@
|
||||
#ifndef _CONFIGURATION_H_
|
||||
#define _CONFIGURATION_H_
|
||||
#define NO_PIN -1 // indikator nepouziteho pinu
|
||||
|
||||
#define VERSION "0.0.3"
|
||||
#define SYSTEM_BUILD 3
|
||||
|
||||
#define __INOVERSION__ __FILE__ " Compiled @" __DATE__ " " __TIME__
|
||||
|
||||
#define DEBUG_BUILD // **** ladici varianta s Arduino OTA
|
||||
|
||||
#define HTTP_UPDATE // **** moznost aktualizace firmware pres www server pomoci http://%s.local/update
|
||||
#define HTTP_UPDATE_USERNAME "admin" // **** uzivatelske jmeno pro update firmware (zapoznamkovanim teto definice vypneme nutnost prihlasovani)
|
||||
#define HTTP_UPDATE_PASSWORD "nimda" // **** uzivatelske heslo pro update firmware
|
||||
|
||||
//#define USE_SPIFFS // **** podpora pro praci s SPIFFS souborovym systemem (webovy server dokaze servirovat stranky z SPIFFS)
|
||||
|
||||
#define FORCE_CONFIG_BUTTON_PIN NO_PIN // **** I/O pin, pouzity pro vynuceni konfigurace
|
||||
|
||||
#define LED_PIN 2//NO_PIN // pin, ke kteremu je pripojena LED dioda
|
||||
|
||||
#define HTTP_PORT 80 // port, na kterem pobezi HTTP (www) server
|
||||
|
||||
#ifdef DEBUG_BUILD
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#include <trace.h>
|
||||
|
||||
#define TRACE(severity, ...) trace_print(severity, __VA_ARGS__)
|
||||
#define TRACEFUNC(severity, ...) trace_printfunc(severity, __func__, __FILE__, TOSTRING(__LINE__), __VA_ARGS__)
|
||||
#define TRACEDUMP(severity, prefix, address, size) trace_dump(severity, prefix, address, size)
|
||||
#define TRACE_INIT trace_init()
|
||||
#define TRACE_ADDWEB(srv) trace_addweb(srv)
|
||||
#define TRACE_POLL trace_poll()
|
||||
#else
|
||||
#define TRACE(...) ((void)0) // from assert.h "NOP" - http://stackoverflow.com/questions/9187628/c-empty-function-macros
|
||||
#define TRACEFUNC(...) ((void)0)
|
||||
#define TRACEDUMP(...) ((void)0)
|
||||
#define TRACE_INIT ((void)0)
|
||||
#define TRACE_ADDWEB(a) ((void)0)
|
||||
#define TRACE_POLL ((void)0)
|
||||
#endif
|
||||
|
||||
#define BUFFERSIZE 128 // velikost vyrovnavaciho bufferu
|
||||
|
||||
#define VCP_PORT 5555 // cislo pouziteho portu
|
||||
|
||||
#define NVT_TX_MAXSIZE 64
|
||||
|
||||
#define TX_TIMEOUT_MULTIPLIER 3
|
||||
|
||||
#define TX_TIMEOUT_DIVISOR 2
|
||||
|
||||
//#define RX_BUFFER_SIZE 4096 // velikost prijimaciho bufferu pro seriovy port v pripade, ze Core uz podporuje nastaveni velikosti (v soucasne dobe pouze github verze...)
|
||||
|
||||
#define INITIAL_SERIAL_SPEED 9600 // pocatecni prenosova rychlost
|
||||
|
||||
#define EEPROM_MAGIC 0xaabbccdc
|
||||
|
||||
#ifdef USE_CRASHDUMP
|
||||
#define SAVE_CRASH_SPACE_SIZE 0x0200 // space reserved to store crash data
|
||||
#define SAVE_CRASH_EEPROM_OFFSET (EEPROM_CONFIG_ORIGIN + offsetof(eepromconfig_t, sc))
|
||||
#endif
|
||||
|
||||
#define EEPROM_SIZE (sizeof(wificonfigarea_t) + sizeof(eepromconfig_t) + 10) // velikost EEPROM oblasti (POZOR!!! zbytecnym zvetsovanim se zaroven zmensuje velikost RAM kvuli zrcadlu!!!)
|
||||
|
||||
#define EEPROM_WIFICONFIG_ORIGIN (EEPROM_SIZE - sizeof(wificonfigarea_t)) // pocatek oblasti, pouzivane WiFiConfig
|
||||
|
||||
#define EEPROM_CONFIG_ORIGIN (0)
|
||||
|
||||
#define CORS_DEBUG
|
||||
|
||||
#endif
|
425
src/nvt.cpp
Normal file
425
src/nvt.cpp
Normal file
@ -0,0 +1,425 @@
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "nvt.h"
|
||||
#include "nvt_int.h"
|
||||
#include <string.h>
|
||||
|
||||
static uint8_t DONOTIFYLINESTATE[] = {NVT_IAC, NVT_DO, COM_PORT_OPTION};
|
||||
static uint8_t NOTIFYMODEMSTATE[] = {NVT_IAC, NVT_SB, COM_PORT_OPTION, ASC_NOTIFY_MODEMSTATE, 16 + 64, NVT_IAC, NVT_SE};
|
||||
|
||||
static const char TXBFROVFL[] PROGMEM = "NVT: tx buffer overflow";
|
||||
|
||||
void nvt::puttotx(uint8_t c)
|
||||
{
|
||||
|
||||
if (_txptr < sizeof(_nvttxbuff))
|
||||
{
|
||||
_nvttxbuff[_txptr] = c;
|
||||
++_txptr;
|
||||
}
|
||||
else
|
||||
TRACE(TRACE_ERROR, FPSTR(TXBFROVFL));
|
||||
}
|
||||
|
||||
void nvt::puttotxesc(uint8_t c)
|
||||
{
|
||||
|
||||
if ((_txptr + 1) < sizeof(_nvttxbuff))
|
||||
{
|
||||
_nvttxbuff[_txptr] = c;
|
||||
++_txptr;
|
||||
if (NVT_IAC == c)
|
||||
{
|
||||
_nvttxbuff[_txptr] = c;
|
||||
++_txptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
TRACE(TRACE_ERROR, FPSTR(TXBFROVFL));
|
||||
}
|
||||
|
||||
void nvt::outdata(uint8_t *ptr, size_t size)
|
||||
{
|
||||
|
||||
if (_netchr)
|
||||
{
|
||||
while (size)
|
||||
{
|
||||
_netchr(*ptr);
|
||||
++ptr;
|
||||
--size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nvt::getnvtbyte(uint8_t *dta)
|
||||
{
|
||||
|
||||
if (_getindex < _cmdindex)
|
||||
{
|
||||
*dta = _nvtcmd[_getindex];
|
||||
_getindex++;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1; // neni dalsi byte
|
||||
}
|
||||
|
||||
// Zpracovani NVT povelu
|
||||
void nvt::donvtcmd(void)
|
||||
{
|
||||
uint8_t dta;
|
||||
uint8_t cmd;
|
||||
bool wontquit = true;
|
||||
uint32_t parameter;
|
||||
|
||||
_getindex = 0;
|
||||
|
||||
if (0 == getnvtbyte(&dta))
|
||||
// while ((0 == getnvtbyte(&dta)) && wontquit)
|
||||
{
|
||||
switch (dta)
|
||||
{
|
||||
case COM_PORT_OPTION:
|
||||
if (0 == getnvtbyte(&cmd))
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case CAS_SIGNATURE:
|
||||
break;
|
||||
|
||||
case CAS_SET_BAUDRATE:
|
||||
if ((_cmdindex - _getindex) >= 4)
|
||||
{
|
||||
getnvtbyte(&dta);
|
||||
parameter = dta << 24;
|
||||
getnvtbyte(&dta);
|
||||
parameter += dta << 16;
|
||||
getnvtbyte(&dta);
|
||||
parameter += dta << 8;
|
||||
getnvtbyte(&dta);
|
||||
parameter += dta;
|
||||
if (0 != parameter)
|
||||
{
|
||||
_speed = parameter;
|
||||
_setserial(_speed, -_databits, -_parity, -_stopbits); // aktualizujeme prenosovou rychlost
|
||||
}
|
||||
parameter = _speed;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAS_SET_DATASIZE:
|
||||
if (0 == getnvtbyte(&dta))
|
||||
{
|
||||
if (0 != dta)
|
||||
{
|
||||
_databits = dta;
|
||||
_setserial(-_speed, _databits, -_parity, -_stopbits);
|
||||
}
|
||||
parameter = _databits;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAS_SET_PARITY:
|
||||
if (0 == getnvtbyte(&dta))
|
||||
{
|
||||
if (0 != dta)
|
||||
{
|
||||
_parity = dta;
|
||||
_setserial(-_speed, -_databits, _parity, -_stopbits);
|
||||
}
|
||||
parameter = _parity;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAS_SET_STOPSIZE:
|
||||
if (0 == getnvtbyte(&dta))
|
||||
{
|
||||
if (0 != dta)
|
||||
{
|
||||
_stopbits = dta;
|
||||
_setserial(-_speed, -_databits, -_parity, _stopbits);
|
||||
}
|
||||
parameter = _stopbits;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAS_SET_CONTROL:
|
||||
if (0 == getnvtbyte(&dta))
|
||||
{
|
||||
if (_setgetcontrol)
|
||||
parameter = _setgetcontrol(dta);
|
||||
else
|
||||
parameter = 1; // No Flow Control available
|
||||
TRACE(TRACE_INFO, F("Set/Get Control returns %i"), (int)parameter);
|
||||
}
|
||||
break;
|
||||
|
||||
case CAS_SET_LINESTATE_MASK:
|
||||
if (0 == getnvtbyte(&dta))
|
||||
{
|
||||
_linestatemask = dta;
|
||||
parameter = _linestatemask;
|
||||
TRACE(TRACE_INFO, F("Line state mask set to %i"), (int)_linestatemask);
|
||||
}
|
||||
break;
|
||||
|
||||
case CAS_SET_MODEMSTATE_MASK:
|
||||
if (0 == getnvtbyte(&dta))
|
||||
{
|
||||
_modemstatemask = dta;
|
||||
parameter = _modemstatemask;
|
||||
TRACE(TRACE_INFO, F("Modem state mask set to %i"), (int)_modemstatemask);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE(TRACE_ERROR, F("Unsupported CAS %i"), (int)dta);
|
||||
wontquit = false;
|
||||
break;
|
||||
}
|
||||
// odeslani odpovedi
|
||||
if (wontquit)
|
||||
{
|
||||
_txptr = 0;
|
||||
puttotx(NVT_IAC);
|
||||
puttotx(NVT_SB);
|
||||
puttotx(COM_PORT_OPTION);
|
||||
puttotx(cmd + 100); // z dotazu udelame odpoved
|
||||
if (CAS_SET_BAUDRATE == cmd)
|
||||
{ // nastaveni/dotaz na prenosovou rychlost vraci 4 byty
|
||||
puttotxesc((parameter >> 24) & 0xff);
|
||||
puttotxesc((parameter >> 16) & 0xff);
|
||||
puttotxesc((parameter >> 8) & 0xff);
|
||||
puttotxesc((parameter >> 0) & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
puttotxesc(parameter & 0xff); // ostatni povely vraci jeden byte
|
||||
}
|
||||
puttotx(NVT_IAC);
|
||||
puttotx(NVT_SE);
|
||||
outdata(_nvttxbuff, _txptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE(TRACE_ERROR, F("Unsupported cmd %i"), (int)dta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Standardni metoda pro prepousteni dat do vystupu
|
||||
void nvt::terminalbyte(uint8_t dta)
|
||||
{
|
||||
|
||||
if (_putchr)
|
||||
_putchr(dta);
|
||||
}
|
||||
|
||||
// metoda reseni subnegotiation options
|
||||
void nvt::subnegotiationbyte(uint8_t dta)
|
||||
{
|
||||
|
||||
_nvtcmd[_cmdindex] = dta;
|
||||
_cmdindex++;
|
||||
if (MAX_NVT_CMD_SIZE == _cmdindex)
|
||||
{ // preteceni bufferu
|
||||
_streamstate = NVT_IAC_HUNT; // rusime zpracovani povelu
|
||||
TRACE(TRACE_ERROR, F("Internal buffer overflow"));
|
||||
}
|
||||
}
|
||||
|
||||
// Standardni metoda reakce na NVT povel
|
||||
void nvt::terminalescape(uint8_t dta)
|
||||
{
|
||||
|
||||
switch (dta)
|
||||
{
|
||||
case NVT_NOP:
|
||||
break;
|
||||
|
||||
case NVT_AYT:
|
||||
{
|
||||
if (0 == strlen(_aytstring))
|
||||
outdata((uint8_t*)"Yes", 3); // genericka odpoved
|
||||
else
|
||||
outdata((uint8_t *)_aytstring, strlen(_aytstring)); // uzivatelska odpoved
|
||||
}
|
||||
break;
|
||||
|
||||
case NVT_SB: // zacatek subnegotiation
|
||||
_streamstate = NVT_SB_FOUND; // nasli jsme zacatek subnegotiation
|
||||
_cmdindex = 0; // nastavime index na zacatek
|
||||
break;
|
||||
|
||||
case NVT_SE: // konec subnegotiation
|
||||
_streamstate = NVT_IAC_HUNT; // rusime osetrovani subnegotiation
|
||||
if (_cmdindex)
|
||||
donvtcmd(); // zpracujeme NVT povel
|
||||
break;
|
||||
|
||||
case NVT_WILL:
|
||||
case NVT_WONT:
|
||||
case NVT_DO:
|
||||
case NVT_DONT:
|
||||
wwdd = dta; // ulozime si typ povelu WILL/WONT/DO/DONT
|
||||
_streamstate = NVT_WILL_WONT_DO_DONT_PARAM; // priste budeme analyzovat parametr
|
||||
break;
|
||||
|
||||
default:
|
||||
// Detekovan neznamy znak po <IAC>
|
||||
TRACE(TRACE_ERROR, F("Unknown NVT %i"), (int)dta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void nvt::handlewwddp(uint8_t p)
|
||||
{
|
||||
|
||||
TRACE(TRACE_INFO, F("DO/DONT/WILL/WONT"));
|
||||
_txptr = 0;
|
||||
puttotx(NVT_IAC);
|
||||
switch (wwdd)
|
||||
{
|
||||
case NVT_WILL:
|
||||
if (COM_PORT_OPTION == p)
|
||||
puttotx(NVT_DO);
|
||||
else
|
||||
puttotx(NVT_DONT);
|
||||
break;
|
||||
|
||||
case NVT_WONT:
|
||||
puttotx(NVT_DONT);
|
||||
break;
|
||||
|
||||
case NVT_DO:
|
||||
if (COM_PORT_OPTION == p)
|
||||
puttotx(NVT_WILL);
|
||||
else
|
||||
puttotx(NVT_WONT);
|
||||
break;
|
||||
|
||||
case NVT_DONT:
|
||||
puttotx(NVT_WONT);
|
||||
break;
|
||||
}
|
||||
puttotx(p);
|
||||
outdata(_nvttxbuff, _txptr);
|
||||
}
|
||||
|
||||
void nvt::parsenvtstream(uint8_t dta)
|
||||
{
|
||||
|
||||
switch (_streamstate)
|
||||
{
|
||||
case NVT_SB_FOUND:
|
||||
if (NVT_IAC == dta)
|
||||
_streamstate = NVT_IAC_SB_FOUND;
|
||||
else
|
||||
subnegotiationbyte(dta); // prijimame bezny byte z SB - SE povelu
|
||||
break;
|
||||
|
||||
case NVT_IAC_SB_FOUND:
|
||||
_streamstate = NVT_SB_FOUND;
|
||||
if (NVT_IAC == dta)
|
||||
subnegotiationbyte(dta); // byl to obycejny <IAC><IAC> escapovany byte ze subnegotiation sekvence
|
||||
else
|
||||
terminalescape(dta); // byl to nejaky povel - doufame, ze to byl <SE>
|
||||
break;
|
||||
|
||||
case NVT_IAC_FOUND:
|
||||
_streamstate = NVT_IAC_HUNT;
|
||||
if (NVT_IAC == dta)
|
||||
terminalbyte(dta); // data do vystupu (->serial)
|
||||
else // slo o <IAC><povel> - signalizujeme IAC
|
||||
terminalescape(dta);
|
||||
break;
|
||||
|
||||
case NVT_WILL_WONT_DO_DONT_PARAM:
|
||||
_streamstate = NVT_IAC_HUNT;
|
||||
handlewwddp(dta);
|
||||
break;
|
||||
|
||||
default:
|
||||
_streamstate = NVT_IAC_HUNT;
|
||||
case NVT_IAC_HUNT:
|
||||
if (NVT_IAC != dta)
|
||||
terminalbyte(dta); // data do vystupu
|
||||
else
|
||||
_streamstate = NVT_IAC_FOUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void nvt::handlestream(uint8_t *ptr, int len)
|
||||
{
|
||||
|
||||
while (len)
|
||||
{
|
||||
parsenvtstream(*ptr);
|
||||
++ptr;
|
||||
--len;
|
||||
}
|
||||
}
|
||||
|
||||
void nvt::createsendstream(uint8_t *ptr, int len)
|
||||
{
|
||||
uint8_t dta;
|
||||
|
||||
while (len)
|
||||
{
|
||||
dta = *ptr;
|
||||
++ptr;
|
||||
--len;
|
||||
if (_netchr)
|
||||
{
|
||||
_netchr(dta);
|
||||
if (NVT_IAC == dta)
|
||||
{ // NVT_IAC je escapovany
|
||||
_netchr(dta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nvt::init(setserial_cb setserial, putchr_cb putchr, netchr_cb netchr)
|
||||
{
|
||||
|
||||
_setserial = setserial;
|
||||
_putchr = putchr;
|
||||
_netchr = netchr;
|
||||
_speed = NVT_INITIAL_SPEED;
|
||||
_databits = NVT_INITIAL_DATA_BITS;
|
||||
_parity = NVT_INITIAL_PARITY;
|
||||
_stopbits = NVT_INITIAL_STOP_BITS;
|
||||
_setserial(_speed, _databits, _parity, _stopbits);
|
||||
_streamstate = NVT_IAC_HUNT;
|
||||
_modemstatemask = 0;
|
||||
_linestatemask = 0;
|
||||
}
|
||||
|
||||
void nvt::setAYTstring(const char *aytstring)
|
||||
{
|
||||
|
||||
strcpy(_aytstring, aytstring);
|
||||
}
|
||||
|
||||
void nvt::newguy(void)
|
||||
{
|
||||
|
||||
// outdata(DONOTIFYLINESTATE, sizeof(DONOTIFYLINESTATE)); // zajima nas zmena stavu ridicich signalu
|
||||
// outdata(NOTIFYMODEMSTATE, sizeof(NOTIFYMODEMSTATE));
|
||||
}
|
||||
|
||||
void nvt::setSetGetCtrl(setgetcontrol_cb sgc)
|
||||
{
|
||||
|
||||
_setgetcontrol = sgc;
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
107
src/nvt.h
Normal file
107
src/nvt.h
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @file nvt.h
|
||||
* @author Pavel Brychta, http://www.xpablo.cz
|
||||
*
|
||||
* Copyright (c) 2014,15,16 Pavel Brychta. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NVT_H_
|
||||
#define _NVT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NVT_PARITY_NONE 1
|
||||
#define NVT_PARITY_EVEN 3
|
||||
#define NVT_PARITY_ODD 2
|
||||
|
||||
#define NVT_STOP_BITS_1 1
|
||||
#define NVT_STOP_BITS_15 3
|
||||
#define NVT_STOP_BITS_2 2
|
||||
|
||||
#define NVT_INITIAL_SPEED 9600
|
||||
#define NVT_INITIAL_DATA_BITS 8
|
||||
#define NVT_INITIAL_PARITY NVT_PARITY_NONE
|
||||
#define NVT_INITIAL_STOP_BITS NVT_STOP_BITS_1
|
||||
|
||||
#define MAX_NVT_CMD_SIZE 64 // maximalni velikost povelu
|
||||
#define MAX_NVT_RESP_SIZE 64 // maximalni velikost jedne odpovedi na NVT povel
|
||||
#ifndef NVT_MAX_AYT_LENGTH
|
||||
#define NVT_MAX_AYT_LENGTH 64
|
||||
#endif
|
||||
|
||||
typedef void (*putchr_cb)(uint8_t c); // callback pro vystup bytu - smer NVT stream->Seriovy port
|
||||
typedef void (*netchr_cb)(uint8_t c); // callback pro vystup bytu - smer NVT stream->Network port
|
||||
typedef void (*setserial_cb)(int32_t speed, int32_t databits, int32_t parity, int32_t stopbits); // nastaveni parametru seriove linky (cislo mensi nez 0 udava, ze parametr je stejny, jako z minuleho volani - kvuli optimalizaci nastavovani)
|
||||
typedef uint8_t (*setgetcontrol_cb)(uint8_t newcontrol); // nastaveni/ziskani
|
||||
|
||||
class nvt
|
||||
{
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
NVT_IAC_HUNT = 0, // testujeme na IAC
|
||||
NVT_IAC_FOUND, // minuly znak byl IAC
|
||||
NVT_SB_FOUND, // nasli jsme SB - sledujeme povel
|
||||
NVT_IAC_SB_FOUND, // detekovali jsme IAC behem SB
|
||||
NVT_WILL_WONT_DO_DONT_PARAM, // parametr WILL/WONT/DO/DONT
|
||||
} _streamstate;
|
||||
|
||||
uint8_t _nvtcmd[MAX_NVT_CMD_SIZE]; // misto pro prikaz, uvozeny <SB> a ukonceny <SE>
|
||||
int _cmdindex; // aktualni pozice v nvtcmd
|
||||
int _getindex; // zpracovavaci ukazatel
|
||||
int wwdd; // posledni detekovany WILL/WONT/DO/DONT
|
||||
|
||||
uint32_t _speed; // aktualni prenosova rychlost
|
||||
uint8_t _databits; // aktualni pocet datovych bitu
|
||||
uint8_t _parity; // aktualni parita
|
||||
uint8_t _stopbits; // pocet stop bitu
|
||||
uint8_t _linestatemask; // aktivni maska odesilani zmen stavu
|
||||
uint8_t _modemstatemask; // aktivni maska odesilani zmen stavu
|
||||
|
||||
uint8_t _nvttxbuff[MAX_NVT_RESP_SIZE]; // buffer pro sestaveni odpovedi z NVT
|
||||
int _txptr; // ukazatel v bufferu pro sestaveni odpovedi
|
||||
|
||||
char _aytstring[NVT_MAX_AYT_LENGTH]; // misto pro AYT retezec
|
||||
|
||||
putchr_cb _putchr; // metoda pro vystup bytu - smer NVT_Stream->Output (seriovy port)
|
||||
netchr_cb _netchr; // metoda pro vystup bytu - smer sitovy port
|
||||
setserial_cb _setserial; // nastaveni parametru seriove linky
|
||||
setgetcontrol_cb _setgetcontrol; // nastaveni/ziskani
|
||||
|
||||
void puttotx(uint8_t c);
|
||||
void puttotxesc(uint8_t c);
|
||||
void outdata(uint8_t *ptr, size_t size); // vystup proudu dat do _netchr
|
||||
int getnvtbyte(uint8_t *dta);
|
||||
void donvtcmd(void);
|
||||
void terminalbyte(uint8_t dta);
|
||||
void subnegotiationbyte(uint8_t dta);
|
||||
void terminalescape(uint8_t dta);
|
||||
void parsenvtstream(uint8_t dta);
|
||||
void handlewwddp(uint8_t p);
|
||||
|
||||
public:
|
||||
void init(setserial_cb setserial, putchr_cb putchr, netchr_cb netchr);
|
||||
void setAYTstring(const char *aytstring);
|
||||
void handlestream(uint8_t *ptr, int len);
|
||||
void createsendstream(uint8_t *ptr, int len);
|
||||
void newguy(void);
|
||||
void setSetGetCtrl(setgetcontrol_cb sgc);
|
||||
};
|
||||
|
||||
#endif
|
46
src/nvt_int.h
Normal file
46
src/nvt_int.h
Normal file
@ -0,0 +1,46 @@
|
||||
// Interni konstanty protokolu dle RFC
|
||||
|
||||
#define NVT_IAC (0xff) // NVT command prefix
|
||||
|
||||
#define NVT_SE (0xf0) // End of sub negotiation parameters
|
||||
#define NVT_NOP (0xf1) // No operation
|
||||
#define NVT_AYT (0xf6) // Are You There
|
||||
#define NVT_SB (0xfa) // Indicates that what follows is sub negotiation of the indicated option.
|
||||
#define NVT_WILL 251
|
||||
#define NVT_WONT 252
|
||||
#define NVT_DO 253
|
||||
#define NVT_DONT 254
|
||||
|
||||
#define COM_PORT_OPTION 44
|
||||
|
||||
#define CAS_SIGNATURE 0
|
||||
#define CAS_SET_BAUDRATE 1
|
||||
#define CAS_SET_DATASIZE 2
|
||||
#define CAS_SET_PARITY 3
|
||||
#define CAS_SET_STOPSIZE 4
|
||||
#define CAS_SET_CONTROL 5
|
||||
#define CAS_NOTIFY_LINESTATE 6
|
||||
#define CAS_NOTIFY_MODEMSTATE 7
|
||||
#define CAS_FLOWCONTROL_SUSPEND 8
|
||||
#define CAS_FLOWCONTROL_RESUME 9
|
||||
#define CAS_SET_LINESTATE_MASK 10
|
||||
#define CAS_SET_MODEMSTATE_MASK 11
|
||||
#define CAS_PURGE_DATA 12
|
||||
#define CAS_OPT_GPIO 50
|
||||
#define CAS_SET_GPIO 51
|
||||
|
||||
#define ASC_SIGNATURE 100
|
||||
#define ASC_SET_BAUDRATE 101
|
||||
#define ASC_SET_DATASIZE 102
|
||||
#define ASC_SET_PARITY 103
|
||||
#define ASC_SET_STOPSIZE 104
|
||||
#define ASC_SET_CONTROL 105
|
||||
#define ASC_NOTIFY_LINESTATE 106
|
||||
#define ASC_NOTIFY_MODEMSTATE 107
|
||||
#define ASC_FLOWCONTROL_SUSPEND 108
|
||||
#define ASC_FLOWCONTROL_RESUME 109
|
||||
#define ASC_SET_LINESTATE_MASK 110
|
||||
#define ASC_SET_MODEMSTATE_MASK 111
|
||||
#define ASC_PURGE_DATA 112
|
||||
#define ASC_OPT_GPIO 150
|
||||
#define ASC_SET_GPIO 151
|
132
src/obfuscator.h
Normal file
132
src/obfuscator.h
Normal file
@ -0,0 +1,132 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//-------------------------------------------------------------//
|
||||
// "Malware related compile-time hacks with C++11" by LeFF //
|
||||
// You can use this code however you like, I just don't really //
|
||||
// give a shit, but if you feel some respect for me, please //
|
||||
// don't cut off this comment when copy-pasting... ;-) //
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
// Usage examples:
|
||||
void exampleRandom1() __attribute__((noinline));
|
||||
void exampleRandom2() __attribute__((noinline));
|
||||
void exampleHashing() __attribute__((noinline));
|
||||
void exampleEncryption() __attribute__((noinline));
|
||||
|
||||
#ifndef vxCPLSEED
|
||||
// If you don't specify the seed for algorithms, the time when compilation
|
||||
// started will be used, seed actually changes the results of algorithms...
|
||||
#define vxCPLSEED ((__TIME__[7] - '0') * 1 + (__TIME__[6] - '0') * 10 + \
|
||||
(__TIME__[4] - '0') * 60 + (__TIME__[3] - '0') * 600 + \
|
||||
(__TIME__[1] - '0') * 3600 + (__TIME__[0] - '0') * 36000)
|
||||
#endif
|
||||
|
||||
// The constantify template is used to make sure that the result of constexpr
|
||||
// function will be computed at compile-time instead of run-time
|
||||
template <uint32_t Const> struct vxCplConstantify { enum { Value = Const }; };
|
||||
|
||||
// Compile-time mod of a linear congruential pseudorandom number generator,
|
||||
// the actual algorithm was taken from "Numerical Recipes" book
|
||||
constexpr uint32_t vxCplRandom(uint32_t Id)
|
||||
{ return (1013904223 + 1664525 * ((Id > 0) ? (vxCplRandom(Id - 1)) : (vxCPLSEED))) & 0xFFFFFFFF; }
|
||||
|
||||
// Compile-time random macros, can be used to randomize execution
|
||||
// path for separate builds, or compile-time trash code generation
|
||||
#define vxRANDOM(Min, Max) (Min + (vxRAND() % (Max - Min + 1)))
|
||||
#define vxRAND() (vxCplConstantify<vxCplRandom(__COUNTER__ + 1)>::Value)
|
||||
|
||||
// Compile-time recursive mod of string hashing algorithm,
|
||||
// the actual algorithm was taken from Qt library (this
|
||||
// function isn't case sensitive due to vxCplTolower)
|
||||
constexpr char vxCplTolower(char Ch) { return (Ch >= 'A' && Ch <= 'Z') ? (Ch - 'A' + 'a') : (Ch); }
|
||||
constexpr uint32_t vxCplHashPart3(char Ch, uint32_t Hash) { return ((Hash << 4) + vxCplTolower(Ch)); }
|
||||
constexpr uint32_t vxCplHashPart2(char Ch, uint32_t Hash) { return (vxCplHashPart3(Ch, Hash) ^ ((vxCplHashPart3(Ch, Hash) & 0xF0000000) >> 23)); }
|
||||
constexpr uint32_t vxCplHashPart1(char Ch, uint32_t Hash) { return (vxCplHashPart2(Ch, Hash) & 0x0FFFFFFF); }
|
||||
constexpr uint32_t vxCplHash(const char* Str) { return (*Str) ? (vxCplHashPart1(*Str, vxCplHash(Str + 1))) : (0); }
|
||||
|
||||
// Compile-time hashing macro, hash values changes using the first pseudorandom number in sequence
|
||||
#define vxHASH(Str) (uint32_t)(vxCplConstantify<vxCplHash(Str)>::Value ^ vxCplConstantify<vxCplRandom(1)>::Value)
|
||||
|
||||
// Compile-time generator for list of indexes (0, 1, 2, ...)
|
||||
template <uint32_t...> struct vxCplIndexList {};
|
||||
template <typename IndexList, uint32_t Right> struct vxCplAppend;
|
||||
template <uint32_t... Left, uint32_t Right> struct vxCplAppend<vxCplIndexList<Left...>, Right> { typedef vxCplIndexList<Left..., Right> Result; };
|
||||
template <uint32_t N> struct vxCplIndexes { typedef typename vxCplAppend<typename vxCplIndexes<N - 1>::Result, N - 1>::Result Result; };
|
||||
template <> struct vxCplIndexes<0> { typedef vxCplIndexList<> Result; };
|
||||
|
||||
// Compile-time string encryption of a single character
|
||||
const char vxCplEncryptCharKey = vxRANDOM(0, 0xFF);
|
||||
constexpr char vxCplEncryptChar(const char Ch, uint32_t Idx) { return Ch ^ (vxCplEncryptCharKey + Idx); }
|
||||
|
||||
// Compile-time string encryption class
|
||||
template <typename IndexList> struct vxCplEncryptedString;
|
||||
template <uint32_t... Idx> struct vxCplEncryptedString<vxCplIndexList<Idx...> >
|
||||
{
|
||||
char Value[sizeof...(Idx) + 1]; // Buffer for a string
|
||||
|
||||
// Compile-time constructor
|
||||
constexpr inline vxCplEncryptedString(const char* const Str)
|
||||
: Value({ vxCplEncryptChar(Str[Idx], Idx)... }) {}
|
||||
|
||||
// Run-time decryption
|
||||
char* decrypt()
|
||||
{
|
||||
for(volatile uint32_t t = 0; t < sizeof...(Idx); t++)
|
||||
{ this->Value[t] = this->Value[t] ^ (vxCplEncryptCharKey + t); }
|
||||
this->Value[sizeof...(Idx)] = '\0'; return this->Value;
|
||||
}
|
||||
};
|
||||
|
||||
// Compile-time string encryption macro
|
||||
#define vxENCRYPT(Str) (vxCplEncryptedString<vxCplIndexes<sizeof(Str) - 1>::Result>(Str).decrypt())
|
||||
|
||||
/*
|
||||
// A small random code path example
|
||||
void exampleRandom1()
|
||||
{
|
||||
switch(vxRANDOM(1, 4))
|
||||
{
|
||||
case 1: { printf("exampleRandom1: Code path 1!\n"); break; }
|
||||
case 2: { printf("exampleRandom1: Code path 2!\n"); break; }
|
||||
case 3: { printf("exampleRandom1: Code path 3!\n"); break; }
|
||||
case 4: { printf("exampleRandom1: Code path 4!\n"); break; }
|
||||
default: { printf("Fucking poltergeist!\n"); }
|
||||
}
|
||||
}
|
||||
|
||||
// A small random code generator example
|
||||
void exampleRandom2()
|
||||
{
|
||||
volatile uint32_t RndVal = vxRANDOM(0, 100);
|
||||
if(vxRAND() % 2) { RndVal += vxRANDOM(0, 100); }
|
||||
else { RndVal -= vxRANDOM(0, 200); }
|
||||
printf("exampleRandom2: %d\n", RndVal);
|
||||
}
|
||||
|
||||
// A small string hasing example
|
||||
void exampleHashing()
|
||||
{
|
||||
printf("exampleHashing: 0x%08X\n", vxHASH("hello world!"));
|
||||
printf("exampleHashing: 0x%08X\n", vxHASH("HELLO WORLD!"));
|
||||
}
|
||||
|
||||
void exampleEncryption()
|
||||
{
|
||||
printf("exampleEncryption: %s\n", vxENCRYPT("Hello world!"));
|
||||
}
|
||||
|
||||
extern "C" void Main()
|
||||
{
|
||||
exampleRandom1();
|
||||
exampleRandom2();
|
||||
exampleHashing();
|
||||
exampleEncryption();
|
||||
}
|
||||
|
||||
// Example
|
||||
#define vxENCRYPT2(Str) (vxCplEncryptedString<vxCplIndexes<sizeof(Str) - 1>::Result>(Str))
|
||||
auto enc = vxENCRYPT2("secret");
|
||||
printf("str: %s\n", enc.decrypt());
|
||||
*/
|
||||
|
394
src/vsp.ino
Normal file
394
src/vsp.ino
Normal file
@ -0,0 +1,394 @@
|
||||
//#include <Arduino.h>
|
||||
|
||||
#include <cbuf.h>
|
||||
#include "nvt.h"
|
||||
#include <uinterval.h>
|
||||
|
||||
WiFiServer server(VCP_PORT);
|
||||
WiFiClient client;
|
||||
cbuf fromNet(3000);
|
||||
cbuf toNet(3000);
|
||||
uint8_t sbuf[128]; // vyrovnavaci buffer pro vycitani serioveho portu/sitoveho soketu
|
||||
|
||||
nvt netterm; // network virtual terminal objekt
|
||||
|
||||
uint8_t nvttx[1500]; // vyrovnavaci vystupni buffer
|
||||
uInterval nvtt; // casovac pro rizeni odesilani bufferu
|
||||
uint32_t baudtiming; // vypocitana delka cekani pri paketizaci
|
||||
|
||||
int control = 1; // aktivni rezim rizeni vystupu atd... (implicitne je to No Flow Control)
|
||||
int dtrstate;
|
||||
int breakstate;
|
||||
int rtsstate;
|
||||
|
||||
int newguy = 0;
|
||||
|
||||
// statistika
|
||||
uint32_t serial_tx; // pocet odeslanych bytu na seriove rozhrani
|
||||
uint32_t serial_rx; // pocet prijatych bytu ze serioveho rozhrani
|
||||
uint32_t drop_tx; // pocet vynechanych bytu pri odesilani (preplneny buffer ze site)
|
||||
uint32_t drop_rx; // pocet vynechanych bytu pri prijmu (preplneny buffer ze serioveho portu)
|
||||
|
||||
/* Nastaveni parametru serioveho portu
|
||||
*/
|
||||
void setserialport(int32_t speed, int32_t databits, int32_t parity, int32_t stopbits) // nastaveni parametru seriove linky ( cislo mensi nez 0 udava, ze parametr je steny, jako z minuleho volani - kvuli optimalizaci nastavovani)
|
||||
{
|
||||
uint32_t spd;
|
||||
int serialMode;
|
||||
int totalbits; // celkovy pocet bitu ve slove pro vypocet timeoutu
|
||||
|
||||
if (speed > 0)
|
||||
TRACE(TRACE_INFO, F("New serial speed set to %i"), (int)speed);
|
||||
spd = abs(speed);
|
||||
|
||||
/* Nastaveni poctu datovych bitu
|
||||
BITS:
|
||||
Value Data Bit Size
|
||||
0 Request Current Data Bit Size
|
||||
1 Available for Future Use
|
||||
2 Available for Future Use
|
||||
3 Available for Future Use
|
||||
4 Available for Future Use
|
||||
5 5
|
||||
6 6
|
||||
7 7
|
||||
8 8
|
||||
9-127 Available for Future Use
|
||||
*/
|
||||
switch (abs(databits))
|
||||
{
|
||||
case 5:
|
||||
serialMode |= UART_NB_BIT_5;
|
||||
totalbits = 5 + 1;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
serialMode |= UART_NB_BIT_6;
|
||||
totalbits = 6 + 1;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
serialMode |= UART_NB_BIT_7;
|
||||
totalbits = 7 + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
serialMode |= UART_NB_BIT_8;
|
||||
totalbits = 8 + 1;
|
||||
break;
|
||||
}
|
||||
if (databits > 0)
|
||||
TRACE(TRACE_INFO, F("New databits set to %i"), (int)databits);
|
||||
|
||||
/* Nastaveni typu parity
|
||||
PARITY:
|
||||
1 NONE
|
||||
2 ODD
|
||||
3 EVEN
|
||||
4 MARK
|
||||
5 SPACE
|
||||
*/
|
||||
switch (abs(parity))
|
||||
{
|
||||
case 2:
|
||||
serialMode |= UART_PARITY_ODD;
|
||||
totalbits += 1;
|
||||
if (parity > 0)
|
||||
TRACE(TRACE_INFO, F("Parity set to ODD"));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
serialMode |= UART_PARITY_EVEN;
|
||||
totalbits += 1;
|
||||
if (parity > 0)
|
||||
TRACE(TRACE_INFO, F("Parity set to EVEN"));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 5:
|
||||
if (parity > 0)
|
||||
TRACE(TRACE_ERROR, F("Unsupported parity type"));
|
||||
default:
|
||||
if (parity > 0)
|
||||
TRACE(TRACE_INFO, F("Parity set to NONE"));
|
||||
serialMode |= UART_PARITY_NONE;
|
||||
totalbits += 0;
|
||||
break;
|
||||
}
|
||||
/* Nastaveni poctu stop bitu
|
||||
STOPBITS:
|
||||
Value Stop Bit Size
|
||||
0 Request Current Number of Stop Bits
|
||||
1 1
|
||||
2 2
|
||||
3 1.5
|
||||
4-127 Available for Future Use
|
||||
*/
|
||||
switch (abs(stopbits))
|
||||
{
|
||||
case 2:
|
||||
serialMode |= UART_NB_STOP_BIT_2;
|
||||
totalbits += 2;
|
||||
if (stopbits > 0)
|
||||
TRACE(TRACE_INFO, F("Stop bits set to 2"));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
serialMode |= UART_NB_STOP_BIT_15;
|
||||
totalbits += 2; // 1,5 je jako dva...
|
||||
if (stopbits > 0)
|
||||
TRACE(TRACE_INFO, F("Stop bits set to 1.5"));
|
||||
break;
|
||||
|
||||
default:
|
||||
serialMode |= UART_NB_STOP_BIT_1;
|
||||
totalbits += 1;
|
||||
if (stopbits > 0)
|
||||
TRACE(TRACE_INFO, F("Stop bits set to 1"));
|
||||
break;
|
||||
}
|
||||
// podle poctu bitu a prenosove rychlosti spocitame casovou konstantu pro paketovaci casovac
|
||||
uint32_t work = (totalbits * 1000000ul * TX_TIMEOUT_MULTIPLIER) / (spd * TX_TIMEOUT_DIVISOR);
|
||||
if (baudtiming != work)
|
||||
TRACE(TRACE_DEBUG, "Interval set to %i us", (int)work);
|
||||
baudtiming = work;
|
||||
// skutecne zmenime nastaveni serioveho portu
|
||||
Serial.flush();
|
||||
// delay(200);
|
||||
Serial.end();
|
||||
delay(10); // 100
|
||||
Serial.begin(spd, (SerialConfig)serialMode);
|
||||
Serial.setDebugOutput(false);
|
||||
delay(10); // 100
|
||||
Serial.flush();
|
||||
serial_tx = 0;
|
||||
serial_rx = 0;
|
||||
}
|
||||
|
||||
// Odeslani dat na seriovy port
|
||||
void sputchar(uint8_t c)
|
||||
{
|
||||
|
||||
if (fromNet.empty() && Serial.availableForWrite())
|
||||
{
|
||||
Serial.write(c);
|
||||
++serial_tx;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!fromNet.full())
|
||||
{
|
||||
fromNet.write(c);
|
||||
}
|
||||
else
|
||||
++drop_tx;
|
||||
}
|
||||
}
|
||||
|
||||
// Ulozeni bytu do sitoveho vystupniho bufferu
|
||||
void nputchar(uint8_t c)
|
||||
{
|
||||
|
||||
if (!toNet.full())
|
||||
{
|
||||
toNet.write(c);
|
||||
nvtt.set(baudtiming); // timeout pro odeslani bloku dat
|
||||
}
|
||||
else
|
||||
++drop_rx;
|
||||
}
|
||||
|
||||
/*
|
||||
This command is sent by the client to the access server to set
|
||||
special com port options. The command can also be sent to query
|
||||
the current option value. The value is one octet (byte). The
|
||||
value is an index into the following value table:
|
||||
|
||||
Value Control Commands
|
||||
0 Request Com Port Flow Control Setting
|
||||
(outbound/both)
|
||||
1 Use No Flow Control (outbound/both)
|
||||
2 Use XON/XOFF Flow Control (outbound/both)
|
||||
3 Use HARDWARE Flow Control (outbound/both)
|
||||
4 Request BREAK State
|
||||
5 Set BREAK State ON
|
||||
6 Set BREAK State OFF
|
||||
7 Request DTR Signal State
|
||||
8 Set DTR Signal State ON
|
||||
9 Set DTR Signal State OFF
|
||||
10 Request RTS Signal State
|
||||
11 Set RTS Signal State ON
|
||||
12 Set RTS Signal State OFF
|
||||
13 Request Com Port Flow Control Setting (inbound)
|
||||
14 Use No Flow Control (inbound)
|
||||
15 Use XON/XOFF Flow Control (inbound)
|
||||
16 Use HARDWARE Flow Control (inbound)
|
||||
17 Use DCD Flow Control (outbound/both)
|
||||
18 Use DTR Flow Control (inbound)
|
||||
19 Use DSR Flow Control (outbound/both)
|
||||
20-127 Available for Future Use
|
||||
*/
|
||||
uint8_t setgetcontrol(uint8_t _ctrl)
|
||||
{
|
||||
uint8_t result;
|
||||
|
||||
TRACE(TRACE_INFO, F("Set/Get control %i"), (int)_ctrl);
|
||||
switch (_ctrl)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
control = _ctrl;
|
||||
result = control;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
result = breakstate;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
breakstate = 1;
|
||||
result = breakstate;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
breakstate = 0;
|
||||
result = breakstate;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
result = dtrstate;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
dtrstate = 1;
|
||||
result = dtrstate;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
dtrstate = 0;
|
||||
result = dtrstate;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
result = rtsstate;
|
||||
break;
|
||||
|
||||
case 11:
|
||||
rtsstate = 1;
|
||||
result = rtsstate;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
rtsstate = 0;
|
||||
result = rtsstate;
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE(TRACE_ERROR, F("Unsupported control %i"), (int)_ctrl);
|
||||
case 0:
|
||||
result = control; // ziskame aktualni stav
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Inicializace virtualniho serioveho portu NVT
|
||||
void vsp_init()
|
||||
{
|
||||
|
||||
Serial.begin(INITIAL_SERIAL_SPEED);
|
||||
#ifdef RX_BUFFER_SIZE
|
||||
int rxsize = Serial.setRxBufferSize(RX_BUFFER_SIZE);
|
||||
TRACE(TRACE_INFO, F("RX buffser size set to %i"), rxsize);
|
||||
#endif
|
||||
Serial.setDebugOutput(false);
|
||||
|
||||
// Inicializace NVT parametru
|
||||
netterm.init(setserialport, sputchar, nputchar);
|
||||
netterm.setSetGetCtrl(setgetcontrol);
|
||||
server.begin();
|
||||
}
|
||||
|
||||
void vsp_loop()
|
||||
{
|
||||
int len;
|
||||
|
||||
// kontrola, zda se nepripojil kilent
|
||||
if (server.hasClient())
|
||||
{
|
||||
if (!client || !client.connected())
|
||||
{
|
||||
if (client)
|
||||
client.stop();
|
||||
client = server.available();
|
||||
client.setNoDelay(true);
|
||||
++newguy;
|
||||
TRACE(TRACE_INFO, "TCP: New client");
|
||||
}
|
||||
WiFiClient serverClient = server.available();
|
||||
serverClient.stop();
|
||||
}
|
||||
|
||||
// testovani, zda ma UART nejaka data
|
||||
if (int len = Serial.available())
|
||||
{
|
||||
size_t will_copy = (len < sizeof(sbuf)) ? len : sizeof(sbuf);
|
||||
Serial.readBytes(sbuf, will_copy);
|
||||
netterm.createsendstream(sbuf, will_copy);
|
||||
serial_rx += will_copy;
|
||||
}
|
||||
|
||||
// testovani, zda TCP klient neposlal nejaka data
|
||||
if (client && client.connected())
|
||||
{
|
||||
if (len = client.available())
|
||||
{
|
||||
while ((len > 0) && ((fromNet.room() >= len) || (fromNet.room() >= sizeof(sbuf))))
|
||||
{
|
||||
size_t will_copy = (len < sizeof(sbuf)) ? len : sizeof(sbuf);
|
||||
client.readBytes(sbuf, will_copy);
|
||||
// TRACE(TRACE_INFO, F("RX:%i"), will_copy);
|
||||
netterm.handlestream(sbuf, will_copy);
|
||||
len -= will_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// testovani, zda neposlat nejaka data do TCP klienta
|
||||
if (!toNet.empty() && nvtt.expired())
|
||||
{
|
||||
size_t read = toNet.read((char *)&nvttx[0], sizeof(nvttx));
|
||||
|
||||
if (client && client.connected())
|
||||
{
|
||||
uint32_t t = micros();
|
||||
client.write((const uint8_t *)&nvttx[0], read); // data do TCP soketu
|
||||
// TRACE(TRACE_INFO, F("TX: %i, took %i us"), read, (int)micros() - t);
|
||||
}
|
||||
}
|
||||
|
||||
// testovani, zda neposlat nejaka data do serioveho rozhrani
|
||||
if (!fromNet.empty() && (len = Serial.availableForWrite()))
|
||||
{
|
||||
size_t will_copy = (len < sizeof(sbuf)) ? len : sizeof(sbuf);
|
||||
will_copy = fromNet.read((char *)sbuf, will_copy);
|
||||
Serial.write(sbuf, will_copy);
|
||||
serial_tx += will_copy;
|
||||
}
|
||||
|
||||
if (newguy)
|
||||
{
|
||||
newguy = 0;
|
||||
netterm.newguy();
|
||||
}
|
||||
}
|
||||
|
212
src/web.ino
Normal file
212
src/web.ino
Normal file
@ -0,0 +1,212 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
// Obsluha weboveho serveru
|
||||
Ticker deferred; // zpozdene veci (konkretne restart ESP treba po aktualizaci)
|
||||
const char TEXTPLAIN[] PROGMEM = "text/plain";
|
||||
const char TEXTJSON[] PROGMEM = "text/json";
|
||||
const char TEXTHTML[] PROGMEM = "text/html";
|
||||
const char CCLEAR[] PROGMEM = "Crash area cleared!";
|
||||
|
||||
const char RESTARTING[] PROGMEM = "Restarting...";
|
||||
|
||||
void handleReset(AsyncWebServerRequest *request)
|
||||
{
|
||||
|
||||
deferred.once_ms(500, []()
|
||||
{
|
||||
ESP.restart();
|
||||
});
|
||||
|
||||
request->send_P(200, FPSTR(TEXTPLAIN), RESTARTING);
|
||||
}
|
||||
|
||||
void handleEEDump(AsyncWebServerRequest *request)
|
||||
{
|
||||
AsyncWebServerResponse *response = request->beginChunkedResponse("application/octet-stream", [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t {
|
||||
size_t written = 0;
|
||||
|
||||
while ((index < EEPROM_SIZE) && (written < maxLen))
|
||||
{
|
||||
buffer[written] = EEPROM.read(index);
|
||||
++index;
|
||||
++written;
|
||||
}
|
||||
return written;
|
||||
});
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
#ifdef USE_CRASHDUMP
|
||||
void handleCrash(AsyncWebServerRequest *request)
|
||||
{
|
||||
String st;
|
||||
|
||||
st.reserve(2000);
|
||||
crashGet(st);
|
||||
request->send(200, FPSTR(TEXTHTML), st);
|
||||
}
|
||||
|
||||
void handleCrashClear(AsyncWebServerRequest *request)
|
||||
{
|
||||
String st;
|
||||
|
||||
crashClear();
|
||||
request->send_P(200, FPSTR(TEXTPLAIN), CCLEAR);
|
||||
}
|
||||
#endif
|
||||
|
||||
void handleNotFound(AsyncWebServerRequest *request)
|
||||
{
|
||||
|
||||
#ifdef CORS_DEBUG
|
||||
if (request->method() == HTTP_OPTIONS)
|
||||
{
|
||||
request->send(200);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
String message;
|
||||
|
||||
message.reserve(1024);
|
||||
|
||||
message = F("Page Not Found\r\n\r\nURI:");
|
||||
message.concat(request->url());
|
||||
message.concat(F("\r\nMethod: "));
|
||||
message.concat((request->method() == HTTP_GET) ? F("GET") : F("POST"));
|
||||
message.concat(F("\r\nParams: "));
|
||||
message.concat(request->params());
|
||||
message.concat(F("\r\n"));
|
||||
|
||||
for (unsigned int i = 0; i < request->params(); i++ )
|
||||
{
|
||||
AsyncWebParameter *p = request->getParam(i);
|
||||
message.concat(F(" "));
|
||||
message.concat(p->name());
|
||||
message.concat(F(": "));
|
||||
message.concat(p->value());
|
||||
message.concat(F("\r\n"));
|
||||
}
|
||||
request->send(404, FPSTR(TEXTPLAIN), message);
|
||||
}
|
||||
|
||||
void www_onUpgrade(AsyncWebServerRequest *request)
|
||||
{
|
||||
AsyncWebServerResponse *response = request->beginResponse(200, FPSTR(TEXTPLAIN), Update.hasError() ? F("FAIL") : F("OK"));
|
||||
|
||||
response->addHeader(FPSTR("Connection"), FPSTR("close"));
|
||||
if (!Update.hasError())
|
||||
{
|
||||
deferred.once_ms(100, []()
|
||||
{
|
||||
ESP.restart();
|
||||
});
|
||||
}
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
void www_onUpgradeData(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final)
|
||||
{
|
||||
|
||||
if (!index)
|
||||
{
|
||||
TRACE(TRACE_DEBUG, F("[UPGRADE] Start: %s"), filename.c_str());
|
||||
Update.runAsync(true);
|
||||
if (!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000))
|
||||
{
|
||||
TRACE(TRACE_ERROR, F("[UPGRADE] Error: %i"), Update.getError());
|
||||
}
|
||||
}
|
||||
if (!Update.hasError())
|
||||
{
|
||||
if (Update.write(data, len) != len)
|
||||
{
|
||||
TRACE(TRACE_ERROR, F("[UPGRADE] Error: %i"), Update.getError());
|
||||
}
|
||||
}
|
||||
if (final)
|
||||
{
|
||||
if (Update.end(true))
|
||||
{
|
||||
//TRACE(TRACE_DEBUG, F("[UPGRADE] Success: %u bytes"), index + len);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(TRACE_ERROR, F("[UPGRADE] Error: %i"), Update.getError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// DEBUG_MSG_P(PSTR("[UPGRADE] Progress: %u bytes\r"), index + len);
|
||||
}
|
||||
}
|
||||
|
||||
void www_onScan(AsyncWebServerRequest *request)
|
||||
{
|
||||
String json;
|
||||
|
||||
json.reserve(1024);
|
||||
json = F("[");
|
||||
int n = WiFi.scanComplete();
|
||||
|
||||
if (n == -2)
|
||||
{
|
||||
WiFi.scanNetworks(true);
|
||||
} else if (n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (i)
|
||||
json.concat(F(","));
|
||||
json.concat(("{\"rssi\":"));
|
||||
json.concat(String(WiFi.RSSI(i)));
|
||||
json.concat(F(",\"ssid\":\""));
|
||||
json.concat(WiFi.SSID(i));
|
||||
json.concat(F("\",\"bssid\":\""));
|
||||
json.concat(WiFi.BSSIDstr(i));
|
||||
json.concat(F("\",\"channel\":"));
|
||||
json.concat(String(WiFi.channel(i)));
|
||||
json.concat(F(",\"secure\":"));
|
||||
json.concat(String(WiFi.encryptionType(i)));
|
||||
json.concat(F(",\"hidden\":"));
|
||||
json.concat(String(WiFi.isHidden(i)?F("true"):F("false")));
|
||||
json.concat(F("}"));
|
||||
}
|
||||
WiFi.scanDelete();
|
||||
if (WiFi.scanComplete() == -2)
|
||||
{
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
}
|
||||
json.concat(F("]"));
|
||||
request->send(200, FPSTR(TEXTJSON), json);
|
||||
}
|
||||
|
||||
void webserver_init(void)
|
||||
{
|
||||
|
||||
www.rewrite("/", "/index.htm");
|
||||
init_websocket();
|
||||
#ifdef HTTP_UPDATE
|
||||
httpUpdater.setup(&www);
|
||||
#endif
|
||||
// TRACE_ADDWEB(&www); // ladici stranka
|
||||
#ifdef USE_CRASHDUMP
|
||||
www.on("/crash", handleCrash);
|
||||
www.on("/crashclear", handleCrashClear);
|
||||
#endif
|
||||
www.on("/rst", handleReset);
|
||||
www.on("/eedump", handleEEDump);
|
||||
#ifdef USE_EDITOR
|
||||
www.addHandler(new SPIFFSEditor("admin", "nimda"));
|
||||
#endif
|
||||
#ifdef USE_PROFILING
|
||||
www.on("/profile", handleProfiling)
|
||||
#endif
|
||||
www.serveStatic("/", SPIFFS, "/");
|
||||
www.onNotFound(handleNotFound);
|
||||
#ifdef CORS_DEBUG
|
||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
|
||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "content-type");
|
||||
#endif
|
||||
www.begin();
|
||||
}
|
126
src/websocket.ino
Normal file
126
src/websocket.ino
Normal file
@ -0,0 +1,126 @@
|
||||
//
|
||||
AsyncWebSocket wsStatus("/wss");
|
||||
|
||||
int wsSConnected(void)
|
||||
{
|
||||
|
||||
return wsStatus.count();
|
||||
}
|
||||
|
||||
void wsSSend(String &txt)
|
||||
{
|
||||
|
||||
wsStatus.textAll(txt); // odesleme informace do klienta
|
||||
}
|
||||
|
||||
// Osetreni komunikace pres webovy soket
|
||||
void wseStatus(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case WS_EVT_DISCONNECT:
|
||||
break;
|
||||
|
||||
case WS_EVT_CONNECT:
|
||||
{ // zalogovani pripojeni prohlizece
|
||||
|
||||
// odesilame prvni informace do klienta
|
||||
String inf;
|
||||
|
||||
inf.reserve(512);
|
||||
inf = F("{\"type\":\"hwinfo\"");
|
||||
inf.concat(F(",\"version\":\""));
|
||||
inf.concat(F(VERSION));
|
||||
inf.concat(F("\""));
|
||||
inf.concat(F("}"));
|
||||
|
||||
trace_forceupdate(); // vynutime take odeslani informaci ze stopare po pripojeni
|
||||
client->text(inf); // odesleme informace do klienta
|
||||
}
|
||||
break;
|
||||
|
||||
case WS_EVT_DATA:
|
||||
{
|
||||
int free = ESP.getFreeHeap();
|
||||
AwsFrameInfo *info = (AwsFrameInfo *)arg;
|
||||
|
||||
if (WS_TEXT == info->opcode)
|
||||
{
|
||||
if (!strncmp_P((const char *)data, PSTR("status"), info->len))
|
||||
{
|
||||
String inf;
|
||||
|
||||
inf.reserve(512);
|
||||
inf = F("{\"type\":\"status\",\"ram\":");
|
||||
int load = 0;
|
||||
|
||||
if (upcounter > 0)
|
||||
load = 100 - (100 * loopCounterLast / loopCounterMax);
|
||||
inf.concat(free);
|
||||
inf.concat(F(",\"load\":"));
|
||||
inf.concat(load);
|
||||
inf.concat(F(",\"lc\":"));
|
||||
inf.concat(loopCounterLast);
|
||||
inf.concat(F("}"));
|
||||
client->text(inf);
|
||||
}
|
||||
|
||||
if (!strncmp_P((const char *)data, PSTR("wscan"), info->len))
|
||||
{ // ziskani seznamu WiFi siti v dosahu
|
||||
TRACE(TRACE_INFO, F("Request WiFi scan"));
|
||||
String json;
|
||||
|
||||
json.reserve(2048);
|
||||
json = F("[");
|
||||
int n = WiFi.scanComplete();
|
||||
|
||||
if (n == -2)
|
||||
{
|
||||
WiFi.scanNetworks(true);
|
||||
} else if (n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (i)
|
||||
json.concat(F(","));
|
||||
json.concat(F("{"));
|
||||
json.concat(F("\"rssi\":"));
|
||||
json.concat(String(WiFi.RSSI(i)));
|
||||
json.concat(F(",\"ssid\":\""));
|
||||
json.concat(WiFi.SSID(i));
|
||||
json.concat(F("\",\"bssid\":\""));
|
||||
json.concat(WiFi.BSSIDstr(i));
|
||||
json.concat(F("\",\"channel\":"));
|
||||
json.concat(String(WiFi.channel(i)));
|
||||
json.concat(F(",\"secure\":"));
|
||||
json.concat(String(WiFi.encryptionType(i)));
|
||||
json.concat(F(",\"hidden\":"));
|
||||
json.concat(String(WiFi.isHidden(i)?F("true"):F("false")));
|
||||
json.concat(F("}"));
|
||||
}
|
||||
WiFi.scanDelete();
|
||||
if (WiFi.scanComplete() == -2)
|
||||
{
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
}
|
||||
json.concat(F("]"));
|
||||
client->text(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void init_websocket(void)
|
||||
{
|
||||
|
||||
wsStatus.onEvent(wseStatus);
|
||||
www.addHandler(&wsStatus);
|
||||
TRACE_ADDWEB(&wsStatus);
|
||||
}
|
218
src/xpvsp.ino
Normal file
218
src/xpvsp.ino
Normal file
@ -0,0 +1,218 @@
|
||||
/**
|
||||
* Transparentni seriovy port s podporou NVT pro ESP8266
|
||||
*
|
||||
* @file xpvsp.ino
|
||||
* @author Pavel Brychta, http://www.xpablo.cz
|
||||
*
|
||||
* Copyright (c) 2016-2018 Pavel Brychta. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "configuration.h"
|
||||
#include <EEPROM.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#include <ESPAsyncUDP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#ifdef USE_EDITOR
|
||||
#include <SPIFFSEditor.h>
|
||||
#endif
|
||||
#include <ArduinoOTA.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <Ticker.h>
|
||||
#include <SPI.h>
|
||||
#ifdef HTTP_UPDATE
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
#endif
|
||||
#include <interval.h>
|
||||
#include <ESP8266NetBIOS.h>
|
||||
#include <WiFiConfig.h>
|
||||
#if (LED_PIN != NO_PIN)
|
||||
#include <led.h>
|
||||
#endif
|
||||
#ifdef USE_SPIFFS
|
||||
#warning Pouzivame SPIFFS - nezapomen pripravit obsah flash!
|
||||
#include "FS.h"
|
||||
#endif
|
||||
#include "obfuscator.h"
|
||||
|
||||
// Definice obsazeni EEPROM
|
||||
#define elementSize(type, element) sizeof(((type *)0)->element)
|
||||
typedef struct
|
||||
{
|
||||
wificonfigarea_t wc; // oblast, vyhrazena pro konfiguraci WiFi
|
||||
// **** sem pokracuji dalsi polozky, ukladane do EEPROM
|
||||
|
||||
} eepromdata_t;
|
||||
|
||||
#if (LED_PIN != NO_PIN)
|
||||
LED led(LED_PIN, LOW, HIGH);
|
||||
const uint8_t LS_CONNECTING[] = {LEDS_ONFOR + 0, LEDS_OFFFOR + 8, LEDS_RESTART};
|
||||
const uint8_t LS_CONFIGAP[] = {LEDS_ONFOR + 0, LEDS_OFFFOR + 0, LEDS_ONFOR + 0, LEDS_OFFFOR + 6, LEDS_RESTART};
|
||||
const uint8_t LS_CONNECTED[] = {LEDS_ONFOR + 0, LEDS_OFFFOR + 0, LEDS_ONFOR + 0, LEDS_OFFFOR + 0, LEDS_ONFOR + 0, LEDS_OFFFOR + 6, LEDS_RESTART};
|
||||
#endif
|
||||
|
||||
#ifdef HTTP_UPDATE
|
||||
ESP8266HTTPUpdateServer httpUpdater;
|
||||
#ifdef HTTP_UPDATE_USERNAME
|
||||
#define vxENCRYPT2(Str) (vxCplEncryptedString<vxCplIndexes<sizeof(Str) - 1>::Result>(Str))
|
||||
auto _huuser = vxENCRYPT2(HTTP_UPDATE_USERNAME);
|
||||
auto _hupass = vxENCRYPT2(HTTP_UPDATE_PASSWORD);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int otaActive = 0; // priznak moznosti aktivovat OTA
|
||||
AsyncWebServer www(HTTP_PORT); // webovy server
|
||||
Interval timer30s; // tikani po 30-ti sekundach
|
||||
uint32_t upcounter; // citac poctu ubehlych 30-ti sekund (pro mereni uptime)
|
||||
// Profiling
|
||||
uint32_t start = 0;
|
||||
uint32_t elapsed = 0;
|
||||
uint32_t loopCounter = 0;
|
||||
uint32_t loopCounterLast = 0;
|
||||
uint32_t loopCounterMax = 1;
|
||||
// **** sem je mozne dopsat dalsi globalni promenne
|
||||
|
||||
void wificfgcb(wificonfigstate_t state)
|
||||
{
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case WCS_CONNECTSTART:
|
||||
// **** kod pro start signalizace, oznamujici zacatek pripojovani k WiFi siti (volano pouze jednou)
|
||||
#if (LED_PIN != NO_PIN)
|
||||
led.set(LS_CONNECTING);
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case WCS_CONNECTING:
|
||||
// **** kod pro periodickou signalizaci probihajiciho pripojovani k WiFi siti (volano periodicky)
|
||||
|
||||
break;
|
||||
|
||||
case WCS_CONNECTED:
|
||||
// **** kod pro start signalizace uspesneho pripojeni k WiFi siti (volano pouze jednou)
|
||||
#if (LED_PIN != NO_PIN)
|
||||
led.set(LS_CONNECTED);
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case WCS_CONFIGSTART:
|
||||
// **** kod pro start signalizace, oznamujici spusteni konfiguracniho AP (volano pouze jednou)
|
||||
#if (LED_PIN != NO_PIN)
|
||||
led.set(LS_CONFIGAP);
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case WCS_CONFIGWAIT:
|
||||
// **** kod pro periodickou signalizaci beziciho konfiguracniho AP (volano periodicky)
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void runEach30Seconds(void)
|
||||
{
|
||||
|
||||
timer30s.set(30000); // nove nastaveni casovace
|
||||
++upcounter; // celkova delka behu
|
||||
|
||||
// mereni pro vypocet zatizeni zarizeni
|
||||
loopCounterLast = loopCounter;
|
||||
loopCounter = 0;
|
||||
if (loopCounterLast > loopCounterMax)
|
||||
loopCounterMax = loopCounterLast;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR setup()
|
||||
{
|
||||
int _fc;
|
||||
|
||||
TRACE_INIT; // inicializace ladeni
|
||||
EEPROM.begin(sizeof(eepromdata_t) + 10); // zahajujeme praci s EEPROM (10 bytu je jen rezerva)
|
||||
#if (LED_PIN != NO_PIN)
|
||||
led.begin(); // inicializace signalizace
|
||||
#endif
|
||||
|
||||
#if (FORCE_CONFIG_BUTTON_PIN != NO_PIN)
|
||||
pinMode(FORCE_CONFIG_BUTTON_PIN, INPUT_PULLUP);
|
||||
delay(20); // male zpozdeni, aby se ustalila hodnota na vstupu
|
||||
_fc = digitalRead(FORCE_CONFIG_BUTTON_PIN); // pokud je na I/O pinu hodnota 0, tak vynutime nastavovaci AP
|
||||
#else
|
||||
_fc = 1; // nevstupujeme do konfigurace
|
||||
#endif
|
||||
{
|
||||
WiFiConfig wifi; // konfigurace WiFi casti ESP modulu
|
||||
|
||||
if (WCR_OK != wifi.begin(offsetof(eepromdata_t, wc), _fc, 60, wificfgcb)) // startujeme pripojeni
|
||||
ESP.restart();
|
||||
}
|
||||
if (ESP.getFlashChipRealSize() > 1000000)
|
||||
otaActive = 1; // flash pameti je dost - povolime OTA
|
||||
|
||||
if (strlen(WiFiDeviceName))
|
||||
{
|
||||
NBNS.begin(WiFiDeviceName);
|
||||
if (otaActive)
|
||||
{
|
||||
ArduinoOTA.setHostname(WiFiDeviceName);
|
||||
ArduinoOTA.begin();
|
||||
TRACE(TRACE_INFO, F("OTA aktivovano"));
|
||||
}
|
||||
else
|
||||
{
|
||||
MDNS.begin(WiFiDeviceName);
|
||||
MDNS.addService("http", "tcp", HTTP_PORT);
|
||||
}
|
||||
}
|
||||
// montaz souboroveho systemu
|
||||
#ifdef USE_SPIFFS
|
||||
if (!SPIFFS.begin())
|
||||
TRACE(TRACE_ERROR, F("SPIFFS neni pripojeny!"));
|
||||
#endif
|
||||
// Start weboveho serveru - sem je mozno pridavat odkazy na dalsi stranky
|
||||
|
||||
#ifdef HTTP_UPDATE
|
||||
#ifndef HTTP_UPDATE_USERNAME
|
||||
httpUpdater.setup(&www);
|
||||
#else
|
||||
httpUpdater.setup(&www, _huuser.decrypt(), _hupass.decrypt());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
webserver_init(); // startujeme webovy server
|
||||
vsp_init();
|
||||
// **** dalsi uzivatelska inicializace
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
if (otaActive)
|
||||
{ // pripadna obsluha OTA aktualizace FW
|
||||
ArduinoOTA.handle();
|
||||
}
|
||||
TRACE_POLL;
|
||||
if (timer30s.expired())
|
||||
runEach30Seconds();
|
||||
++loopCounter;
|
||||
// **** dalsi uzivatelske metody
|
||||
vsp_loop();
|
||||
}
|
Loading…
Reference in New Issue
Block a user