Reorg (#1)
* reorg to include core and librany deps in project using submodules * added script to insure submodules and such are setup * added OTA update support and started on syslog logging * added syslog logging support & Config saving via SPIFFS/Json file * start travis builds * DebugLevel * added eagle designs * added enclosure * update README
This commit is contained in:
parent
245cbc2dea
commit
8a53197001
20
.gitignore
vendored
20
.gitignore
vendored
|
|
@ -1,13 +1,15 @@
|
|||
.metadata
|
||||
.DS_Store
|
||||
.ino.cpp
|
||||
.project
|
||||
.cproject
|
||||
.settings
|
||||
Release
|
||||
Debug
|
||||
libraries
|
||||
core
|
||||
*.bak
|
||||
*-bak
|
||||
spec.d
|
||||
/.setup_hook.sh
|
||||
/ESPNTPServer/.ino.cpp
|
||||
/ESPNTPServer/.project
|
||||
/ESPNTPServer/.cproject
|
||||
/ESPNTPServer/.settings
|
||||
/ESPNTPServer/Release
|
||||
/ESPNTPServer/Debug
|
||||
/ESPNTPServer/libraries
|
||||
/ESPNTPServer/core
|
||||
/ESPNTPServer/spec.d
|
||||
/RemoteSystemsTempFiles
|
||||
|
|
|
|||
30
.gitmodules
vendored
30
.gitmodules
vendored
|
|
@ -0,0 +1,30 @@
|
|||
[submodule "hardware/esp8266com/esp8266"]
|
||||
path = hardware/esp8266com/esp8266
|
||||
url = https://github.com/esp8266/Arduino.git
|
||||
[submodule "libraries/DLog"]
|
||||
path = libraries/DLog
|
||||
url = https://github.com/liebman/DLog.git
|
||||
[submodule "libraries/DLogNet"]
|
||||
path = libraries/DLogNet
|
||||
url = https://github.com/liebman/DLogNet.git
|
||||
[submodule "libraries/MicroNMEA"]
|
||||
path = libraries/MicroNMEA
|
||||
url = https://github.com/liebman/MicroNMEA.git
|
||||
branch = handle-empty-date-or-time
|
||||
[submodule "libraries/WiFiManager"]
|
||||
path = libraries/WiFiManager
|
||||
url = https://github.com/liebman/WiFiManager.git
|
||||
branch = stdfunc
|
||||
[submodule "libraries/esp8266-oled-ssd1306"]
|
||||
path = libraries/esp8266-oled-ssd1306
|
||||
url = https://github.com/liebman/esp8266-oled-ssd1306.git
|
||||
branch = cleanup-warnings
|
||||
[submodule "libraries/ESPAsyncUDP"]
|
||||
path = libraries/ESPAsyncUDP
|
||||
url = https://github.com/me-no-dev/ESPAsyncUDP.git
|
||||
[submodule "libraries/Syslog"]
|
||||
path = libraries/Syslog
|
||||
url = https://github.com/arcao/Syslog.git
|
||||
[submodule "libraries/ArduinoJson"]
|
||||
path = libraries/ArduinoJson
|
||||
url = https://github.com/bblanchon/ArduinoJson.git
|
||||
46
.travis.yml
Normal file
46
.travis.yml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
language: python
|
||||
- "2.7"
|
||||
|
||||
sudo: required
|
||||
|
||||
env:
|
||||
global:
|
||||
- APPLICATION_FOLDER="${HOME}/arduino-ide"
|
||||
- SKETCHBOOK_FOLDER="${TRAVIS_BUILD_DIR}"
|
||||
- ESP8266_DEVICE="esp8266com:esp8266:generic:CpuFrequency=160,CrystalFreq=26,FlashFreq=40,FlashMode=qio,FlashSize=4M1M,led=2,LwIPVariant=v2mss536,Debug=Serial1,DebugLevel=None____"
|
||||
- ESPNTPSERVER_DIR="${TRAVIS_BUILD_DIR}/ESPNTPServer"
|
||||
|
||||
before_install:
|
||||
- echo HOME is "'${HOME}'"
|
||||
- id
|
||||
- cd "${TRAVIS_BUILD_DIR}"
|
||||
- ./setup.sh
|
||||
# setup arduino-ci-script
|
||||
- git clone https://github.com/per1234/arduino-ci-script.git "${HOME}/scripts"
|
||||
- cd "${HOME}/scripts"
|
||||
# Get new tags from the remote
|
||||
- git fetch --tags
|
||||
# Checkout the latest tag
|
||||
- git checkout $(git describe --tags `git rev-list --tags --max-count=1`)
|
||||
- source "${HOME}/scripts/arduino-ci-script.sh"
|
||||
|
||||
# Uncomment the following lines to get verbose output for debugging
|
||||
# 0 (minimum/default) - 2 (maximum) verbosity
|
||||
#- set_script_verbosity 1
|
||||
# Turn on verbose output during compilation
|
||||
#- set_verbose_output_during_compilation "true"
|
||||
|
||||
# Don't for library issues that don't affect compilation
|
||||
- set_library_testing "false"
|
||||
|
||||
- set_application_folder "$APPLICATION_FOLDER"
|
||||
- set_sketchbook_folder "$SKETCHBOOK_FOLDER"
|
||||
|
||||
- install_ide "1.8.5"
|
||||
|
||||
# make it look like a sketch for arduino
|
||||
- touch "${ESPNTPSERVER_DIR}/ESPNTPServer.ino"
|
||||
|
||||
script:
|
||||
# build with arduino
|
||||
- build_sketch "${ESPNTPSERVER_DIR}" "${ESP8266_DEVICE}" "false" "1.8.5"
|
||||
120
ESPNTPServer/Config.cpp
Normal file
120
ESPNTPServer/Config.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Config.cpp
|
||||
*
|
||||
* Created on: Jun 10, 2018
|
||||
* Author: chris.l
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
#include "FS.h"
|
||||
#include "Log.h"
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
static const char* TAG = "Config";
|
||||
static const char* CONFIG_FILE = "Config.json";
|
||||
|
||||
|
||||
Config::Config() : _syslog_host(), _syslog_port(0)
|
||||
{
|
||||
}
|
||||
|
||||
Config::~Config()
|
||||
{
|
||||
}
|
||||
|
||||
bool Config::begin()
|
||||
{
|
||||
dlog.info(TAG, "begin: Mounting SPIFFS");
|
||||
|
||||
if (!SPIFFS.begin())
|
||||
{
|
||||
dlog.warning(TAG, "begin: Formatting SPIFFS!!!!!");
|
||||
if (SPIFFS.format())
|
||||
{
|
||||
dlog.error(TAG, "begin: SPIFFS format failed!");
|
||||
return false;
|
||||
}
|
||||
dlog.info(TAG, "begin: mounting SPIFFS after format!");
|
||||
if (!SPIFFS.begin())
|
||||
{
|
||||
dlog.error(TAG, "begin: SPIFFS mount failed!!!!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Config::load()
|
||||
{
|
||||
dlog.info(TAG, "load: file: '%s'", CONFIG_FILE);
|
||||
|
||||
if (!SPIFFS.exists(CONFIG_FILE))
|
||||
{
|
||||
dlog.warning(TAG, "load: config file does not exist!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File f = SPIFFS.open(CONFIG_FILE, "r");
|
||||
if (!f)
|
||||
{
|
||||
dlog.error(TAG, "load: failed to open config file!");
|
||||
return false;
|
||||
}
|
||||
|
||||
StaticJsonBuffer<512> buffer;
|
||||
|
||||
dlog.debug(TAG, "load: parsing file contents");
|
||||
JsonObject& root = buffer.parseObject(f);
|
||||
f.close();
|
||||
|
||||
if (!root.success())
|
||||
{
|
||||
dlog.error(TAG, "load: fails to parse file!");
|
||||
return false;
|
||||
}
|
||||
|
||||
strlcpy(_syslog_host, root["syslogHost"]|"", sizeof(_syslog_host));
|
||||
_syslog_port = root["syslogPort"] | 0;
|
||||
|
||||
dlog.info(TAG, "load: config loaded!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void Config::save()
|
||||
{
|
||||
dlog.info(TAG, "save: file: '%s'", CONFIG_FILE);
|
||||
|
||||
File f = SPIFFS.open(CONFIG_FILE, "w");
|
||||
|
||||
StaticJsonBuffer<512> buffer;
|
||||
JsonObject& root = buffer.createObject();
|
||||
|
||||
root["syslogHost"] = _syslog_host;
|
||||
root["syslogPort"] = _syslog_port;
|
||||
|
||||
root.printTo(f);
|
||||
f.close();
|
||||
|
||||
dlog.info(TAG, "save: config saved");
|
||||
}
|
||||
|
||||
const char* Config::getSyslogHost()
|
||||
{
|
||||
return _syslog_host;
|
||||
}
|
||||
|
||||
void Config::setSyslogHost(const char* host)
|
||||
{
|
||||
strlcpy(_syslog_host, host, sizeof(_syslog_host));
|
||||
}
|
||||
|
||||
uint16_t Config::getSyslogPort()
|
||||
{
|
||||
return _syslog_port;
|
||||
}
|
||||
|
||||
void Config::setSyslogPort(uint16_t port)
|
||||
{
|
||||
_syslog_port = port;
|
||||
}
|
||||
36
ESPNTPServer/Config.h
Normal file
36
ESPNTPServer/Config.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Config.h
|
||||
*
|
||||
* Created on: Jun 10, 2018
|
||||
* Author: chris.l
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H_
|
||||
#define CONFIG_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
class ConfigImpl;
|
||||
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
Config();
|
||||
virtual ~Config();
|
||||
|
||||
bool begin();
|
||||
|
||||
bool load();
|
||||
void save();
|
||||
|
||||
const char* getSyslogHost();
|
||||
void setSyslogHost(const char* host);
|
||||
uint16_t getSyslogPort();
|
||||
void setSyslogPort(uint16_t port);
|
||||
|
||||
private:
|
||||
char _syslog_host[64];
|
||||
uint16_t _syslog_port;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_H_ */
|
||||
|
|
@ -122,6 +122,19 @@ void Display::process()
|
|||
display();
|
||||
}
|
||||
|
||||
void Display::message(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
clear();
|
||||
align(TEXT_ALIGN_CENTER);
|
||||
vprint(64, 32, fmt, ap);
|
||||
display();
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Display::clear()
|
||||
{
|
||||
_dsp.clear();
|
||||
|
|
@ -146,9 +159,13 @@ void Display::print(int16_t x, int16_t y, const char* fmt, ...)
|
|||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprint(x, y, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Display::vprint(int16_t x, int16_t y, const char* fmt, va_list ap)
|
||||
{
|
||||
vsnprintf(_buffer, DISPLAY_BUFFER_LEN, fmt, ap);
|
||||
_buffer[DISPLAY_BUFFER_LEN-1] = '\0';
|
||||
va_end(ap);
|
||||
|
||||
_dsp.drawString(x, y, _buffer);
|
||||
}
|
||||
|
|
@ -24,12 +24,15 @@ public:
|
|||
void end();
|
||||
void process();
|
||||
|
||||
void message(const char* fmt, ...);
|
||||
|
||||
void clear();
|
||||
void display();
|
||||
void align(OLEDDISPLAY_TEXT_ALIGNMENT alignment);
|
||||
void font(const char* fontData);
|
||||
|
||||
void print(int16_t x, int16_t y, const char* fmt, ...);
|
||||
void vprint(int16_t x, int16_t y, const char* fmt, va_list ap);
|
||||
private:
|
||||
SSD1306Wire _dsp;
|
||||
GPS& _gps;
|
||||
|
|
@ -23,15 +23,20 @@
|
|||
#include "ESPNTPServer.h"
|
||||
#include "Log.h"
|
||||
#include "DLogPrintWriter.h"
|
||||
#include "DLogSyslogWriter.h"
|
||||
|
||||
#include "GPS.h"
|
||||
#include "NTP.h"
|
||||
#include "Display.h"
|
||||
#include "Config.h"
|
||||
|
||||
DLog& dlog = DLog::getLog();
|
||||
GPS gps(Serial, SYNC_PIN);
|
||||
NTP ntp(gps);
|
||||
Display display(gps, ntp, SDA_PIN, SCL_PIN);
|
||||
DLog& dlog = DLog::getLog();
|
||||
Config config;
|
||||
|
||||
char devicename[32];
|
||||
|
||||
const char* SETUP_TAG = "setup";
|
||||
const char* LOOP_TAG = "loop";
|
||||
|
|
@ -54,9 +59,62 @@ void logTimeFirst(DLogBuffer& buffer, DLogLevel level)
|
|||
tv.tv_usec);
|
||||
}
|
||||
|
||||
void processOTA(const char* ota_url, const char* ota_fp)
|
||||
{
|
||||
static PROGMEM const char TAG[] = "processOTA";
|
||||
dlog.info(FPSTR(TAG), F("OTA update"));
|
||||
|
||||
dlog.info(FPSTR(TAG), F("checking for OTA from: '%s'"), ota_url);
|
||||
display.message("Starting OTA");
|
||||
|
||||
ESPhttpUpdate.rebootOnUpdate(false);
|
||||
|
||||
t_httpUpdate_return ret;
|
||||
|
||||
if (strncmp(ota_url, "https:", 6) == 0)
|
||||
{
|
||||
ret = ESPhttpUpdate.update(ota_url, "0.4", ota_fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ESPhttpUpdate.update(ota_url, "0.4");
|
||||
}
|
||||
|
||||
String reason = ESPhttpUpdate.getLastErrorString();
|
||||
|
||||
switch(ret)
|
||||
{
|
||||
case HTTP_UPDATE_OK:
|
||||
dlog.info(FPSTR(TAG), F("OTA update OK! restarting..."));
|
||||
dlog.end();
|
||||
display.message("Success!");
|
||||
delay(10000);
|
||||
ESP.restart();
|
||||
break;
|
||||
|
||||
case HTTP_UPDATE_FAILED:
|
||||
dlog.info(FPSTR(TAG), F("OTA update failed! reason:'%s'"), reason.c_str());
|
||||
display.message("FAILED!");
|
||||
delay(10000);
|
||||
break;
|
||||
|
||||
case HTTP_UPDATE_NO_UPDATES:
|
||||
dlog.info(FPSTR(TAG), F("OTA no updates! reason:'%s'"), reason.c_str());
|
||||
display.message("NO Update!");
|
||||
delay(10000);
|
||||
break;
|
||||
|
||||
default:
|
||||
dlog.info(FPSTR(TAG), F("OTA update WTF? unexpected return code: %d reason: '%s'"), ret, reason.c_str());
|
||||
display.message("Unknown!");
|
||||
delay(10000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(5000); // delay for IDE to re-open serial
|
||||
//delay(5000); // delay for IDE to re-open serial
|
||||
|
||||
//
|
||||
// Setup DLog with Serial1, set the pre function to add the date/time
|
||||
|
|
@ -65,32 +123,81 @@ void setup()
|
|||
dlog.begin(new DLogPrintWriter(Serial1));
|
||||
dlog.setPreFunc(&logTimeFirst);
|
||||
//dlog.setLevel("GPS", DLogLevel::DLOG_LEVEL_DEBUG);
|
||||
dlog.setLevel("Config", DLogLevel::DLOG_LEVEL_DEBUG);
|
||||
|
||||
dlog.info(SETUP_TAG, F("Startup!"));
|
||||
|
||||
String id = "ESPNTP:" + String(ESP.getChipId(), 16);
|
||||
strncpy(devicename, id.c_str(), 32);
|
||||
dlog.info(SETUP_TAG, "Device name: %s", devicename);
|
||||
|
||||
dlog.info(SETUP_TAG, F("initializing display"));
|
||||
display.begin();
|
||||
|
||||
|
||||
dlog.info(SETUP_TAG, F("initializing serial for GPS"));
|
||||
Serial.begin(9600);
|
||||
Serial.swap();
|
||||
|
||||
dlog.info(SETUP_TAG, F("initializing GPS"));
|
||||
display.message("Starting GPS");
|
||||
gps.begin();
|
||||
display.process();
|
||||
|
||||
bool force_config = false;
|
||||
|
||||
config.begin();
|
||||
|
||||
if (!config.load())
|
||||
{
|
||||
dlog.warning(SETUP_TAG, "no config found, forcing config portal!");
|
||||
force_config = true;
|
||||
}
|
||||
|
||||
// if the reset/config button is pressed then force config
|
||||
if (digitalRead(CONFIG_PIN) == 0)
|
||||
{
|
||||
time_t start = millis();
|
||||
|
||||
while (digitalRead(CONFIG_PIN) == 0)
|
||||
{
|
||||
time_t delta = millis() - start;
|
||||
if (!force_config && delta > CONFIG_DELAY)
|
||||
{
|
||||
dlog.info(SETUP_TAG, F("reset button held, forcing config!"));
|
||||
force_config = true;
|
||||
display.message("Force Config");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(USE_NO_WIFI)
|
||||
dlog.info(SETUP_TAG, F("initializing wifi"));
|
||||
#if 0
|
||||
WiFiManager wifi;
|
||||
wifi.setDebugStream(Serial1);
|
||||
wifi.setDebugOutput(false);
|
||||
#else
|
||||
WiFiManager wifi(Serial1);
|
||||
wifi.setDebugOutput(true);
|
||||
#endif
|
||||
wifi.setDebugOutput(true);
|
||||
String ssid = "ESPNTPServer" + String(ESP.getChipId());
|
||||
wifi.autoConnect(ssid.c_str(), NULL);
|
||||
display.message("Starting WiFi");
|
||||
WiFiSetup wifi(config, display, Serial1, false, devicename);
|
||||
wifi.connect(force_config);
|
||||
|
||||
const char* syslog_host = config.getSyslogHost();
|
||||
uint16_t syslog_port = config.getSyslogPort();
|
||||
if (syslog_host != nullptr && strlen(syslog_host) > 0 && syslog_port != 0)
|
||||
{
|
||||
dlog.info(SETUP_TAG, "enabling syslog: '%s:%u'", syslog_host, syslog_port);
|
||||
dlog.begin(new DLogSyslogWriter("192.168.0.31", 514, devicename));
|
||||
}
|
||||
const char* url = wifi.getOTAURL();
|
||||
const char* fp = wifi.getOTAFP();
|
||||
if (fp == nullptr)
|
||||
{
|
||||
fp = "";
|
||||
}
|
||||
|
||||
if (url != nullptr)
|
||||
{
|
||||
processOTA(url, fp);
|
||||
}
|
||||
|
||||
WiFiMode_t mode = WiFi.getMode();
|
||||
dlog.error(SETUP_TAG, "WiFi mode: %d", mode);
|
||||
#endif
|
||||
|
||||
display.process();
|
||||
|
|
@ -140,6 +247,14 @@ void loop()
|
|||
last_ip = ip;
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint32_t m = millis();
|
||||
if (m % 1000 == 0)
|
||||
{
|
||||
dlog.info("loop", "uptime: %lu millis: %lu", m);
|
||||
}
|
||||
#endif
|
||||
|
||||
gps.process();
|
||||
|
||||
static time_t last_seconds;
|
||||
|
|
@ -27,14 +27,18 @@
|
|||
#include "Arduino.h"
|
||||
#include "Ticker.h"
|
||||
#if !defined(USE_NO_WIFI)
|
||||
#include "WiFiManager.h"
|
||||
#include "WiFiSetup.h"
|
||||
#endif
|
||||
#include "ESP8266httpUpdate.h"
|
||||
#include <time.h>
|
||||
|
||||
// pin definitions
|
||||
#define SYNC_PIN 12 // (GPIO12) pin tied to 1hz square wave from GPS
|
||||
#define SYNC_PIN 12 // GPIO12 pin tied to 1hz square wave from GPS
|
||||
#define CONFIG_PIN 14 // GPIO14 tied to reset/config button
|
||||
#define SDA_PIN 4
|
||||
#define SCL_PIN 5
|
||||
|
||||
#define CONFIG_DELAY 1000 // how long to hold the button for config mode.
|
||||
|
||||
|
||||
#endif /* _ESPNTPServer_H_ */
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* GPS.cpp
|
||||
*
|
||||
* Copyright 2017 Christopher B. Liebman
|
||||
* Copyright 2018 Christopher B. Liebman
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -116,7 +116,9 @@ void GPS::process()
|
|||
|
||||
while (_stream.available() > 0)
|
||||
{
|
||||
if (_nmea.process(_stream.read()))
|
||||
int c = _stream.read();
|
||||
dlog.trace(TAG, F("c: %c"), c);
|
||||
if (_nmea.process(c))
|
||||
{
|
||||
struct timeval tv;
|
||||
getTime(&tv);
|
||||
|
|
@ -125,9 +127,9 @@ void GPS::process()
|
|||
const char * id = _nmea.getMessageID();
|
||||
|
||||
//
|
||||
// if it was a GGA and its valid then check and maybe update the time
|
||||
// if it was a RMC and its valid then check and maybe update the time
|
||||
//
|
||||
if (_nmea.getYear() > 2000 && strcmp("RMC", id) == 0)
|
||||
if (_nmea.getYear() > 2017 && strcmp("RMC", id) == 0)
|
||||
{
|
||||
struct tm tm;
|
||||
tm.tm_year = _nmea.getYear() - 1900;
|
||||
|
|
@ -174,7 +176,7 @@ void GPS::process()
|
|||
}
|
||||
else /* nmea not valid or sat count < 4 */
|
||||
{
|
||||
if (_gps_valid)
|
||||
if (_gps_valid || _valid_delay)
|
||||
{
|
||||
invalidate("NMEA:%s SATS:%d from: '%s'",
|
||||
_nmea.isValid() ? "valid" : "invalid",
|
||||
|
|
@ -220,6 +222,7 @@ void ICACHE_RAM_ATTR GPS::invalidate(const char* fmt, ...)
|
|||
}
|
||||
_valid = false;
|
||||
_gps_valid = false;
|
||||
_valid_delay = 0;
|
||||
_last_micros = 0;
|
||||
}
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
#include "Ticker.h"
|
||||
|
||||
#define REASON_SIZE 128
|
||||
#define NMEA_BUFFER_SIZE 128
|
||||
#define NMEA_BUFFER_SIZE 250
|
||||
#define PPS_TIMING_PIN 12 // (GPIO12) if defined PPS interrupt will make high during processing
|
||||
#define VALID_DELAY 120 // delay (seconds) from gps valid to valid
|
||||
#define VALID_TIMER_MS 1001 // if this timer expires we invalidate!
|
||||
128
ESPNTPServer/WiFiSetup.cpp
Normal file
128
ESPNTPServer/WiFiSetup.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* WiFiSetup.cpp
|
||||
*
|
||||
* Copyright 2018 Christopher B. Liebman
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Created on: May 27, 2018
|
||||
* Author: chris.l
|
||||
*/
|
||||
|
||||
#include "WiFiSetup.h"
|
||||
#include <functional>
|
||||
|
||||
#include "Log.h"
|
||||
static const char* TAG = "WiFiSetup";
|
||||
|
||||
WiFiSetup::WiFiSetup(Config& config, Display& display, Stream& serial, boolean debug, const char* devicename)
|
||||
: _config(config),
|
||||
_display(display),
|
||||
_wm(serial),
|
||||
_ota_url("ota_url", "OTA URL", "", 128),
|
||||
_ota_fp("ota_fp", "OTA Fingerprint", "", 64),
|
||||
_syslog_host("syslog_host", "Syslog Host", "", 64),
|
||||
_syslog_port("syslog_port", "Syslog Port", "514", 8),
|
||||
_devicename(devicename)
|
||||
{
|
||||
_wm.setDebugOutput(debug);
|
||||
|
||||
using namespace std::placeholders;
|
||||
_wm.setAPCallback(std::bind(&WiFiSetup::startingPortal, this, _1));
|
||||
_wm.setSaveConfigCallback(std::bind(&WiFiSetup::saveConfig, this));
|
||||
}
|
||||
|
||||
WiFiSetup::~WiFiSetup()
|
||||
{
|
||||
}
|
||||
|
||||
void WiFiSetup::connect(bool force_config)
|
||||
{
|
||||
WiFi.mode(WiFiMode::WIFI_STA);
|
||||
if (force_config)
|
||||
{
|
||||
dlog.info(TAG, F("connect: starting forced config portal!"));
|
||||
_wm.startConfigPortal(_devicename, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
dlog.info(TAG, F("connect: auto-connecting"));
|
||||
_wm.autoConnect(_devicename, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiSetup::startingPortal(WiFiManager* wmp)
|
||||
{
|
||||
(void) wmp;
|
||||
dlog.info(TAG, F("startingPortal: updating param values"));
|
||||
_syslog_host.setValue(_config.getSyslogHost(), 64);
|
||||
char value[10];
|
||||
snprintf(value, sizeof(value), "%u", _config.getSyslogPort());
|
||||
_syslog_port.setValue(value, 8);
|
||||
dlog.info(TAG, F("startingPortal: adding params"));
|
||||
_wm.addParameter(&_ota_url);
|
||||
_wm.addParameter(&_ota_fp);
|
||||
_wm.addParameter(&_syslog_host);
|
||||
_wm.addParameter(&_syslog_port);
|
||||
|
||||
dlog.debug(TAG, F("startingPortal: params added!"));
|
||||
|
||||
//
|
||||
// Update the display with the SSID to show portal is up
|
||||
//
|
||||
dlog.info(TAG, F("startingPortal: updating display"));
|
||||
_display.message("SSID: %s", _wm.getConfigPortalSSID().c_str());
|
||||
}
|
||||
|
||||
void WiFiSetup::saveConfig()
|
||||
{
|
||||
dlog.info(TAG, "saveConfig: updating values");
|
||||
_config.setSyslogHost(_syslog_host.getValue());
|
||||
_config.setSyslogPort(atoi(_syslog_port.getValue()));
|
||||
dlog.debug(TAG, "saveConfig: saving!");
|
||||
_config.save();
|
||||
}
|
||||
|
||||
const char* WiFiSetup::getParam(WiFiManagerParameter& param)
|
||||
{
|
||||
const char* value = param.getValue();
|
||||
|
||||
if (strlen(value) > 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* WiFiSetup::getOTAURL()
|
||||
{
|
||||
return getParam(_ota_url);
|
||||
}
|
||||
|
||||
const char* WiFiSetup::getOTAFP()
|
||||
{
|
||||
return getParam(_ota_fp);
|
||||
}
|
||||
|
||||
const char* WiFiSetup::getSyslogHost()
|
||||
{
|
||||
return getParam(_syslog_host);
|
||||
}
|
||||
|
||||
uint16_t WiFiSetup::getSyslogPort()
|
||||
{
|
||||
const char* value = getParam(_syslog_port);
|
||||
int port = atoi(value);
|
||||
return port;
|
||||
}
|
||||
54
ESPNTPServer/WiFiSetup.h
Normal file
54
ESPNTPServer/WiFiSetup.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* WiFiSetup.h
|
||||
*
|
||||
* Copyright 2018 Christopher B. Liebman
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Created on: May 27, 2018
|
||||
* Author: chris.l
|
||||
*/
|
||||
|
||||
#ifndef WIFISETUP_H_
|
||||
#define WIFISETUP_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "WiFiManager.h"
|
||||
#include "Display.h"
|
||||
#include "Config.h"
|
||||
|
||||
class WiFiSetup {
|
||||
public:
|
||||
WiFiSetup(Config& config, Display& display, Stream& serial, boolean debug, const char* devicename);
|
||||
virtual ~WiFiSetup();
|
||||
void connect(bool force_config = false);
|
||||
const char* getOTAURL();
|
||||
const char* getOTAFP();
|
||||
const char* getSyslogHost();
|
||||
uint16_t getSyslogPort();
|
||||
private:
|
||||
Config& _config;
|
||||
Display& _display;
|
||||
WiFiManager _wm;
|
||||
WiFiManagerParameter _ota_url;
|
||||
WiFiManagerParameter _ota_fp;
|
||||
WiFiManagerParameter _syslog_host;
|
||||
WiFiManagerParameter _syslog_port;
|
||||
const char* _devicename;
|
||||
void startingPortal(WiFiManager* wmp);
|
||||
void saveConfig();
|
||||
const char*getParam(WiFiManagerParameter& param);
|
||||
|
||||
};
|
||||
|
||||
#endif /* WIFISETUP_H_ */
|
||||
20
README.md
20
README.md
|
|
@ -1,6 +1,22 @@
|
|||
# ESPNTPServer
|
||||
GPS fueled ESP8266 based NTP Server
|
||||
|
||||
GPS: any with standard NMEA sentences & a pulse per second signal..
|
||||
[](https://travis-ci.org/liebman/ESPNTPServer.svg)
|
||||
|
||||
Work in progress....
|
||||
[ESPNTPServer](ESPNTPServer) Contains the code for the NTP Server
|
||||
|
||||
[hardware](hardware) contains the esp8266 arduino core version used as a git submodule
|
||||
|
||||
[libraries](libraries) has all needed libraries as git submodules
|
||||
|
||||
[eagle](eagle) contains the schematic and board designs in Eagle cad.
|
||||
|
||||
[enclosure](enclosure) contains the STL files for the enclosure.
|
||||
|
||||
This is designed around [this GPS module](https://www.amazon.com/gp/product/B075DD5746/) but any module with standard NMEA output and a pult per second signal will work if you redesign the board or use an adapter.
|
||||
|
||||
I also used [this display module](https://www.amazon.com/gp/product/B00O2KDQBE/). You can use others but be careful with the power polarity, I have modules where VCC and ground pins are in a different order.
|
||||
|
||||

|
||||

|
||||

|
||||
|
|
|
|||
2218
eagle/ESPNTPServer/ESPNTPServer.brd
Normal file
2218
eagle/ESPNTPServer/ESPNTPServer.brd
Normal file
File diff suppressed because it is too large
Load Diff
194
eagle/ESPNTPServer/ESPNTPServer.cam
Normal file
194
eagle/ESPNTPServer/ESPNTPServer.cam
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
{
|
||||
"author": {
|
||||
"email": "liebman@zod.com",
|
||||
"name": "Chris Liebman"
|
||||
},
|
||||
"description": {
|
||||
"EN": "EAGLE default 2 layer CAM job."
|
||||
},
|
||||
"output_type": "zip",
|
||||
"outputs": [
|
||||
{
|
||||
"format_specifier": {
|
||||
"decimal": 3,
|
||||
"integer": 3
|
||||
},
|
||||
"output_type": "drill",
|
||||
"outputs": [
|
||||
{
|
||||
"drills": {
|
||||
"NPTH": true,
|
||||
"PTH": true,
|
||||
"VIA": true
|
||||
},
|
||||
"filename_format": "outputs/drills.xln",
|
||||
"layers": {
|
||||
"from": 1,
|
||||
"to": 16
|
||||
},
|
||||
"name": "Excellon",
|
||||
"type": "excellon"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"filename_prefix": "outputs",
|
||||
"format_specifier": {
|
||||
"decimal": 4,
|
||||
"integer": 3
|
||||
},
|
||||
"generate_job_file": true,
|
||||
"output_type": "gerber",
|
||||
"outputs": [
|
||||
{
|
||||
"board_outline": false,
|
||||
"config": {
|
||||
"file_function": "Copper",
|
||||
"layer": 1,
|
||||
"layer_details": "mixed",
|
||||
"layer_type": "top"
|
||||
},
|
||||
"filename_format": "%PREFIX/copper_top.gbr",
|
||||
"layers": [
|
||||
1,
|
||||
18,
|
||||
17
|
||||
],
|
||||
"name": "Top Copper",
|
||||
"polarity": "positive",
|
||||
"type": "gerber_layer"
|
||||
},
|
||||
{
|
||||
"board_outline": false,
|
||||
"config": {
|
||||
"file_function": "Copper",
|
||||
"layer": 2,
|
||||
"layer_details": "mixed",
|
||||
"layer_type": "bottom"
|
||||
},
|
||||
"filename_format": "%PREFIX/copper_bottom.gbr",
|
||||
"layers": [
|
||||
16,
|
||||
17,
|
||||
18
|
||||
],
|
||||
"name": "Bottom Copper",
|
||||
"polarity": "positive",
|
||||
"type": "gerber_layer"
|
||||
},
|
||||
{
|
||||
"board_outline": true,
|
||||
"config": {
|
||||
"file_function": "Profile",
|
||||
"plating": "non-plated"
|
||||
},
|
||||
"filename_format": "%PREFIX/profile.gbr",
|
||||
"layers": [
|
||||
],
|
||||
"milling": true,
|
||||
"polarity": "positive",
|
||||
"type": "gerber_layer"
|
||||
},
|
||||
{
|
||||
"board_outline": false,
|
||||
"config": {
|
||||
"file_function": "Soldermask",
|
||||
"index": 1,
|
||||
"layer_type": "top"
|
||||
},
|
||||
"filename_format": "%PREFIX/soldermask_top.gbr",
|
||||
"layers": [
|
||||
29
|
||||
],
|
||||
"name": "Soldermask Top",
|
||||
"polarity": "negative",
|
||||
"type": "gerber_layer"
|
||||
},
|
||||
{
|
||||
"board_outline": false,
|
||||
"config": {
|
||||
"file_function": "Soldermask",
|
||||
"index": 1,
|
||||
"layer_type": "bottom"
|
||||
},
|
||||
"filename_format": "%PREFIX/soldermask_bottom.gbr",
|
||||
"layers": [
|
||||
30
|
||||
],
|
||||
"name": "Soldermask Bottom",
|
||||
"polarity": "negative",
|
||||
"type": "gerber_layer"
|
||||
},
|
||||
{
|
||||
"board_outline": false,
|
||||
"config": {
|
||||
"file_function": "Paste",
|
||||
"layer_type": "top"
|
||||
},
|
||||
"filename_format": "%PREFIX/solderpaste_top.gbr",
|
||||
"layers": [
|
||||
31
|
||||
],
|
||||
"milling": false,
|
||||
"name": "Solderpaste Top",
|
||||
"polarity": "positive",
|
||||
"type": "gerber_layer"
|
||||
},
|
||||
{
|
||||
"board_outline": false,
|
||||
"config": {
|
||||
"file_function": "Paste",
|
||||
"layer_type": "bottom"
|
||||
},
|
||||
"filename_format": "%PREFIX/solderpaste_bottom.gbr",
|
||||
"layers": [
|
||||
32
|
||||
],
|
||||
"milling": false,
|
||||
"name": "Solderpaste Bottom",
|
||||
"polarity": "positive",
|
||||
"type": "gerber_layer"
|
||||
},
|
||||
{
|
||||
"board_outline": false,
|
||||
"config": {
|
||||
"file_function": "Legend",
|
||||
"index": 1,
|
||||
"layer_type": "top"
|
||||
},
|
||||
"filename_format": "%PREFIX/silkscreen_top.gbr",
|
||||
"layers": [
|
||||
21,
|
||||
25
|
||||
],
|
||||
"milling": false,
|
||||
"name": "Silkscreen Top",
|
||||
"polarity": "positive",
|
||||
"type": "gerber_layer"
|
||||
},
|
||||
{
|
||||
"board_outline": false,
|
||||
"config": {
|
||||
"file_function": "Legend",
|
||||
"index": 1,
|
||||
"layer_type": "bottom"
|
||||
},
|
||||
"filename_format": "%PREFIX/silkscreen_bottom.gbr",
|
||||
"layers": [
|
||||
22,
|
||||
26
|
||||
],
|
||||
"milling": false,
|
||||
"name": "Silkscreen Bottom",
|
||||
"polarity": "positive",
|
||||
"type": "gerber_layer"
|
||||
}
|
||||
],
|
||||
"version": "X2"
|
||||
}
|
||||
],
|
||||
"timestamp": "2018-05-27T17:04:39",
|
||||
"type": "EAGLE CAM job",
|
||||
"units": "metric",
|
||||
"version": "8.6.1"
|
||||
}
|
||||
4907
eagle/ESPNTPServer/ESPNTPServer.lbr
Normal file
4907
eagle/ESPNTPServer/ESPNTPServer.lbr
Normal file
File diff suppressed because it is too large
Load Diff
18799
eagle/ESPNTPServer/ESPNTPServer.sch
Normal file
18799
eagle/ESPNTPServer/ESPNTPServer.sch
Normal file
File diff suppressed because it is too large
Load Diff
365
eagle/ESPNTPServer/eagle.epf
Normal file
365
eagle/ESPNTPServer/eagle.epf
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
[Eagle]
|
||||
Version="09 00 01"
|
||||
Platform="Mac OS X"
|
||||
Globals="Globals"
|
||||
Desktop="Desktop"
|
||||
|
||||
[Globals]
|
||||
AutoSaveProject=1
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:79"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:88"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:178"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:179"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:180"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:181"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:182"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:183"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:184"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:185"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:186"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:187"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:89"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:188"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:189"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:190"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:191"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:192"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:193"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:194"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:195"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:196"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:197"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:90"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:198"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:199"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:200"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:201"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:202"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:203"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:204"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:205"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:206"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:207"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:91"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:208"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:209"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:210"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:211"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:212"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:213"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:214"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:215"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:216"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:217"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:92"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:218"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:219"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:220"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:221"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:222"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:223"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:224"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:225"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:226"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:227"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:93"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:228"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:229"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:230"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:231"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:232"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:233"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:234"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:235"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:236"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:237"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:94"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:238"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:239"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:240"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:241"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:242"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:243"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:244"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:245"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:246"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:247"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:95"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:248"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:249"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:250"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:251"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:252"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:253"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:254"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:255"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:256"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:257"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:96"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:258"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:259"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:260"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:261"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:262"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:263"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:264"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:265"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:266"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:267"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:97"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:268"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:269"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:270"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:271"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:272"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:273"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:274"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:275"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:276"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:277"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:80"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:98"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:278"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:279"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:280"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:281"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:282"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:283"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:284"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:285"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:286"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:287"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:99"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:288"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:289"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:290"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:291"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:292"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:293"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:294"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:295"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:296"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:297"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:100"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:298"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:299"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:300"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:301"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:302"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:303"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:304"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:305"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:306"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:307"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:101"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:308"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:309"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:310"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:311"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:312"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:313"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:314"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:315"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:316"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:317"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:102"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:318"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:319"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:320"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:321"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:322"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:323"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:324"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:325"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:326"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:327"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:103"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:328"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:329"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:330"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:331"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:332"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:333"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:334"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:335"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:336"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:337"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:104"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:338"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:339"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:340"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:341"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:342"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:343"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:344"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:345"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:346"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:347"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:105"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:348"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:349"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:350"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:351"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:352"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:353"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:354"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:355"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:356"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:357"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:106"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:358"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:359"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:360"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:361"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:362"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:363"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:364"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:365"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:366"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:367"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:107"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:368"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:369"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:370"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:371"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:372"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:373"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:374"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:375"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:376"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:377"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:81"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:108"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:378"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:379"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:380"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:381"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:382"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:383"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:384"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:385"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:386"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:387"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:109"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:388"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:389"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:390"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:391"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:392"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:393"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:394"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:395"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:396"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:397"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:110"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:398"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:399"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:400"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:401"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:402"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:403"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:404"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:405"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:406"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:407"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:111"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:408"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:409"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:410"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:411"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:412"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:413"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:414"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:415"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:416"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:417"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:112"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:418"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:419"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:527439"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:536"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:531"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:518"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:113"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:114"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:115"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:116"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:117"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:82"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:118"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:119"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:120"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:121"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:122"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:123"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:124"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:125"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:126"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:127"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:83"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:128"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:129"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:130"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:131"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:132"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:133"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:134"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:135"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:136"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:137"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:84"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:138"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:139"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:140"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:141"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:142"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:143"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:144"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:145"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:146"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:147"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:85"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:148"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:149"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:150"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:151"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:152"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:153"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:154"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:155"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:156"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:157"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:86"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:158"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:159"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:160"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:161"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:162"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:163"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:164"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:165"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:166"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:167"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:87"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:168"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:169"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:170"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:171"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:172"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:173"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:174"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:175"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:176"
|
||||
UsedLibraryUrn="urn:adsk.eagle:library:177"
|
||||
UsedLibrary="/Users/chris.l/Dropbox/Eagle/lbr/MCP1825.lbr"
|
||||
UsedLibrary="/Users/chris.l/Dropbox/Eagle/SynchroClock/SynchroClock.lbr"
|
||||
UsedLibrary="/Users/chris.l/Dropbox/Eagle/lbr/SparkFun-Eagle-Libraries/SparkFun-Connectors.lbr"
|
||||
UsedLibrary="ESPNTPServer.lbr"
|
||||
|
||||
[Win_1]
|
||||
Type="Control Panel"
|
||||
Number=0
|
||||
|
||||
[Desktop]
|
||||
Screen="1680 1050"
|
||||
Window="Win_1"
|
||||
BIN
enclosure/Bottom-0.5v33.stl
Normal file
BIN
enclosure/Bottom-0.5v33.stl
Normal file
Binary file not shown.
BIN
enclosure/Top-0.5v33.stl
Normal file
BIN
enclosure/Top-0.5v33.stl
Normal file
Binary file not shown.
1
hardware/esp8266com/esp8266
Submodule
1
hardware/esp8266com/esp8266
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 9c5c16e9c8d90c3bd21a756c3a1487f3826b6e24
|
||||
BIN
images/ESPNTPServer.png
Normal file
BIN
images/ESPNTPServer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
BIN
images/closed.png
Normal file
BIN
images/closed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 MiB |
BIN
images/open.png
Normal file
BIN
images/open.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 MiB |
1
libraries/ArduinoJson
Submodule
1
libraries/ArduinoJson
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7b229e4c3810c65fc3c5620a42fc3f934d7f1b59
|
||||
1
libraries/DLog
Submodule
1
libraries/DLog
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 733b67f7c650e5f6652172b7194b3044d8d73ee4
|
||||
1
libraries/DLogNet
Submodule
1
libraries/DLogNet
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 26fd5f194b978ae19b5726022410b9cc86cfeb1d
|
||||
1
libraries/ESPAsyncUDP
Submodule
1
libraries/ESPAsyncUDP
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit b592ac6e93e9dbfd61db70ce80dcd04a2afcc76a
|
||||
1
libraries/MicroNMEA
Submodule
1
libraries/MicroNMEA
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 87d5508cc105be222cc62f090742b2b26ea580bc
|
||||
1
libraries/Syslog
Submodule
1
libraries/Syslog
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 9f1a2506b38e49312f2b353559ef4eca11616975
|
||||
1
libraries/WiFiManager
Submodule
1
libraries/WiFiManager
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 2d194ea518e22424d12418d8a7b36ff4406dec5c
|
||||
1
libraries/esp8266-oled-ssd1306
Submodule
1
libraries/esp8266-oled-ssd1306
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ca4e8b7d2e7062475686181cc01251bffa67dcce
|
||||
Loading…
Reference in New Issue
Block a user