Compare commits
10 Commits
8c1a403008
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 239665559f | |||
| 98888215e9 | |||
| 98078e7517 | |||
| 7c53fd81b4 | |||
| 2ece05505f | |||
| a81d497dcc | |||
|
|
a0825b629e | ||
|
|
4597350845 | ||
|
|
c47c37a891 | ||
|
|
74543a99f8 |
@@ -0,0 +1,2 @@
|
||||
[InternetShortcut]
|
||||
URL=https://github.com/sparkfun/Zio-Qwiic-Soil-Moisture-Sensor/blob/master/Firmware/Qwiic_Soil_Moisture_Sensor_Gateway_Firmware/Qwiic_Soil_Moisture_Firmware/Qwiic_Soil_Moisture_Firmware.ino
|
||||
392
Firmware/CustomHandlers.cpp
Normal file
@@ -0,0 +1,392 @@
|
||||
//
|
||||
//
|
||||
#include "CustomHandlers.h"
|
||||
#include "WiFiStateHandler.h"
|
||||
|
||||
// General Purpose helper stuff
|
||||
|
||||
// Handlers
|
||||
|
||||
void HandleNotFound() {
|
||||
bool found = false;
|
||||
const DirEntry *de = Directory;
|
||||
Serial.printf("No Custom Handler for '%s'\n", server.uri().c_str()+1);
|
||||
while (de->Filename) {
|
||||
Serial.printf("test for '%s' with '%s'\n", de->Filename, server.uri().c_str()+1);
|
||||
#if 0
|
||||
if (0 == strcmp(server.uri().c_str()+1, de->Filename)) {
|
||||
Serial.printf("send '%s' (%i B) as '%s'\n", de->Filename, de->Filesize, de->Filetype);
|
||||
server.send_P(200, de->Filetype, (const char *)de->Filedata, de->Filesize);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
de++;
|
||||
}
|
||||
if (!found) {
|
||||
Serial.printf("!found '%s' - redirect to home\n", server.uri().c_str());
|
||||
server.sendHeader("Location", "/", true);
|
||||
server.send(302, "text/plain", "Not supported. Heading for home.");
|
||||
}
|
||||
}
|
||||
|
||||
void HandleMyIP_js() {
|
||||
server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
|
||||
String message = "var mySite = 'http://";
|
||||
message += String(WiFi.localIP()[0]);
|
||||
message += "." + String(WiFi.localIP()[1]);
|
||||
message += "." + String(WiFi.localIP()[2]);
|
||||
message += "." + String(WiFi.localIP()[3]);
|
||||
message += "';\n";
|
||||
server.send(200, "text/javascript", message);
|
||||
}
|
||||
|
||||
|
||||
void HandleRootPage() {
|
||||
if (server.hasArg("SW")) {
|
||||
String newState = server.arg("SW");
|
||||
if (newState == "1") {
|
||||
// @todo SetCircuit(CMD_On);
|
||||
Serial.printf("SW 1\n");
|
||||
} else if (newState == "0") {
|
||||
// @todo SetCircuit(CMD_Off);
|
||||
Serial.printf("SW 0\n");
|
||||
} else if (newState == "2") {
|
||||
// @todo SetCircuit(CMD_Toggle);
|
||||
Serial.printf("SW 2\n");
|
||||
} else {
|
||||
Serial.printf("SW %s ???\n", newState.c_str());
|
||||
; // no action
|
||||
}
|
||||
}
|
||||
// @todo String modeText = (isStationMode) ? "Station mode<br/>" : "Access Point mode<br/>";
|
||||
// @todo String status = GetCircuitStatus() ? "On<br/>" : "Off<br/>";
|
||||
String myIP = String(WiFi.localIP()[0]);
|
||||
myIP += "." + String(WiFi.localIP()[1]);
|
||||
myIP += "." + String(WiFi.localIP()[2]);
|
||||
myIP += "." + String(WiFi.localIP()[3]);
|
||||
server.send_P(200, "text/html", (const char *)index_htm);
|
||||
}
|
||||
|
||||
static String EncType_str(uint8_t encType) {
|
||||
switch (encType) {
|
||||
case ENC_TYPE_NONE:
|
||||
return "open";
|
||||
break;
|
||||
case ENC_TYPE_WEP:
|
||||
return "wep";
|
||||
break;
|
||||
case ENC_TYPE_TKIP:
|
||||
return "wpa psk";
|
||||
break;
|
||||
case ENC_TYPE_CCMP:
|
||||
return "wpa2 psk";
|
||||
break;
|
||||
case ENC_TYPE_AUTO:
|
||||
return "wpa wpa2 psk";
|
||||
break;
|
||||
default:
|
||||
return "unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleAPScan() {
|
||||
// WiFi.scanNetworks will return the number of networks found
|
||||
Serial.println("Scan ...");
|
||||
int n = WiFi.scanNetworks(false, true); // blocking call and show hidden.
|
||||
Serial.println("scan done.");
|
||||
if (n == 0) {
|
||||
Serial.println("no networks found");
|
||||
} else {
|
||||
Serial.print(n);
|
||||
Serial.println(" networks found");
|
||||
server.sendContent_P("HTTP/1.1 200 OK\r\n");
|
||||
server.sendContent_P("Content-Type: text/html\r\n");
|
||||
server.sendContent_P("\r\n");
|
||||
server.sendContent_P(
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head><title>Grow Controller - Scan</title></head>\n"
|
||||
"<body>\n"
|
||||
"<h1>Grow Controller - Scan</h1>"
|
||||
);
|
||||
|
||||
server.sendContent_P(
|
||||
" <form action=\"/config\">\n"
|
||||
" <blockquote>\n"
|
||||
" <table width='800' border='0'>\n"
|
||||
" <tr bgcolor='#E0E0E0'><td colspan='2'>Net</td><td>RSSI</td><td>SSID</td><td>BSSID</td><td>Encryption</td><td>Channel</td><td>Hidden</td></tr>\n"
|
||||
);
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
// Select, Network #, RSSI, SSID, BSSID, Channel, Hidden
|
||||
String bgcolor = (i & 1) ? "#E0E0E0" : "#FFFFFF";
|
||||
String record =
|
||||
" <tr bgcolor='" + bgcolor + "'><td><input type='radio' name='ssid' value='" + WiFi.SSID(i) + "'></td>\n"
|
||||
+ " <td>" + (i + 1) + "</td>\n"
|
||||
+ " <td>" + WiFi.RSSI(i) + "</td>\n"
|
||||
+ " <td>" + WiFi.SSID(i) + "<br/>"
|
||||
+ " <img src='/green1x1.png' width='" + String(5 * (100 + WiFi.RSSI(i))) + "' height='3'></td>\n"
|
||||
+ " <td>" + WiFi.BSSIDstr(i) + "</td>\n";
|
||||
|
||||
record += " <td>" + EncType_str(WiFi.encryptionType(i)) + "</td>\n";
|
||||
record += " <td>" + String(WiFi.channel(i));
|
||||
record += "</td>\n";
|
||||
record += WiFi.isHidden(i)
|
||||
? " <td>Yes</td>\n"
|
||||
: " <td>No</td>\n";
|
||||
record += " </tr>\n";
|
||||
server.sendContent(record);
|
||||
//
|
||||
Serial.print(i + 1);
|
||||
Serial.print(": ");
|
||||
Serial.print(WiFi.SSID(i));
|
||||
Serial.print(" (");
|
||||
Serial.print(WiFi.RSSI(i));
|
||||
Serial.print(")");
|
||||
Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
|
||||
}
|
||||
server.sendContent_P(
|
||||
" <tr><td> </td>\n"
|
||||
" <td colspan='7'>\n"
|
||||
" <input type=\"submit\" value=\"Select\" />\n"
|
||||
" <input type=\"reset\"/>\n"
|
||||
" </td>\n"
|
||||
" </tr>\n"
|
||||
" </table>\n"
|
||||
" </blockquote>\n"
|
||||
" </form>\n"
|
||||
"NAV: "
|
||||
" <a href='/'>Home</a> | "
|
||||
" <a href='/config'>Config</a> | "
|
||||
" <a href='/scan'>Scan</a> | "
|
||||
" <a href='/rssi'>RSSI</a> | "
|
||||
" <a href='/curr'>Current</a> | "
|
||||
" <a href='/config?ssid=reset&pass=reset' onclick=\"return confirm('Are you sure?')\">Factory Reset</a> | "
|
||||
" <a href='/about'>About</a>\n"
|
||||
" <br/>\n"
|
||||
"</body>\n"
|
||||
"</html>\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleAPConfigPage() {
|
||||
String name = wifiConfig.getName();
|
||||
String ssid = wifiConfig.getSSID();
|
||||
String pass = wifiConfig.getPassword();
|
||||
String url = wifiConfig.getURL();
|
||||
String ntp = wifiConfig.getNTPServerName();
|
||||
|
||||
// Handle submissions from the client
|
||||
if (server.hasArg("ssid") && server.hasArg("pass")) {
|
||||
String _ssid = server.hasArg("_ssid") ? server.arg("_ssid") : "";
|
||||
String _pass = server.hasArg("_pass") ? server.arg("_pass") : "";
|
||||
name = server.arg("name");
|
||||
ssid = server.arg("ssid");
|
||||
pass = server.arg("pass");
|
||||
url = server.hasArg("url") ? server.arg("url") : "";
|
||||
ntp = server.hasArg("ntp") ? server.arg("ntp") : "";
|
||||
if (ssid == "reset" && pass == "reset") {
|
||||
FactoryReset(true);
|
||||
}
|
||||
wifiConfig.setName(name);
|
||||
wifiConfig.setSSID(ssid);
|
||||
wifiConfig.setPassword(pass);
|
||||
wifiConfig.setURL(url);
|
||||
wifiConfig.setNTPServerName(ntp);
|
||||
wifiConfig.save();
|
||||
Serial.println("Settings saved.");
|
||||
if (ssid != _ssid || pass != _pass) {
|
||||
// They changed stuff that requires a restart.
|
||||
server.send(200, "text/html", "Configuration Saved! Restarting in 3 sec...");
|
||||
Serial.printf("Config saved. Restarting in 3 sec . . .");
|
||||
delay(3000);
|
||||
ESP.restart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Send [updated] Configuration page to client
|
||||
//
|
||||
String modeText = (WiFiStateGet() == WFC_JoinedAP) ? "Station mode<br/>" : "Access Point mode<br/>";
|
||||
if (server.hasArg("ssid") && !server.hasArg("pass")) {
|
||||
ssid = server.arg("ssid");
|
||||
pass = "";
|
||||
Serial.println("ssid: " + ssid + ", pass: " + pass);
|
||||
} else {
|
||||
Serial.printf("name : %s\n", name.c_str());
|
||||
Serial.printf(" ssid: %s\n", ssid.c_str());
|
||||
Serial.printf(" pass: %s\n", pass.c_str());
|
||||
}
|
||||
if (server.hasArg("url"))
|
||||
url = server.arg("url");
|
||||
//if (server.hasArg("ntp"))
|
||||
// ntp = server.arg("ntp");
|
||||
server.send(200, "text/html",
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head><title>Grow Controller - Config</title>\n"
|
||||
"<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>\n"
|
||||
"<meta name='viewport' content='initial-scale=1.0, width=device-width'>\n"
|
||||
"</head>\n"
|
||||
"<body onload='NavInit();'>\n"
|
||||
"<h1>Grow Controller - Configuration</h1>"
|
||||
" <form action=\"\">\n"
|
||||
" <blockquote>\n"
|
||||
" <table border='0'>\n"
|
||||
" <tr>\n"
|
||||
" <td>Node Name</td>\n"
|
||||
" <td><input type='text' size='32' maxlength='32' name='name' value='" + name + "' /></td>\n"
|
||||
" </tr>\n"
|
||||
" <tr>\n"
|
||||
" <td>SSID</td>\n"
|
||||
" <td><input type='text' size='32' maxlength='32' name='ssid' value='" + ssid + "' /> **\n"
|
||||
" <input type='hidden' name='_ssid' value='" + ssid + "' /></td>\n"
|
||||
" </tr>\n"
|
||||
" <tr nowrap='nowrap'>\n"
|
||||
" <td>Password</td>\n"
|
||||
" <td nowrap='nowrap'><input type='password' size='32' maxlength='64' name='pass' value='" + pass + "' /> **\n"
|
||||
" <input type='hidden' name='_pass' value='" + pass + "' /></td>\n"
|
||||
" </tr>\n"
|
||||
" <tr>\n"
|
||||
" <td>Update URL</td>\n"
|
||||
" <td><input type='text' size='32' maxlength='64' name='url' value='" + url + "' /></td>\n"
|
||||
" </tr>\n"
|
||||
" <tr>\n"
|
||||
" <td>NTP Server</td>\n"
|
||||
" <td><input type=\"text\" size=\"64\" name=\"ntp\" value=\"" + ntp + "\" /></td>\n"
|
||||
" </tr>\n"
|
||||
" <tr>\n"
|
||||
" <td> </td>\n"
|
||||
" <td>\n"
|
||||
" <input type='submit' value='Save' />\n"
|
||||
" <input type='reset'/> ** Changes to these will trigger a module restart.\n"
|
||||
" </td>\n"
|
||||
" </tr>\n"
|
||||
" <tr>\n"
|
||||
" <td colspan='2'><hr/></td>\n"
|
||||
" </tr>\n"
|
||||
" <tr>\n"
|
||||
" <td> </td>\n"
|
||||
" <td><a href='/swupdatecheck'>Check for SW update (module will restart if updated)</a></td/>\n"
|
||||
" </tr>\n"
|
||||
" </table>\n"
|
||||
" </blockquote>\n"
|
||||
" </form>\n"
|
||||
"<span id='nav'></span>\n"
|
||||
"</body>\n"
|
||||
"</html>\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ###################################################################
|
||||
//
|
||||
// Old handlers, for 'static' information that needs to be send to
|
||||
// build a web page.
|
||||
//
|
||||
// This is to be obsoleted by the new method at the top of this file.
|
||||
//
|
||||
// ###################################################################
|
||||
|
||||
|
||||
void HandlePlantModel() {
|
||||
Serial.printf("PlantModel\n");
|
||||
server.send_P(200, "image/png", plantmodel_png, sizeof(plantmodel_png));
|
||||
}
|
||||
void HandlePlantModel_css() {
|
||||
server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
|
||||
server.send_P(200, "text/css", plantmodel_css);
|
||||
}
|
||||
void HandleButton_css() {
|
||||
server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
|
||||
server.send_P(200, "text/css", button_css);
|
||||
}
|
||||
void HandleIndex_js() {
|
||||
server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
|
||||
server.send_P(200, "text/javascript", index_js);
|
||||
}
|
||||
void HandleAbout_htm() {
|
||||
server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
|
||||
server.send_P(200, "text/html", about_htm);
|
||||
}
|
||||
void HandleAbout_js() {
|
||||
server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
|
||||
server.send_P(200, "text/javascript", about_js);
|
||||
}
|
||||
void HandleFavIcon() {
|
||||
Serial.printf("favicon.ico\n");
|
||||
server.send_P(200, "image/x-icon", favicon_ico, sizeof(favicon_ico));
|
||||
}
|
||||
void HandleIcon() {
|
||||
Serial.printf("icon.png\n");
|
||||
server.send_P(200, "image/png", icon_png, sizeof(icon_png));
|
||||
}
|
||||
void HandleOpenDoor() {
|
||||
Serial.printf("open.png\n");
|
||||
server.send_P(200, "image/png", open_png, sizeof(open_png));
|
||||
}
|
||||
void HandleGreen1x1() {
|
||||
Serial.printf("green1x1.png\n");
|
||||
server.send_P(200, "image/png", green1x1_png, sizeof(green1x1_png));
|
||||
}
|
||||
void HandleHeaterOn() {
|
||||
Serial.printf("soilheater_on.png\n");
|
||||
server.send_P(200, "image/png", soilheater_on_png, sizeof(soilheater_on_png));
|
||||
}
|
||||
void HandleHeaterOff() {
|
||||
Serial.printf("soilheater_off.png\n");
|
||||
server.send_P(200, "image/png", soilheater_off_png, sizeof(soilheater_off_png));
|
||||
}
|
||||
void HandleThermometer() {
|
||||
Serial.printf("thermometer.png\n");
|
||||
server.send_P(200, "image/png", thermometer_png, sizeof(thermometer_png));
|
||||
}
|
||||
void HandleSoilMoisture() {
|
||||
Serial.printf("soilmoisture.png\n");
|
||||
server.send_P(200, "image/png", soilmoisture_png, sizeof(soilmoisture_png));
|
||||
}
|
||||
void HandlePointer() {
|
||||
Serial.printf("pointer.png\n");
|
||||
server.send_P(200, "image/png", pointer_png, sizeof(pointer_png));
|
||||
}
|
||||
void HandleWater() {
|
||||
Serial.printf("water.png\n");
|
||||
server.send_P(200, "image/png", water_png, sizeof(water_png));
|
||||
}
|
||||
void HandleRSSIPage() {
|
||||
server.send_P(200, "text/html", rssi_htm);
|
||||
}
|
||||
void HandleRSSI_js() {
|
||||
server.send_P(200, "text/javascript", rssi_js);
|
||||
}
|
||||
void HandleCurrPage() {
|
||||
server.send_P(200, "text/html", curr_htm);
|
||||
}
|
||||
void HandleCurr_js() {
|
||||
server.send_P(200, "text/javascript", curr_js);
|
||||
}
|
||||
void HandleNav_js() {
|
||||
server.send_P(200, "text/javascript", nav_js);
|
||||
}
|
||||
void HandleSWUpdateCheck() {
|
||||
updateCheck = true;
|
||||
HandleAPConfigPage();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void HandleCircuitOn() {
|
||||
//SetCircuit(CMD_On);
|
||||
HandleGetState(); // Reply with current state
|
||||
}
|
||||
void HandleCircuitOff() {
|
||||
//SetCircuit(CMD_Off);
|
||||
HandleGetState(); // Reply with current state
|
||||
}
|
||||
void HandleCircuitToggle() {
|
||||
//SetCircuit(CMD_Toggle);
|
||||
HandleGetState(); // Reply with current state
|
||||
}
|
||||
#endif
|
||||
59
Firmware/CustomHandlers.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
//
|
||||
// Custom Web Page Handlers
|
||||
//
|
||||
// For accepting and processing arguments, or for custom page
|
||||
// generation.
|
||||
//
|
||||
#ifndef CUSTOMHANDERS_H
|
||||
#define CUSTOMHANDERS_H
|
||||
|
||||
#include "ProjGlobals.h"
|
||||
#include "Web_Resources.h"
|
||||
|
||||
/// If a URI does not have a custom handler hook, it will scan the file system for the target resource.
|
||||
/// Only if it is then not found will it try to redirect the user to the main page.
|
||||
///
|
||||
void HandleNotFound();
|
||||
|
||||
///
|
||||
/// For all of the following, there is actively generated content on the page,
|
||||
/// so it must have a custom handler.
|
||||
///
|
||||
void HandleRootPage();
|
||||
void HandleMyIP_js();
|
||||
void HandleAPConfigPage();
|
||||
|
||||
void HandlePlantModel();
|
||||
|
||||
|
||||
void HandleAPScan();
|
||||
void HandlePlantModel();
|
||||
void HandlePlantModel_css();
|
||||
void HandleButton_css();
|
||||
void HandleIndex_js();
|
||||
void HandleAbout_htm();
|
||||
void HandleAbout_js();
|
||||
void HandleCircuitOn();
|
||||
void HandleCircuitOff();
|
||||
void HandleCircuitToggle();
|
||||
void HandleSWUpdateCheck();
|
||||
void HandleFavIcon();
|
||||
void HandleIcon();
|
||||
void HandleOpenDoor();
|
||||
void HandleGreen1x1();
|
||||
void HandleFavIcon();
|
||||
void HandleHeaterOn();
|
||||
void HandleWater();
|
||||
void HandleRSSIPage();
|
||||
void HandleRSSI_js();
|
||||
void HandleCurrPage();
|
||||
void HandleCurr_js();
|
||||
void HandleNav_js();
|
||||
void HandleHeaterOn();
|
||||
void HandleHeaterOff();
|
||||
void HandleThermometer();
|
||||
void HandleSoilMoisture();
|
||||
void HandlePointer();
|
||||
|
||||
#endif // CUSTOMHANDERS_H
|
||||
146
Firmware/DNSServer.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include "./DNSServer.h"
|
||||
#include <lwip/def.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG
|
||||
#define DEBUG_OUTPUT Serial
|
||||
|
||||
DNSServer::DNSServer() {
|
||||
_ttl = htonl(60);
|
||||
_errorReplyCode = DNSReplyCode::NonExistentDomain;
|
||||
}
|
||||
|
||||
bool DNSServer::start(const uint16_t &port, const String &domainName,
|
||||
const IPAddress &resolvedIP) {
|
||||
_port = port;
|
||||
_domainName = domainName;
|
||||
_resolvedIP[0] = resolvedIP[0];
|
||||
_resolvedIP[1] = resolvedIP[1];
|
||||
_resolvedIP[2] = resolvedIP[2];
|
||||
_resolvedIP[3] = resolvedIP[3];
|
||||
downcaseAndRemoveWwwPrefix(_domainName);
|
||||
return _udp.begin(_port) == 1;
|
||||
}
|
||||
|
||||
void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode) {
|
||||
_errorReplyCode = replyCode;
|
||||
}
|
||||
|
||||
void DNSServer::setTTL(const uint32_t &ttl) {
|
||||
_ttl = htonl(ttl);
|
||||
}
|
||||
|
||||
void DNSServer::stop() {
|
||||
_udp.stop();
|
||||
}
|
||||
|
||||
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName) {
|
||||
domainName.toLowerCase();
|
||||
domainName.replace("www.", "");
|
||||
}
|
||||
|
||||
void DNSServer::processNextRequest() {
|
||||
_currentPacketSize = _udp.parsePacket();
|
||||
if (_currentPacketSize) {
|
||||
_buffer = (unsigned char*) malloc(_currentPacketSize * sizeof(char));
|
||||
if (_buffer == NULL) {
|
||||
Serial.printf("ERROR in %s line %d\n", __FILE__, __LINE__);
|
||||
} else {
|
||||
_udp.read(_buffer, _currentPacketSize);
|
||||
_dnsHeader = (DNSHeader*) _buffer;
|
||||
|
||||
if (_dnsHeader->QR == DNS_QR_QUERY &&
|
||||
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
|
||||
requestIncludesOnlyOneQuestion() &&
|
||||
(_domainName == "*" || getDomainNameWithoutWwwPrefix() == _domainName)
|
||||
) {
|
||||
replyWithIP();
|
||||
} else if (_dnsHeader->QR == DNS_QR_QUERY) {
|
||||
replyWithCustomCode();
|
||||
}
|
||||
}
|
||||
free(_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool DNSServer::requestIncludesOnlyOneQuestion() {
|
||||
return ntohs(_dnsHeader->QDCount) == 1 &&
|
||||
_dnsHeader->ANCount == 0 &&
|
||||
_dnsHeader->NSCount == 0 &&
|
||||
_dnsHeader->ARCount == 0;
|
||||
}
|
||||
|
||||
String DNSServer::getDomainNameWithoutWwwPrefix() {
|
||||
String parsedDomainName = "";
|
||||
unsigned char *start = _buffer + 12;
|
||||
if (*start == 0) {
|
||||
return parsedDomainName;
|
||||
}
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
unsigned char labelLength = *(start + pos);
|
||||
for (int i = 0; i < labelLength; i++) {
|
||||
pos++;
|
||||
parsedDomainName += (char)*(start + pos);
|
||||
}
|
||||
pos++;
|
||||
if (*(start + pos) == 0) {
|
||||
downcaseAndRemoveWwwPrefix(parsedDomainName);
|
||||
return parsedDomainName;
|
||||
} else {
|
||||
parsedDomainName += ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DNSServer::replyWithIP() {
|
||||
_dnsHeader->QR = DNS_QR_RESPONSE;
|
||||
_dnsHeader->ANCount = _dnsHeader->QDCount;
|
||||
_dnsHeader->QDCount = _dnsHeader->QDCount;
|
||||
//_dnsHeader->RA = 1;
|
||||
|
||||
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
||||
_udp.write(_buffer, _currentPacketSize);
|
||||
|
||||
_udp.write((uint8_t) 192); // answer name is a pointer
|
||||
_udp.write((uint8_t) 12); // pointer to offset at 0x00c
|
||||
|
||||
_udp.write((uint8_t) 0); // 0x0001 answer is type A query (host address)
|
||||
_udp.write((uint8_t) 1);
|
||||
|
||||
_udp.write((uint8_t) 0); //0x0001 answer is class IN (internet address)
|
||||
_udp.write((uint8_t) 1);
|
||||
|
||||
_udp.write((unsigned char*) &_ttl, 4);
|
||||
|
||||
// Length of RData is 4 bytes (because, in this case, RData is IPv4)
|
||||
_udp.write((uint8_t) 0);
|
||||
_udp.write((uint8_t) 4);
|
||||
_udp.write(_resolvedIP, sizeof(_resolvedIP));
|
||||
_udp.endPacket();
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
DEBUG_OUTPUT.print("DNS responds: ");
|
||||
DEBUG_OUTPUT.print(_resolvedIP[0]);
|
||||
DEBUG_OUTPUT.print(".");
|
||||
DEBUG_OUTPUT.print(_resolvedIP[1]);
|
||||
DEBUG_OUTPUT.print(".");
|
||||
DEBUG_OUTPUT.print(_resolvedIP[2]);
|
||||
DEBUG_OUTPUT.print(".");
|
||||
DEBUG_OUTPUT.print(_resolvedIP[3]);
|
||||
DEBUG_OUTPUT.print(" for ");
|
||||
DEBUG_OUTPUT.println(getDomainNameWithoutWwwPrefix());
|
||||
#endif
|
||||
}
|
||||
|
||||
void DNSServer::replyWithCustomCode() {
|
||||
_dnsHeader->QR = DNS_QR_RESPONSE;
|
||||
_dnsHeader->RCode = (unsigned char) _errorReplyCode;
|
||||
_dnsHeader->QDCount = 0;
|
||||
|
||||
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
||||
_udp.write(_buffer, sizeof(DNSHeader));
|
||||
_udp.endPacket();
|
||||
}
|
||||
68
Firmware/DNSServer.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef DNSServer_h
|
||||
#define DNSServer_h
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#define DNS_QR_QUERY 0
|
||||
#define DNS_QR_RESPONSE 1
|
||||
#define DNS_OPCODE_QUERY 0
|
||||
|
||||
enum class DNSReplyCode {
|
||||
NoError = 0,
|
||||
FormError = 1,
|
||||
ServerFailure = 2,
|
||||
NonExistentDomain = 3,
|
||||
NotImplemented = 4,
|
||||
Refused = 5,
|
||||
YXDomain = 6,
|
||||
YXRRSet = 7,
|
||||
NXRRSet = 8
|
||||
};
|
||||
|
||||
struct DNSHeader {
|
||||
uint16_t ID; // identification number
|
||||
unsigned char RD : 1; // recursion desired
|
||||
unsigned char TC : 1; // truncated message
|
||||
unsigned char AA : 1; // authoritive answer
|
||||
unsigned char OPCode : 4; // message_type
|
||||
unsigned char QR : 1; // query/response flag
|
||||
unsigned char RCode : 4; // response code
|
||||
unsigned char Z : 3; // its z! reserved
|
||||
unsigned char RA : 1; // recursion available
|
||||
uint16_t QDCount; // number of question entries
|
||||
uint16_t ANCount; // number of answer entries
|
||||
uint16_t NSCount; // number of authority entries
|
||||
uint16_t ARCount; // number of resource entries
|
||||
};
|
||||
|
||||
class DNSServer {
|
||||
public:
|
||||
DNSServer();
|
||||
void processNextRequest();
|
||||
void setErrorReplyCode(const DNSReplyCode &replyCode);
|
||||
void setTTL(const uint32_t &ttl);
|
||||
|
||||
// Returns true if successful, false if there are no sockets available
|
||||
bool start(const uint16_t &port,
|
||||
const String &domainName,
|
||||
const IPAddress &resolvedIP);
|
||||
// stops the DNS server
|
||||
void stop();
|
||||
|
||||
private:
|
||||
WiFiUDP _udp;
|
||||
uint16_t _port;
|
||||
String _domainName;
|
||||
unsigned char _resolvedIP[4];
|
||||
int _currentPacketSize;
|
||||
unsigned char* _buffer;
|
||||
DNSHeader* _dnsHeader;
|
||||
uint32_t _ttl;
|
||||
DNSReplyCode _errorReplyCode;
|
||||
|
||||
void downcaseAndRemoveWwwPrefix(String &domainName);
|
||||
String getDomainNameWithoutWwwPrefix();
|
||||
bool requestIncludesOnlyOneQuestion();
|
||||
void replyWithIP();
|
||||
void replyWithCustomCode();
|
||||
};
|
||||
#endif // DNSServer_h
|
||||
144
Firmware/Firmware.ino
Normal file
@@ -0,0 +1,144 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266SSDP.h>
|
||||
|
||||
#include "ProjGlobals.h" // Some global settings
|
||||
#include "WiFiConfiguration.h" //
|
||||
#include "WiFiStateHandler.h" // Startup as AP or client and transition
|
||||
#include "CustomHandlers.h" // Handlers for the web pages
|
||||
#include "PlantModel.h" // The Plant Model controller/simulator/status
|
||||
|
||||
const String AP_NAME = "GrowController"; ///< Network name when in Access Point mode
|
||||
const String AP_VERS = "v1.00.11"; ///< Compared to the server version for SW Updates
|
||||
|
||||
ESP8266WebServer server(80);
|
||||
ConfigManager wifiConfig; ///< Track various configuration items
|
||||
|
||||
//ESP8266HTTPUpdate Updater;
|
||||
bool updateCheck = false; ///< Set when a SW update check is pending
|
||||
|
||||
|
||||
// Register the urls with custom handlers
|
||||
// Register the SSDP interface
|
||||
//
|
||||
void StartWebServer();
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.printf("\n");
|
||||
Serial.printf("\n******************************************************************\n");
|
||||
Serial.printf(" %s Web Server - Build " __DATE__ " " __TIME__ "\n", AP_NAME.c_str());
|
||||
Serial.printf(" Version %s\n", AP_VERS.c_str());
|
||||
Serial.printf(" Copyright (c) 2021 by Smartware Computing, all rights reserved.\n");
|
||||
Serial.printf("******************************************************************\n");
|
||||
wifiConfig.load();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop() {
|
||||
//
|
||||
// Process WiFi State Changes
|
||||
//
|
||||
static WiFiConnectState lastState = WFC_Idle;
|
||||
WiFiConnectState currState = WiFiStateHandler();
|
||||
if (lastState != currState) {
|
||||
lastState = currState;
|
||||
switch (currState) { // On change to this state
|
||||
default:
|
||||
break;
|
||||
case WFC_HostingAP:
|
||||
case WFC_JoinedAP:
|
||||
StartWebServer();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (currState) {
|
||||
default:
|
||||
break;
|
||||
case WFC_HostingAP:
|
||||
case WFC_JoinedAP:
|
||||
server.handleClient();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
simulation();
|
||||
// @todo delay(1);
|
||||
}
|
||||
|
||||
void StartWebServer() {
|
||||
// path /firmware
|
||||
Serial.println("HTTP server starting ...");
|
||||
//httpUpdater.setup(&server, update_path, update_username, update_password);
|
||||
server.on("/", HandleRootPage);
|
||||
server.on("/config", HandleAPConfigPage);
|
||||
server.on("/myip.js", HandleMyIP_js);
|
||||
server.on("/nav.js", HandleNav_js);
|
||||
server.on("/plantmodel.png", HandlePlantModel);
|
||||
server.on("/plantmodel.css", HandlePlantModel_css);
|
||||
server.on("/button.css", HandleButton_css);
|
||||
server.on("/index.js", HandleIndex_js);
|
||||
server.on("/about.htm", HandleAbout_htm);
|
||||
server.on("/about.js", HandleAbout_js);
|
||||
server.on("/favicon.ico", HandleFavIcon);
|
||||
server.on("/soilheater_on.png", HandleHeaterOn);
|
||||
server.on("/soilheater_off.png", HandleHeaterOff);
|
||||
server.on("/thermometer.png", HandleThermometer);
|
||||
server.on("/soilmoisture.png", HandleSoilMoisture);
|
||||
server.on("/pointer.png", HandlePointer);
|
||||
server.on("/water.png", HandleWater);
|
||||
server.on("/green1x1.png", HandleGreen1x1);
|
||||
server.on("/rssi.htm", HandleRSSIPage);
|
||||
server.on("/rssi.js", HandleRSSI_js);
|
||||
server.on("/curr.htm", HandleCurrPage);
|
||||
server.on("/curr.js", HandleCurr_js);
|
||||
server.on("/icon.png", HandleIcon);
|
||||
server.on("/open.png", HandleOpenDoor);
|
||||
server.on("/swupdatecheck", HandleSWUpdateCheck);
|
||||
server.on("/scan", HandleAPScan);
|
||||
//server.on("/on", HandleCircuitOn);
|
||||
//server.on("/off", HandleCircuitOff);
|
||||
//server.on("/toggle", HandleCircuitToggle);
|
||||
server.on("/state", HandleGetState);
|
||||
server.on("/description.xml", HTTP_GET, []() {
|
||||
Serial.printf("description.xml handler.\n");
|
||||
SSDP.schema(server.client());
|
||||
});
|
||||
server.onNotFound(HandleNotFound);
|
||||
server.begin();
|
||||
Serial.println("HTTP server started.");
|
||||
|
||||
//
|
||||
// SSDP Startup
|
||||
//
|
||||
Serial.printf("SSDP server starting ...\n");
|
||||
SSDP.setSchemaURL("description.xml");
|
||||
SSDP.setHTTPPort(80);
|
||||
SSDP.setName(wifiConfig.getName().c_str()); // "Philips hue clone");
|
||||
SSDP.setSerialNumber("001788102201");
|
||||
SSDP.setURL("/"); // Root Page
|
||||
SSDP.setModelName(AP_NAME.c_str()); // "Philips hue bridge 2012");
|
||||
SSDP.setModelNumber("929000226503");
|
||||
SSDP.setModelURL("https://www.smart-family.net/GrowController");
|
||||
SSDP.setManufacturer("Smartware Computing");
|
||||
SSDP.setManufacturerURL("https://www.smart-family.net");
|
||||
SSDP.setDeviceType("upnp:rootdevice");
|
||||
SSDP.begin();
|
||||
Serial.println("SSDP server started.");
|
||||
}
|
||||
|
||||
void FactoryReset(bool forceRestart) {
|
||||
Serial.println("Factory Reset Configuration...\n");
|
||||
wifiConfig.factoryReset();
|
||||
wifiConfig.save();
|
||||
if (forceRestart) {
|
||||
Serial.println("Restart in 3 sec ...");
|
||||
delay(3000);
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
34
Firmware/Firmware.ses
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<NotepadPlus>
|
||||
<Session activeView="0">
|
||||
<mainView activeIndex="18">
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="968" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Web_Resources.h" backupFilePath="" originalFileLastModifTimestamp="-1740723406" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1139802112" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="8" xOffset="0" scrollWidth="968" startPos="1055" endPos="1055" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\WifiConfiguration.cpp" backupFilePath="" originalFileLastModifTimestamp="-1744253404" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="512" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="164" xOffset="0" scrollWidth="840" startPos="6208" endPos="6208" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\WiFiConfiguration.h" backupFilePath="" originalFileLastModifTimestamp="-1740783399" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="512" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="34" xOffset="0" scrollWidth="800" startPos="1339" endPos="1339" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\WiFiStateHandler.cpp" backupFilePath="" originalFileLastModifTimestamp="-1740693408" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1139802112" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="6" xOffset="0" scrollWidth="568" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\WiFiStateHandler.h" backupFilePath="" originalFileLastModifTimestamp="-1744853417" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1139802112" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="816" startPos="37" endPos="37" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\CustomHandlers.cpp" backupFilePath="" originalFileLastModifTimestamp="-1740813409" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="61" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="21" xOffset="0" scrollWidth="824" startPos="1410" endPos="1410" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\CustomHandlers.h" backupFilePath="" originalFileLastModifTimestamp="-1744983407" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="477" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="57" xOffset="0" scrollWidth="896" startPos="2588" endPos="2604" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Firmware.ino" backupFilePath="" originalFileLastModifTimestamp="-1745163414" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="793" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="147" xOffset="0" scrollWidth="896" startPos="5800" endPos="5800" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\PlantModel.cpp" backupFilePath="" originalFileLastModifTimestamp="-1745073400" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1273" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="192" startPos="156" endPos="156" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\PlantModel.h" backupFilePath="" originalFileLastModifTimestamp="-1744383409" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="308" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="38" xOffset="0" scrollWidth="952" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\ProjGlobals.h" backupFilePath="" originalFileLastModifTimestamp="-1744703417" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="67" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="552" startPos="469" endPos="469" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Utility.cpp" backupFilePath="" originalFileLastModifTimestamp="-1744533396" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1588" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="968" startPos="553" endPos="553" selMode="0" offset="0" wrapCount="1" lang="C++" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Utility.h" backupFilePath="" originalFileLastModifTimestamp="-1744143406" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1351" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="1" lang="JavaScript" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\index.js" backupFilePath="" originalFileLastModifTimestamp="-1743093392" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="954" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="0" lang="JavaScript" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\myip.js" backupFilePath="" originalFileLastModifTimestamp="-1742013411" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="0" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="0" lang="JavaScript" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\nav.js" backupFilePath="" originalFileLastModifTimestamp="-1741213410" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="556" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="0" lang="JavaScript" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\rssi.js" backupFilePath="" originalFileLastModifTimestamp="-1741833407" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="538976315" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="0" lang="HTML" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\about.htm" backupFilePath="" originalFileLastModifTimestamp="-1741013423" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1035" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="736" startPos="651" endPos="651" selMode="0" offset="0" wrapCount="1" lang="HTML" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\curr.htm" backupFilePath="" originalFileLastModifTimestamp="-1740983405" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1114" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="0" lang="HTML" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\index.htm" backupFilePath="" originalFileLastModifTimestamp="-1741673407" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1194" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="0" lang="HTML" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\navigation.htm" backupFilePath="" originalFileLastModifTimestamp="-1742483431" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1819569769" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="0" lang="HTML" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\rssi.htm" backupFilePath="" originalFileLastModifTimestamp="-1740843407" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1431" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="1" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="0" lang="CSS" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\button.css" backupFilePath="" originalFileLastModifTimestamp="-1740943390" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="147" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="208" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="1" lang="CSS" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\plantmodel.css" backupFilePath="" originalFileLastModifTimestamp="-1742173407" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="227" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="0" xOffset="0" scrollWidth="512" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="1" lang="JavaScript" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\about.js" backupFilePath="" originalFileLastModifTimestamp="-1742643407" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="393" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
<File firstVisibleLine="53" xOffset="0" scrollWidth="816" startPos="0" endPos="0" selMode="0" offset="0" wrapCount="1" lang="JavaScript" encoding="-1" userReadOnly="no" filename="D:\Projects\GrowController\Firmware\Resources\curr.js" backupFilePath="" originalFileLastModifTimestamp="-1742343396" originalFileLastModifTimestampHigh="30920687" mapFirstVisibleDisplayLine="-1" mapFirstVisibleDocLine="-1" mapLastVisibleDocLine="-1" mapNbLine="-1" mapHigherPos="-1" mapWidth="-1" mapHeight="-1" mapKByteInDoc="1748" mapWrapIndentMode="-1" mapIsWrap="no" />
|
||||
</mainView>
|
||||
<subView activeIndex="0" />
|
||||
</Session>
|
||||
</NotepadPlus>
|
||||
246
Firmware/PlantModel.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
//
|
||||
//
|
||||
// PlantModel
|
||||
//
|
||||
//
|
||||
|
||||
#include "ProjGlobals.h"
|
||||
#include "PlantModel.h"
|
||||
#include "WiFiStateHandler.h"
|
||||
#include "Utility.h"
|
||||
|
||||
|
||||
PlantData_T plant; /// This keeps track of everything relevant to this system
|
||||
|
||||
|
||||
String OnOffText(bool isOn) {
|
||||
if (isOn)
|
||||
return String("On");
|
||||
else
|
||||
return String("Off");
|
||||
}
|
||||
|
||||
String DrumStateText(DrumState_E state) {
|
||||
switch (state) {
|
||||
case DrumIsOpen:
|
||||
return String("Open");
|
||||
case DrumIsClosed:
|
||||
return String("Closed");
|
||||
case DrumIsMoving:
|
||||
return String("Moving");
|
||||
default:
|
||||
return String("Error");
|
||||
}
|
||||
}
|
||||
|
||||
String DrumMotorText(DrumMotor_E state) {
|
||||
switch (state) {
|
||||
case DrumOff:
|
||||
return String("Stopped");
|
||||
case DrumCW:
|
||||
return String("CW Rotation");
|
||||
case DrumCCW:
|
||||
return String("CCW Rotation");
|
||||
default:
|
||||
return String("Error");
|
||||
}
|
||||
}
|
||||
|
||||
String DrumOpenText(bool isOpen) {
|
||||
if (isOpen)
|
||||
return String("Open");
|
||||
else
|
||||
return String("not open");
|
||||
}
|
||||
String DrumClosedText(bool isClosed) {
|
||||
if (isClosed)
|
||||
return String("Closed");
|
||||
else
|
||||
return String("not closed");
|
||||
}
|
||||
|
||||
String WaterInTankText(bool waterInTank) {
|
||||
if (waterInTank)
|
||||
return String("OK");
|
||||
else
|
||||
return String("Empty");
|
||||
}
|
||||
|
||||
// {
|
||||
// "id": "5c:cf:7f:c0:52:82",
|
||||
// "name": "3-Way Switch",
|
||||
// "state": 0,
|
||||
// "sense": 56,
|
||||
// "ip": "192.168.1.23",
|
||||
// "rssi": "-63",
|
||||
// "countdown": "3:45",
|
||||
// "uptime": "0:11:45",
|
||||
// "wifimode": "station"|"ap"
|
||||
// }
|
||||
//
|
||||
void HandleGetState() {
|
||||
int day, hr, minute, sec;
|
||||
char _upTime[15]; // 0000.00:00:00\0 + 1 spare
|
||||
|
||||
sec = millis() / 1000;
|
||||
minute = sec / 60;
|
||||
hr = minute / 60;
|
||||
day = hr / 24;
|
||||
if (day)
|
||||
snprintf(_upTime, sizeof(_upTime), "%dd %d:%02d:%02d", day, hr % 24, minute % 60, sec % 60);
|
||||
else if (hr)
|
||||
snprintf(_upTime, sizeof(_upTime), "%d:%02d:%02d", hr, minute % 60, sec % 60);
|
||||
else
|
||||
snprintf(_upTime, sizeof(_upTime), "%02d:%02d", minute % 60, sec % 60);
|
||||
|
||||
String modeText = (WiFiStateGet() == WFC_JoinedAP) ? "Station" : "Access Point";
|
||||
String message = "{\n";
|
||||
message += "\t\"id\": \"" + GetMacString() + "\",\n";
|
||||
message += "\t\"name\": \"" + wifiConfig.getName() + "\",\n";
|
||||
message += "\t\"version\": \"" + AP_VERS + "\",\n";
|
||||
//message += "\t\"state\": " + String(CurrStatus) + ",\n";
|
||||
//message += "\t\"raw\": " + String(iRaw) + ",\n";
|
||||
//message += "\t\"sense\": " + String(iRawSum / AVG_RATIO) + ",\n";
|
||||
message += "\t\"ip\": \""
|
||||
+ String(WiFi.localIP()[0])
|
||||
+ "." + String(WiFi.localIP()[1])
|
||||
+ "." + String(WiFi.localIP()[2])
|
||||
+ "." + String(WiFi.localIP()[3])
|
||||
+ "\",\n";
|
||||
message += "\t\"rssi\": \"" + String(WiFi.RSSI()) + "\",\n";
|
||||
message += "\t\"uptime\": \"" + String(_upTime) + "\",\n";
|
||||
message += "\t\"wifimode\": \"" + modeText + "\",\n";
|
||||
|
||||
snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.SecondsToday/3660, (plant.SecondsToday/60)%60);
|
||||
message += "\t\"TimeOfDay\": \"" + String(_upTime) + "\",\n";
|
||||
message += "\t\"Fahrenheit\": \"" + String(plant.Fahrenheit) + "\",\n";
|
||||
|
||||
message += "\t\"ChamberTemp_C\": \"" + String(plant.ChamberTemp_C) + "\",\n";
|
||||
message += "\t\"ChamberHumi\": \"" + String(plant.ChamberHumi) + " % \",\n";
|
||||
message += "\t\"SoilHeater\": \"" + OnOffText(plant.SoilHeater) + "\",\n";
|
||||
message += "\t\"SoilTemp_C\": \"" + String(plant.SoilTemp_C) + "\",\n";
|
||||
message += "\t\"AmbientTemp_C\": \"" + String(plant.AmbientTemp_C) + "\",\n";
|
||||
message += "\t\"DrumDoorIcon\": \"" + DrumStateText(plant.DrumDoorIcon) + "\",\n";
|
||||
message += "\t\"DrumOpenSensor\": \"" + DrumOpenText(plant.DrumOpenSensor) + "\",\n";
|
||||
message += "\t\"DrumClosedSensor\": \"" + DrumClosedText(plant.DrumClosedSensor) + "\",\n";
|
||||
message += "\t\"DrumMotorStatus\": \"" + DrumMotorText(plant.DrumMotorStatus) + "\",\n";
|
||||
message += "\t\"DrumMotor_V\": \"" + String(plant.DrumMotor_V) + "\",\n";
|
||||
message += "\t\"DrumMotor_I\": \"" + String(plant.DrumMotor_I) + "\",\n";
|
||||
|
||||
snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.DrumMotorOn_sec/60, plant.DrumMotorOn_sec%60);
|
||||
message += "\t\"DrumMotorOn_sec\": \"" + String(_upTime) + "\",\n";
|
||||
message += "\t\"WaterInTank\": \"" + String(plant.WaterInTank) + "\",\n";
|
||||
message += "\t\"WaterMotor_V\": \"" + String(plant.WaterPumpStatus) + "\",\n";
|
||||
message += "\t\"SoilMoisture_X\": \"" + String(plant.SoilMoisture_X) + "\",\n";
|
||||
|
||||
snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCyclePeriod_sec/60, plant.WaterCyclePeriod_sec%60);
|
||||
message += "\t\"WaterCyclePeriod_sec\": \"" + String(_upTime) + "\",\n";
|
||||
|
||||
snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCycleOn_sec/60, plant.WaterCycleOn_sec%60);
|
||||
message += "\t\"WaterCycleOn_sec\": \"" + String(_upTime) + "\",\n";
|
||||
|
||||
snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCycle_sec/60, plant.WaterCycle_sec%60);
|
||||
message += "\t\"waterCycle\": \"" + String(_upTime) + "\"\n";
|
||||
//message += "\t\"toggle\": " + String(!digitalRead(SW_TOGGLE)) + ",\n";
|
||||
//message += "\t\"reset\": " + String(!digitalRead(SW_RESET));
|
||||
message += "}\n";
|
||||
server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
|
||||
server.send(200, "application/json", message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void simulation() {
|
||||
if (++plant.SecondsToday >= (24*3600)) { // Seconds are advancing really fast for the simulation
|
||||
plant.SecondsToday -= (24 * 3600);
|
||||
}
|
||||
static int lastMinutesToday = -1;
|
||||
int hoursToday = plant.SecondsToday / 3600;
|
||||
int minutesToday = plant.SecondsToday / 60;
|
||||
// Simulate Ambient temp rising and falling
|
||||
if (lastMinutesToday != minutesToday) {
|
||||
lastMinutesToday = minutesToday;
|
||||
//Serial.printf("%02u:%02u, Ambient %3.1f\n", hoursToday, minutesToday % 60, plant.AmbientTemp_C);
|
||||
|
||||
if (hoursToday < 15) {
|
||||
// warming part of the day
|
||||
if (plant.AmbientTemp_C < 45.0) {
|
||||
plant.AmbientTemp_C += (float)(rand() % 10)/1000.0;
|
||||
}
|
||||
} else {
|
||||
// cooling part of the day
|
||||
if (plant.AmbientTemp_C > 10.0) {
|
||||
plant.AmbientTemp_C -= (float)(rand() % 10)/1000.0;
|
||||
}
|
||||
}
|
||||
if (plant.SoilTemp_C > 40.0) {
|
||||
plant.SoilHeater = false;
|
||||
} else if (plant.SoilTemp_C < 20.0) {
|
||||
plant.SoilHeater = true;
|
||||
}
|
||||
if (plant.SoilHeater) {
|
||||
if (plant.SoilTemp_C < 50.0) {
|
||||
plant.SoilTemp_C += (float)(rand() % 10)/1000.0;
|
||||
}
|
||||
} else {
|
||||
if (plant.SoilTemp_C < plant.ChamberTemp_C) {
|
||||
plant.SoilTemp_C += (float)(rand() % 10)/1000.0;
|
||||
} else {
|
||||
plant.SoilTemp_C -= (float)(rand() % 10)/1000.0;
|
||||
}
|
||||
}
|
||||
if (plant.DrumMotorStatus == DrumCW) {
|
||||
plant.DrumMotorOn_sec++;
|
||||
} else if (plant.DrumMotorStatus == DrumCCW) {
|
||||
plant.DrumMotorOn_sec++;
|
||||
} else {
|
||||
plant.DrumMotorOn_sec = 0;
|
||||
}
|
||||
if (plant.ChamberTemp_C > 50.0) {
|
||||
if (!plant.DrumOpenSensor) {
|
||||
plant.DrumMotorStatus = DrumCW;
|
||||
if (plant.DrumMotorOn_sec > 50) {
|
||||
plant.DrumOpenSensor = true;
|
||||
plant.DrumClosedSensor = false;
|
||||
}
|
||||
}
|
||||
} else if (plant.ChamberTemp_C < 40.0) {
|
||||
if (!plant.DrumClosedSensor) {
|
||||
plant.DrumMotorStatus = DrumCW;
|
||||
if (plant.DrumMotorOn_sec > 50) {
|
||||
plant.DrumOpenSensor = false;
|
||||
plant.DrumClosedSensor = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (plant.DrumDoorIcon == DrumIsOpen) {
|
||||
if (plant.ChamberTemp_C > plant.AmbientTemp_C) {
|
||||
plant.ChamberTemp_C -= (float)(rand() % 10)/1000.0;
|
||||
} else if (plant.ChamberTemp_C < plant.AmbientTemp_C) {
|
||||
plant.ChamberTemp_C += (float)(rand() % 10)/1000.0;
|
||||
}
|
||||
} else {
|
||||
if (plant.ChamberTemp_C > plant.AmbientTemp_C) {
|
||||
plant.ChamberTemp_C -= (float)(rand() % 5)/1000.0;
|
||||
} else if (plant.ChamberTemp_C < plant.AmbientTemp_C) {
|
||||
plant.ChamberTemp_C += (float)(rand() % 20)/1000.0;
|
||||
}
|
||||
}
|
||||
plant.ChamberHumi = (float)(rand() % 73) + 25;
|
||||
if (++plant.WaterCycle_sec >= plant.WaterCyclePeriod_sec) {
|
||||
plant.WaterCycle_sec -= plant.WaterCyclePeriod_sec;
|
||||
}
|
||||
if (plant.WaterCycle_sec >= plant.WaterCycleOn_sec) {
|
||||
plant.WaterPumpStatus = false;
|
||||
}
|
||||
if (plant.SoilMoisture_X < 60.0 && plant.WaterCycle_sec < plant.WaterCycleOn_sec) {
|
||||
plant.WaterPumpStatus = true;
|
||||
}
|
||||
if (plant.WaterPumpStatus) {
|
||||
plant.SoilMoisture_X += (float)(rand() % 40)/100.0;
|
||||
} else {
|
||||
plant.SoilMoisture_X -= (float)(rand() % 5)/100.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Firmware/PlantModel.h
Normal file
@@ -0,0 +1,12 @@
|
||||
//
|
||||
//
|
||||
//
|
||||
#ifndef PLANTMODEL_H
|
||||
#define PLANTMODEL_H
|
||||
|
||||
#include "ProjGlobals.h"
|
||||
|
||||
void HandleGetState();
|
||||
void simulation();
|
||||
|
||||
#endif // PLANTMODEL_H
|
||||
66
Firmware/ProjGlobals.h
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Project Global Settings
|
||||
//
|
||||
|
||||
#ifndef PROJGLOBALS_H
|
||||
#define PROJGLOBALS_H
|
||||
|
||||
#include <ESP8266WebServer.h>
|
||||
|
||||
// Manage the WiFi Configuration, AP, SSID, etc.
|
||||
#include "WiFiConfiguration.h"
|
||||
|
||||
typedef enum {
|
||||
DrumIsOpen,
|
||||
DrumIsClosed,
|
||||
DrumIsMoving,
|
||||
DrumIsStuck,
|
||||
} DrumState_E;
|
||||
|
||||
typedef enum {
|
||||
DrumOff,
|
||||
DrumCW,
|
||||
DrumCCW
|
||||
} DrumMotor_E;
|
||||
|
||||
typedef struct {
|
||||
uint32_t SecondsToday; // elapsed seconds from midnight (for simulation)
|
||||
bool Fahrenheit; // Show temp in Fahrenheit.
|
||||
|
||||
float ChamberTemp_C; // Chamber Temp
|
||||
float ChamberHumi; // Chamber Humidity - if installed
|
||||
|
||||
bool SoilHeater;
|
||||
float SoilTemp_C; // Soil Temp - if installed
|
||||
float SoilMoisture_X; // Soil Moisture - unitless number, if installed
|
||||
|
||||
float AmbientTemp_C; //
|
||||
|
||||
DrumState_E DrumDoorIcon; // Current State: open/close/moving
|
||||
bool DrumOpenSensor;
|
||||
bool DrumClosedSensor;
|
||||
DrumMotor_E DrumMotorStatus; // Off, CW, CCW
|
||||
uint32_t DrumMotorOn_sec;
|
||||
float DrumMotor_V;
|
||||
float DrumMotor_I;
|
||||
|
||||
bool WaterInTank; // controls image of the WaterLevelIcon
|
||||
bool WaterPumpStatus; // WaterLevelIcon pump on
|
||||
float WaterMotor_V;
|
||||
uint32_t WaterCyclePeriod_sec; // Total Time (allows WaterLevelIcon to soak in)
|
||||
uint32_t WaterCycleOn_sec; // WaterLevelIcon Pump on time
|
||||
uint32_t WaterCycle_sec; // Running timer
|
||||
} PlantData_T;
|
||||
|
||||
|
||||
extern void FactoryReset(bool forceRestart);
|
||||
extern const String AP_NAME;
|
||||
extern const String AP_VERS;
|
||||
// extern bool isStationMode;
|
||||
extern ESP8266WebServer server;
|
||||
extern ConfigManager wifiConfig;
|
||||
|
||||
extern PlantData_T plant; /// This keeps track of everything relevant to this system
|
||||
extern bool updateCheck;
|
||||
|
||||
#endif // PROJGLOBALS_H
|
||||
48
Firmware/Resources/Button.css
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
|
||||
input.BigButton {
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
padding: 10px;
|
||||
white-space: normal;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 120%;
|
||||
background: #3366cc;
|
||||
color: #fff;
|
||||
border: 5px solid #112233;
|
||||
border-radius: 10px;
|
||||
-moz-box-shadow: 6px 6px 5px #999;
|
||||
-webkit-box-shadow: 6px 6px 5px #999;
|
||||
box-shadow: 6px 6px 5px #999;
|
||||
}
|
||||
|
||||
input.BigButton:hover {
|
||||
color: #ffff00;
|
||||
background: #000;
|
||||
border: 5px solid #fff;
|
||||
}
|
||||
|
||||
input.SmallButton {
|
||||
width: 150px;
|
||||
height: 50px;
|
||||
padding: 10px;
|
||||
white-space: normal;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: 100%;
|
||||
background: #3366cc;
|
||||
color: #fff;
|
||||
border: 5px solid #112233;
|
||||
border-radius: 10px;
|
||||
-moz-box-shadow: 6px 6px 5px #999;
|
||||
-webkit-box-shadow: 6px 6px 5px #999;
|
||||
box-shadow: 6px 6px 5px #999;
|
||||
}
|
||||
|
||||
input.SmallButton:hover {
|
||||
color: #ffff00;
|
||||
background: #000;
|
||||
border: 5px solid #fff;
|
||||
}
|
||||
BIN
Firmware/Resources/Green1x1.png
Normal file
|
After Width: | Height: | Size: 119 B |
BIN
Firmware/Resources/Open.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
Firmware/Resources/PlantModel.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
Firmware/Resources/Water.png
Normal file
|
After Width: | Height: | Size: 869 B |
41
Firmware/Resources/about.htm
Normal file
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Grow Controller</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, width=device-width">
|
||||
<script type='text/javascript' src='myip.js'></script>
|
||||
<script type='text/javascript' src='about.js'></script>
|
||||
<script type='text/javascript' src='nav.js'></script>
|
||||
</head>
|
||||
<body onload="NavInit();">
|
||||
<h1>Grow Controller</h1>
|
||||
by Smartware Computing
|
||||
<blockquote>
|
||||
<table cellpadding="5">
|
||||
<tr valign="top">
|
||||
<td><img src="icon.png" title="logo" /></td>
|
||||
<td>
|
||||
This Grow Controller is an IOT device based on an ESP8266-12 module. The software for it has been
|
||||
derived from various sources and where copyrights have been identified, they are listed below.<br />
|
||||
<ul>
|
||||
<li>The composite work is Copyright © 2018-2021 by Smartware Computing, all rights reserved.</li>
|
||||
<li>Libraries; Copyright © 2001-2013 Free Software Foundation, Inc.</li>
|
||||
</ul>
|
||||
<dl>
|
||||
<dt>Toggle Button</dt>
|
||||
<dd>Each press will toggle the circuit between on and off.</dd>
|
||||
<dt>Reset Button</dt>
|
||||
<dd>Momentary press resets unit. Very Long press causes Factory reset back to Access Point mode.</dd>
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Mode:
|
||||
Uptime:
|
||||
|
||||
</blockquote>
|
||||
<span id='nav'></span>
|
||||
</body>
|
||||
</html>
|
||||
30
Firmware/Resources/about.js
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// rssi script
|
||||
//
|
||||
// var mySite = 'http://192.168.1.23' from myip.js
|
||||
var url = mySite + '/state';
|
||||
setInterval(RefreshStatus, 5000);
|
||||
|
||||
getIt = function(aUrl, callback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', aUrl, true);
|
||||
xhr.responseType = 'text';
|
||||
xhr.onload = function(e) {
|
||||
if (this.status === 200) {
|
||||
callback(this.response);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function RefreshStatus() {
|
||||
getIt(url,
|
||||
function(data) {
|
||||
obj = JSON.parse(data);
|
||||
var elms = document.querySelectorAll('.' + 'ip'), i;
|
||||
for (i = 0; i < elms.length; ++i) {
|
||||
elms[i].textContent = obj.ip;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
32
Firmware/Resources/curr.htm
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Grow Controller</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, width=device-width">
|
||||
<script type='text/javascript' src='myip.js'></script>
|
||||
<script type='text/javascript' src='curr.js'></script>
|
||||
<script type='text/javascript' src='nav.js'></script>
|
||||
</head>
|
||||
<body onload='CurrInit(); NavInit();'>
|
||||
<h1>Grow Controller - Current Sense</h1>
|
||||
<blockquote>
|
||||
<table width='800' border='0'>
|
||||
<tr>
|
||||
<td colspan='3' align='center'>
|
||||
<canvas id='curr' width='790' height='400'></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='*' align='left'>
|
||||
<div id='uptime'>x:xx:xx</div>
|
||||
</td>
|
||||
<td width='20%' align='right'>
|
||||
<div id='currText'>xx</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
<span id='nav'></span>
|
||||
</body>
|
||||
</html>
|
||||
141
Firmware/Resources/curr.js
Normal file
@@ -0,0 +1,141 @@
|
||||
//
|
||||
// curr script
|
||||
//
|
||||
// var mySite = 'http://192.168.1.23' from myip.js
|
||||
var url = mySite + '/state';
|
||||
var rawData = [];
|
||||
var avgData = [];
|
||||
var currIndex = 0;
|
||||
var axes = {};
|
||||
var totalSamples = 400; // Width of the graph
|
||||
for (var i = 0; i < totalSamples; i++)
|
||||
rawData[i] = avgData[i] = 0;
|
||||
setInterval(RefreshStatus, 500);
|
||||
|
||||
// -------------------------
|
||||
|
||||
getIt = function (aUrl, callback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', aUrl, true);
|
||||
xhr.responseType = 'text';
|
||||
xhr.onload = function (e) {
|
||||
if (this.status === 200) {
|
||||
callback(this.response);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
function RefreshStatus() {
|
||||
getIt(url,
|
||||
function (data) {
|
||||
obj = JSON.parse(data);
|
||||
UpdateGraph(obj.raw, obj.sense); // raw and averaged
|
||||
document.getElementById('uptime').innerHTML = 'Uptime: ' + obj.uptime;
|
||||
document.getElementById('currText').innerHTML = 'raw: ' + obj.raw + ', avg: ' + obj.sense;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function CurrInit() {
|
||||
var canvas = document.getElementById('curr');
|
||||
if (null === canvas || !canvas.getContext)
|
||||
return;
|
||||
ctx = canvas.getContext('2d');
|
||||
axes.w = 0.9 * canvas.width;
|
||||
axes.h = 0.8 * canvas.height;
|
||||
axes.x0 = 0.07 * canvas.width; // x0 pixels from left to x=0
|
||||
axes.y0 = 0.10 * canvas.height; // y0 pixels from top to y=0
|
||||
axes.scaleX = totalSamples; // # pixels from x=0 to x=1
|
||||
axes.scaleY = 1024;
|
||||
axes.doNegativeX = false;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.rect(0, 0, canvas.width - 1, canvas.height - 1);
|
||||
ctx.strokeStyle = 'black';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
showAxes(ctx, axes);
|
||||
}
|
||||
|
||||
function UpdateGraph(rawCurr, avgCurr) {
|
||||
var xx, yy;
|
||||
var i;
|
||||
|
||||
if (rawCurr > axes.scaleY) // safety limit
|
||||
rawCurr = axes.scaleY;
|
||||
else if (rawCurr < 0)
|
||||
rawCurr = 0;
|
||||
if (avgCurr > axes.scaleY) // safety limit
|
||||
avgCurr = axes.scaleY;
|
||||
else if (avgCurr < 0)
|
||||
avgCurr = 0;
|
||||
rawData[currIndex] = rawCurr;
|
||||
avgData[currIndex] = avgCurr;
|
||||
console.log('UpdateGraph(-' + rawCurr + ')');
|
||||
CurrInit();
|
||||
|
||||
// Draw Raw
|
||||
x0 = axes.x0;
|
||||
y0 = axes.y0;
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = '#FF8080';
|
||||
ctx.lineWidth = 3;
|
||||
for (i = 0; i < totalSamples; i++) {
|
||||
pi = (currIndex + 1 + i) % totalSamples;
|
||||
xx = x0 + i / axes.scaleX * axes.w;
|
||||
yy = y0 + axes.h - rawData[pi] / axes.scaleY * axes.h;
|
||||
ctx.lineTo(xx, yy);
|
||||
}
|
||||
ctx.stroke();
|
||||
// Circle
|
||||
ctx.beginPath();
|
||||
ctx.arc(xx, yy, 7, 0, 2 * Math.PI, false);
|
||||
ctx.fillstyle = '#FF8080';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = '#FF0000';
|
||||
ctx.stroke();
|
||||
|
||||
// Draw Average
|
||||
x0 = axes.x0;
|
||||
y0 = axes.y0;
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = '#8080FF';
|
||||
ctx.lineWidth = 3;
|
||||
for (i = 0; i < totalSamples; i++) {
|
||||
pi = (currIndex + 1 + i) % totalSamples;
|
||||
xx = x0 + i / axes.scaleX * axes.w;
|
||||
yy = y0 + axes.h - avgData[pi] / axes.scaleY * axes.h;
|
||||
ctx.lineTo(xx, yy);
|
||||
}
|
||||
ctx.stroke();
|
||||
// Circle
|
||||
ctx.beginPath();
|
||||
ctx.arc(xx, yy, 7, 0, 2 * Math.PI, false);
|
||||
ctx.fillstyle = '#8080FF';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = '#0000FF';
|
||||
ctx.stroke();
|
||||
currIndex++;
|
||||
currIndex %= totalSamples;
|
||||
}
|
||||
|
||||
function showAxes(ctx, axes) {
|
||||
var x0 = axes.x0, w = axes.w;
|
||||
var y0 = axes.y0, h = axes.h;
|
||||
var xmin = axes.doNegativeX ? 0 : x0;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.font = '12px Arial';
|
||||
ctx.textAlign = 'end';
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = 'rgb(128,128,128)';
|
||||
ctx.moveTo(x0, y0); ctx.lineTo(x0, y0 + h); // Y axis
|
||||
for (var y = 0; y <= axes.scaleY; y += 100) {
|
||||
yy = axes.y0 + axes.h - y / axes.scaleY * axes.h;
|
||||
ctx.moveTo(xmin, yy); ctx.lineTo(x0 + w, yy); // X axis
|
||||
ctx.fillText(y, x0 - 3, yy + 3);
|
||||
}
|
||||
ctx.font = '18px Arial';
|
||||
ctx.textAlign = 'start';
|
||||
ctx.fillText('Current Graph', axes.x0, axes.y0 - 6);
|
||||
ctx.stroke();
|
||||
}
|
||||
BIN
Firmware/Resources/favicon.ico
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
Firmware/Resources/icon.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
102
Firmware/Resources/index.htm
Normal file
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Grow Controller</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, width=device-width">
|
||||
<link rel="stylesheet" type="text/css" href="button.css" media="all" />
|
||||
<link rel="stylesheet" type="text/css" href="plantmodel.css" media="all" />
|
||||
<script type='text/javascript' src='nav.js'></script>
|
||||
<script type='text/javascript' src='myip.js'></script>
|
||||
<script type='text/javascript' src='about.js'></script>
|
||||
<script type='text/javascript' src='index.js'></script>
|
||||
</head>
|
||||
<body onload="NavInit();">
|
||||
<h1><span id='name'>Grow Controller</span></h1>
|
||||
<form>
|
||||
<table border='0'>
|
||||
<tr>
|
||||
<td width='45%' align='center'>
|
||||
<div class="box">
|
||||
<div style="position: relative; z-index: -10;">
|
||||
<!-- 243 x 488 -->
|
||||
<img src='plantmodel.png' title='Picture of the System' />
|
||||
</div>
|
||||
<div class='TimeOfDay' id='TimeOfDay'>--:--</div>
|
||||
|
||||
<div class='AmbientTemp_C' id='AmbientTemp_C' >--.- °F</div>
|
||||
<div class='AmbientTempIcon' id='AmbientTempIcon' ><img src='thermometer.png' title='Ambient Temperature' /></div>
|
||||
|
||||
<div class='ChamberTemp_C' id='ChamberTemp_C' >--.- °F</div>
|
||||
<div class='ChamberHumi' id='ChamberHumi' >-- %</div>
|
||||
<div class='ChamberTempIcon' id='ChamberTempIcon' ><img src='thermometer.png' title='Chamber Temperature' /></div>
|
||||
<div class='SoilHeater' id='SoilHeater' >Heat</div>
|
||||
<div class='SoilHeaterOnIcon' id='SoilHeaterOnIcon' ><img src='soilheater_on.png' title='Soil Heater' /></div>
|
||||
<div class='SoilHeaterOffIcon' id='SoilHeaterOffIcon' ><img src='soilheater_off.png' title='Soil Heater' /></div>
|
||||
|
||||
<div class='SoilThermoIcon' id='SoilThermoIcon' ><img src='thermometer.png' title='Soil Temperature' /></div>
|
||||
<div class='SoilHumiIcon' id='SoilHumiIcon' ><img src='soilmoisture.png' title='Soil Temperature' /></div>
|
||||
<div class='SoilTemp_C' id='SoilTemp_C' >--.- °F</div>
|
||||
<div class='SoilMoisture_X' id='SoilMoisture_X' >-- %</div>
|
||||
|
||||
<div class='DrumState' id='DrumState' ><img src='open.png' title='Open' /></div>
|
||||
<div class='DrumOpenSensor' id='DrumOpenSensor' >O</div>
|
||||
<div class='DrumClosedSensor' id='DrumClosedSensor' >C</div>
|
||||
<div class='DrumMotorLabel' id='DrumMotorLabel' >Motor</div>
|
||||
<div class='DrumMotorStatus' id='DrumMotorStatus' >Off</div>
|
||||
<div class='DrumMotor_V' id='DrumMotor_V' >12.5 V</div>
|
||||
<div class='DrumMotor_I' id='DrumMotor_I' >1.2 A</div>
|
||||
<div class='DrumMotorOn_sec' id='DrumMotorOn_sec' >10 s</div>
|
||||
|
||||
<div class='WaterInTank' id='WaterInTank'>Low Water</div>
|
||||
<div class='WaterPumpLabel' id='WaterPumpLabel' >Pump</div>
|
||||
<div class='WaterPumpStatus' id='WaterPumpStatus' >On</div>
|
||||
<div class='WaterLevelIcon' id='WaterLevelIcon'><img src='water.png' title='Water in Tank' /></div>
|
||||
<div class='WaterMotor_V' id='WaterMotor_V' >10.7 V</div>
|
||||
<div class='WaterCyclePeriod_sec' id='WaterCyclePeriod_sec' >90 s</div>
|
||||
<div class='WaterCycleOn_sec' id='WaterCycleOn_sec' >8 s</div>
|
||||
<div class='WaterCycle_sec' id='WaterCycle_sec' >10 s</div>
|
||||
<div class='WaterCycleOnBox' id='WaterCycleOnBox' ></div>
|
||||
<div class='WaterCyclePointer_sec' id='WaterCyclePointer_sec' ><img src='pointer.png' title='Pump On Time' /></div>
|
||||
</div>
|
||||
</td>
|
||||
<td width='10%' align='center'>
|
||||
</td>
|
||||
<td width='45%' align='center'>
|
||||
<input class='BigButton' type='button' value='Automatic' onclick="window.location.href='/?SW=1'" />
|
||||
<br />
|
||||
<input class='BigButton' type='button' value='Manual [Open|Close]' onclick="window.location.href='/?SW=0'" />
|
||||
<br />
|
||||
<br />
|
||||
<input class='BigButton' type='button' value='Grow Settings' onclick="window.location.href='/?SW=2'" />
|
||||
<br />
|
||||
<input class='SmallButton' type='button' value='Load Monitor' onclick="window.location.href='/curr'" />
|
||||
<br />
|
||||
<input class='SmallButton' type='button' value='Wi-Fi Config.' onclick="window.location.href='/config'" />
|
||||
<br />
|
||||
<input class='SmallButton' type='button' value='RSSI Monitor' onclick="window.location.href='/rssi'" />
|
||||
<br />
|
||||
<input class='SmallButton' type='button' value='Scan for APs' onclick="window.location.href='/scan'" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<p></p>
|
||||
<span id='state'></span>
|
||||
<span id='raw'></span>
|
||||
<span id='sense'></span>
|
||||
<span id='toggle'></span>
|
||||
<span id='reset'></span>
|
||||
<span id='countdown'></span>
|
||||
<span id='uptime'></span>
|
||||
<span id='wifimode'></span>
|
||||
<span id='nav'></span>
|
||||
<hr>
|
||||
<table border='0'>
|
||||
<tr>
|
||||
<td>GrowController by Smartware Computing</td>
|
||||
<td align="right"><a href="/swupdatecheck">Firmware</a>: <span id='version'>v0.00.00</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
116
Firmware/Resources/index.js
Normal file
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// Main Page period status update
|
||||
//
|
||||
// @todo Draw the 'drum' as an arc instead of trying to rotate a picture of an arc.
|
||||
// which will work better to reflect the opening.
|
||||
//
|
||||
//
|
||||
// var mySite = 'http://192.168.1.23'; // from myip.js
|
||||
var url = mySite + '/state';
|
||||
setInterval(RefreshStatus, 1000); // @todo speed this up to 500 msec or even 250
|
||||
|
||||
getIt = function (aUrl, callback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', aUrl, true);
|
||||
xhr.responseType = 'text';
|
||||
xhr.onload = function (e) {
|
||||
if (this.status === 200) {
|
||||
callback(this.response);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
function ConvertTempToString(tempC, showF) {
|
||||
var tempF = tempC * 9 / 5 + 32;
|
||||
if (showF == 0)
|
||||
return tempF.toFixed(0) + "°F";
|
||||
else
|
||||
return tempC.toFixed(0) + "°C";
|
||||
}
|
||||
|
||||
function ConvertSecToMMSS(sec) {
|
||||
mm = parseInt(sec/60).toString().padStart(4,'0');
|
||||
ss = (sec%60).toString().padStart(2,'0');
|
||||
return mm + ":" + ss;
|
||||
}
|
||||
|
||||
function RefreshStatus() {
|
||||
getIt(url,
|
||||
function(data) {
|
||||
obj = JSON.parse(data);
|
||||
document.getElementById('version').innerHTML = obj.version;
|
||||
document.getElementById('name').innerHTML = obj.name;
|
||||
document.getElementById('uptime').innerHTML = 'Uptime: ' + obj.uptime;
|
||||
document.getElementById('wifimode').innerHTML = 'WiFi Mode: ' + obj.wifimode;
|
||||
// IP Address
|
||||
var elms = document.querySelectorAll('.' + 'ip'), i;
|
||||
for (i = 0; i < elms.length; ++i) {
|
||||
elms[i].textContent = obj.ip;
|
||||
}
|
||||
// Plant status
|
||||
document.getElementById('TimeOfDay').innerHTML = obj.TimeOfDay;
|
||||
var userF = obj.Fahrenheit;
|
||||
|
||||
if (typeof obj.AmbientTemp_C != "undefined") {
|
||||
document.getElementById('AmbientTemp_C').innerHTML = ConvertTempToString(obj.AmbientTemp_C, userF);
|
||||
} else {
|
||||
document.getElementById('AmbientTemp_C').innerHTML = "--";
|
||||
}
|
||||
|
||||
if (typeof obj.ChamberTemp_C != "undefined") {
|
||||
document.getElementById('ChamberTemp_C').innerHTML = ConvertTempToString(obj.ChamberTemp_C, userF);
|
||||
document.getElementById('ChamberHumi').innerHTML = parseInt(obj.ChamberHumi) + "%";
|
||||
} else {
|
||||
document.getElementById('ChamberTemp_C').innerHTML = "--";
|
||||
document.getElementById('ChamberHumi').innerHTML = "--"
|
||||
}
|
||||
|
||||
if (typeof obj.SoilHeater != "undefined") {
|
||||
document.getElementById('SoilHeater').innerHTML = (obj.SoilHeater) ? "Heat On" : "Heat Off";
|
||||
} else {
|
||||
document.getElementById('SoilHeater').innerHTML = "--";
|
||||
}
|
||||
|
||||
if (typeof obj.SoilTemp_C != "undefined") {
|
||||
document.getElementById('SoilTemp_C').innerHTML = ConvertTempToString(obj.SoilTemp_C, userF);
|
||||
} else {
|
||||
document.getElementById('SoilTemp_C').innerHTML = "--";
|
||||
}
|
||||
if (typeof obj.SoilTemp_C != "undefined") {
|
||||
document.getElementById('SoilMoisture_X').innerHTML = obj.SoilMoisture_X;
|
||||
} else {
|
||||
document.getElementById('SoilMoisture_X').innerHTML = "--";
|
||||
}
|
||||
|
||||
if (obj.DrumState == 1) { // closed, hide the "open" image
|
||||
document.getElementById('DrumState').style.display === "none";
|
||||
} else {
|
||||
document.getElementById('DrumState').style.display === "block";
|
||||
}
|
||||
document.getElementById('DrumOpenSensor').innerHTML = (obj.DrumOpenSensor) ? "O" : "!O";
|
||||
document.getElementById('DrumClosedSensor').innerHTML = (obj.DrumClosedSensor) ? "C" : "!C";
|
||||
document.getElementById('DrumMotorStatus').innerHTML = (obj.DrumMotorStatus == 0) ? "stopped" : (obj.DrumMotorStatus == 1) ? "CW" : "CCW";
|
||||
document.getElementById('DrumMotorOn_sec').innerHTML = obj.DrumMotorOn_sec + "s";
|
||||
document.getElementById('DrumMotor_V').innerHTML = parseFloat(obj.DrumMotor_V).toFixed(1) + " V";
|
||||
document.getElementById('DrumMotor_I').innerHTML = parseFloat(obj.DrumMotor_I).toFixed(1) + " A";
|
||||
|
||||
document.getElementById('WaterInTank').innerHTML = obj.WaterInTank;
|
||||
document.getElementById('WaterPumpStatus').innerHTML = (obj.WaterPumpStatus) ? "On" : "Off";
|
||||
document.getElementById('WaterMotor_V').innerHTML = parseFloat(obj.WaterMotor_V).toFixed(1) + " V";
|
||||
document.getElementById('WaterCyclePeriod_sec').innerHTML = ConvertSecToMMSS(obj.WaterCyclePeriod_sec);
|
||||
document.getElementById('WaterCycleOn_sec').innerHTML = ConvertSecToMMSS(obj.WaterCycleOn_sec);
|
||||
document.getElementById('WaterCycle_sec').innerHTML = ConvertSecToMMSS(obj.WaterCycle_sec);
|
||||
|
||||
// The full-scale pump timer box ranges from 22 to 234px
|
||||
// The WaterCycleOnBox.width is proportional to the WaterCyclePeriod_sec and the (234 - 22)px width
|
||||
var boxW = (234 - 22);
|
||||
// The WaterCyclePointer_sec.width (24) is positioned from 22 to 234 - 1/2 width.
|
||||
var onW = (obj.WaterCycleOn_sec/obj.WaterCyclePeriod_sec) * boxW;
|
||||
var ptrX = 22 + (obj.WaterCycle_sec/obj.WaterCyclePeriod_sec) * boxW - 12;
|
||||
console.log("onW: " + onW + ", ptrX: " + ptrX);
|
||||
document.getElementById('WaterCycleOnBox').width = onW;
|
||||
document.getElementById('WaterCyclePointer_sec').left = ptrX;
|
||||
}
|
||||
);
|
||||
}
|
||||
5
Firmware/Resources/myip.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
// Normally provided by the application intercepting this request,
|
||||
// but for debug it can be handy to fix it.
|
||||
//
|
||||
var mySite = 'http://192.168.1.10'; // from myip.js
|
||||
20
Firmware/Resources/nav.js
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
//
|
||||
function NavInit() {
|
||||
nav = document.getElementById('nav');
|
||||
var txt = "<table>";
|
||||
txt += "<tr valign='top'>";
|
||||
txt += " <td>NAV:</td>";
|
||||
txt += " <td>";
|
||||
txt += " <a href='index.htm'>Home</a> | ";
|
||||
txt += " <a href='config'>Config</a> | ";
|
||||
txt += " <a href='scan'>Scan</a> | ";
|
||||
txt += " <a href='rssi.htm'>RSSI</a> | ";
|
||||
txt += " <a href='curr.htm'>Current</a> | ";
|
||||
txt += " <a href='config?ssid=reset&pass=reset' onclick=\\\"return confirm('Are you sure?')\\\">Factory Reset</a> | ";
|
||||
txt += " <a href='about.htm'>About</a>";
|
||||
txt += " </td>";
|
||||
txt += "</tr>";
|
||||
txt += "</table>";
|
||||
nav.innerHTML = txt;
|
||||
}
|
||||
22
Firmware/Resources/navigation.htm
Normal file
@@ -0,0 +1,22 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td>NAV:</td>
|
||||
<td>
|
||||
<a href='/'>Home</a> |
|
||||
<a href='config'>Config</a> |
|
||||
<a href='scan'>Scan</a> |
|
||||
<a href='rssi'>RSSI</a> |
|
||||
<a href='curr'>Current</a> |
|
||||
<a href='config?ssid=reset&pass=reset' onclick=\"return confirm('Are you sure?')\">Factory Reset</a> |
|
||||
<a href='about'>About</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
249
Firmware/Resources/plantmodel.css
Normal file
@@ -0,0 +1,249 @@
|
||||
<style>
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
.box {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
border-color: black;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
div.TimeOfDay {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 2px;
|
||||
width: 40px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
div.AmbientTemp_C {
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 2px;
|
||||
width: 40px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
div.AmbientTempIcon {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
div.ChamberTempIcon {
|
||||
position: absolute;
|
||||
left: 142px;
|
||||
top: 40px;
|
||||
}
|
||||
div.ChamberTemp_C {
|
||||
position: absolute;
|
||||
left: 160px;
|
||||
top: 40px;
|
||||
}
|
||||
div.ChamberHumi {
|
||||
position: absolute;
|
||||
left: 160px;
|
||||
top: 55px;
|
||||
}
|
||||
div.SoilMoisture_X {
|
||||
position: absolute;
|
||||
left: 135px;
|
||||
top: 135px;
|
||||
color: white;
|
||||
}
|
||||
div.SoilHumiIcon {
|
||||
position: absolute;
|
||||
left: 140px;
|
||||
top: 95px;
|
||||
}
|
||||
div.SoilThermoIcon {
|
||||
position: absolute;
|
||||
left: 175px;
|
||||
top: 100px;
|
||||
}
|
||||
div.SoilTemp_C {
|
||||
position: absolute;
|
||||
left: 170px;
|
||||
top: 135px;
|
||||
color: white;
|
||||
}
|
||||
div.SoilHeater {
|
||||
position: absolute;
|
||||
left: 105px;
|
||||
top: 156px;
|
||||
color: white;
|
||||
}
|
||||
div.SoilHeaterOnIcon {
|
||||
position: absolute;
|
||||
left: 76px;
|
||||
top: 167px;
|
||||
}
|
||||
div.SoilHeaterOffIcon {
|
||||
position: absolute;
|
||||
left: 89px;
|
||||
top: 181px;
|
||||
}
|
||||
|
||||
div.DrumState {
|
||||
position: absolute;
|
||||
transform: rotate(180deg);
|
||||
left: 14px;
|
||||
top: 0px;
|
||||
}
|
||||
div.DrumOpenSensor {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 96px;
|
||||
}
|
||||
div.DrumClosedSensor {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 96px;
|
||||
}
|
||||
div.DrumMotorLabel {
|
||||
position: absolute;
|
||||
left: 95px;
|
||||
top: 260px;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
div.DrumMotorStatus {
|
||||
position: absolute;
|
||||
left: 95px;
|
||||
top: 280px;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
div.DrumMotor_V {
|
||||
position: absolute;
|
||||
left: 180px;
|
||||
top: 225px;
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
//color: Red;
|
||||
}
|
||||
div.DrumMotor_I {
|
||||
position: absolute;
|
||||
left: 180px;
|
||||
top: 245px;
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
div.DrumMotorOn_sec {
|
||||
position: absolute;
|
||||
left: 180px;
|
||||
top: 315px;
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
div.WaterInTank {
|
||||
position: absolute;
|
||||
left: 55px;
|
||||
top: 365px;
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
div.WaterPumpLabel {
|
||||
position: absolute;
|
||||
left: 124px;
|
||||
top: 390px;
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
div.WaterPumpStatus {
|
||||
position: absolute;
|
||||
left: 124px;
|
||||
top: 410px;
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
div.WaterLevelIcon {
|
||||
position: absolute;
|
||||
left: 42px;
|
||||
top: 393px;
|
||||
z-index: -55;
|
||||
}
|
||||
div.WaterMotor_V {
|
||||
position: absolute;
|
||||
left: 180px;
|
||||
top: 350px;
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
div.WaterCyclePeriod_sec {
|
||||
position: absolute;
|
||||
left: 182px;
|
||||
top: 467px;
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
//border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
div.WaterCycleOn_sec {
|
||||
position: absolute;
|
||||
left: 23px;
|
||||
top: 467px;
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
//border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
div.WaterCycle_sec {
|
||||
position: absolute;
|
||||
left: 180px;
|
||||
top: 440px;
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
border-color: green;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
div.WaterCycleOnBox {
|
||||
position: absolute;
|
||||
left: 22px;
|
||||
top: 464px;
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
background-color: #BDD7EE;
|
||||
z-index: -35;
|
||||
border-color: red;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
div.WaterCyclePointer_sec {
|
||||
position: absolute;
|
||||
left: 80px;
|
||||
top: 469px;
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
z-index: -25;
|
||||
border-color: green;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
</style>
|
||||
BIN
Firmware/Resources/pointer.png
Normal file
|
After Width: | Height: | Size: 418 B |
32
Firmware/Resources/rssi.htm
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Grow Controller RSSI</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, width=device-width">
|
||||
<script type='text/javascript' src='nav.js'></script>
|
||||
<script type='text/javascript' src='myip.js'></script>
|
||||
<script type='text/javascript' src='rssi.js'></script>
|
||||
</head>
|
||||
<body onload='RSSIInit(); NavInit();'>
|
||||
<h1>Grow Controller - RSSI</h1>
|
||||
<blockquote>
|
||||
<table width='800' border='0'>
|
||||
<tr>
|
||||
<td colspan='3' align='center'>
|
||||
<canvas id='RSSIGraph' width='790' height='400'></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='*' align='left'>
|
||||
<div id='uptime'>x:xx:xx</div>
|
||||
</td>
|
||||
<td width='20%' align='right'>
|
||||
<div id='rssi'>-xx</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
<span id='nav'></span>
|
||||
</body>
|
||||
</html>
|
||||
109
Firmware/Resources/rssi.js
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// rssi script
|
||||
//
|
||||
// var mySite = 'http://192.168.1.23' from myip.js
|
||||
var url = mySite + '/state';
|
||||
var rssiData = [];
|
||||
var rssiIndex = 0;
|
||||
var axes = {};
|
||||
for (var i = 0; i<100; i++)
|
||||
rssiData[i] = 0;
|
||||
setInterval(RefreshStatus, 250);
|
||||
|
||||
// -------------------------
|
||||
|
||||
getIt = function (aUrl, callback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', aUrl, true);
|
||||
xhr.responseType = 'text';
|
||||
xhr.onload = function (e) {
|
||||
if (this.status === 200) {
|
||||
callback(this.response);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
function RefreshStatus() {
|
||||
getIt(url,
|
||||
function(data) {
|
||||
obj = JSON.parse(data);
|
||||
UpdateGraph(obj.rssi);
|
||||
document.getElementById('rssi').innerHTML = 'RSSI: ' + obj.rssi;
|
||||
document.getElementById('uptime').innerHTML = 'Uptime: ' + obj.uptime;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function RSSIInit() {
|
||||
var canvas = document.getElementById('RSSIGraph');
|
||||
if (null === canvas || !canvas.getContext)
|
||||
return;
|
||||
ctx = canvas.getContext('2d');
|
||||
axes.w = 0.9 * canvas.width;
|
||||
axes.h = 0.8 * canvas.height;
|
||||
axes.x0 = 0.07 * canvas.width; // x0 pixels from left to x=0
|
||||
axes.y0 = 0.10 * canvas.height; // y0 pixels from top to y=0
|
||||
axes.scaleX = 100; // # pixels from x=0 to x=1
|
||||
axes.scaleY = 100;
|
||||
axes.doNegativeX = false;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.rect(0, 0, canvas.width - 1, canvas.height - 1);
|
||||
ctx.strokeStyle = 'black';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
showAxes(ctx, axes);
|
||||
}
|
||||
|
||||
function UpdateGraph(rssi) {
|
||||
var xx, yy;
|
||||
rssi = -rssi; // invert for convenience
|
||||
if (rssi > axes.scaleY) // safety limit
|
||||
rssi = axes.scaleY;
|
||||
else if (rssi < 0)
|
||||
rssi = 0;
|
||||
rssiData[rssiIndex] = rssi;
|
||||
console.log('UpdateGraph(-' + rssi + ')');
|
||||
RSSIInit();
|
||||
x0 = axes.x0;
|
||||
y0 = axes.y0;
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = 'rgb(250,128,128)';
|
||||
ctx.lineWidth = 5;
|
||||
for (var i = 0; i<100; i++) {
|
||||
pi = (rssiIndex + 1 + i) % 100;
|
||||
xx = x0 + i / axes.scaleX * axes.w;
|
||||
yy = y0 + rssiData[pi] / axes.scaleY * axes.h;
|
||||
ctx.lineTo(xx, yy);
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.arc(xx, yy, 7, 0, 2 * Math.PI, false);
|
||||
ctx.fillstyle = 'green';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = '#003300';
|
||||
ctx.stroke();
|
||||
rssiIndex++;
|
||||
rssiIndex %= 100;
|
||||
}
|
||||
|
||||
function showAxes(ctx, axes) {
|
||||
var x0 = axes.x0, w = axes.w;
|
||||
var y0 = axes.y0, h = axes.h;
|
||||
var xmin = axes.doNegativeX ? 0 : x0;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.font = '12px Arial';
|
||||
ctx.textAlign = 'end';
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = 'rgb(128,128,128)';
|
||||
ctx.moveTo(x0, y0); ctx.lineTo(x0, y0 + h); // Y axis
|
||||
for (var y = 0; y <= axes.scaleY; y += 10) {
|
||||
yy = axes.y0 + y / axes.scaleY * axes.h;
|
||||
ctx.moveTo(xmin, yy); ctx.lineTo(x0 + w, yy); // X axis
|
||||
ctx.fillText(-y, x0 - 3, yy + 3);
|
||||
}
|
||||
ctx.font = '18px Arial';
|
||||
ctx.textAlign = 'start';
|
||||
ctx.fillText('RSSI Graph', axes.x0, axes.y0 - 6);
|
||||
ctx.stroke();
|
||||
}
|
||||
BIN
Firmware/Resources/soilheater_off.png
Normal file
|
After Width: | Height: | Size: 488 B |
BIN
Firmware/Resources/soilheater_on.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Firmware/Resources/soilmoisture.png
Normal file
|
After Width: | Height: | Size: 249 B |
BIN
Firmware/Resources/thermometer.png
Normal file
|
After Width: | Height: | Size: 777 B |
57
Firmware/Utility.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
//
|
||||
// Utility functions
|
||||
//
|
||||
//
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#include "Utility.h"
|
||||
|
||||
static String macToStr(const uint8_t * mac, char padd = ':');
|
||||
|
||||
String GetMacString(char padd) {
|
||||
unsigned char mac[6];
|
||||
WiFi.macAddress(mac);
|
||||
String clientMac(macToStr(mac, padd));
|
||||
return clientMac;
|
||||
}
|
||||
|
||||
static String macToStr(const uint8_t * mac, char padd) {
|
||||
String result;
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
result += String(mac[i], 16);
|
||||
if (i < 5) {
|
||||
if (padd)
|
||||
result += padd;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void HexDump(const char * title, const uint8_t * p, int count)
|
||||
{
|
||||
int i;
|
||||
char buf[100] = "0000: ";
|
||||
char asc[17] = " ";
|
||||
|
||||
if (*title) {
|
||||
printf("%s [@%08X]\n", title, (uint32_t)p);
|
||||
}
|
||||
for (i=0; i<count; ) {
|
||||
sprintf(buf + strlen(buf), "%02X ", *(p+i));
|
||||
asc[i % 16] = isprint(*(p+i)) ? *(p+i) : '.';
|
||||
if ((++i & 0x0F) == 0x00) {
|
||||
printf("%-55s | %s |\n", buf, asc);
|
||||
if (i < count) {
|
||||
sprintf(buf, "%04X: ", i);
|
||||
} else {
|
||||
buf[0] = '\0';
|
||||
asc[0] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strlen(buf)) {
|
||||
printf("%-55s | %s |\n", buf, asc);
|
||||
}
|
||||
}
|
||||
35
Firmware/Utility.h
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
//
|
||||
// Utility.h
|
||||
//
|
||||
//
|
||||
#ifndef UTILITY_H
|
||||
#define UTILITY_H
|
||||
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
// Returns the MAC Address as a string object
|
||||
String GetMacString(char padd = ':');
|
||||
|
||||
|
||||
// Dump a block of memory as a hex title-named listing
|
||||
//
|
||||
void HexDump(const char * title, const uint8_t * p, int count);
|
||||
|
||||
|
||||
// A macro to generate a build error on the condition
|
||||
//
|
||||
// Example:
|
||||
// BUILD_BUG_ON(sizeof(something) > limit);
|
||||
//
|
||||
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
|
||||
|
||||
// And the more positive direction
|
||||
//
|
||||
// Example:
|
||||
// COMPILER_ASSERT(sizeof(something) <= limit);
|
||||
//
|
||||
#define COMPILER_ASSERT(condition) ((void)sizeof(char[-!(condition)]))
|
||||
|
||||
#endif // UTILITY_H
|
||||
4654
Firmware/Web_Resources.h
Normal file
203
Firmware/WiFiConfiguration.h
Normal file
@@ -0,0 +1,203 @@
|
||||
///
|
||||
/// Simple WiFi Configuration features
|
||||
///
|
||||
#ifndef WIFICONFIGURATION_H
|
||||
#define WIFICONFIGURATION_H
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#define CFG_NAMESIZE 32
|
||||
#define CFG_SSIDSIZE 32
|
||||
#define CFG_PASSSIZE 64
|
||||
#define CFG_UPDURLSIZE 64
|
||||
#define CFG_NTPSSIZE 64
|
||||
|
||||
/// Provides a handy interface for WiFi configuration and user NV data.
|
||||
///
|
||||
/// Because the WiFi needs to have its configuration managed through
|
||||
/// non-volatile memory.
|
||||
///
|
||||
/// @code
|
||||
/// WiFiConfiguration config;
|
||||
/// ...
|
||||
/// config.load();
|
||||
/// String ssid = config.getSSID();
|
||||
/// String pass = config.getPassword();
|
||||
/// ...
|
||||
/// WiFi.begin(ssid.c_str(), pass.c_str());
|
||||
///
|
||||
/// @endcode
|
||||
///
|
||||
class ConfigManager {
|
||||
public:
|
||||
|
||||
/// Data structure that is used for 'factory reset' of this node,
|
||||
/// where all setup data is erased. This reset state can include
|
||||
/// specific settings, such as the device name (as it will appear
|
||||
/// on the network, and the default software update server, and so on.
|
||||
typedef struct {
|
||||
const char * name; ///< the device name
|
||||
const char * UPDURL; ///< the URL of a SW update server
|
||||
const char * NTPURL; ///< The URL of an NTP server
|
||||
} ConfigDefaults_t;
|
||||
|
||||
/// load checks the version of the image for validity.
|
||||
///
|
||||
typedef enum {
|
||||
MATCHING, ///< The current version matches the expected version
|
||||
IS_OLDER, ///< [Newer firmware] detected an older configuration
|
||||
IS_NEWER, ///< detected a configuration that is newer than this app knows.
|
||||
IS_BROKEN, ///< format check failed, this image is bad.
|
||||
} FirmwareCheck_t;
|
||||
|
||||
/// Instantiate the WiFi Configuration Manager, which also manages
|
||||
/// user non-volatile storage.
|
||||
///
|
||||
/// This creates a RAM cache (typically 512B), where information is
|
||||
/// held. This is then saved to non-volatile (save), or overwritten
|
||||
/// from non-volatile (load).
|
||||
///
|
||||
/// Instantiation does not automatically load from non-volatile.
|
||||
///
|
||||
/// @param[in] defaults is an optional pointer to the default information.
|
||||
///
|
||||
ConfigManager(const ConfigDefaults_t * defaults = NULL);
|
||||
|
||||
/// Destructor, which is usually not used in an embedded system.
|
||||
///
|
||||
~ConfigManager();
|
||||
|
||||
/// loads the information from non-volatile storage into RAM
|
||||
///
|
||||
/// @returns status of the firmware check. @see FirmwareCheck_t
|
||||
///
|
||||
FirmwareCheck_t load();
|
||||
|
||||
/// get the current firmware version
|
||||
///
|
||||
/// specific software may be able to upgrade (or even downgrade) the
|
||||
/// non-volatile data storage format.
|
||||
///
|
||||
/// @returns the format version number (only useful if load is not broken.
|
||||
///
|
||||
uint8_t getFormatVersion();
|
||||
|
||||
|
||||
/// saves the information to non-volatile.
|
||||
///
|
||||
void save();
|
||||
|
||||
/// Resets the RAM information to factory defaults, completely wiping
|
||||
/// all data, so it cannot be extracted.
|
||||
///
|
||||
/// To complete the wipe, be sure to issue to the save command.
|
||||
///
|
||||
void factoryReset();
|
||||
|
||||
/// get the name of this device, as it will appear on the network.
|
||||
///
|
||||
/// @returns string of the name.
|
||||
///
|
||||
String getName();
|
||||
|
||||
/// set the name of this device, to a maximum length of CFG_NAMESIZE.
|
||||
///
|
||||
/// @param[in] _name is the name to assign it.
|
||||
///
|
||||
void setName(String _name);
|
||||
|
||||
/// get the ssid that this node is assigned to.
|
||||
///
|
||||
/// @returns the SSID, or a pointer to NULL if none set.
|
||||
///
|
||||
String getSSID();
|
||||
|
||||
/// set the ssid that this node is assigned to.
|
||||
///
|
||||
/// @param[in] _ssid to assign this device to, to a maximum length of CFG_SSIDSIZE
|
||||
///
|
||||
void setSSID(String _ssid);
|
||||
|
||||
/// get the passcode that this node will use with the joined ssid.
|
||||
///
|
||||
/// @returns the passcode.
|
||||
///
|
||||
String getPassword();
|
||||
|
||||
/// set the passcode that this node uses.
|
||||
///
|
||||
/// @param[in] passcode to assign this device to, to a maximum length of CFG_PASSSIZE
|
||||
///
|
||||
void setPassword(String _password);
|
||||
|
||||
/// get the URL that this node will use for software updates
|
||||
///
|
||||
/// @returns the url.
|
||||
///
|
||||
String getURL();
|
||||
|
||||
/// set the URL that this node will use for software updates
|
||||
///
|
||||
/// @param[in] _url to assign this device to, to a maximum length of CFG_UPDURLSIZE
|
||||
///
|
||||
void setURL(String _url);
|
||||
|
||||
/// get the URL of the NTP server that this node will use for setting the clock
|
||||
///
|
||||
/// @returns the url.
|
||||
///
|
||||
String getNTPServerName();
|
||||
|
||||
/// set the URL of the NTP server that this node will use for software updates
|
||||
///
|
||||
/// @param[in] _url to assign this device to, to a maximum length of CFG_NTPSSIZE
|
||||
///
|
||||
void setNTPServerName(String _url);
|
||||
|
||||
/// get a pointer to the portion of the data that will be saved to non-volatile
|
||||
///
|
||||
/// This points to the block of memory that is for user settings. The user code
|
||||
/// will typically create a structure, and overlay it on this location.
|
||||
///
|
||||
/// The size is fixed at compile time, but may be queried with getUserDataSize()
|
||||
/// to ensure that there is no buffer overrun.
|
||||
///
|
||||
/// @returns the pointer to the memory for the user to use.
|
||||
///
|
||||
uint8_t * getUserDataHandle();
|
||||
|
||||
/// get the size of the user data block that can be saved to non-volatile.
|
||||
///
|
||||
/// @returns the size (in bytes) of the user space.
|
||||
///
|
||||
int getUserDataSize();
|
||||
|
||||
private:
|
||||
|
||||
#define EEROM_SIZE 512
|
||||
|
||||
// Change this when it is required to force a reinitialization
|
||||
//
|
||||
#define EXPECTED_FMT 0x04
|
||||
|
||||
#define SYSTEMSIZE (2 + CFG_NAMESIZE + CFG_SSIDSIZE + CFG_PASSSIZE + CFG_UPDURLSIZE + CFG_NTPSSIZE)
|
||||
#define USERSIZE (EEROM_SIZE - SYSTEMSIZE)
|
||||
|
||||
typedef struct {
|
||||
uint8_t format[2]; // Format of this data structure, and ~format check
|
||||
struct info {
|
||||
char name[CFG_NAMESIZE]; // Network Discoverable Name of this node
|
||||
char ssid[CFG_SSIDSIZE]; // SSID of the saved network [max length defined by standard]
|
||||
char pass[CFG_PASSSIZE]; // PASScode of the saved network
|
||||
char UPDURL[CFG_UPDURLSIZE]; // URL of the trusted server with code updates
|
||||
char NTPURL[CFG_NTPSSIZE]; // Name or IP of the NTP Server
|
||||
} info;
|
||||
uint8_t userData[USERSIZE]; // User data here and to the EEROM_SIZE end.
|
||||
} NVConfig_04_t; // This layout matches EXPECTED_FMT == 04
|
||||
|
||||
NVConfig_04_t Configuration; // the instantiation of the Configuration
|
||||
|
||||
const ConfigDefaults_t * defaults;
|
||||
};
|
||||
|
||||
#endif // !WIFICONFIGURATION_H
|
||||
107
Firmware/WiFiStateHandler.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#include "ProjGlobals.h"
|
||||
#include "WiFiStateHandler.h"
|
||||
|
||||
#include <DNSServer.h> ///< Required for Captive Portal behavior.
|
||||
const byte DNS_PORT = 53; ///< Capture DNS requests on port 53
|
||||
//DNSServer dnsServer; ///< Used for the captive portal AP mode
|
||||
|
||||
WiFiConnectState wifiConState; ///< Track the current WiFi state
|
||||
|
||||
|
||||
void WiFiStateSet(WiFiConnectState newState) {
|
||||
wifiConState = newState;
|
||||
}
|
||||
|
||||
WiFiConnectState WiFiStateGet() {
|
||||
return wifiConState;
|
||||
}
|
||||
|
||||
WiFiConnectState WiFiStateHandler() {
|
||||
static unsigned long timeStateChange = 0;
|
||||
// @todo static unsigned long timeLEDControl;
|
||||
// @todo unsigned long timeLEDCycle;
|
||||
String ssid = wifiConfig.getSSID();
|
||||
String pass = wifiConfig.getPassword();
|
||||
IPAddress myIP;
|
||||
|
||||
// @todo
|
||||
#if 0
|
||||
timeLEDCycle = millis() - timeLEDControl;
|
||||
if (timeLEDCycle >= LED_PERIOD__MS) {
|
||||
timeLEDControl = millis();
|
||||
timeLEDCycle = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (wifiConState) {
|
||||
case WFC_ConnectToAP:
|
||||
// @todo isStationMode = true;
|
||||
WiFi.mode(WIFI_STA);
|
||||
wifi_set_sleep_type(NONE_SLEEP_T); // rumor is that this fixes multicast receive
|
||||
//ssid = wifiConfig.getSSID();
|
||||
//pass = wifiConfig.getPassword();
|
||||
WiFi.begin(ssid.c_str(), pass.c_str());
|
||||
timeStateChange = millis();
|
||||
// @todo timeLEDControl = timeStateChange;
|
||||
wifiConState = WFC_JoiningAP;
|
||||
break;
|
||||
case WFC_JoiningAP:
|
||||
// @todo if (timeLEDCycle <= LED_JOINING_MS) {
|
||||
// @todo SetLED(LED_WIFI, 1);
|
||||
// @todo } else {
|
||||
// @todo SetLED(LED_WIFI, 0);
|
||||
// @todo }
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
myIP = WiFi.localIP();
|
||||
Serial.printf("IP Address: %s\n", myIP.toString().c_str());
|
||||
timeStateChange = millis();
|
||||
//StartWebServer();
|
||||
wifiConState = WFC_JoinedAP;
|
||||
} else if (millis() - timeStateChange > 30000) {
|
||||
timeStateChange = millis();
|
||||
wifiConState = WFC_CreateAP; // failed for 30 sec, now what. retry or CreateAP?
|
||||
}
|
||||
break;
|
||||
case WFC_CreateAP:
|
||||
// @todo if (timeLEDCycle <= LED_APMODE__MS) {
|
||||
// @todo SetLED(LED_WIFI, 1);
|
||||
// @todo } else {
|
||||
// @todo SetLED(LED_WIFI, 0);
|
||||
// @todo }
|
||||
// @todo isStationMode = false;
|
||||
Serial.printf("Starting Access Point %s\n", AP_NAME.c_str());
|
||||
WiFi.softAP(AP_NAME.c_str());
|
||||
myIP = WiFi.softAPIP();
|
||||
Serial.printf("IP Address: %s\n", myIP.toString().c_str());
|
||||
//dnsServer.start(DNS_PORT, "growcontroller.info", myIP);
|
||||
timeStateChange = millis();
|
||||
//StartWebServer();
|
||||
wifiConState = WFC_HostingAP;
|
||||
break;
|
||||
case WFC_JoinedAP:
|
||||
// @todo if (timeLEDCycle <= LED_JOINED__MS) {
|
||||
// @todo SetLED(LED_WIFI, 1);
|
||||
// @todo } else {
|
||||
// @todo SetLED(LED_WIFI, 0);
|
||||
// @todo }
|
||||
// @todo server.handleClient();
|
||||
break;
|
||||
case WFC_HostingAP:
|
||||
// @todo if (timeLEDCycle <= LED_APMODE__MS) {
|
||||
// @todo SetLED(LED_WIFI, 1);
|
||||
// @todo } else {
|
||||
// @todo SetLED(LED_WIFI, 0);
|
||||
// @todo }
|
||||
// @todo server.handleClient();
|
||||
// dnsServer.processNextRequest();
|
||||
break;
|
||||
default:
|
||||
case WFC_Idle:
|
||||
break;
|
||||
}
|
||||
return wifiConState;
|
||||
}
|
||||
58
Firmware/WiFiStateHandler.h
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
//
|
||||
// WiFi Connection - handles the state - AP or Client
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef WIFISTATEHANDLER_H
|
||||
#define WIFISTATEHANDLER_H
|
||||
#include <Arduino.h>
|
||||
|
||||
/// WiFi Connection States of connection
|
||||
typedef enum {
|
||||
WFC_ConnectToAP, ///< Connect to an Access Point
|
||||
WFC_JoiningAP, ///< Joining the Access Point
|
||||
WFC_JoinedAP, ///< Joined to the Access Point
|
||||
WFC_CreateAP, ///< Create an Access Point
|
||||
WFC_HostingAP, ///< Hosting an Access Point
|
||||
WFC_Idle, ///< Idle take no action, or invalid
|
||||
} WiFiConnectState;
|
||||
|
||||
/// Get the current state
|
||||
///
|
||||
/// @returns the current state
|
||||
///
|
||||
WiFiConnectState WiFiStateGet();
|
||||
|
||||
|
||||
/// Called from the main loop to manage the WiFi connection state
|
||||
///
|
||||
/// @returns current connection state
|
||||
///
|
||||
/// @code
|
||||
/// void loop() {
|
||||
/// ...
|
||||
/// WiFiStateHandler();
|
||||
/// ...
|
||||
/// }
|
||||
/// @endcode
|
||||
WiFiConnectState WiFiStateHandler(); ///< WiFi interface manager
|
||||
|
||||
/// Used to force a specific state
|
||||
///
|
||||
/// @param[in] newState is the state to set the WiFi connection to
|
||||
///
|
||||
/// @code
|
||||
/// void setup() {
|
||||
/// ...
|
||||
/// if (ssid == "" || pass == "")
|
||||
/// WiFiStateSet(WFC_CreateAP);
|
||||
/// else
|
||||
/// WiFiStateSet(WFC_ConnectToAP);
|
||||
/// ...
|
||||
/// }
|
||||
/// @endcode
|
||||
///
|
||||
void WiFiStateSet(WiFiConnectState newState);
|
||||
|
||||
#endif // WIFISTATEHANDLER_H
|
||||
162
Firmware/WifiConfiguration.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// This file hosts all the non-volatile configuration options for this node
|
||||
//
|
||||
#include <EEPROM.h>
|
||||
|
||||
#include "WiFiConfiguration.h"
|
||||
#include "Utility.h"
|
||||
|
||||
|
||||
ConfigManager::ConfigManager(const ConfigDefaults_t * _defaults) {
|
||||
(void)_defaults;
|
||||
// defaults = _defaults;
|
||||
COMPILER_ASSERT(sizeof(NVConfig_04_t) <= EEROM_SIZE);
|
||||
EEPROM.begin(EEROM_SIZE); // Set for the max expected size
|
||||
// Here we could perform a 'load()' followed by a format check,
|
||||
// and it could then do a graceful update from one version to another,
|
||||
// and then commit it back to the rest of the program doesn't notice.
|
||||
int ret = load();
|
||||
switch (ret) {
|
||||
case MATCHING:
|
||||
// life is good, continue.
|
||||
break;
|
||||
case IS_OLDER:
|
||||
//if (getFormatVersion() == 3) {
|
||||
// Upgrade();
|
||||
// save();
|
||||
//} else {
|
||||
// factoryReset();
|
||||
// save();
|
||||
//}
|
||||
break;
|
||||
case IS_NEWER:
|
||||
// can't politely downgrade, so factory reset it.
|
||||
case IS_BROKEN:
|
||||
default:
|
||||
// factoryReset(); // Can't fix it, so factory reset it.
|
||||
// save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Quite likely that this never runs...
|
||||
ConfigManager::~ConfigManager() {
|
||||
EEPROM.end();
|
||||
}
|
||||
|
||||
|
||||
uint8_t ConfigManager::getFormatVersion() {
|
||||
return Configuration.format[0];
|
||||
}
|
||||
|
||||
uint8_t * ConfigManager::getUserDataHandle() {
|
||||
return Configuration.userData;
|
||||
}
|
||||
|
||||
int ConfigManager::getUserDataSize() {
|
||||
return USERSIZE;
|
||||
}
|
||||
|
||||
|
||||
void ConfigManager::factoryReset() {
|
||||
memset(&Configuration, 0, sizeof(NVConfig_04_t)); // Wipe them to be more secure
|
||||
Configuration.format[0] = EXPECTED_FMT; // put back the minimal
|
||||
Configuration.format[1] = ~EXPECTED_FMT;
|
||||
if (defaults) {
|
||||
strcpy(Configuration.info.name, defaults->name);
|
||||
strcpy(Configuration.info.UPDURL, defaults->UPDURL);
|
||||
strcpy(Configuration.info.NTPURL, defaults->NTPURL);
|
||||
}
|
||||
HexDump("factoryReset", (uint8_t *)&Configuration, sizeof(Configuration));
|
||||
}
|
||||
|
||||
|
||||
ConfigManager::FirmwareCheck_t ConfigManager::load() {
|
||||
uint8_t * ptr = (uint8_t *)&Configuration;
|
||||
size_t i = 0;
|
||||
do {
|
||||
*ptr++ = EEPROM.read(i++);
|
||||
} while (i < sizeof(Configuration));
|
||||
// if ((Configuration.format[0] & 0xFF) != (~Configuration.format[1] & 0xFF)) {
|
||||
// // Factory default
|
||||
// Serial.printf("Bad Configuration\n");
|
||||
// return IS_BROKEN; // Fatal and restored to factory default.
|
||||
// } else if (Configuration.format[0] < EXPECTED_FMT) {
|
||||
// Serial.printf("Old Configuration. It needs an update!\n");
|
||||
// return IS_OLDER;
|
||||
// } else if (Configuration.format[0] > EXPECTED_FMT) {
|
||||
// Serial.printf("Too new a configuration.\n");
|
||||
// return IS_NEWER;
|
||||
// }
|
||||
Serial.printf("Loading from EEROM\n");
|
||||
Serial.printf("Node Name: %s\n", Configuration.info.name);
|
||||
Serial.printf("SSID: %s\n", Configuration.info.ssid);
|
||||
Serial.printf("PASS: %s\n", Configuration.info.pass);
|
||||
Serial.printf("URL : %s\n", Configuration.info.UPDURL);
|
||||
Serial.printf("NTP : %s\n", Configuration.info.NTPURL);
|
||||
HexDump("After Load", (uint8_t *)&Configuration, sizeof(Configuration));
|
||||
// //delay(500);
|
||||
return MATCHING; // no error
|
||||
}
|
||||
|
||||
|
||||
void ConfigManager::save(void) {
|
||||
uint8_t * ptr = (uint8_t *)&Configuration;
|
||||
size_t i = 0;
|
||||
do {
|
||||
EEPROM.write(i++, *ptr++);
|
||||
} while (i < sizeof(Configuration));
|
||||
if (EEPROM.commit()) {
|
||||
Serial.printf("EEPROM.commit() success.\n");
|
||||
} else {
|
||||
Serial.printf("EEPROM.commit() FAILED !!!!!!!! FAILED !!!!!!!! FAILED !!!!!!!!\n");
|
||||
}
|
||||
HexDump("After Save", (uint8_t *)&Configuration, sizeof(Configuration));
|
||||
//delay(500);
|
||||
}
|
||||
|
||||
|
||||
String ConfigManager::getNTPServerName() {
|
||||
return String(Configuration.info.NTPURL);
|
||||
}
|
||||
void ConfigManager::setNTPServerName(String _name) {
|
||||
strncpy(Configuration.info.NTPURL, _name.c_str(), sizeof(Configuration.info.NTPURL));
|
||||
Serial.printf("setNTPServerName(%s)\n", Configuration.info.NTPURL);
|
||||
}
|
||||
|
||||
String ConfigManager::getName() {
|
||||
return String(Configuration.info.name);
|
||||
}
|
||||
|
||||
void ConfigManager::setName(String _name) {
|
||||
strncpy(Configuration.info.name, _name.c_str(), sizeof(Configuration.info.name));
|
||||
Serial.printf("setName(%s)\n", Configuration.info.name);
|
||||
}
|
||||
|
||||
String ConfigManager::getSSID() {
|
||||
return String(Configuration.info.ssid);
|
||||
}
|
||||
|
||||
void ConfigManager::setSSID(String _ssid) {
|
||||
strncpy(Configuration.info.ssid, _ssid.c_str(), sizeof(Configuration.info.ssid));
|
||||
Serial.printf("setSSID(%s)\n", Configuration.info.ssid);
|
||||
}
|
||||
|
||||
String ConfigManager::getPassword() {
|
||||
return String(Configuration.info.pass);
|
||||
}
|
||||
|
||||
void ConfigManager::setPassword(String _password) {
|
||||
strncpy(Configuration.info.pass, _password.c_str(), sizeof(Configuration.info.pass));
|
||||
Serial.printf("setPass(%s)\n", Configuration.info.pass);
|
||||
}
|
||||
|
||||
String ConfigManager::getURL() {
|
||||
return String(Configuration.info.UPDURL);
|
||||
}
|
||||
|
||||
void ConfigManager::setURL(String _url) {
|
||||
strncpy(Configuration.info.UPDURL, _url.c_str(), sizeof(Configuration.info.UPDURL));
|
||||
Serial.printf("setURL (%s)\n", Configuration.info.UPDURL);
|
||||
}
|
||||
|
||||
325
Firmware/doxyfile.dxy
Normal file
@@ -0,0 +1,325 @@
|
||||
# Doxyfile 1.8.14
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "Code Review"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY =
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING = ino=c
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = YES
|
||||
SORT_MEMBERS_CTORS_1ST = YES
|
||||
SORT_GROUP_NAMES = YES
|
||||
SORT_BY_SCOPE_NAME = YES
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = YES
|
||||
WARN_AS_ERROR = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
INPUT =
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.ino \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.idl \
|
||||
*.ddl \
|
||||
*.odl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.cs \
|
||||
*.d \
|
||||
*.php \
|
||||
*.php4 \
|
||||
*.php5 \
|
||||
*.phtml \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.markdown \
|
||||
*.md \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.pyw \
|
||||
*.f90 \
|
||||
*.f95 \
|
||||
*.f03 \
|
||||
*.f08 \
|
||||
*.f \
|
||||
*.for \
|
||||
*.tcl \
|
||||
*.vhd \
|
||||
*.vhdl \
|
||||
*.ucf \
|
||||
*.qsf
|
||||
RECURSIVE = YES
|
||||
EXCLUDE = "Debug" \
|
||||
"Release"
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = YES
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
CLANG_OPTIONS =
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = CodeReview_files/html
|
||||
HTML_FILE_EXTENSION = .htm
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = NO
|
||||
HTML_DYNAMIC_MENUS = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = YES
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = NO
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_PROGRAMLISTING = YES
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
CLASS_DIAGRAMS = YES
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = YES
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = YES
|
||||
CALLER_GRAPH = YES
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH = "C:/Program Files (x86)/Graphviz2.38/bin"
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_CFG_FILE =
|
||||
PLANTUML_INCLUDE_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 1000
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
290
Hardware/GrowController.sch
Normal file
@@ -0,0 +1,290 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE eagle SYSTEM "eagle.dtd">
|
||||
<eagle version="7.7.0">
|
||||
<drawing>
|
||||
<settings>
|
||||
<setting alwaysvectorfont="no"/>
|
||||
<setting verticaltext="up"/>
|
||||
</settings>
|
||||
<grid distance="0.1" unitdist="inch" unit="inch" style="lines" multiple="1" display="no" altdistance="0.01" altunitdist="inch" altunit="inch"/>
|
||||
<layers>
|
||||
<layer number="1" name="Top" color="4" fill="1" visible="no" active="no"/>
|
||||
<layer number="2" name="Route2" color="1" fill="3" visible="no" active="no"/>
|
||||
<layer number="3" name="Route3" color="4" fill="3" visible="no" active="no"/>
|
||||
<layer number="4" name="Route4" color="1" fill="4" visible="no" active="no"/>
|
||||
<layer number="5" name="Route5" color="4" fill="4" visible="no" active="no"/>
|
||||
<layer number="6" name="Route6" color="1" fill="8" visible="no" active="no"/>
|
||||
<layer number="7" name="Route7" color="4" fill="8" visible="no" active="no"/>
|
||||
<layer number="8" name="Route8" color="1" fill="2" visible="no" active="no"/>
|
||||
<layer number="9" name="Route9" color="4" fill="2" visible="no" active="no"/>
|
||||
<layer number="10" name="Route10" color="1" fill="7" visible="no" active="no"/>
|
||||
<layer number="11" name="Route11" color="4" fill="7" visible="no" active="no"/>
|
||||
<layer number="12" name="Route12" color="1" fill="5" visible="no" active="no"/>
|
||||
<layer number="13" name="Route13" color="4" fill="5" visible="no" active="no"/>
|
||||
<layer number="14" name="Route14" color="1" fill="6" visible="no" active="no"/>
|
||||
<layer number="15" name="Route15" color="4" fill="6" visible="no" active="no"/>
|
||||
<layer number="16" name="Bottom" color="1" fill="1" visible="no" active="no"/>
|
||||
<layer number="17" name="Pads" color="2" fill="1" visible="no" active="no"/>
|
||||
<layer number="18" name="Vias" color="2" fill="1" visible="no" active="no"/>
|
||||
<layer number="19" name="Unrouted" color="6" fill="1" visible="no" active="no"/>
|
||||
<layer number="20" name="Dimension" color="15" fill="1" visible="no" active="no"/>
|
||||
<layer number="21" name="tPlace" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="22" name="bPlace" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="23" name="tOrigins" color="15" fill="1" visible="no" active="no"/>
|
||||
<layer number="24" name="bOrigins" color="15" fill="1" visible="no" active="no"/>
|
||||
<layer number="25" name="tNames" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="26" name="bNames" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="27" name="tValues" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="28" name="bValues" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="29" name="tStop" color="7" fill="3" visible="no" active="no"/>
|
||||
<layer number="30" name="bStop" color="7" fill="6" visible="no" active="no"/>
|
||||
<layer number="31" name="tCream" color="7" fill="4" visible="no" active="no"/>
|
||||
<layer number="32" name="bCream" color="7" fill="5" visible="no" active="no"/>
|
||||
<layer number="33" name="tFinish" color="6" fill="3" visible="no" active="no"/>
|
||||
<layer number="34" name="bFinish" color="6" fill="6" visible="no" active="no"/>
|
||||
<layer number="35" name="tGlue" color="7" fill="4" visible="no" active="no"/>
|
||||
<layer number="36" name="bGlue" color="7" fill="5" visible="no" active="no"/>
|
||||
<layer number="37" name="tTest" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="38" name="bTest" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="39" name="tKeepout" color="4" fill="11" visible="no" active="no"/>
|
||||
<layer number="40" name="bKeepout" color="1" fill="11" visible="no" active="no"/>
|
||||
<layer number="41" name="tRestrict" color="4" fill="10" visible="no" active="no"/>
|
||||
<layer number="42" name="bRestrict" color="1" fill="10" visible="no" active="no"/>
|
||||
<layer number="43" name="vRestrict" color="2" fill="10" visible="no" active="no"/>
|
||||
<layer number="44" name="Drills" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="45" name="Holes" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="46" name="Milling" color="3" fill="1" visible="no" active="no"/>
|
||||
<layer number="47" name="Measures" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="48" name="Document" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="49" name="Reference" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="50" name="dxf" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="51" name="tDocu" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="52" name="bDocu" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="53" name="tGND_GNDA" color="7" fill="9" visible="no" active="no"/>
|
||||
<layer number="54" name="bGND_GNDA" color="1" fill="9" visible="no" active="no"/>
|
||||
<layer number="56" name="wert" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="57" name="tCAD" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="59" name="tCarbon" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="60" name="bCarbon" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="90" name="Modules" color="5" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="91" name="Nets" color="2" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="92" name="Busses" color="1" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="93" name="Pins" color="2" fill="1" visible="no" active="yes"/>
|
||||
<layer number="94" name="Symbols" color="4" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="95" name="Names" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="96" name="Values" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="97" name="Info" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="98" name="Guide" color="6" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="99" name="SpiceOrder" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="100" name="Muster" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="101" name="Patch_Top" color="12" fill="4" visible="yes" active="yes"/>
|
||||
<layer number="102" name="Vscore" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="103" name="tMap" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="104" name="Name" color="16" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="105" name="tPlate" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="106" name="bPlate" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="107" name="Crop" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="108" name="tplace-old" color="10" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="109" name="ref-old" color="11" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="110" name="fp0" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="111" name="LPC17xx" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="112" name="tSilk" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="113" name="IDFDebug" color="4" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="114" name="Route14" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="115" name="Route15" color="7" fill="1" visible="no" active="no"/>
|
||||
<layer number="116" name="Patch_BOT" color="9" fill="4" visible="yes" active="yes"/>
|
||||
<layer number="117" name="mPads" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="118" name="mVias" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="119" name="mUnrouted" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="120" name="mDimension" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="121" name="_tsilk" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="122" name="_bsilk" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="123" name="mtOrigins" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="124" name="mbOrigins" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="125" name="mtNames" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="126" name="mbNames" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="127" name="mtValues" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="128" name="mbValues" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="129" name="mtStop" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="130" name="mbStop" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="131" name="mtCream" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="132" name="mbCream" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="133" name="mtFinish" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="134" name="mbFinish" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="135" name="mtGlue" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="136" name="mbGlue" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="137" name="mtTest" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="138" name="mbTest" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="139" name="mtKeepout" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="140" name="mbKeepout" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="141" name="mtRestrict" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="142" name="mbRestrict" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="143" name="mvRestrict" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="144" name="Drill_legend" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="145" name="mHoles" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="146" name="mMilling" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="147" name="mMeasures" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="148" name="mDocument" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="149" name="mReference" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="150" name="Notes" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="151" name="HeatSink" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="152" name="mbDocu" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="153" name="FabDoc1" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="154" name="FabDoc2" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="155" name="FabDoc3" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="160" name="Outline" color="14" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="188" name="Graphics" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="191" name="mNets" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="192" name="mBusses" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="193" name="mPins" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="194" name="mSymbols" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="195" name="mNames" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="196" name="mValues" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="199" name="Contour" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="200" name="200bmp" color="1" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="201" name="201bmp" color="2" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="202" name="202bmp" color="3" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="203" name="203bmp" color="4" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="204" name="204bmp" color="5" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="205" name="205bmp" color="6" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="206" name="206bmp" color="7" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="207" name="207bmp" color="8" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="208" name="208bmp" color="9" fill="10" visible="yes" active="yes"/>
|
||||
<layer number="209" name="209bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="210" name="210bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="211" name="211bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="212" name="212bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="213" name="213bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="214" name="214bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="215" name="215bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="216" name="SMD16" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="217" name="217bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="218" name="218bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="219" name="219bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="220" name="220bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="221" name="221bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="222" name="222bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="223" name="223bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="224" name="224bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="225" name="225bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="226" name="226bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="227" name="227bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="228" name="228bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="229" name="229bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="230" name="230bmp" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="231" name="Eagle3D_PG1" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="232" name="Eagle3D_PG2" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="233" name="Eagle3D_PG3" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="248" name="Housing" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="249" name="Edge" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="250" name="Descript" color="3" fill="1" visible="no" active="no"/>
|
||||
<layer number="251" name="SMDround" color="12" fill="11" visible="no" active="no"/>
|
||||
<layer number="254" name="cooling" color="7" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="255" name="Accent" color="7" fill="1" visible="yes" active="yes"/>
|
||||
</layers>
|
||||
<schematic xreflabel="%F%N/%S.%C%R" xrefpart="/%S.%C%R">
|
||||
<libraries>
|
||||
<library name="Smartware">
|
||||
<description><b>Parts</b></description>
|
||||
<packages>
|
||||
</packages>
|
||||
<symbols>
|
||||
<symbol name="FRAME_A_L">
|
||||
<frame x1="0" y1="0" x2="254" y2="196.85" columns="6" rows="5" layer="94" border-bottom="no"/>
|
||||
</symbol>
|
||||
<symbol name="DOCFIELD">
|
||||
<wire x1="0" y1="0" x2="71.12" y2="0" width="0.1016" layer="94"/>
|
||||
<wire x1="101.6" y1="10.16" x2="80.01" y2="10.16" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="0" x2="0" y2="5.08" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="5.08" x2="71.12" y2="5.08" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="5.08" x2="0" y2="10.16" width="0.1016" layer="94"/>
|
||||
<wire x1="101.6" y1="10.16" x2="101.6" y2="5.08" width="0.1016" layer="94"/>
|
||||
<wire x1="71.12" y1="5.08" x2="71.12" y2="0" width="0.1016" layer="94"/>
|
||||
<wire x1="71.12" y1="5.08" x2="80.01" y2="5.08" width="0.1016" layer="94"/>
|
||||
<wire x1="71.12" y1="0" x2="101.6" y2="0" width="0.1016" layer="94"/>
|
||||
<wire x1="80.01" y1="10.16" x2="80.01" y2="5.08" width="0.1016" layer="94"/>
|
||||
<wire x1="80.01" y1="10.16" x2="0" y2="10.16" width="0.1016" layer="94"/>
|
||||
<wire x1="80.01" y1="5.08" x2="101.6" y2="5.08" width="0.1016" layer="94"/>
|
||||
<wire x1="101.6" y1="5.08" x2="101.6" y2="0" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="10.16" x2="0" y2="15.24" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="15.24" x2="0" y2="24.13" width="0.1016" layer="94"/>
|
||||
<wire x1="101.6" y1="34.29" x2="0" y2="34.29" width="0.1016" layer="94"/>
|
||||
<wire x1="101.6" y1="34.29" x2="101.6" y2="29.21" width="0.1016" layer="94"/>
|
||||
<wire x1="101.6" y1="29.21" x2="101.6" y2="24.13" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="24.13" x2="101.6" y2="24.13" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="24.13" x2="0" y2="29.21" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="29.21" x2="0" y2="34.29" width="0.1016" layer="94"/>
|
||||
<wire x1="101.6" y1="24.13" x2="101.6" y2="15.24" width="0.1016" layer="94"/>
|
||||
<wire x1="101.6" y1="15.24" x2="101.6" y2="10.16" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="29.21" x2="101.6" y2="29.21" width="0.1016" layer="94"/>
|
||||
<wire x1="0" y1="15.24" x2="101.6" y2="15.24" width="0.1016" layer="94"/>
|
||||
<text x="1.27" y="1.27" size="2.54" layer="94" font="vector">Date:</text>
|
||||
<text x="12.7" y="1.27" size="2.54" layer="94" font="vector">>LAST_DATE_TIME</text>
|
||||
<text x="72.39" y="1.27" size="2.54" layer="94" font="vector">Sheet:</text>
|
||||
<text x="86.36" y="1.27" size="2.54" layer="94" font="vector">>SHEET</text>
|
||||
<text x="81.28" y="6.35" size="2.54" layer="94" font="vector">Rev:</text>
|
||||
<text x="1.27" y="30.48" size="2.54" layer="94" font="vector">Document Title:</text>
|
||||
<text x="1.27" y="6.35" size="2.54" layer="94" font="vector">Part Number:</text>
|
||||
<text x="35.56" y="30.48" size="2.54" layer="94" font="vector">>DRAWING_NAME</text>
|
||||
<text x="1.27" y="25.4" size="2.54" layer="94" font="vector">Sheet Function:</text>
|
||||
<text x="30.48" y="6.35" size="2.54" layer="94" font="vector">>PART_NUMBER</text>
|
||||
<text x="91.44" y="6.35" size="2.54" layer="94" font="vector">>PART_REV</text>
|
||||
<text x="5.08" y="20.32" size="2.54" layer="94" font="vector">>COMPANY_NAME</text>
|
||||
<text x="5.08" y="16.51" size="2.54" layer="94" font="vector">>COMPANY_ADDR</text>
|
||||
<text x="1.27" y="11.43" size="2.54" layer="94" font="vector">Drawn:</text>
|
||||
<text x="30.48" y="11.43" size="2.54" layer="94" font="vector">>ENGINEER</text>
|
||||
<text x="35.56" y="25.4" size="2.54" layer="94" font="vector">>MODULE</text>
|
||||
</symbol>
|
||||
</symbols>
|
||||
<devicesets>
|
||||
<deviceset name="FRAME_A_L" prefix="FRAME" uservalue="yes">
|
||||
<description><b>FRAME - A Landscape</b><br/>
|
||||
Smartware Computing</description>
|
||||
<gates>
|
||||
<gate name="G$1" symbol="FRAME_A_L" x="0" y="0" addlevel="always"/>
|
||||
<gate name="G$2" symbol="DOCFIELD" x="148.59" y="0" addlevel="always"/>
|
||||
</gates>
|
||||
<devices>
|
||||
<device name="">
|
||||
<technologies>
|
||||
<technology name=""/>
|
||||
</technologies>
|
||||
</device>
|
||||
</devices>
|
||||
</deviceset>
|
||||
</devicesets>
|
||||
</library>
|
||||
</libraries>
|
||||
<attributes>
|
||||
<attribute name="COMPANY_ADDR" value="https://smart-family.net/Smartware"/>
|
||||
<attribute name="COMPANY_NAME" value="Smartware Computing"/>
|
||||
<attribute name="ENGINEER" value="D.Smart"/>
|
||||
<attribute name="PART_NUMBER" value="GrowController"/>
|
||||
<attribute name="PART_REV" value="0.0"/>
|
||||
</attributes>
|
||||
<variantdefs>
|
||||
</variantdefs>
|
||||
<classes>
|
||||
<class number="0" name="default" width="0" drill="0">
|
||||
</class>
|
||||
</classes>
|
||||
<parts>
|
||||
<part name="FRAME1" library="Smartware" deviceset="FRAME_A_L" device=""/>
|
||||
</parts>
|
||||
<sheets>
|
||||
<sheet>
|
||||
<plain>
|
||||
</plain>
|
||||
<instances>
|
||||
<instance part="FRAME1" gate="G$1" x="0" y="0"/>
|
||||
<instance part="FRAME1" gate="G$2" x="148.59" y="0"/>
|
||||
</instances>
|
||||
<busses>
|
||||
</busses>
|
||||
<nets>
|
||||
</nets>
|
||||
</sheet>
|
||||
</sheets>
|
||||
</schematic>
|
||||
</drawing>
|
||||
</eagle>
|
||||
362
Hardware/eagle.epf
Normal file
@@ -0,0 +1,362 @@
|
||||
[Eagle]
|
||||
Version="07 07 00"
|
||||
Platform="Windows"
|
||||
Serial="6C0781BDA8-LSR-WLM-1CP"
|
||||
Globals="Globals"
|
||||
Desktop="Desktop"
|
||||
|
||||
[Globals]
|
||||
AutoSaveProject=1
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/19inch.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/40xx.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/41xx.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/45xx.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/74ac-logic.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/74ttl-din.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/74xx-eu.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/74xx-little-de.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/74xx-little-us.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/74xx-us.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/751xx.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/IQD-Frequency-Products.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/advanced-test-technologies.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/agilent-technologies.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/allegro.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/altera-cyclone-II.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/altera-cyclone-III.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/altera-stratix-iv.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/altera.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/am29-memory.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/amd-mach.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/amd.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/amis.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/analog-devices.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/aplus.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/ase.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/atmel.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/austriamicrosystems.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/avago.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/axis.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/battery.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/belton-engineering.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/burr-brown.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/busbar.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/buzzer.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/c-trimm.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/california-micro-devices.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/capacitor-wima.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/chipcard-siemens.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/cirrus-logic.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-3m.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-4ucon.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-amp-champ.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-amp-micromatch.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-amp-mt.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-amp-mt6.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-amp-quick.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-amp-te.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-amp.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-amphenol.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-avx.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-berg.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-bosch.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-chipcard-iso7816.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-coax.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-commcon.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-conrad.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-cpci.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-cui.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-cypressindustries.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-deutsch.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-dil.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-ebyelectro.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-elco.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-erni.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-faston.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-fci.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-friwo.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-garry.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-harting-h.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-harting-ml.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-harting-v.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-harting.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-hirose.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-hirschmann.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-jack.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-jae.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-jst.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-kycon.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-kyocera-elco.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-lemo.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-leotronics.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-lsta.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-lstb.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-lumberg.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-ml.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-molex.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-neutrik_ag.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-omron.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-panasonic.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-panduit.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-pc.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-pc104.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-254.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-3.81.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-350.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-500.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-508.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-762.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-me_max.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-mkds_5.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-phoenix-smkdsp.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-ptr500.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-pulse.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-rib.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-samtec.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-shallin.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-shiua-chyuan.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-stewart.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-stocko.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-subd.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-sullinselectronics.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-thomas-betts.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-tyco.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-tycoelectronics.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-vg.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-wago-500.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-wago-508.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-wago.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-wago255.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-weidmueller-sl35.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-wenzhou-yihua.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-xmultiple.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/con-yamaichi.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/crystal.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/csr.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/cypress.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/davicom.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/dc-dc-converter.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/dimensions.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/diode.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/discrete.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/display-hp.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/display-kingbright.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/display-lcd.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/docu-dummy.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/dom-key.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/eagle-ltspice.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/ecl.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/em-microelectronic.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/etx-board.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/exar.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/fairchild-semic.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/farnell.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/fiber-optic-hp.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/fiber-optic-siemens.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/fifo.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/flexipanel.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/fox-electronics.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/frames.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/freescale.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/ftdichip.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/fujitsu.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/fuse.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/gennum.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/halo-electronics.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/heatsink.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/holes.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/holtek.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/ic-package.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/inductor-coilcraft.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/inductor-neosid.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/inductor-nkl.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/inductors.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/infineon-tricore.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/infineon.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/intersil-techwell.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/intersil.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/ir.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/isd.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/johanson-technology.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/jump-0r-smd.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/jumper.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/lantronix.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/lattice.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/lc-filter.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/led-7-segment.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/led-citizen-electronics.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/led-lumiled.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/led.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/lem.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/linear-technology.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/linear.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/linx.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/logo.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/lprs.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/lsi-computer-systems.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/lumiled.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/marks.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/maxim.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/maxstream.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/melexis.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/memory-hitachi.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/memory-idt.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/memory-micron.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/memory-motorola-dram.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/memory-nec.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/memory-samsung.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/memory-sram.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/memory.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/mems.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micrel.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-cyrod.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-fujitsu.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-harris.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-hitachi.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-infineon.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-intel.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-mc68000.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-motorola.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-philips.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-renesas.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-samsung.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micro-siemens.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/microchip.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micron.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/micronas.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/microphon.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/microwave.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/midori-sensor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/minicircuits.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/mitsubishi-semiconductor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/motorola-sensor-driver.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/murata-filter.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/murata-sensor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/nanotec.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/national-instruments.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/national-semiconductor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/nec-lqfp100-pack.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/nec.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/nrj-semiconductor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/omnivision.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/on-semiconductor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/opto-honeywell-3000.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/opto-honeywell-4000.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/opto-honeywell.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/opto-micro-linear.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/opto-trans-siemens.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/opto-transmittter-hp.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/opto-vishay.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/optocoupler.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/pal.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/philips-semiconductors.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/photo-elements.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/piher.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/pinhead.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/plcc-socket.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/pld-intel.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/plxtech.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/pot-vitrohm.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/pot-xicor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/pot.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/ptc-ntc.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/quantum-research-group.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/rcl.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/recom-international.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/rectifier.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/ref-packages-longpad.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/ref-packages.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/relay.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/renesas.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/resistor-bourns.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/resistor-dil.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/resistor-net.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/resistor-power.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/resistor-ruf.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/resistor-shunt.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/resistor-sil.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/resistor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/rf-micro-devices.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/rf-solutions.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/rohm.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/roundsolutions.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/semicon-smd-ipc.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/sensor-comus-group.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/sensor-heraeus.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/sensor-infratec.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/sharp.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/silabs.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/sim-technology.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/sipex.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/smd-ipc.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/smd-special.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/solomon-systech.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/solpad.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/speaker.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/special-drill.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/special.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/st-microelectronics.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/stm32xx.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/supertex.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/supply1.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/supply2.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/switch-alps.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/switch-coto.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/switch-dil.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/switch-misc.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/switch-omron.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/switch-raychem.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/switch-reed.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/switch.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/telcom.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/telecontrolli.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/telefunken.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/test-mate.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/testpad.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/texas-sn55-sn75.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/texas.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/toshiba.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/traco-electronic.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/trafo-bei.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/trafo-hammondmfg.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/trafo-siemens.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/trafo-xicon.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/trafo.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/transformer-pulse.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/transistor-fet.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/transistor-neu-to92.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/transistor-npn.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/transistor-pnp.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/transistor-power.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/transistor-small-signal.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/transistor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/triac.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/trimble.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/tripas.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/u-blox.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/uln-udn.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/v-reg-micrel.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/v-reg.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/varistor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/wafer-scale-psd.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/wirepad.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/xicor.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/xilinx-virtex-v5.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/xilinx-xc18v.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/xilinx-xc9.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/xilinx-xcv.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/zetex.lbr"
|
||||
UsedLibrary="C:/Program Files/EAGLE-7.7.0/lbr/zilog.lbr"
|
||||
UsedLibrary="d:/Projects/Eagle/lbr/ESP8266Modules.lbr"
|
||||
UsedLibrary="d:/Projects/Eagle/lbr/Enclosures-PCBs.lbr"
|
||||
UsedLibrary="d:/Projects/Eagle/lbr/Smartware.lbr"
|
||||
|
||||
[Win_1]
|
||||
Type="Control Panel"
|
||||
Loc="380 195 1389 808"
|
||||
State=2
|
||||
Number=0
|
||||
|
||||
[Desktop]
|
||||
Screen="3840 1080"
|
||||
Window="Win_1"
|
||||
268
Tools/MakeByteArray.pl
Normal file
@@ -0,0 +1,268 @@
|
||||
# MakeByteArray
|
||||
#
|
||||
#
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
my $maxCols = 16;
|
||||
my $maxLines = 0;
|
||||
my $ESP = 0;
|
||||
my $DIR = 0;
|
||||
my $ROOT = 0;
|
||||
my $UINT8 = 0;
|
||||
my $file = "";
|
||||
my $ctrlC = 0; # User induced termination
|
||||
my $lineT = 0; # Linecount induced termination
|
||||
|
||||
$SIG{INT} = \&CtrlCHandler;
|
||||
$SIG{QUIT} = \&CtrlCHandler;
|
||||
|
||||
my %DirInfo; # Name and FileSize
|
||||
|
||||
my $prg = $0;
|
||||
$prg =~ s/^.*[\\\/](.*)/$1/;
|
||||
$prg =~ s/(.*)\..*/$1/;
|
||||
|
||||
my $VERSION = 1.0;
|
||||
|
||||
# Extension in this list must be lower case.
|
||||
my %FileType = (
|
||||
"htm" => "text/html",
|
||||
"html" => "text/html",
|
||||
"gif" => "image/gif",
|
||||
"svg" => "image/svg+xml",
|
||||
"css" => "text/css",
|
||||
"ico" => "image/x-icon",
|
||||
"png" => "image/png",
|
||||
"jpg" => "image/jpeg",
|
||||
"js" => "text/javascript",
|
||||
);
|
||||
|
||||
|
||||
if (!@ARGV)
|
||||
{
|
||||
print <<EOM;
|
||||
|
||||
$prg [file|<wildcard> [...]] [-n=##] [-l=##] [-ESP] [-DIR] [-o=outfile]
|
||||
version $VERSION
|
||||
|
||||
Dumps out the contents of the [file(s)] as a c array.
|
||||
|
||||
If the file is binary, it emits a hex char-array using
|
||||
the -n and -l settings.
|
||||
If the file is text, it emits as an ascii char-array
|
||||
where each source line is one ascii quoted line.
|
||||
|
||||
-ESP adds the PROGMEM attribute to the byte array data.
|
||||
|
||||
-DIR adds a 'directory' at the end of the output, providing
|
||||
a reference to each input file. Most useful for a set
|
||||
of files.
|
||||
|
||||
-ROOT prefixes each entry in the 'directory' with '/',
|
||||
so "index.htm" becomes
|
||||
|
||||
-o=outfile Writes the output to outfile.
|
||||
|
||||
-u overrides the default 'char' array to be 'uint8_t'
|
||||
NOTE that the filename and type info remains 'char'.
|
||||
-n=## sets the byte count for each line, defaults 32.
|
||||
-l=## sets a termination after ## lines have been printed.
|
||||
|
||||
Example: MakeByteArray -ESP srcpath\\*.* -o=dstpath\\Web_Resources.h
|
||||
|
||||
EOM
|
||||
exit;
|
||||
}
|
||||
|
||||
my @files;
|
||||
my $outfile = "";
|
||||
|
||||
#printf("ARGS: '%s'\n", join("|", @ARGV));
|
||||
foreach (@ARGV)
|
||||
{
|
||||
if (/-n=(\d+)/)
|
||||
{ $maxCols = $1; }
|
||||
elsif (/-l=(\d+)/)
|
||||
{ $maxLines = $1; }
|
||||
elsif (/-o=(.*)/)
|
||||
{ $outfile = $1; }
|
||||
elsif (/-ESP/)
|
||||
{ $ESP = 1; }
|
||||
elsif (/-ROOT/)
|
||||
{ $ROOT = 1; }
|
||||
elsif (/-DIR/)
|
||||
{ $DIR = 1; }
|
||||
elsif (/-u/)
|
||||
{ $UINT8 = 1; }
|
||||
elsif (-e $_ )
|
||||
{ push @files, $_; }
|
||||
elsif (/[\*\?]/)
|
||||
{
|
||||
my @gFiles = glob($_);
|
||||
foreach (@gFiles)
|
||||
{
|
||||
push @files, $_ if (-e $_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ print "unrecognized command.\n"; exit; }
|
||||
}
|
||||
|
||||
if (!@files)
|
||||
{
|
||||
print "No files to process.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
my $oldHandle;
|
||||
if ($outfile ne "") {
|
||||
#printf("Open for write '%s'\n", $outfile);
|
||||
open(FO, ">$outfile") || die("Can't write to $outfile");
|
||||
$oldHandle = select FO;
|
||||
} else {
|
||||
printf("No outfile, emitting to console.\n");
|
||||
}
|
||||
printf("//\n");
|
||||
printf("// Command: %s %s\n", $prg, join(" ", @ARGV));
|
||||
printf("// version: %2.1f\n", $VERSION);
|
||||
printf("// From cwd: %s\n", cwd);
|
||||
printf("// Generated: %s\n", scalar localtime());
|
||||
printf("// NOTE: Run script in command shell, not PowerShell\n");
|
||||
printf("//\n");
|
||||
|
||||
if ($ESP) {
|
||||
print <<EOM;
|
||||
// PROGMEM is not recognized by Win32 tools...
|
||||
#ifdef WIN32
|
||||
#define PROGMEM
|
||||
#endif
|
||||
EOM
|
||||
}
|
||||
|
||||
my @summary;
|
||||
foreach my $file (@files) {
|
||||
push @summary, Process($file);
|
||||
last if ($ctrlC);
|
||||
}
|
||||
|
||||
print "\n// Prototypes:\n// " . join("\n// ", @summary) . "\n";
|
||||
|
||||
if ($DIR) {
|
||||
my $type = "char "; #($UINT8) ? "uint8_t" : "char ";
|
||||
print <<EOM;
|
||||
|
||||
// Directory of Files
|
||||
//
|
||||
// This typedef is used to iterate through the directory listing, until
|
||||
// an empty "" Filename is reached.
|
||||
//
|
||||
typedef struct {
|
||||
const char * Filename;
|
||||
const $type * Filedata;
|
||||
const char * Filetype;
|
||||
uint16_t Filesize;
|
||||
} DirEntry;
|
||||
|
||||
EOM
|
||||
|
||||
printf("const DirEntry Directory[] %s= {\n", ($ESP) ? "PROGMEM " : "");
|
||||
foreach my $file (sort keys %DirInfo) {
|
||||
#printf(STDERR "file %s, title %s, size %d\n", $file, $DirInfo{$file}{'reference'}, $DirInfo{$file}{'size'});
|
||||
my $title = $DirInfo{$file}{'reference'};
|
||||
my $fn = sprintf("\"%s%s\"", $ROOT ? "/" : "", $file);
|
||||
my $ext = "";
|
||||
$ext = $1 if ($file =~ /.*\.(.*)/);
|
||||
my $ftype = sprintf("\"%s\"", $FileType{$ext});
|
||||
#printf(STDERR "ext: '%s' => '%s'\n", $ext, $FileType{lc($ext)});
|
||||
printf("\t{ %-20s, %-20s, %24s, %6d },\n", $fn, $title, $ftype, $DirInfo{$file}{'size'});
|
||||
}
|
||||
printf("\t{ %-20s, %-20s, %24s, %6d }\n", "NULL", "NULL", "NULL", 0);
|
||||
printf("};\n\n");
|
||||
}
|
||||
|
||||
if ($outfile) {
|
||||
close FO;
|
||||
select($oldHandle);
|
||||
}
|
||||
print "\nTerminated by operator\n" if ($ctrlC == 1);
|
||||
exit;
|
||||
|
||||
# ####################################
|
||||
|
||||
sub Process {
|
||||
my $file = shift;
|
||||
my $title = $file;
|
||||
my $isText = 0;
|
||||
my $prototype;
|
||||
|
||||
$title =~ s/\./_/g;
|
||||
$isText = 1 if (-T $file);
|
||||
open(FH, "<$file") || die("Can't read $file.\n");
|
||||
binmode FH if ($isText);
|
||||
my $cols = 0;
|
||||
my $c;
|
||||
my $ascii = "";
|
||||
my $address = 0;
|
||||
my $lineCount = 0;
|
||||
printf("\n");
|
||||
printf("// File: %s\n", $file);
|
||||
printf("//\n");
|
||||
$prototype = sprintf("const %s %s[]%s", ($UINT8) ? "uint8_t" : "char", $title, ($ESP) ? " PROGMEM" : "");
|
||||
printf("%s = {\n", $prototype);
|
||||
|
||||
my $size = 0;
|
||||
if ($isText) {
|
||||
while (<FH>) {
|
||||
my $line = $_;
|
||||
chomp $line;
|
||||
$line =~ s/\t/ /g;
|
||||
$line =~ s/\\"/"/g;
|
||||
$line =~ s/\r//g;
|
||||
$line =~ s/"/\\"/g;
|
||||
printf("\t\"%s\\n\"\n", $line);
|
||||
$size += length($line) + 1; # +1 for the \n line termination.
|
||||
}
|
||||
} else {
|
||||
printf("\t");
|
||||
while (sysread(FH, $c, 1) && !$ctrlC && !$lineT) {
|
||||
my $b = ord($c);
|
||||
printf("0x%02X,", $b);
|
||||
if ($b >= 0x20 && $b <= 0x7F)
|
||||
{ $ascii .= chr($b); }
|
||||
else
|
||||
{ $ascii .= "."; }
|
||||
++$cols;
|
||||
++$address;
|
||||
$cols %= $maxCols;
|
||||
if ($cols == 0) {
|
||||
#print " // $ascii";
|
||||
print "\n";
|
||||
$ascii = "";
|
||||
$lineCount++;
|
||||
$lineT = 1 if ($maxLines && $lineCount >= $maxLines);
|
||||
if (!$lineT) {
|
||||
printf("\t");
|
||||
}
|
||||
}
|
||||
$size += 1;
|
||||
}
|
||||
if ($ascii ne "") {
|
||||
print " " x ($maxCols - $cols);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("}; // %s, %d bytes\n", $title, $size);
|
||||
close FH;
|
||||
$DirInfo{$file}{'reference'} = $title;
|
||||
$DirInfo{$file}{'size'} = $size;
|
||||
return $prototype;
|
||||
}
|
||||
|
||||
# If the user presses Control-C, signal it.
|
||||
#
|
||||
sub CtrlCHandler {
|
||||
$ctrlC = 1;
|
||||
}
|
||||
|
||||
55
Tools/MakeResourceFiles.cmd
Normal file
@@ -0,0 +1,55 @@
|
||||
@echo off
|
||||
REM
|
||||
REM "Compile" the web resources folder into code modules.
|
||||
REM
|
||||
REM Command : MakeByteArray -ESP -ROOT -DIR *.* -o=..\Web_Resources.h
|
||||
REM From cwd : C:/Projects/SmartSwitch/Firmware/Resources
|
||||
REM Run script in command shell, not PowerShell
|
||||
REM
|
||||
REM External Dependency:
|
||||
REM MakeByteArray - Converts 1 or more files into a .h file byte array.
|
||||
REM
|
||||
REM +------------------------------------------------+
|
||||
REM | MakeResourceFiles.cmd |
|
||||
REM +------------------------------------------------+
|
||||
REM ||
|
||||
REM +----------+ +-----------+ +-----------+
|
||||
REM +----------+ | |Make | | |
|
||||
REM |source | | |Byte | |Resources.h|
|
||||
REM |.htm | | ==> |Array.pl | ==> | |
|
||||
REM |.js | | | | | |
|
||||
REM |.jpg | | | | | |
|
||||
REM |etc... |-+ | | | |
|
||||
REM +----------+ +-----------+ +-----------+
|
||||
setlocal
|
||||
|
||||
REM ######################################################################
|
||||
REM
|
||||
REM Configuration Options
|
||||
REM
|
||||
|
||||
set SRC=..\Firmware\Resources
|
||||
set TARG=..\Web_Resources.h
|
||||
|
||||
REM
|
||||
REM End of Configuration
|
||||
REM
|
||||
REM ######################################################################
|
||||
|
||||
echo.
|
||||
echo.Make Resource Files
|
||||
echo.Change to %SRC% ...
|
||||
pushd %SRC%
|
||||
|
||||
echo.Show web resources
|
||||
dir /b
|
||||
|
||||
echo.
|
||||
echo.Compiling the web resources into code modules...
|
||||
MakeByteArray -ESP -ROOT -DIR *.* -o=%TARG%
|
||||
|
||||
echo.
|
||||
echo.Done. %TARG% has been updated and returning to prior folder.
|
||||
dir %TARG%
|
||||
popd
|
||||
endlocal
|
||||
124
Tools/MoveToServer.pl
Normal file
@@ -0,0 +1,124 @@
|
||||
#
|
||||
# Move to Server
|
||||
#
|
||||
# Monitor the debug and release folders for a new binary.
|
||||
# If found,
|
||||
# 1 Read the .ino file to find the current version string.
|
||||
# 2 Rename the .bin to include the version string.
|
||||
# 3 Move it to the server.
|
||||
#
|
||||
# Searches .ino file for: const String MyVer = "SmartSwitch v1.02.24";
|
||||
#
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
###################### Configuration ###########################
|
||||
#
|
||||
# Target Server Path
|
||||
#
|
||||
my $ServerPath = "\\\\server1\\web\\mbed\\ESPbin";
|
||||
|
||||
# Sleep Time between checks
|
||||
#
|
||||
my $SleepTime = 5;
|
||||
|
||||
# Verbose mode
|
||||
# 0 = off
|
||||
# 1 = highlights
|
||||
# 2 = detailed
|
||||
#
|
||||
my $Verbose = 1;
|
||||
|
||||
#####################
|
||||
|
||||
my $continue = 1;
|
||||
|
||||
$SIG{INT} = sub { $continue = 0; };
|
||||
$SIG{TERM} = sub { $continue = 0; };
|
||||
|
||||
do {
|
||||
printf("\n") if ($Verbose > 1);
|
||||
printf("MoveToServer check at %s\n", scalar localtime()) if ($Verbose == 1);
|
||||
chdir "../Firmware";
|
||||
Process();
|
||||
Pause($SleepTime);
|
||||
} while ($continue);
|
||||
|
||||
exit;
|
||||
|
||||
####################################################################
|
||||
|
||||
|
||||
sub Process {
|
||||
my $slnFile = "";
|
||||
|
||||
my @files = glob("*.sln");
|
||||
foreach (@files) {
|
||||
$slnFile = $_;
|
||||
printf(" Found: %s\n", $slnFile) if ($Verbose > 1);
|
||||
}
|
||||
|
||||
if ($slnFile eq "") {
|
||||
printf(" *** No Solution Files found ...\n") if ($Verbose == 1);
|
||||
return;
|
||||
}
|
||||
|
||||
my $inoFile = $slnFile;
|
||||
$inoFile =~ s/(.*)\.sln/$1\.ino/;
|
||||
if (!-e $inoFile) {
|
||||
printf(" *** %s not found ...\n", $inoFile) if ($Verbose == 1);
|
||||
return;
|
||||
}
|
||||
printf(" Search %s\n", $inoFile) if ($Verbose > 1);
|
||||
my $verString = GetVerString($inoFile);
|
||||
if ($verString eq "") {
|
||||
printf(" *** No Version string in %s ...\n", $inoFile) if ($Verbose == 1);
|
||||
return;
|
||||
}
|
||||
printf(" Version '%s'\n", $verString) if ($Verbose > 1);
|
||||
|
||||
my $targBin = $slnFile;
|
||||
$targBin =~ s/(.*)\.sln/$1\.bin/;
|
||||
printf(" Target Bin file is %s\n", $targBin) if ($Verbose > 1);
|
||||
|
||||
my @Folders = qw(Debug Release);
|
||||
foreach my $f (@Folders) {
|
||||
printf(" Scanning %s\n", $f) if ($Verbose > 1);
|
||||
my $tF = "$f\\$targBin";
|
||||
if (-e $tF) {
|
||||
printf(" Processing %s\n", $tF) if ($Verbose > 1);
|
||||
my $srvrFile = "$ServerPath\\$verString.bin";
|
||||
my $cmd = sprintf("move /Y \"%s\" \"%s\"", $tF, $srvrFile);
|
||||
printf(" > %s\n", $cmd);
|
||||
`$cmd`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub Pause {
|
||||
my $dly = shift;
|
||||
my $count = 0;
|
||||
|
||||
while ($count++ < $dly && $continue) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
sub GetVerString {
|
||||
my $iF = shift;
|
||||
my $ver = "";
|
||||
|
||||
open(IF, "<$iF") || return $ver;
|
||||
#const String MyVer = "SmartSwitch v1.02.24";
|
||||
while (<IF>) {
|
||||
if (/String MyVer = \"(.*)\"/) {
|
||||
$ver = $1;
|
||||
last;
|
||||
#close IF;
|
||||
#return $ver;
|
||||
}
|
||||
}
|
||||
close IF;
|
||||
return $ver;
|
||||
}
|
||||