Cant get code to compile

I've been trying to get this code for a Autonomous satellite tracker to work, but I am now at a loss.

I' using an Adafruit Feather HUZZAH with ESP8266

I dl'd from here: https://www.clearskyinstitute.com/ham/AST/AutoSatTracker-2016082822.zip

I made my own avr subfolder with all of the needed avr files.

Any and all help is greatly appreciated.

Sam

In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\magdecl.cpp:5:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: note: suggested alternative: 'uint_fast8_t'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
                         uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:44: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                                            ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: note: suggested alternative: 'uint_fast8_t'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
                          uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:52: error: expected primary-expression before 'len'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                    ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: expression list treated as compound expression in initializer [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1560:36: error: 'uint_farptr_t' has not been declared
 extern void *memcpy_PF(void *dest, uint_farptr_t src, size_t len);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1575:36: error: 'uint_farptr_t' has not been declared
 extern char *strcpy_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1595:37: error: 'uint_farptr_t' has not been declared
 extern char *strncpy_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1611:36: error: 'uint_farptr_t' has not been declared
 extern char *strcat_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1632:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1649:37: error: 'uint_farptr_t' has not been declared
 extern char *strncat_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1665:38: error: 'uint_farptr_t' has not been declared
 extern int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                      ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1682:39: error: 'uint_farptr_t' has not been declared
 extern int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                       ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1698:42: error: 'uint_farptr_t' has not been declared
 extern int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1716:43: error: 'uint_farptr_t' has not been declared
 extern int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                           ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1732:40: error: 'uint_farptr_t' has not been declared
 extern char *strstr_PF(const char *s1, uint_farptr_t s2);
                                        ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1744:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1760:36: error: 'uint_farptr_t' has not been declared
 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\magdecl.cpp: In function 'int E0000(int*, double, double, double, double, double*, double*, double*, double*)':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:671:41: error: cast from 'const double*' to 'uint16_t' {aka 'short unsigned int'} loses precision [-fpermissive]
     __LPM_float((uint16_t)(address_short))
                                         ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:557:36: note: in definition of macro '__LPM_float_classic__'
     uint16_t __addr16 = (uint16_t)(addr);   \
                                    ^~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:671:5: note: in expansion of macro '__LPM_float'
     __LPM_float((uint16_t)(address_short))
     ^~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\magdecl.cpp:83:18: note: in expansion of macro 'pgm_read_float_near'
        c[i][j] = pgm_read_float_near (&c0[i][j]);
                  ^~~~~~~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:671:41: error: cast from 'const double*' to 'uint16_t' {aka 'short unsigned int'} loses precision [-fpermissive]
     __LPM_float((uint16_t)(address_short))
                                         ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:557:36: note: in definition of macro '__LPM_float_classic__'
     uint16_t __addr16 = (uint16_t)(addr);   \
                                    ^~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:671:5: note: in expansion of macro '__LPM_float'
     __LPM_float((uint16_t)(address_short))
     ^~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\magdecl.cpp:84:19: note: in expansion of macro 'pgm_read_float_near'
        cd[i][j] = pgm_read_float_near (&cd0[i][j]);
                   ^~~~~~~~~~~~~~~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.cpp:5:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: note: suggested alternative: 'uint_fast8_t'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
                         uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:44: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                                            ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: note: suggested alternative: 'uint_fast8_t'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
                          uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:52: error: expected primary-expression before 'len'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                    ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: expression list treated as compound expression in initializer [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1560:36: error: 'uint_farptr_t' has not been declared
 extern void *memcpy_PF(void *dest, uint_farptr_t src, size_t len);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1575:36: error: 'uint_farptr_t' has not been declared
 extern char *strcpy_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1595:37: error: 'uint_farptr_t' has not been declared
 extern char *strncpy_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1611:36: error: 'uint_farptr_t' has not been declared
 extern char *strcat_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1632:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1649:37: error: 'uint_farptr_t' has not been declared
 extern char *strncat_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1665:38: error: 'uint_farptr_t' has not been declared
 extern int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                      ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1682:39: error: 'uint_farptr_t' has not been declared
 extern int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                       ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1698:42: error: 'uint_farptr_t' has not been declared
 extern int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1716:43: error: 'uint_farptr_t' has not been declared
 extern int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                           ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1732:40: error: 'uint_farptr_t' has not been declared
 extern char *strstr_PF(const char *s1, uint_farptr_t s2);
                                        ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1744:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1760:36: error: 'uint_farptr_t' has not been declared
 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
                                    ^~~~~~~~~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:13,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:9,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.cpp:7:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h: In member function 'void Circum::startPolling()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:23:6: error: 'OCR0A' was not declared in this scope
      OCR0A = 0xAF;
      ^~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:6: error: 'TIMSK0' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
      ^~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:8,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:9,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.cpp:7:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:20: error: 'OCIE0A' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
                    ^~~~~~
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:107:25: note: in definition of macro '_BV'
 #define _BV(b) (1UL << (b))
                         ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.cpp: In constructor 'Webpage::Webpage()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.cpp:30:36: error: invalid new-expression of abstract class type 'EthernetServer'
  httpServer = new EthernetServer(80);    // http
                                    ^
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:8,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:9,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.cpp:7:
C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:254:7: note:   because the following virtual functions are pure within 'EthernetServer':
 class EthernetServer : public Server {
       ^~~~~~~~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:182,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:8,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:9,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.cpp:7:
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Server.h:28:18: note: 	'virtual void Server::begin(uint16_t)'
     virtual void begin(uint16_t port=0) =0;
                  ^~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:13,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\AutoSatTracker.ino:23:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: note: suggested alternative: 'uint_fast8_t'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
                         uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:44: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                                            ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: note: suggested alternative: 'uint_fast8_t'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
                          uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:52: error: expected primary-expression before 'len'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                    ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: expression list treated as compound expression in initializer [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1560:36: error: 'uint_farptr_t' has not been declared
 extern void *memcpy_PF(void *dest, uint_farptr_t src, size_t len);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1575:36: error: 'uint_farptr_t' has not been declared
 extern char *strcpy_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1595:37: error: 'uint_farptr_t' has not been declared
 extern char *strncpy_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1611:36: error: 'uint_farptr_t' has not been declared
 extern char *strcat_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1632:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1649:37: error: 'uint_farptr_t' has not been declared
 extern char *strncat_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1665:38: error: 'uint_farptr_t' has not been declared
 extern int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                      ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1682:39: error: 'uint_farptr_t' has not been declared
 extern int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                       ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1698:42: error: 'uint_farptr_t' has not been declared
 extern int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1716:43: error: 'uint_farptr_t' has not been declared
 extern int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                           ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1732:40: error: 'uint_farptr_t' has not been declared
 extern char *strstr_PF(const char *s1, uint_farptr_t s2);
                                        ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1744:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1760:36: error: 'uint_farptr_t' has not been declared
 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
                                    ^~~~~~~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/WString.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:176,
                 from C:\Users\samue\AppData\Local\Temp\arduino\sketches\8698D904881A0D5503C378136C59D476\sketch\AutoSatTracker.ino.cpp:1:
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/pgmspace.h:81:23: error: 'size_t strlen(const char*)' was declared 'extern' and later 'static' [-fpermissive]
 #define strlen_P      strlen
                       ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1780:61: note: in expansion of macro 'strlen_P'
 __attribute__((__always_inline__)) static __inline__ size_t strlen_P(const char * s);
                                                             ^~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:29,
                 from C:\Users\samue\AppData\Local\Temp\arduino\sketches\8698D904881A0D5503C378136C59D476\sketch\AutoSatTracker.ino.cpp:1:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\sys-include\string.h:41:9: note: previous declaration of 'size_t strlen(const char*)'
 size_t  strlen (const char *);
         ^~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:13,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\AutoSatTracker.ino:23:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h: In member function 'void Circum::startPolling()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:23:6: error: 'OCR0A' was not declared in this scope
      OCR0A = 0xAF;
      ^~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:6: error: 'TIMSK0' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
      ^~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\io.h:99,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:90,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:13,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\AutoSatTracker.ino:23:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:20: error: 'OCIE0A' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
                    ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\sfr_defs.h:208:25: note: in definition of macro '_BV'
 #define _BV(bit) (1 << (bit))
                         ^~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h: In member function 'void Circum::startPolling()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:23:6: error: 'OCR0A' was not declared in this scope
      OCR0A = 0xAF;
      ^~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:6: error: 'TIMSK0' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
      ^~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:20: error: 'OCIE0A' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
                    ^~~~~~
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:107:25: note: in definition of macro '_BV'
 #define _BV(b) (1UL << (b))
                         ^
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h: At global scope:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: note: suggested alternative: 'uint_fast8_t'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
                         uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:44: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                                            ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: note: suggested alternative: 'uint_fast8_t'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
                          uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:52: error: expected primary-expression before 'len'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                    ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: expression list treated as compound expression in initializer [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1560:36: error: 'uint_farptr_t' has not been declared
 extern void *memcpy_PF(void *dest, uint_farptr_t src, size_t len);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1575:36: error: 'uint_farptr_t' has not been declared
 extern char *strcpy_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1595:37: error: 'uint_farptr_t' has not been declared
 extern char *strncpy_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1611:36: error: 'uint_farptr_t' has not been declared
 extern char *strcat_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1632:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1649:37: error: 'uint_farptr_t' has not been declared
 extern char *strncat_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1665:38: error: 'uint_farptr_t' has not been declared
 extern int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                      ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1682:39: error: 'uint_farptr_t' has not been declared
 extern int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                       ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1698:42: error: 'uint_farptr_t' has not been declared
 extern int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1716:43: error: 'uint_farptr_t' has not been declared
 extern int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                           ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1732:40: error: 'uint_farptr_t' has not been declared
 extern char *strstr_PF(const char *s1, uint_farptr_t s2);
                                        ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1744:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1760:36: error: 'uint_farptr_t' has not been declared
 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
                                    ^~~~~~~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/WString.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:176,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/pgmspace.h:81:23: error: 'size_t strlen(const char*)' was declared 'extern' and later 'static' [-fpermissive]
 #define strlen_P      strlen
                       ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1780:61: note: in expansion of macro 'strlen_P'
 __attribute__((__always_inline__)) static __inline__ size_t strlen_P(const char * s);
                                                             ^~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:29,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\sys-include\string.h:41:9: note: previous declaration of 'size_t strlen(const char*)'
 size_t  strlen (const char *);
         ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp: In member function 'bool Target::overrideValue(char*, char*)':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:283:36: error: no matching function for call to 'min(double, int)'
      el = max (min (atof(value), 90), 0);
                                    ^
In file included from c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\algorithm:62,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:172,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\bits\stl_algo.h:3456:5: note: candidate: 'template<class _Tp, class _Compare> _Tp std::min(std::initializer_list<_Tp>, _Compare)'
     min(initializer_list<_Tp> __l, _Compare __comp)
     ^~~
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\bits\stl_algo.h:3456:5: note:   template argument deduction/substitution failed:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:283:36: note:   mismatched types 'std::initializer_list<_Tp>' and 'double'
      el = max (min (atof(value), 90), 0);
                                    ^
In file included from c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\algorithm:62,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:172,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\bits\stl_algo.h:3450:5: note: candidate: 'template<class _Tp> _Tp std::min(std::initializer_list<_Tp>)'
     min(initializer_list<_Tp> __l)
     ^~~
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\bits\stl_algo.h:3450:5: note:   template argument deduction/substitution failed:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:283:36: note:   mismatched types 'std::initializer_list<_Tp>' and 'double'
      el = max (min (atof(value), 90), 0);
                                    ^
In file included from c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\algorithm:61,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:172,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\bits\stl_algobase.h:243:5: note: candidate: 'template<class _Tp, class _Compare> const _Tp& std::min(const _Tp&, const _Tp&, _Compare)'
     min(const _Tp& __a, const _Tp& __b, _Compare __comp)
     ^~~
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\bits\stl_algobase.h:243:5: note:   template argument deduction/substitution failed:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:283:36: note:   deduced conflicting types for parameter 'const _Tp' ('double' and 'int')
      el = max (min (atof(value), 90), 0);
                                    ^
In file included from c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\algorithm:61,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:172,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:4:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\bits\stl_algobase.h:195:5: note: candidate: 'template<class _Tp> const _Tp& std::min(const _Tp&, const _Tp&)'
     min(const _Tp& __a, const _Tp& __b)
     ^~~
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\include\c++\8.4.0\bits\stl_algobase.h:195:5: note:   template argument deduction/substitution failed:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.cpp:283:36: note:   deduced conflicting types for parameter 'const _Tp' ('double' and 'int')
      el = max (min (atof(value), 90), 0);
                                    ^
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.cpp:5:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: note: suggested alternative: 'uint_fast8_t'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
                         uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:44: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                                            ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: note: suggested alternative: 'uint_fast8_t'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
                          uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:52: error: expected primary-expression before 'len'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                    ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: expression list treated as compound expression in initializer [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1560:36: error: 'uint_farptr_t' has not been declared
 extern void *memcpy_PF(void *dest, uint_farptr_t src, size_t len);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1575:36: error: 'uint_farptr_t' has not been declared
 extern char *strcpy_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1595:37: error: 'uint_farptr_t' has not been declared
 extern char *strncpy_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1611:36: error: 'uint_farptr_t' has not been declared
 extern char *strcat_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1632:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1649:37: error: 'uint_farptr_t' has not been declared
 extern char *strncat_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1665:38: error: 'uint_farptr_t' has not been declared
 extern int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                      ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1682:39: error: 'uint_farptr_t' has not been declared
 extern int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                       ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1698:42: error: 'uint_farptr_t' has not been declared
 extern int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1716:43: error: 'uint_farptr_t' has not been declared
 extern int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                           ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1732:40: error: 'uint_farptr_t' has not been declared
 extern char *strstr_PF(const char *s1, uint_farptr_t s2);
                                        ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1744:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1760:36: error: 'uint_farptr_t' has not been declared
 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
                                    ^~~~~~~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/WString.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:176,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.cpp:5:
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/pgmspace.h:81:23: error: 'size_t strlen(const char*)' was declared 'extern' and later 'static' [-fpermissive]
 #define strlen_P      strlen
                       ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1780:61: note: in expansion of macro 'strlen_P'
 __attribute__((__always_inline__)) static __inline__ size_t strlen_P(const char * s);
                                                             ^~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:29,
                 from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:5,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.cpp:5:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\sys-include\string.h:41:9: note: previous declaration of 'size_t strlen(const char*)'
 size_t  strlen (const char *);
         ^~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.cpp:5:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h: In member function 'void Circum::startPolling()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:23:6: error: 'OCR0A' was not declared in this scope
      OCR0A = 0xAF;
      ^~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:6: error: 'TIMSK0' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
      ^~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\io.h:99,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:90,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.cpp:5:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:20: error: 'OCIE0A' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
                    ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\sfr_defs.h:208:25: note: in definition of macro '_BV'
 #define _BV(bit) (1 << (bit))
                         ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.cpp: At global scope:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.cpp:338:4: error: expected constructor, destructor, or type conversion before '(' token
 ISR(TIMER0_COMPA_vect)
    ^
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.h:11,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h: In member function 'void Circum::startPolling()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:23:6: error: 'OCR0A' was not declared in this scope
      OCR0A = 0xAF;
      ^~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:6: error: 'TIMSK0' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
      ^~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\libraries\Ethernet\src/Ethernet.h:51,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:20: error: 'OCIE0A' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
                    ^~~~~~
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Arduino.h:107:25: note: in definition of macro '_BV'
 #define _BV(b) (1UL << (b))
                         ^
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.h:11,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h: At global scope:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: note: suggested alternative: 'uint_fast8_t'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
                         uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:44: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                                            ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: note: suggested alternative: 'uint_fast8_t'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
                          uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:52: error: expected primary-expression before 'len'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                    ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: expression list treated as compound expression in initializer [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1560:36: error: 'uint_farptr_t' has not been declared
 extern void *memcpy_PF(void *dest, uint_farptr_t src, size_t len);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1575:36: error: 'uint_farptr_t' has not been declared
 extern char *strcpy_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1595:37: error: 'uint_farptr_t' has not been declared
 extern char *strncpy_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1611:36: error: 'uint_farptr_t' has not been declared
 extern char *strcat_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1632:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1649:37: error: 'uint_farptr_t' has not been declared
 extern char *strncat_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1665:38: error: 'uint_farptr_t' has not been declared
 extern int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                      ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1682:39: error: 'uint_farptr_t' has not been declared
 extern int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                       ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1698:42: error: 'uint_farptr_t' has not been declared
 extern int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1716:43: error: 'uint_farptr_t' has not been declared
 extern int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                           ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1732:40: error: 'uint_farptr_t' has not been declared
 extern char *strstr_PF(const char *s1, uint_farptr_t s2);
                                        ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1744:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1760:36: error: 'uint_farptr_t' has not been declared
 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
                                    ^~~~~~~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/WString.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Print.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Stream.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\libraries\Wire\src/Wire.h:35,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.h:6,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.cpp:4:
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/pgmspace.h:81:23: error: 'size_t strlen(const char*)' was declared 'extern' and later 'static' [-fpermissive]
 #define strlen_P      strlen
                       ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1780:61: note: in expansion of macro 'strlen_P'
 __attribute__((__always_inline__)) static __inline__ size_t strlen_P(const char * s);
                                                             ^~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/esp32-hal.h:29,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\libraries\Wire\src/Wire.h:29,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.h:6,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Gimbal.cpp:4:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\sys-include\string.h:41:9: note: previous declaration of 'size_t strlen(const char*)'
 size_t  strlen (const char *);
         ^~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:13,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:25: note: suggested alternative: 'uint_fast8_t'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                         ^~~~~~~~~~~~~
                         uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1529:44: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
                                            ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: error: 'uint_farptr_t' was not declared in this scope
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:26: note: suggested alternative: 'uint_fast8_t'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                          ^~~~~~~~~~~~~
                          uint_fast8_t
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:52: error: expected primary-expression before 'len'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                    ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: attributes after parenthesized initializer ignored [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:94:49: error: expression list treated as compound expression in initializer [-fpermissive]
 #define __ATTR_CONST__ __attribute__((__const__))
                                                 ^
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1545:57: note: in expansion of macro '__ATTR_CONST__'
 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
                                                         ^~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1560:36: error: 'uint_farptr_t' has not been declared
 extern void *memcpy_PF(void *dest, uint_farptr_t src, size_t len);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1575:36: error: 'uint_farptr_t' has not been declared
 extern char *strcpy_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1595:37: error: 'uint_farptr_t' has not been declared
 extern char *strncpy_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1611:36: error: 'uint_farptr_t' has not been declared
 extern char *strcat_PF(char *dest, uint_farptr_t src);
                                    ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1632:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1649:37: error: 'uint_farptr_t' has not been declared
 extern char *strncat_PF(char *dest, uint_farptr_t src, size_t len);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1665:38: error: 'uint_farptr_t' has not been declared
 extern int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                      ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1682:39: error: 'uint_farptr_t' has not been declared
 extern int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                       ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1698:42: error: 'uint_farptr_t' has not been declared
 extern int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;
                                          ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1716:43: error: 'uint_farptr_t' has not been declared
 extern int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
                                           ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1732:40: error: 'uint_farptr_t' has not been declared
 extern char *strstr_PF(const char *s1, uint_farptr_t s2);
                                        ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1744:37: error: 'uint_farptr_t' has not been declared
 extern size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz);
                                     ^~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1760:36: error: 'uint_farptr_t' has not been declared
 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
                                    ^~~~~~~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/WString.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Print.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/Stream.h:26,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\libraries\Wire\src/Wire.h:35,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:4:
C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/pgmspace.h:81:23: error: 'size_t strlen(const char*)' was declared 'extern' and later 'static' [-fpermissive]
 #define strlen_P      strlen
                       ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:1780:61: note: in expansion of macro 'strlen_P'
 __attribute__((__always_inline__)) static __inline__ size_t strlen_P(const char * s);
                                                             ^~~~~~~~
In file included from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32/esp32-hal.h:29,
                 from C:\Users\samue\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.11\libraries\Wire\src/Wire.h:29,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:4:
c:\users\samue\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\esp-2021r2-patch5-8.4.0\xtensa-esp32-elf\sys-include\string.h:41:9: note: previous declaration of 'size_t strlen(const char*)'
 size_t  strlen (const char *);
         ^~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:13,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h: In member function 'void Circum::startPolling()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:23:6: error: 'OCR0A' was not declared in this scope
      OCR0A = 0xAF;
      ^~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:6: error: 'TIMSK0' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
      ^~~~~~
In file included from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\io.h:99,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\pgmspace.h:90,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Webpage.h:7,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Target.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:10,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.h:13,
                 from C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:4:
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Circum.h:24:20: error: 'OCIE0A' was not declared in this scope
      TIMSK0 |= _BV(OCIE0A);
                    ^~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\avr\sfr_defs.h:208:25: note: in definition of macro '_BV'
 #define _BV(bit) (1 << (bit))
                         ^~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp: In constructor 'Sensor::Sensor()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:12:45: error: 'OPERATION_MODE_NDOF' is not a member of 'Adafruit_BNO055'
  sensor_found = bno->begin(Adafruit_BNO055::OPERATION_MODE_NDOF);
                                             ^~~~~~~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp: In member function 'void Sensor::saveCalibration()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:117:33: error: 'OPERATION_MODE_CONFIG' is not a member of 'Adafruit_BNO055'
  bno->setMode (Adafruit_BNO055::OPERATION_MODE_CONFIG);
                                 ^~~~~~~~~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:138:33: error: 'OPERATION_MODE_NDOF' is not a member of 'Adafruit_BNO055'
  bno->setMode (Adafruit_BNO055::OPERATION_MODE_NDOF);
                                 ^~~~~~~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp: In member function 'void Sensor::installCalibration()':
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:164:33: error: 'OPERATION_MODE_CONFIG' is not a member of 'Adafruit_BNO055'
  bno->setMode (Adafruit_BNO055::OPERATION_MODE_CONFIG);
                                 ^~~~~~~~~~~~~~~~~~~~~
C:\Users\samue\Downloads\AutoSatTracker-2016082822\AutoSatTracker\Sensor.cpp:179:33: error: 'OPERATION_MODE_NDOF' is not a member of 'Adafruit_BNO055'
  bno->setMode (Adafruit_BNO055::OPERATION_MODE_NDOF);
                                 ^~~~~~~~~~~~~~~~~~~

exit status 1

Compilation error: 'uint_farptr_t' was not declared in this scope

Would you download the zip file, unzip it, and upload the sketch to this topic? Thank you.

Look farther down in the webpage for the code for the ESP8266, the code you are compiling looks like it is intended for an Arduino Mega, no other boards I know of used far pointers for PROGMEM.

https://www.clearskyinstitute.com/ham/AST/AutoSatTracker-ESP-2023053003.zip

AutoSatTracker-ESP.ino

/* Autonomous Satellite Tracker.
 *
 * Connections on Adafruit ESP8266 Huzzah:
 *   Servo controller connects to SDA and SCL
 *   GPS TX connects to 16, RX to 2
 *
 */


#include "AutoSatTracker-ESP.h"
#include "NV.h"
#include "Sensor.h"
#include "Circum.h"
#include "Gimbal.h"
#include "Target.h"
#include "Webpage.h"
#include "Wire.h"
#include "SSD1306Wire.h"

NV *nv;
Sensor *sensor;
Circum *circum;
Gimbal *gimbal;
Target *target;
Webpage *webpage;

//Globale Variablen die in anderen Modulen gesetzt werden
extern bool gps_lock;
extern bool track_status;
extern String satname;

const int oled_contrast = 64;

//Display settings for 0.96 OLED display
const int I2C_DISPLAY_ADDRESS = 0x3c;
#if defined(ESP8266)
//const int SDA_PIN = D3;
//const int SDC_PIN = D4;
const int SDA_PIN = D2; // same as I2C pins for the rest
const int SDC_PIN = D1; 
#else
const int SDA_PIN = 5; //D3;
const int SDC_PIN = 4; //D4;
#endif

SSD1306Wire     display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);

/* called first and once
 */
void
setup()
{

    // init serial monitor
    Serial.begin (115200);
    delay(500);

    // this just resets the soft timeout, the hard timeout is still 6 seconds
    ESP.wdtDisable();

    // scan for I2C devices
    resetWatchdog();
    Serial.println();
    Serial.print (F("Scanning I2C:"));
    Wire.begin(); // original code did not have Wire.begin and I2C scan was not working
    for (uint8_t a = 1; a < 127; a++) {
	    Wire.beginTransmission(a);
	    if (Wire.endTransmission(true) == 0) 
      {
	      Serial.print (F(" ")); Serial.print (a,HEX);
      }
    }
    Serial.println();

    // instantiate each module
    
    // initialize display
    Serial.println(F("Making OLED"));
    display.init();
    display.clear();
    display.display();

    //  display.flipScreenVertically();
    display.setFont(ArialMT_Plain_24);
    display.setTextAlignment(TEXT_ALIGN_CENTER);
    display.setContrast(oled_contrast);
    display.drawString(64,0,"Welcome");
    display.drawString(64,19,"to");
    display.drawString(64,39,"SatTrack");
    display.display();
    //show welcome screen until main loop starts
    // change font for main loop display
    display.setFont(ArialMT_Plain_10);
    
    Serial.println (F("making NV"));
    nv = new NV();
    Serial.println (F("making Sensor"));
    sensor = new Sensor();
    Serial.println (F("making Circum"));
    circum = new Circum();
    Serial.println (F("making Gimbal"));
    gimbal = new Gimbal();
    Serial.println (F("making Target"));
    target = new Target();
    Serial.println (F("making Webpage"));
    webpage = new Webpage();
    
    // all set to go.. see you in loop()
    Serial.println (F("Ready"));

}

//Update the OLED Status display
void OLED_update()
{

  String statestring = "";
  char st[64];
  
  resetWatchdog();
  display.clear();

  //Display Title
  display.drawString(64, 0, "SatTrack");

  // Display Sat Name if tracking is active and Tracking State (on or off)
  
  if (target->track_status)
    statestring = target->satname + " tracking";
  else
    statestring = target->satname + " not tracking";
  display.drawString(64, 12, statestring);

  //Display GPS state
  if (circum->nsats !=0xff)
    sprintf(st,"%d",circum->nsats);
  else
    sprintf(st,"%s","INVAL"); 
  if (circum->gps_lock)
    statestring = "GPS locked " + (String)st + " satellites";
  else
    statestring = "GPS UNLOCKED";
  display.drawString(64, 24, statestring);
  
  //Display Gimbal state
  if (gimbal->connected())
  {
    if (gimbal->calibrated())
       statestring="Gimbal ok calibrated";
    else
       statestring="Gimbal ok UNCALIBRATED";
  }
  else
    statestring="GIMBAL MISSING";
  display.drawString(64,36, statestring);
  
  float Gimbal_AZ = 0;
  float Gimbal_EL = 0;
  //Display Azimuth and Elevation of the antenne as derived from sensor
  sensor->getAzEl (&Gimbal_AZ, &Gimbal_EL);
  sprintf(st,"AZ: %3.1f°     EL: %3.1f°",Gimbal_AZ,Gimbal_EL);
  display.drawString(64,48, (String)st);

  //Write everyhting to the display
  display.display();
}

/* called repeatedly forever
 */
void
loop()
{
    // check for ethernet activity
    webpage->checkEthernet();

    // check for new GPS info
    circum->checkGPS();

    // follow the target
    target->track();

    //update Oled Display
    OLED_update();
}

void
resetWatchdog()
{
    ESP.wdtFeed();
    yield();
}

More to follow(character limit).

AskWiFi.cpp

/* ask op for local wifi info
 */

#include "Webpage.h"

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>

// urldecode
//credits for this code go to zenmanenergy (Steve Nelson) on github
unsigned char h2int(char c)
{
    if (c >= '0' && c <='9'){
        return((unsigned char)c - '0');
    }
    if (c >= 'a' && c <='f'){
        return((unsigned char)c - 'a' + 10);
    }
    if (c >= 'A' && c <='F'){
        return((unsigned char)c - 'A' + 10);
    }
    return(0);
}

String urldecode(String str)
{
    
    String encodedString="";
    char c;
    char code0;
    char code1;
    for (int i =0; i < str.length(); i++){
        c=str.charAt(i);
      if (c == '+'){
        encodedString+=' ';  
      }else if (c == '%') {
        i++;
        code0=str.charAt(i);
        i++;
        code1=str.charAt(i);
        c = (h2int(code0) << 4) | h2int(code1);
        encodedString+=c;
      } else{
        
        encodedString+=c;  
      }
      
      yield();
    }
    
   return encodedString;
}


/* set up an Access Point to ask operator for local wifi info, save in NV
 */
void Webpage::askWiFi()
{
	// AP info
	IPAddress ip(192,168,10,10);
	IPAddress gw(192,168,10,10);
	IPAddress nm(255,255,255,0);
	const char *ssid = "SatTrack";

	// start AP
	resetWatchdog();
	WiFi.disconnect(true);
	delay(200);
	WiFi.mode(WIFI_AP);
	if (!WiFi.softAPConfig(ip, gw, nm)) {
	    Serial.println ("Can not configure softAP");
	    return;
	}
	if (!WiFi.softAP (ssid)) {
	    Serial.println ("Can not set AP ssid");
	    return;
	}
	delay(500);
	Serial.print (F("AP IP: ")); Serial.println (WiFi.softAPIP());

	// start HTTP server 
	resetWatchdog();
	WiFiServer remoteServer(80);
	remoteServer.begin();

	// provide clients with an IP pointing back to us
	DNSServer dns;
	dns.start(53, "*", WiFi.softAPIP());

	// repeat until get station info

	int n_info = 0;
	while (n_info < 5) {
	    n_info = 0;

	    // listen for a connection
	    WiFiClient remoteClient;
	    Serial.println ("waiting for client");
	    dns.processNextRequest();
	    do {
		resetWatchdog();
		delay(100);
		remoteClient = remoteServer.available();
	    } while (!remoteClient);
	    Serial.print (F("client connected from ")); Serial.println (remoteClient.remoteIP());

	    // send the WiFI setup page
	    sendAskPage (remoteClient);

	    // look for GET down to blank line
	    char c, line[1024];
	    size_t linel = 0;
	    char *GET = NULL;
	    uint32_t to = millis();
	    while ((c = readNextClientChar (remoteClient, &to)) != 0) {
		if (!GET) {
		    if (c == '\n') {
			line[linel] = '\0';
			linel = 0;
			if (strstr (line, "GET "))
			    GET = line;
		    } else if (linel < sizeof(line)-1)
			line[linel++] = c;
		} else {
		    if (c == '\n') {
			if (linel == 1)	// just \r\n
			    break;
			linel = 0;
		    } else {
			linel++;
		    }
		}
	    }
	    remoteClient.stop();
	    Serial.println (line);

	    // abort if no GET
	    if (!GET) {
		Serial.println (line);
		Serial.println ("No GET");
		break;
	    }

	    // crack GET for desired info
	    char *wifi_id = strstr (line, "id=");
	    char *wifi_pw = strstr (line, "pw=");
	    char *wifi_ip = strstr (line, "ip=");
	    char *wifi_nm = strstr (line, "nm=");
	    char *wifi_gw = strstr (line, "gw=");

	    // TODO: check for special characters

	    // save if looks reasonable
	    char *eos;
	    if (wifi_id) {
		wifi_id += 3;
		eos = strchr (wifi_id, '&');
		if (eos) {
		    *eos = '\0';
		    strncpy (nv->ssid, wifi_id, sizeof(nv->ssid));
		    nv->put();
		    Serial.println(nv->ssid);
		    n_info++;
		}
	    }
	    if (wifi_pw) {
		wifi_pw += 3;
		eos = strchr (wifi_pw, '&');
		if (eos) {
		    *eos = '\0';
// urldecode the string to allow for special characters
        String wifi_pw1 = urldecode((String)wifi_pw);
		    strncpy (nv->pw, (char *)&wifi_pw1[0], sizeof(nv->pw));
		    nv->put();
		    Serial.println(nv->pw);
		    n_info++;
		}
	    }
	    if (wifi_ip) {
		wifi_ip += 3;
		eos = strchr (wifi_ip, '&');
		if (eos) {
		    *eos = '\0';
		    nv->IP.fromString (wifi_ip);
		    nv->put();
        //the original Serial.println(nv->IP.toString()) caused a exception
		    Serial.println(wifi_ip);
		    n_info++;
		}
	    }
        
	    if (wifi_nm) {
		wifi_nm += 3;
		eos = strchr (wifi_nm, '&');
		if (eos) {
		    *eos = '\0';
		    nv->NM.fromString (wifi_nm);
		    nv->put();
        //the original Serial.println(nv->NM.toString()) caused a exception
		    Serial.println(wifi_nm);
		    n_info++;
		}
	    }
     
	    if (wifi_gw) {
		wifi_gw += 3;
		eos = strchr (wifi_gw, ' ');
		if (eos) {
		    *eos = '\0';
		    nv->GW.fromString (wifi_gw);
		    nv->put();
        //the original Serial.println(nv->GW.toString()) caused a exception
		    Serial.println(wifi_gw);
		    n_info++;
		}
	    }
     
	}
	// shut down AP
	WiFi.softAPdisconnect(true);
	delay(200);
}

/* transmit the page that lets operator enter wifi info
 */
void Webpage::sendAskPage(WiFiClient client)
{
        sendHTMLHeader (client);

        // DO NOT HAND EDIT THE FOLLOWING HTML .. use "preppage.pl"
        // DO NOT REMOVE THIS LINE 333333333333333333333333333333
        client.print (F(
            "<!DOCTYPE html> \r\n"
            "<html> \r\n"
            "<head> \r\n"
            "    <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> \r\n"
            " \r\n"
            "    <style> \r\n"
            "        body { \r\n"
            "            background-color:#888; \r\n"
            "            font-family:sans-serif; \r\n"
            "            font-size:13px; \r\n"
            "        } \r\n"
            " \r\n"
            "        table { \r\n"
            "            border-collapse: collapse; \r\n"
            "            border: 3px solid brown; \r\n"
            "            background-color:#F8F8F8; \r\n"
            "            float:left; \r\n"
            "        } \r\n"
            " \r\n"
            "        td { \r\n"
            "            padding: 4px; \r\n"
            "        } \r\n"
            " \r\n"
            "        th { \r\n"
            "            padding: 6px; \r\n"
            "            border: 1px solid brown; \r\n"
            "        } \r\n"
            " \r\n"
            "        input { \r\n"
            "            width : 90%; \r\n"
            "        } \r\n"
            " \r\n"
            "    </style> \r\n"
            " \r\n"
            "</head> \r\n"
            "<body> \r\n"
            " \r\n"
            "    <form>  \r\n"
            "    <table> \r\n"
            "        <tr> \r\n"
            "            <th colspan='2' > \r\n"
            "                Enter local WiFi information: \r\n"
            "            </th> \r\n"
            "        </tr> \r\n"
            "        <tr> \r\n"
            "            <td> \r\n"
            "                SSID: \r\n"
            "            </td> \r\n"
            "            <td> \r\n"
            "                <input name='id'></input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            "        <tr> \r\n"
            "            <td> \r\n"
            "                Password: \r\n"
            "            </td> \r\n"
            "            <td> \r\n"
            "                <input name='pw'></input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            "        <tr> \r\n"
            "            <td> \r\n"
            "                IP: \r\n"
            "            </td> \r\n"
            "            <td> \r\n"
            "                <input name='ip'></input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            "        <tr> \r\n"
            "            <td> \r\n"
            "                Network mask: \r\n"
            "            </td> \r\n"
            "            <td> \r\n"
            "                <input name='nm'></input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            "        <tr> \r\n"
            "            <td> \r\n"
            "                Gateway: \r\n"
            "            </td> \r\n"
            "            <td> \r\n"
            "                <input name='gw'></input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            "        <tr> \r\n"
            "            <td colspan='2' > \r\n"
            "                <button type='submit'>Send</button> \r\n"
            "            </td> \r\n"
            "    </table> \r\n"
            "    </form> \r\n"
            "</body> \r\n"
            "</html> \r\n"
        ));
        // DO NOT REMOVE THIS LINE 444444444444444444444444444444
}

More to follow(character limit).

AutoSatTracker-ESP.h

#ifndef __AST_H
#define __AST_H

extern void resetWatchdog();

extern double myfmod (double a, double n);
extern double myatof (const char *s);


#endif // __AST_H

Circum.cpp

/* information about observing circumstances including time and location from GPS or manually entered.
 */

#include "Circum.h"

// serial configuration for GPS
#define	GPS_TX_PIN	(-1)			// none
#define	GPS_RX_PIN	12                      // Huzzah RX
#define	GPS_BAUD	9600


/* constructor
 */
Circum::Circum ()
{
	// create serial connection to GPS board
	resetWatchdog();
	ss = new SoftwareSerial (GPS_RX_PIN, GPS_TX_PIN);
	ss->begin(GPS_BAUD);

	// create GPS parser
	resetWatchdog();
	GPS = new TinyGPS();

	// init values -- updated when GPS locks
	resetWatchdog();
	latitude = 0.0;
	longitude = 0.0;
	altitude = 0.0;
	obs = NULL;
	newObserver (latitude, longitude, altitude);
	hdop = 99.0;
	nsats = 0;
	setnow (2020, 1, 1, 0, 0, 0);
	magdecl (latitude, longitude, altitude, decimalYear(), &magdeclination);
  
	// init flags
	gps_lock = false;
	gps_ok = false;
	time_overridden = false;
	loc_overridden = false;
}

/* return current time as a decimal year
 */
float Circum::decimalYear()
{
	// get time now, sets dt_now.DN and dt_now.TN
	int year; uint8_t month, day, h, m, s;
	getnow (year, month, day, h, m, s);

	// get time on jan 1 this year
	DateTime y0 (year, 1, 1, 0, 0, 0);

	// n days this year
	int nd = (year%4) ? 365 : 366;

	// return year and fraction
	return (year + ((dt_now.DN + dt_now.TN) - (y0.DN + y0.TN))/nd);
}

/* send latest values to web page.
 * N.B. names must match ids in web page
 */
void Circum::sendNewValues (WiFiClient client)
{

	int year; uint8_t month, day, h, m, s;
	getnow (year, month, day, h, m, s);

	client.print (F("GPS_Date="));
	printDate (client, year, month, day);
	    printPL (client, time_overridden ? BADNEWS : NORMAL);

	client.print (F("GPS_UTC="));
	printHMS (client, h, m, s);
	    printPL (client, time_overridden ? BADNEWS : NORMAL);

	client.print (F("GPS_Status="));
	if (gps_lock) {
	    if (time_overridden || loc_overridden)
		client.println (F("Overridden!"));
	    else
		client.println (F("Locked+"));
	} else if (gps_ok)
	    client.println (F("No lock!"));
	else
	    client.println (F("Not found!"));

	client.print (F("GPS_Enable="));
	if (gps_lock && (time_overridden || loc_overridden))
	    client.println (F("true"));
	else
	    client.println (F("false"));

	client.print (F("GPS_Lat=")); client.print (latitude, 3);
	    printPL (client, loc_overridden ? BADNEWS : NORMAL);
	client.print (F("GPS_Long=")); client.print (longitude, 3);
	    printPL (client, loc_overridden ? BADNEWS : NORMAL);
	client.print (F("GPS_Alt=")); client.print (altitude);
	    printPL (client, loc_overridden ? BADNEWS : NORMAL);

	client.print (F("GPS_MagDecl=")); client.println (magdeclination);
	client.print (F("GPS_HDOP=")); client.println (hdop);
	client.print (F("GPS_NSat=")); client.println (nsats);
}

/* print value v in sexagesimal format, can be negative
 */
void Circum::printSexa (WiFiClient client, float v)
{
	bool isneg = v < 0;
	if (isneg) {
	    v = -v;
	    client.print (F("-"));
	}

        uint8_t h = (uint8_t) v;
        v = (v - h)*60;
        uint8_t m = (uint8_t) v;
        v = (v - m)*60;
        uint8_t s = (uint8_t) v;

	printHMS (client, h, m, s);
}

/* print time
 */
void Circum::printHMS (WiFiClient client, uint8_t h, uint8_t m, uint8_t s)
{
	client.print (h);

	if (m < 10)
	    client.print (F(":0"));
	else
	    client.print (F(":"));
	client.print (m);

	if (s < 10)
	    client.print (F(":0"));
	else
	    client.print (F(":"));
	client.print (s);
}

/* print the given date
 */
void Circum::printDate (WiFiClient client, int y, uint8_t m, uint8_t d)
{
	client.print(y);
	client.print(F(" "));
	client.print(m);
	client.print(F(" "));
	client.print(d);
}

/* end a value with the given print level code
 */
void Circum::printPL (WiFiClient client, PrintLevel pl)
{
	switch (pl) {
	case BADNEWS:
	    client.println (F("!"));
	    break;
	case GOODNEWS:
	    client.println (F("+"));
	    break;
	default:
	    client.println (F(""));
	    break;
	}
}

/* process name = value.
 * return whether we recognize it
 */
bool Circum::overrideValue (char *name, char *value)
{
	if (!strcmp (name, "GPS_UTC")) {
	    // op is setting new UTC
	    int year; uint8_t month, day, h, m, s;
	    getnow (year, month, day, h, m, s);		// start with now
	    char *mat, *sat;				// start of min and sec, if any
	    h = strtol (value, &mat, 10);		// override hour
	    if (mat != value) {				// if new minute ...
		m = strtol (mat, &sat, 10);		// override minutes
		if (sat != mat)				// if new seconds ...
		    s = strtol (sat, NULL, 10);		// override seconds
	    }
	    setnow (year, month, day, h, m, s);		// set system time to new value
	    time_overridden = true;			// set flag that op has overridden GPS time
	    target->updateTopo();			// update target to new time
	    target->findNextPass();			// update pass from now
	    target->computeSkyPath();			// and show
	    return (true);
	}
	if (!strcmp (name, "GPS_Date")) {
	    // op is setting new date
	    int year; uint8_t month, day, h, m, s;
	    getnow (year, month, day, h, m, s);		// start with now
	    char *mat, *dat;				// start of month and day, if any
	    year = strtol (value, &mat, 10);		// override year
	    if (mat != value) {				// if new month ...
		month = strtol (mat, &dat, 10);		// override month
		if (dat != mat)				// if new day ...
		    day = strtol (dat, NULL, 10);	// override day
	    }
	    setnow (year, month, day, h, m, s);		// set system time to new value
	    time_overridden = true;			// set flag that op has overridden GPS time
	    target->updateTopo();			// update target to new time
	    target->findNextPass();			// update pass from now
	    target->computeSkyPath();			// and show
	    return (true);
	}
	if (!strcmp (name, "GPS_Lat")) {
	    latitude = atof (value);
	    newObserver (latitude, longitude, altitude);
	    loc_overridden = true;			// set flag that op has overridden GPS loc
	    target->updateTopo();			// update target to new time
	    target->findNextPass();			// update pass from here
	    target->computeSkyPath();			// and show
	    magdecl (latitude, longitude, altitude, decimalYear(), &magdeclination);
	    return (true);
	}
	if (!strcmp (name, "GPS_Long")) {
	    longitude = atof (value);
	    newObserver (latitude, longitude, altitude);
	    loc_overridden = true;			// set flag that op has overridden GPS loc
	    target->updateTopo();			// update target to new time
	    target->findNextPass();			// update pass from here
	    target->computeSkyPath();			// and show
	    magdecl (latitude, longitude, altitude, decimalYear(), &magdeclination);
	    return (true);
	}
	if (!strcmp (name, "GPS_Alt")) {
	    altitude = atof (value);
	    newObserver (latitude, longitude, altitude);
	    loc_overridden = true;			// set flag that op has overridden GPS loc
	    target->updateTopo();			// update target to new time
	    target->findNextPass();			// update pass from here
	    target->computeSkyPath();			// and show
	    magdecl (latitude, longitude, altitude, decimalYear(), &magdeclination);
	    return (true);
	}
	if (!strcmp (name, "GPS_Enable")) {
	    time_overridden = false;			// resume GPS values
	    loc_overridden = false;			// resume GPS values
	}

	return (false);	// not one of ours
}

/* call occasionally to sync our system time from GPS, if it is running ok.
 */
void Circum::checkGPS()
{
	resetWatchdog();

	// read more from GPS, process when new message complete
	while (ss->available()) {

	    //Serial.print((char)ss->peek());

	    if (GPS->encode(ss->read())) {

		// note we receiving GPS sentences ok
		gps_ok = true;

		// get location and age
		float new_lat, new_lng, new_alt;
		unsigned long loc_fix_age;
		GPS->f_get_position(&new_lat, &new_lng, &loc_fix_age);
		new_alt = GPS->f_altitude();

		// get time and age
		unsigned long time_fix_age;
		int new_year; byte new_mon, new_day, new_hr, new_min, new_sec, new_hund;
		GPS->crack_datetime (&new_year, &new_mon, &new_day, &new_hr, &new_min, &new_sec,
				&new_hund, &time_fix_age);

		// determine whether data are up to date
		if (loc_fix_age == TinyGPS::GPS_INVALID_AGE || time_fix_age  == TinyGPS::GPS_INVALID_AGE) {
		    gps_lock = false;
		    Serial.println("No fix detected");
		} else {
		    gps_lock = true;
		    if (loc_fix_age > 5000 || time_fix_age > 5000)
			Serial.println("Warning: possible stale data!");
		}
    
		if (gps_lock) {

		    // update system time from GPS unless op has overridden
                    double year_diff = 0;
		    if (!time_overridden) {
                        double year0 = decimalYear();
			setnow (new_year, new_mon, new_day, new_hr, new_min, new_sec);
                        year_diff = decimalYear() - year0;
                    }

		    // update location from GPS, unless op has overridden or within allowed jitter
		    if (!loc_overridden 
			    && (fabs(latitude - new_lat) > 0.01
				|| fabs(longitude - new_lng) > 0.01
				|| fabs (altitude - new_alt) > 100
                                || fabs (year_diff) > .01)
			    ) {

			latitude = new_lat;
			longitude = new_lng;
			altitude = new_alt;

			newObserver (latitude, longitude, altitude);
			magdecl (latitude, longitude, altitude, decimalYear(), &magdeclination);
		    }

		    // get fix quality info
		    hdop = 0.01*GPS->hdop();
		    nsats = (int)GPS->satellites();
		}
	    }
	}
}

/* get time from dt_now advanced to current millis()
 */
void Circum::getnow(int &year, uint8_t &month, uint8_t &day, uint8_t &h, uint8_t &m, uint8_t &s)
{
	dt_now.TN = dt_TN0;
	dt_now.DN = dt_DN0;
	dt_now.add ((long)((millis() - dt_m0)/1000));
	dt_now.gettime(year, month, day, h, m, s);
}

/* init dt_now based on current millis()
 */
void Circum::setnow(int year, uint8_t month, uint8_t day, uint8_t h, uint8_t m, uint8_t s)
{
	dt_m0 = millis();
	dt_now.settime(year, month, day, h, m, s);
	dt_TN0 = dt_now.TN;
	dt_DN0 = dt_now.DN;
}

/* return age of satellite elements in days
 */
float Circum::age (Satellite *sat)
{
	return ((dt_now.DN + dt_now.TN) - (sat->DE + sat->TE));

}

/* install a new Observer
 */
void Circum::newObserver (float lat, float lng, float hgt)
{
	if (obs)
	    delete (obs);
	obs = new Observer (lat, lng, hgt);
}

/* return the current Observer
 */
Observer *Circum::observer()
{
	return (obs);
}

More to follow(character limit).

Circum.h

#ifndef _CIRCUM_H
#define	_CIRCUM_H

#include <WiFiClient.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>

#include "AutoSatTracker-ESP.h"
#include "P13.h"
#include "Target.h"

extern int magdecl ( double l, double L, double e, double y, double *mdp);

class Circum {

    private:

	/* flags
	 */
	bool gps_ok;			// set when we get a valid line
	bool time_overridden;		// some element of time has been set by op
	bool loc_overridden;		// some element of location has been set by op

	Observer *obs;			// topocentric place
	SoftwareSerial *ss;		// GPS serial IO

	float decimalYear();
	void newObserver (float lat, float lng, float hgt);

	/* implement on top of DateTime a running time based on elapsed millis()
	 */
	DateTime dt_now;
	float dt_TN0;
	long dt_DN0;
	uint32_t dt_m0;
	void getnow(int &year, uint8_t &month, uint8_t &day, uint8_t &h, uint8_t &m, uint8_t &s);
	void setnow(int year, uint8_t month, uint8_t day, uint8_t h, uint8_t m, uint8_t s);

    public:

	TinyGPS *GPS;			// GPS parser
	double magdeclination;		// true az - magnetic az
	float latitude, longitude;	// degs +N, +E
	float altitude;			// altitude above MSL, m
	float hdop;			// horizontal degradation
	int nsats;			// number of satellites used
  bool gps_lock; // set when we get a valid fix

	Circum ();
	void sendNewValues (WiFiClient client);
	bool overrideValue (char *name, char *value);
	void checkGPS();
	DateTime now() {return dt_now;};
	float age (Satellite *sat);
	Observer *observer();
	void printSexa (WiFiClient client, float v);
	void printHMS (WiFiClient client, uint8_t h, uint8_t m, uint8_t s);
	void printDate (WiFiClient client, int y, uint8_t m, uint8_t d);

	typedef enum {
	    NORMAL, BADNEWS, GOODNEWS
	} PrintLevel;
	void printPL (WiFiClient client, PrintLevel pl);

};

extern Circum *circum;

#endif // _CIRCUM_H

More to follow(character limit).

Gimbal.cpp

// class to control two motors to track a target az and el using the Adafruit I2C interface


#include "Gimbal.h"


/* issue raw motor command in microseconds pulse width, clamped at limit
 */
void Gimbal::setMotorPosition (uint8_t motn, uint16_t newpos)
{
	if (motn >= NMOTORS || !gimbal_found)
	    return;
	MotorInfo *mip = &motor[motn];

	mip->atmin = (newpos <= mip->min);
	if (mip->atmin)
	    newpos = mip->min;
	mip->atmax = (newpos >= mip->max);
	if (mip->atmax)
	    newpos = mip->max;

	mip->del_pos = (int)newpos - (int)mip->pos;
	mip->pos = newpos;
	pwm->setPWM(mip->servo_num, 0, mip->pos/US_PER_BIT);
	// Serial.print(mip->servo_num); Serial.print(" "); Serial.println (newpos);
}

/* constructor 
 */
Gimbal::Gimbal ()
{
	// first confirm whether controller is present
	resetWatchdog();
	Wire.beginTransmission(GIMBAL_I2C_ADDR);
	gimbal_found = (Wire.endTransmission() == 0);
	if (!gimbal_found) {
	    Serial.println (F("PWM controller not found"));
	    return;
	}
	Serial.println (F("PWM controller found ok"));
  
	// instantiate PWM controller
	pwm = new Adafruit_PWMServoDriver(GIMBAL_I2C_ADDR);
	pwm->begin();
	pwm->setPWMFreq(SERVO_FREQ);

	// record axis assignments
	motor[0].servo_num = MOT1_UNIT;
	motor[1].servo_num = MOT2_UNIT;

	// init each motor state
	nv->get();
	motor[0].min = nv->mot0min;
	motor[0].max = nv->mot0max;
	motor[0].pos = 0;
	motor[0].atmin = false;
	motor[0].atmax = false;
	motor[0].az_scale = 0;
	motor[0].el_scale = 0;

	motor[1].min = nv->mot1min;
	motor[1].max = nv->mot1max;
	motor[1].pos = 0;
	motor[1].atmin = false;
	motor[1].atmax = false;
	motor[1].az_scale = 0;
	motor[1].el_scale = 0;

	// init to arbitrary, but at least defined, state
	init_step = 0;
	best_azmotor = 0;
	last_update = 0;
	prevfast_az = prevfast_el = -1000;
	prevstop_az = prevstop_el = -1000;
}

/* move motors towards the given new target az and el 
 */
void Gimbal::moveToAzEl (float az_t, float el_t)
{
	// only update every UPD_PERIOD
	uint32_t now = millis();
	if (now - last_update < UPD_PERIOD)
	    return;
	last_update = now;

	// read current sensor direction
	float az_s, el_s;
	sensor->getAzEl (&az_s, &el_s);

	// only check further when motion has stopped as evidenced by stable sensor values
	if (fabs (azDist (prevfast_az, az_s)) < MAX_SETTLE && fabs (el_s - prevfast_el) < MAX_SETTLE) {

	    // calibrate if not already else seek target
	    if (!calibrated())

		calibrate (az_s, el_s);

	    else

		seekTarget (az_t, el_t, az_s, el_s);
	    

	    // preserve for next stopped iteration
	    prevstop_az = az_s;
	    prevstop_el = el_s;

	}

	// preserve for next fast iteration
	prevfast_az = az_s;
	prevfast_el = el_s;
}

/* run the next step of the initial scale calibration series.
 * steps proceed using init_step up to N_INIT_STEPS
 */
void Gimbal::calibrate (float& az_s, float& el_s)
{
	// handy step ranges
	uint16_t range0 = motor[0].max - motor[0].min;
	uint16_t range1 = motor[1].max - motor[1].min;

	switch (init_step++) {

	case 0:

	    // move near min of each range
	    setMotorPosition (0, motor[0].min + (1-CAL_FRAC)/2*range0);
	    setMotorPosition (1, motor[1].min + (1-CAL_FRAC)/2*range1);
	    break;

	case 1:

	    // move just motor 0 a subtantial distance
	    /*
	    Serial.print(F("Init 1: Mot 0 starts at:\t"));
		Serial.print(az_s); Serial.print(F("\t"));
		Serial.print (el_s); Serial.print(F("\tMoves\t"));
		Serial.println(CAL_FRAC*range0, 0);
	    */
	    setMotorPosition (0, motor[0].pos + CAL_FRAC*range0);
	    break;

	case 2:

	    // calculate scale of motor 0
	    motor[0].az_scale = CAL_FRAC*range0/azDist(prevstop_az, az_s);
	    motor[0].el_scale = CAL_FRAC*range0/(el_s - prevstop_el);
	    /*
	    Serial.print(F("Init 2: Mot 0 ended  at:\t"));
		Serial.print(az_s); Serial.print(F("\t"));
		Serial.print (el_s); Serial.print(F("\tusec:\t"));
		Serial.print (CAL_FRAC*range0); Serial.print (F("\tDel usec/Deg:\t"));
		Serial.print (motor[0].az_scale); Serial.print (F("\t"));
		Serial.println (motor[0].el_scale);
	    */

	    // repeat procedure for motor 1
	    /*
	    Serial.print(F("Init 2: Mot 1 starts at:\t"));
		Serial.print(az_s); Serial.print(F("\t"));
		Serial.print (el_s); Serial.print(F("\tMoves\t"));
		Serial.println(CAL_FRAC*range1, 0);
	    */
	    setMotorPosition (1, motor[1].pos + CAL_FRAC*range1);
	    break;

	case 3:

	    // calculate scale of motor 1
	    motor[1].az_scale = CAL_FRAC*range1/azDist(prevstop_az, az_s);
	    motor[1].el_scale = CAL_FRAC*range1/(el_s - prevstop_el);
	    /*
	    Serial.print(F("Init 3: Mot 1 ended  at:\t"));
		Serial.print(az_s); Serial.print(F("\t"));
		Serial.print (el_s); Serial.print(F("\tusec:\t"));
		Serial.print (CAL_FRAC*range1); Serial.print (F("\tDel usec/Deg:\t"));
		Serial.print (motor[1].az_scale); Serial.print (F("\t"));
		Serial.println (motor[1].el_scale);
	    */

	    // select best motor for az
	    best_azmotor = fabs(motor[0].az_scale) < fabs(motor[1].az_scale) ? 0 : 1;
	    Serial.print (F("Best Az motor:\t"));
		Serial.print (best_azmotor); Serial.print (F("\tScale:\t"));
		Serial.print (motor[best_azmotor].az_scale);
		Serial.print (F("\tEl motor:\t"));
		Serial.print (!best_azmotor); Serial.print (F("\tScale:\t"));
		Serial.println (motor[!best_azmotor].el_scale);

	    // report we have finished calibrating
	    target->setTrackingState (true);
	    break;

	default:

	    webpage->setUserMessage (F("BUG! Bogus init_step"));
	    break;
	}
}

/* run the next step of seeking the given target given the current stable az/el sensor values
 */
void Gimbal::seekTarget (float& az_t, float& el_t, float& az_s, float& el_s)
{
	// find pointing error in each dimension as a move from sensor to target
	float az_err = azDist (az_s, az_t);
	float el_err = el_t - el_s;

	// correct each error using motor with most effect in that axis
	MotorInfo *azmip = &motor[best_azmotor];
	MotorInfo *elmip = &motor[!best_azmotor];

	/*
	Serial.print (F("Az:\t"));
	    Serial.print(az_s); Serial.print(F("\t"));
	    Serial.print(azmip->pos); Serial.print (F("\t"));
	    Serial.print(az_err, 1); Serial.print (F("\t"));
	    Serial.print(az_err*azmip->az_scale, 0);
	Serial.print (F("\tEl:\t"));
	    Serial.print(el_s); Serial.print(F("\t"));
	    Serial.print(elmip->pos); Serial.print (F("\t"));
	    Serial.print(el_err, 1); Serial.print (F("\t"));
	    Serial.println(el_err*elmip->el_scale, 0);
	*/


	// tweak scale if move was substantial and sanity check by believing only small changes
	const float MIN_ANGLE = 30;		// min acceptable move
	const float MAX_CHANGE = 0.1;		// max fractional scale change
	float az_move = azDist (prevstop_az, az_s);
	if (fabs(az_move) >= MIN_ANGLE) {
	    float new_az_scale = azmip->del_pos/az_move;
	    if (fabs((new_az_scale - azmip->az_scale)/azmip->az_scale) < MAX_CHANGE) {
		Serial.print (F("New Az scale\t"));
		    Serial.print (azmip->az_scale); Serial.print (F("\t->\t"));
		    Serial.println(new_az_scale);
		azmip->az_scale = new_az_scale;
	    }
	}
	float el_move = el_s - prevstop_el;
	if (fabs(el_move) >= MIN_ANGLE) {
	    float new_el_scale = elmip->del_pos/el_move;
	    if (fabs((new_el_scale - elmip->el_scale)/elmip->el_scale) < MAX_CHANGE) {
		Serial.print (F("New El scale\t"));
		    Serial.print (elmip->el_scale); Serial.print (F("\t->\t"));
		    Serial.println(new_el_scale);
		elmip->el_scale = new_el_scale;
	    }
	}


	// move each motor to reduce error, but if at Az limit then swing back to near opposite limit
	if (azmip->atmin) {
	    // Serial.println (F("At Az Min"));
	    setMotorPosition (best_azmotor, azmip->min + 0.8*(azmip->max - azmip->min));
	} else if (azmip->atmax) {
	    // Serial.println (F("At Az Max"));
	    setMotorPosition (best_azmotor, azmip->min + 0.2*(azmip->max - azmip->min));
	} else
	    setMotorPosition (best_azmotor, azmip->pos + az_err*azmip->az_scale);
	setMotorPosition (!best_azmotor, elmip->pos + el_err*elmip->el_scale);

}

/* given two azimuth values, return path length going shortest direction
 */
float Gimbal::azDist (float &from, float &to)
{
	float d = to - from;
	if (d < -180)
	    d += 360;
	else if (d > 180)
	    d -= 360;
	return (d);
}

/* send latest web values.
 * N.B. must match id's in main web page
 */
void Gimbal::sendNewValues (WiFiClient client)
{
	if (!gimbal_found) {
	    client.println (F("G_Status=Not found!"));
	    return;
	}

	client.print (F("G_Mot1Pos="));
	if (init_step > 0)
	    client.println (motor[0].pos);
	else
	    client.println (F(""));
	client.print (F("G_Mot1Min=")); client.println (motor[0].min);
	client.print (F("G_Mot1Max=")); client.println (motor[0].max);

	client.print (F("G_Mot2Pos="));
	if (init_step > 0)
	    client.println (motor[1].pos);
	else
	    client.println (F(""));
	client.print (F("G_Mot2Min=")); client.println (motor[1].min);
	client.print (F("G_Mot2Max=")); client.println (motor[1].max);

	client.print (F("G_Status="));
	    if (motor[0].atmin)
		client.println (F("1 at Min!"));
	    else if (motor[0].atmax)
		client.println (F("1 at Max!"));
	    else if (motor[1].atmin)
		client.println (F("2 at Min!"));
	    else if (motor[1].atmax)
		client.println (F("2 at Max!"));
	    else
		client.println (F("Ok+"));

}

/* process name = value.
 * return whether we recognize it
 */
bool Gimbal::overrideValue (char *name, char *value)
{
	const __FlashStringHelper *nog = F("No gimbal!");

	if (!strcmp (name, "G_Mot1Pos")) {
	    if (gimbal_found) {
		target->setTrackingState(false);
		setMotorPosition (0, atoi(value));
	    } else
		webpage->setUserMessage (nog);
	    return (true);
	}
	if (!strcmp (name, "G_Mot1Min")) {
	    if (gimbal_found) {
		nv->mot0min = motor[0].min = atoi(value);
		nv->put();
		webpage->setUserMessage (F("Servo 1 minimum saved in EEPROM+"));
	    } else
		webpage->setUserMessage (nog);
	    return (true);
	}
	if (!strcmp (name, "G_Mot1Max")) {
	    if (gimbal_found) {
		nv->mot0max = motor[0].max = atoi(value);
		nv->put();
		webpage->setUserMessage (F("Servo 1 maximum saved in EEPROM+"));
	    } else
		webpage->setUserMessage (nog);
	    return (true);
	}
	if (!strcmp (name, "G_Mot2Pos")) {
	    if (gimbal_found) {
		target->setTrackingState(false);
		setMotorPosition (1, atoi(value));
	    } else
		webpage->setUserMessage (nog);
	    return (true);
	}
	if (!strcmp (name, "G_Mot2Min")) {
	    if (gimbal_found) {
		nv->mot1min = motor[1].min = atoi(value);
		nv->put();
		webpage->setUserMessage (F("Servo 2 minimum saved in EEPROM+"));
	    } else
		webpage->setUserMessage (nog);
	    return (true);
	}
	if (!strcmp (name, "G_Mot2Max")) {
	    if (gimbal_found) {
		nv->mot1max = motor[1].max = atoi(value);
		nv->put();
		webpage->setUserMessage (F("Servo 2 maximum saved in EEPROM+"));
	    } else
		webpage->setUserMessage (nog);
	    return (true);
	}
	return (false);
}

More to follow(character limit).

Gimbal.h

// class to control two motors to track a target az and el using the Adafruit I2C interface

#ifndef _GIMBAL_H
#define _GIMBAL_H

#include <Wire.h>
#include <WiFiClient.h>
#include <Adafruit_PWMServoDriver.h>

#include "AutoSatTracker-ESP.h"
#include "Target.h"
#include "Sensor.h"

class Gimbal {

    private:

	// I2C servo interface
	Adafruit_PWMServoDriver *pwm;
	static const uint8_t GIMBAL_I2C_ADDR = 0x40;	// I2C bus address of servo controller
	static const uint8_t SERVO_FREQ = 50;		// typical servo pulse frequency, Hz
	static constexpr float US_PER_BIT = (1e6/SERVO_FREQ/4096);	// usec per bit @ 12 bit resolution
	static const uint8_t MOT1_UNIT = 0;		// motor 1 I2C unit number
	static const uint8_t MOT2_UNIT = 1;		// motor 2 I2C unit number
	bool gimbal_found;				// whether PWM controller is present

	// motor info
	typedef struct {
	    float az_scale, el_scale;			// az and el scale: steps (del usec) per degree
	    uint16_t min, max;				// position limits, usec
	    uint16_t pos;				// last commanded position, usec
	    int16_t del_pos;				// change in pos since previous move
	    bool atmin, atmax;				// (would have been commanded to) limit
	    uint8_t servo_num;				// I2C bus address 0..15
	} MotorInfo;
	static const uint8_t NMOTORS = 2;		// not easily changed
	MotorInfo motor[NMOTORS];

	// search info
	// N.B.: max az physical motion must be < 180/CAL_FRAC
	static const uint16_t UPD_PERIOD = 500;		// ms between updates
	static constexpr float MAX_SETTLE = 5.0;	// considered stopped, degs
	static const uint8_t N_INIT_STEPS = 4;		// number of init_steps
	static constexpr float CAL_FRAC = 0.333;	// fraction of full range to move for calibration
							// N.B.: max physical motion must be < 180/CAL_FRAC
	uint8_t init_step;				// initialization sequencing
	uint8_t best_azmotor;				// after cal, motor[] index with most effect in az
	uint32_t last_update;				// millis() time of last move
	float prevfast_az, prevfast_el;			// previous pointing position
	float prevstop_az, prevstop_el;			// previous stopped position

	void setMotorPosition (uint8_t motn, uint16_t newpos);
	void calibrate (float &az_s, float &el_s);
	void seekTarget (float& az_t, float& el_t, float& az_s, float& el_s);
	float azDist (float &from, float &to);

    public:

	Gimbal();

	void moveToAzEl (float az_t, float el_t);
	void sendNewValues (WiFiClient client);
	bool overrideValue (char *name, char *value);
	bool connected() { return (gimbal_found); };
	bool calibrated() { return (init_step >= N_INIT_STEPS); }
};

extern Gimbal *gimbal;

#endif // _GIMBAL_H

More to follow(character limit).

NV.h

/* Class to organize variables stored in EEPROM.
 * The public class variables are mirrored in RAM, so change nv then call put(), or call get() then access nv.
 * The validity of EEPROM is checked using a magic constant that must match. All values will be inited to 0.
 */

#ifndef _NV_H
#define _NV_H

#include <ESP8266WiFi.h>
#include <EEPROM.h>

#include "AutoSatTracker-ESP.h"

class NV {

    private:

	    enum {
	      MAGIC  = 0x5a5aa5a5,
	      NBNO055CALBYTES = 22,
	      EEBYTES = 250,
	    };

    public:

	// these variables are stored in EEPROM
	uint32_t magic;
	IPAddress IP, GW, NM;
	char ssid[64];
	char pw[64];
	uint16_t mot0min, mot0max, mot1min, mot1max;
	uint8_t BNO055cal[NBNO055CALBYTES];

	NV() {
	    EEPROM.begin(EEBYTES);
	}

	void get() {
	    // fill this object from EEPROM
	    byte *this_addr = (byte *)this;
	    for (size_t i = 0; i < sizeof(*this); i++)
		this_addr[i] = EEPROM.read(i);
	    // it no magic cookie, init and save in EEPROM
	    if (magic != MAGIC) {
		memset (this, 0, sizeof(*this));
		magic = MAGIC;
		put();
	    }
	}

	void put() {
	    // save this object in EEPROM
	    byte *this_addr = (byte *)this;
	    for (size_t i = 0; i < sizeof(*this); i++)
		    EEPROM.write(i, this_addr[i]);
	    EEPROM.commit();
	}
};

extern NV *nv;

#endif // _NV_H

More to follow(character limit).

P13.cpp

//
// P13.cpp
//
// An implementation of Plan13 in C++ by Mark VandeWettering
//
// Plan13 is an algorithm for satellite orbit prediction first formulated
// by James Miller G3RUH.  I learned about it when I saw it was the basis 
// of the PIC based antenna rotator project designed by G6LVB.
//
// http://www.g6lvb.com/Articles/LVBTracker2/index.htm
//
// I ported the algorithm to Python, and it was my primary means of orbit
// prediction for a couple of years while I operated the "Easy Sats" with 
// a dual band hand held and an Arrow antenna.
//
// I've long wanted to redo the work in C++ so that I could port the code
// to smaller processors including the Atmel AVR chips.  Bruce Robertson,
// VE9QRP started the qrpTracker project to fufill many of the same goals,
// but I thought that the code could be made more compact and more modular,
// and could serve not just the embedded targets but could be of more
// use for more general applications.  And, I like the BSD License a bit
// better too.
//
// So, here it is!
//

#include "P13.h"

// here are a bunch of constants that will be used throughout the
// code, but which will probably not be helpful outside.

// Updated with 2014 values from
// http://www.amsat.org/amsat/articles/g3ruh/111.html

static const float RE = 6378.137f ;
static const float FL = 1.f/298.257224f ;
static const float GM = 3.986E5f ;
static const float J2 = 1.08263E-3f ;
static const float YM = 365.25f ;
static const float YT = 365.2421874f ;
static const float WW = 2.f*M_PI/YT ;
static const float WE = 2.f*M_PI+ WW ;
static const float W0 = WE/86400.f ;
static const float YG = 2014.f ;
static const float G0 = 99.5828f ;
static const float MAS0 = 356.4105f ;
static const float MASD = 0.98560028f ;
static const float EQC1 = 0.03340 ;
static const float EQC2 = 0.00035 ;
static const float INS = (23.4375f)*M_PI/180.0 ;
static const float CNS = cos(INS) ;
static const float SNS = sin(INS) ;


float
RADIANS(float deg)
{
    return deg * M_PI / 180. ;
}

float
DEGREES(float rad)
{
    return rad * 180. / M_PI ;
}


//----------------------------------------------------------------------
//     _              ___       _      _____ _           
//  __| |__ _ ______ |   \ __ _| |_ __|_   _(_)_ __  ___ 
// / _| / _` (_-<_-< | |) / _` |  _/ -_)| | | | '  \/ -_)
// \__|_\__,_/__/__/ |___/\__,_|\__\___||_| |_|_|_|_\___|
//                                                       
//----------------------------------------------------------------------

static long
fnday(int y, uint8_t m, uint8_t d)
{
    if (m < 3) {
	m += 12 ;
	y -- ;
    }
    return (long) (y * YM) + (long) ((m+1)*30.6f) + (long)d - 428L ;
}

static void
fndate(int &y, uint8_t &m, uint8_t &d, long dt)
{
    dt += 428L ;
    y = (int) ((dt-122.1)/365.25) ;
    dt -= (long) (y*365.25) ;
    m = (uint8_t) (dt / 30.61) ;
    dt -= (long) (m*30.6) ;
    m -- ;
    if (m > 12) {
	m -= 12 ;
	y++ ;
    }
    d = dt ;
}

DateTime::DateTime(int year, uint8_t month, uint8_t day, uint8_t h, uint8_t m, uint8_t s) 
{
    settime(year, month, day, h, m, s) ;
}


// copy constructor
DateTime::DateTime(const DateTime &dt)
{
    DN = dt.DN ;
    TN = dt.TN ;
}

// default constructor
DateTime::DateTime()
{
   DN = 0L ;
   TN = 0. ;
}

// overload assignment
DateTime &DateTime::operator= (const DateTime &source)
{
    DN = source.DN;
    TN = source.TN;
    return *this;
}

void
DateTime::gettime(int &year, uint8_t &month, uint8_t &day, uint8_t &h, uint8_t &m, uint8_t &s)
{
    fndate(year, month, day, DN) ;
    float t = TN ;
    t *= 24. ;
    h = (uint8_t) t ;
    t -= h ;
    t *= 60 ;
    m = (uint8_t) t ;
    t -= m ;
    t *= 60 ;
    s = (uint8_t) (t+0.5) ;
    if (s == 60)
	s = 59;

}

void
DateTime::settime(int year, uint8_t month, uint8_t day, uint8_t h, uint8_t m, uint8_t s) 
{
    DN = fnday(year, month, day) ;
    TN = ((float) h + m / 60. + s / 3600.) / 24. ;
}

void
DateTime::add(float days)
{
    TN += days ;
    DN += (long) TN ;
    TN -= (long) TN ;
}

void
DateTime::add(long seconds)
{
    TN += seconds/(24.0*3600.0);
    DN += (long) TN ;
    TN -= (long) TN ;
}

// return (t0 - this) in days
float
DateTime::diff (DateTime& t0)
{
    long ddn = t0.DN - DN;
    float dtn = t0.TN - TN;
    return (ddn + dtn);
}

//----------------------------------------------------------------------
//     _               ___  _                            
//  __| |__ _ ______  / _ \| |__ ___ ___ _ ___ _____ _ _ 
// / _| / _` (_-<_-< | (_) | '_ (_-</ -_) '_\ V / -_) '_|
// \__|_\__,_/__/__/  \___/|_.__/__/\___|_|  \_/\___|_|  
//                                                      
//----------------------------------------------------------------------

Observer::Observer(float lat, float lng, float hgt)
{
    LA = RADIANS(lat) ;
    LO = RADIANS(lng) ;
    HT = hgt / 1000 ;

    U[0] = cos(LA)*cos(LO) ;
    U[1] = cos(LA)*sin(LO) ;
    U[2] = sin(LA) ;

    E[0] = -sin(LO) ;
    E[1] =  cos(LO) ;
    E[2] =  0. ;

    N[0] = -sin(LA)*cos(LO) ;
    N[1] = -sin(LA)*sin(LO) ;
    N[2] =  cos(LA) ;

    float RP = RE * (1 - FL) ;
    float XX = RE * RE ;
    float ZZ = RP * RP ;
    float D = sqrt(XX*cos(LA)*cos(LA) + 
	            ZZ*sin(LA)*sin(LA)) ;
    float Rx = XX / D + HT ;
    float Rz = ZZ / D + HT ;

    O[0] = Rx * U[0] ;
    O[1] = Rx * U[1] ;
    O[2] = Rz * U[2] ;

    V[0] = -O[1] * W0 ;
    V[1] =  O[0] * W0 ;
    V[2] =  0 ;
}

//----------------------------------------------------------------------
//     _              ___       _       _ _ _ _       
//  __| |__ _ ______ / __| __ _| |_ ___| | (_) |_ ___ 
// / _| / _` (_-<_-< \__ \/ _` |  _/ -_) | | |  _/ -_)
// \__|_\__,_/__/__/ |___/\__,_|\__\___|_|_|_|\__\___|
//
//----------------------------------------------------------------------

static float
getfloat(const char *c, int i0, int i1)
{
    char buf[20] ;
    int i ;
    for (i=0; i0+i<i1; i++) 
	buf[i] = c[i0+i] ;
    buf[i] = '\0' ;
    return strtod(buf, NULL) ;
}

static long
getlong(const char *c, int i0, int i1)
{
    char buf[20] ;
    int i ;
    for (i=0; i0+i<i1; i++) 
	buf[i] = c[i0+i] ;
    buf[i] = '\0' ;
    return atol(buf) ;
}

Satellite::Satellite(const char *l1, const char *l2)
{
    tle(l1, l2) ;
}

Satellite::~Satellite()
{
}

void
Satellite::tle(const char *l1, const char *l2)
{
    // direct quantities from the orbital elements

    N = getlong(l2, 2, 7) ;
    YE = getlong(l1, 18, 20) ;
    if (YE < 58)
	YE += 2000 ;
    else
	YE += 1900 ;

    TE = getfloat(l1, 20, 32) ;
    M2 = RADIANS(getfloat(l1, 33, 43)) ;

    IN = RADIANS(getfloat(l2, 8, 16)) ;
    RA = RADIANS(getfloat(l2, 17, 25)) ;
    EC = getfloat(l2, 26, 33)/1e7f ;
    WP = RADIANS(getfloat(l2, 34, 42)) ;
    MA = RADIANS(getfloat(l2, 43, 51)) ;
    MM = 2.0f * M_PI * getfloat(l2, 52, 63) ;
    RV = getlong(l2, 63, 68) ;

    // derived quantities from the orbital elements 

    // convert TE to DE and TE 
    DE = fnday(YE, 1, 0) + (long) TE ;
    TE -= (long) TE ;
    N0 = MM/86400 ;
    A_0 = pow(GM/(N0*N0), 1./3.) ;
    B_0 = A_0*sqrt(1.-EC*EC) ;
    PC = RE*A_0/(B_0*B_0) ;
    PC = 1.5f*J2*PC*PC*MM ;
    float CI = cos(IN) ;
    QD = -PC*CI ;
    WD =  PC*(5*CI*CI-1)/2 ;
    DC = -2*M2/(3*MM) ;
}
void
Satellite::predict(const DateTime &dt)
{
    long DN = dt.DN ;
    float TN = dt.TN ;

    float TEG = DE - fnday(YG, 1, 0) + TE ;

    float GHAE = RADIANS(G0) + TEG * WE ;

    float T = (float) (DN - DE) + (TN-TE) ;
    float DT = DC * T / 2. ;
    float KD = 1. + 4. * DT ;
    float KDP = 1. - 7. * DT ;
  
    float M = MA + MM * T * (1. - 3. * DT) ;
    float DR = (long) (M / (2. * M_PI)) ;
    M -= DR * 2. * M_PI ;
    float EA = M ;

    float DNOM, C_EA, S_EA ;

    for (;;) {
	C_EA = cos(EA) ;
	S_EA = sin(EA) ;
	DNOM = 1. - EC * C_EA ;
	float D = (EA-EC*S_EA-M)/DNOM ;
	EA -= D ;
	if (fabs(D) < 1e-5)
	    break ;
    }

    float A = A_0 * KD ;
    float B = B_0 * KD ;
    RS = A * DNOM ;

    float Vx, Vy ;
    float Sx, Sy ;
    Sx = A * (C_EA - EC) ;
    Sy = B * S_EA ;

    Vx = -A * S_EA / DNOM * N0 ;
    Vy =  B * C_EA / DNOM * N0 ;

    float AP = WP + WD * T * KDP ;
    float CW = cos(AP) ;
    float SW = sin(AP) ;

    float RAAN = RA + QD * T * KDP ;
 
    float CQ = cos(RAAN) ;
    float SQ = sin(RAAN) ;

    float CI = cos(IN) ;
    float SI = sin(IN) ;

    // CX, CY, and CZ form a 3x3 matrix
    // that converts between orbit coordinates,
    // and celestial coordinates.

    Vec3 CX, CY, CZ ;
   
    CX[0] =  CW * CQ - SW * CI * SQ ;
    CX[1] = -SW * CQ - CW * CI * SQ ;
    CX[2] =  SI * SQ ;

    CY[0] =  CW * SQ + SW * CI * CQ ;
    CY[1] = -SW * SQ + CW * CI * CQ ;
    CY[2] = -SI * CQ ;

    CZ[0] = SW * SI ;
    CZ[1] = CW * SI ;
    CZ[2] = CI ;

    // satellite in celestial coords

    SAT[0] = Sx * CX[0] + Sy * CX[1] ;
    SAT[1] = Sx * CY[0] + Sy * CY[1] ;
    SAT[2] = Sx * CZ[0] + Sy * CZ[1] ;

    VEL[0] = Vx * CX[0] + Vy * CX[1] ;
    VEL[1] = Vx * CY[0] + Vy * CY[1] ;
    VEL[2] = Vx * CZ[0] + Vy * CZ[1] ;

    // and in geocentric coordinates

    float GHAA = (GHAE + WE * T) ;
    float CG = cos(-GHAA) ;
    float SG = sin(-GHAA) ;

    S[0] = SAT[0] * CG - SAT[1] * SG ;
    S[1] = SAT[0] * SG + SAT[1] * CG ;
    S[2] = SAT[2] ;

    V[0] = VEL[0] * CG - VEL[1]* SG ;
    V[1] = VEL[0] * SG + VEL[1]* CG ;
    V[2] = VEL[2] ;
}

void
Satellite::topo(const Observer *obs, float &alt, float &az, float &range, float &range_rate)
{
    Vec3 R ;
    R[0] = S[0] - obs->O[0] ;
    R[1] = S[1] - obs->O[1] ;
    R[2] = S[2] - obs->O[2] ;
    range = sqrt(R[0]*R[0]+R[1]*R[1]+R[2]*R[2]) ;
    R[0] /= range ;
    R[1] /= range ;
    R[2] /= range ;

    range_rate = 1000*((V[0]-obs->V[0])*R[0] + (V[1]-obs->V[1])*R[1] + V[2]*R[2]);	// m/s

    float u = R[0] * obs->U[0] + R[1] * obs->U[1] + R[2] * obs->U[2] ;
    float e = R[0] * obs->E[0] + R[1] * obs->E[1] + R[2] * obs->E[2] ;
    float n = R[0] * obs->N[0] + R[1] * obs->N[1] + R[2] * obs->N[2] ;

    az = DEGREES(atan2(e, n)) ;
    if (az < 0.) az += 360. ;
    alt = DEGREES(asin(u)) ;

    /* N.B. ignore refraction
     */
}

bool
Satellite::eclipsed(Sun *sp)
{
    float CUA = -(SAT[0]*sp->SUN[0]+SAT[1]*sp->SUN[1]+SAT[2]*sp->SUN[2])/RS;
    float UMD = RS*sqrt(1-CUA*CUA)/RE;
    return (UMD<=1 && CUA>=0);
       
}

//----------------------------------------------------------------------

Sun::Sun()
{
}

void
Sun::predict(const DateTime &dt)
{
    long DN = dt.DN ;
    float TN = dt.TN ;

    float T = (float) (DN - fnday(YG, 1, 0)) + TN ;
    float GHAE = RADIANS(G0) + T * WE ;
    float MRSE = RADIANS(G0) + T * WW + M_PI ;
    float MASE = RADIANS(MAS0 + T * MASD) ;
    float TAS = MRSE + EQC1*sin(MASE) + EQC2*sin(2.*MASE) ;
    float C, S ;

    C = cos(TAS) ;
    S = sin(TAS) ;
    SUN[0]=C ;
    SUN[1]=S*CNS ;
    SUN[2]=S*SNS ;
    C = cos(-GHAE) ; 
    S = sin(-GHAE) ; 
    H[0]=SUN[0]*C - SUN[1]*S ;
    H[1]=SUN[0]*S + SUN[1]*C ;
    H[2]=SUN[2] ;
}

More to follow(character limit).

P13.h

#ifndef _P13_H
#define _P13_H

//
// Plan13.cpp
//
// An implementation of Plan13 in C++ by Mark VandeWettering
//
// Plan13 is an algorithm for satellite orbit prediction first formulated
// by James Miller G3RUH.  I learned about it when I saw it was the basis 
// of the PIC based antenna rotator project designed by G6LVB.
//
// http://www.g6lvb.com/Articles/LVBTracker2/index.htm
//
// I ported the algorithm to Python, and it was my primary means of orbit
// prediction for a couple of years while I operated the "Easy Sats" with 
// a dual band hand held and an Arrow antenna.
//
// I've long wanted to redo the work in C++ so that I could port the code
// to smaller processors including the Atmel AVR chips.  Bruce Robertson,
// VE9QRP started the qrpTracker project to fufill many of the same goals,
// but I thought that the code could be made more compact and more modular,
// and could serve not just the embedded targets but could be of more
// use for more general applications.  And, I like the BSD License a bit
// better too.
//
// So, here it is!
//


//----------------------------------------------------------------------

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>

//----------------------------------------------------------------------

// the original BASIC code used three variables (e.g. Ox, Oy, Oz) to
// represent a vector quantity.  I think that makes for slightly more
// obtuse code, so I going to collapse them into a single variable 
// which is an array of three elements

typedef float Vec3[3] ;


extern float RADIANS(float deg);
extern float DEGREES(float rad);


//----------------------------------------------------------------------

class DateTime {
public:
    long DN ;
    float TN ;
    DateTime(int year, uint8_t month, uint8_t day, uint8_t h, uint8_t m, uint8_t s) ;
    DateTime(const DateTime &) ;
    DateTime() ;
    ~DateTime() { } 
    DateTime& operator= (const DateTime &source) ;
    void add(float) ;
    void add(long) ;
    float diff (DateTime& t0);
    void settime(int year, uint8_t month, uint8_t day, uint8_t h, uint8_t m, uint8_t s) ;
    void gettime(int& year, uint8_t& mon, uint8_t& day, uint8_t& h, uint8_t& m, uint8_t& s) ;
} ;

//----------------------------------------------------------------------

class Observer {
public:
    float LA ;
    float LO ;
    float HT ;
    Vec3 U, E, N, O, V  ;
    
    Observer(float, float, float) ;
    ~Observer() { } ;
} ;

//----------------------------------------------------------------------


class Sun {
public:
	Vec3 SUN, H ;
	Sun() ;
	~Sun() { } ;
        void predict(const DateTime &dt) ;
} ;

//----------------------------------------------------------------------

class Satellite { 
  	long N ;
	long YE ;	
	float IN ;
	float RA ;
	float EC ;
	float WP ;
	float MA ;
	float MM ;
	float M2 ;
	float RV ;


	// these values are stored, but could be calculated on the fly
	// during calls to predict() 
	// classic space/time tradeoff

        float N0, A_0, B_0 ;
        float PC ;
        float QD, WD, DC ;
        float RS ;

public:
        long DE ;
	float TE ;

	Vec3 SAT, VEL ;		// celestial coordinates
    	Vec3 S, V ; 		// geocentric coordinates
 
	Satellite() { } ;
	Satellite(const char *l1, const char *l2) ;
	~Satellite() ;
        void tle(const char *l1, const char *l2) ;
        void predict(const DateTime &dt) ;
	bool eclipsed(Sun *sp);
	void topo(const Observer *obs, float &alt, float &az, float &range, float &range_rate);
} ;

#endif // _P13_H

More to follow(character limit).

Sensor.cpp

/* this class contains information about the 9 dof spatial sensor
 */

#include "Sensor.h"

/* class constructor
 */
Sensor::Sensor()
{
	// instantiate, discover and initialize
	resetWatchdog();
	bno = new Adafruit_BNO055(-1, BNO055_I2CADDR);
	resetWatchdog();
	sensor_found = bno->begin(Adafruit_BNO055::OPERATION_MODE_NDOF);
	if (sensor_found)
	    Serial.println (F("Sensor found ok"));
	else
	    Serial.println (F("Sensor not found"));
	installCalibration();
}

/* read the current temperature, in degrees C
 */
int8_t Sensor::getTempC()
{
	if (sensor_found)
	    return bno->getTemp();
	return (-1);
}

/* return whether sensor is connected and calibrated
 */
bool Sensor::calibrated(uint8_t& sys, uint8_t& gyro, uint8_t& accel, uint8_t& mag)
{
	if (!sensor_found)
	    return (false);

	sys = 0;
	gyro = 0;
	accel = 0;
	mag = 0;;
	bno->getCalibration(&sys, &gyro, &accel, &mag);
	return (sys >= 1 && gyro >= 1 && accel >= 1 && mag >= 1);
}

/* read the current az and el, corrected for mag decl but not necessarily calibrated.
 * N.B. we assume this will only be called if we know the sensor is connected.
 * N.B. Adafruit board:
 *   the short dimension is parallel to the antenna boom,
 *   the populated side of the board faces upwards and
 *   the side with the control signals (SDA, SCL etc) points in the rear direction of the antenna pattern.
 * Note that az/el is a left-hand coordinate system.
 */
void Sensor::getAzEl (float *azp, float *elp)
{
	Wire.setClockStretchLimit(2000);
	imu::Vector<3> euler = bno->getVector(Adafruit_BNO055::VECTOR_EULER);
	*azp = myfmod (euler.x() + circum->magdeclination + 540, 360);
	*elp = euler.z();
}

/* process name = value pair
 * return whether we recognize it
 */
bool Sensor::overrideValue (char *name, char *value)
{
	if (!strcmp (name, "SS_Save")) {
	    saveCalibration();
	    webpage->setUserMessage (F("Sensor calibrations saved to EEPROM+"));
	    return (true);
	}

	return (false);
}

/* send latest values to web page
 * N.B. labels must match ids in wab page
 */
void Sensor::sendNewValues (WiFiClient client)
{
	if (!sensor_found) {
	    client.println (F("SS_Status=Not found!"));
	    client.println (F("SS_Save=false"));
	    return;
	}

	float az, el;
	getAzEl (&az, &el);
	client.print (F("SS_Az=")); client.println (az);
	client.print (F("SS_El=")); client.println (el);

	uint8_t sys, gyro, accel, mag;
	bool calok = calibrated (sys, gyro, accel, mag);
	if (calok)
	    client.println (F("SS_Status=Ok+"));
	else
	    client.println (F("SS_Status=Uncalibrated!"));
	client.print (F("SS_SStatus=")); client.println (sys);
	client.print (F("SS_GStatus=")); client.println (gyro);
	client.print (F("SS_MStatus=")); client.println (mag);
	client.print (F("SS_AStatus=")); client.println (accel);

	client.print (F("SS_Save="));
	if (calok && sys == 3 && gyro == 3 && accel == 3 && mag == 3) 
	    client.println (F("true"));
	else
	    client.println (F("false"));

	client.print (F("SS_Temp="));
	client.println (getTempC());
}

/* read the sensor calibration values and save into EEPROM.
 * Wanted to stick with stock Adafruit lib so pulled from
 * post by protonstorm at https://forums.adafruit.com/viewtopic.php?f=19&t=75497
 */
void Sensor::saveCalibration()
{
	// put into config mode
	bno->setMode (Adafruit_BNO055::OPERATION_MODE_CONFIG);
	delay(25);

	// request all bytes starting with the ACCEL
	byte nbytes = (byte)sizeof(nv->BNO055cal);
	Wire.beginTransmission((uint8_t)BNO055_I2CADDR);
	Wire.write((uint8_t)(Adafruit_BNO055::ACCEL_OFFSET_X_LSB_ADDR));
	Wire.endTransmission();
	Wire.requestFrom((uint8_t)BNO055_I2CADDR, nbytes);

	// wait for all 22 bytes to be available
	while (Wire.available() < nbytes);

	// copy to NV
	Serial.println (F("Saving sensor values"));
	for (uint8_t i = 0; i < nbytes; i++) {
	    nv->BNO055cal[i] = Wire.read();
	    Serial.println (nv->BNO055cal[i]);
	}

	// restore NDOF mode
	bno->setMode (Adafruit_BNO055::OPERATION_MODE_NDOF);
	delay(25);

	// save in EEPROM
	nv->put();
}

/* install previously stored calibration data from EEPROM if it looks valid.
 * Wanted to stick with stock Adafruit lib so pulled from
 * post by protonstorm at https://forums.adafruit.com/viewtopic.php?f=19&t=75497
 */
void Sensor::installCalibration()
{
	resetWatchdog();
	byte nbytes = (byte)sizeof(nv->BNO055cal);

	// read from EEPROM, qualify
	nv->get();
	uint8_t i;
	for(i = 0; i < nbytes; i++) {
	    if (nv->BNO055cal[i] != 0)
		break;
	}
	if (i == nbytes)
	    return;		// all zeros can't be valid

	// put into config mode
	bno->setMode (Adafruit_BNO055::OPERATION_MODE_CONFIG);
	delay(25);

	// set from NV
	// Serial.println (F("Restoring sensor values"));
	for(uint8_t i = 0; i < nbytes; i++) {
	    Wire.beginTransmission((uint8_t)BNO055_I2CADDR);
	    Wire.write((Adafruit_BNO055::adafruit_bno055_reg_t)
	    		((uint8_t)(Adafruit_BNO055::ACCEL_OFFSET_X_LSB_ADDR)+i));
	    Wire.write(nv->BNO055cal[i]);
	    // Serial.println (nv->BNO055cal[i]);
	    Wire.endTransmission();
	}

	// restore NDOF mode
	bno->setMode (Adafruit_BNO055::OPERATION_MODE_NDOF);
	delay(25);
}

More to follow(character limit).

Sensor.h

/* this class contains information about the 9 dof spatial sensor
 */

#ifndef _SENSOR_H
#define _SENSOR_H

#include <Wire.h>
#include <WiFiClient.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>


#include "AutoSatTracker-ESP.h"
#include "Circum.h"

class Sensor {

    private:

	Adafruit_BNO055 *bno;		// sensor detail
	bool sensor_found;		// whether sensor is connected
	bool calibrated(uint8_t& sys, uint8_t& gyro, uint8_t& accel, uint8_t& mag);
	enum {
	    BNO055_I2CADDR = 0x28,	// I2C bus address of BNO055
	};

    public:

	Sensor();
	int8_t getTempC();
	void getAzEl (float *azp, float *elp);
	void sendNewValues (WiFiClient client);
	bool connected() { return sensor_found; };
	void saveCalibration(void);
	void installCalibration(void);
	bool overrideValue (char *name, char *value);

};

extern Sensor *sensor;

#endif // _SENSOR_H

More to follow(character limit).

Target.cpp

/* define and track a target
 */

#include "Target.h"

/* constructor
 */
Target::Target()
{
	// init values
	resetWatchdog();
	az = el = range = rate = 0;
	memset (TLE_L0, 0, sizeof(TLE_L0));
	memset (TLE_L1, 0, sizeof(TLE_L1));
	memset (TLE_L2, 0, sizeof(TLE_L2));
	sat = new Satellite();
	sun = new Sun();
  satname = "";
  track_status = false;
	// init flags
	tle_ok = false;
	tracking = false;
	overridden = false;
	set_ok = rise_ok = trans_ok = false;
	nskypath = 0;
}

/* update target if valid, and move gimbal if tracking
 */
void Target::track()
{
	resetWatchdog();

	// update ephemerides
	updateTopo();

	// update gimbal if tracking
	if (tracking)
	    gimbal->moveToAzEl (az, el);
}

/* update target info
 */
void Target::updateTopo()
{
	if (tle_ok && !overridden) {
	    DateTime now (circum->now());
	    sat->predict (now);
	    sun->predict (now);
	    sat->topo (circum->observer(), el, az, range, rate);
	}
}

/* turn tracking on or off if it makes sense to do so
 */
void Target::setTrackingState (bool want_on)
{
	if (want_on) {
	    if (!gimbal->connected()) {
		webpage->setUserMessage (F("Can not track without a gimbal!"));
		tracking = false;
	    } else if (!gimbal->calibrated()) {
		webpage->setUserMessage (F("Calibrating gimbal motor scales!"));
		tracking = true;
	    } else if (!sensor->connected()) {
		webpage->setUserMessage (F("Can not track without a position sensor!"));
		tracking = false;
	    } else if (overridden) {
		webpage->setUserMessage (F("Now tracking overridden Az and El+"));
		tracking = true;
    satname = "Override";
	    } else if (tle_ok) {
		webpage->setUserMessage (F("Now tracking: "), TLE_L0, '+');
    satname = TLE_L0;
		tracking = true;
	    } else {
		webpage->setUserMessage (F("First Upload a TLE or override Target Az and El!"));
		tracking = false;
	    }
	} else {
	    webpage->setUserMessage (F("Tracking is off"));
	    tracking = false;
	}
  if (tracking)
    track_status = true;
  else
    track_status = false;
}

/* send latest values to web page.
 * N.B. names must match ids in web page
 */
void Target::sendNewValues (WiFiClient client)
{

	const __FlashStringHelper *zerostr = F("");

	// update pass info just after main events
	// N.B. transit jiggles back and forth too much to recompute after it
	DateTime now (circum->now());
	bool just_rose = rise_ok && now.diff(rise_time) < 0;
	bool just_sat = set_ok && now.diff(set_time) < 0;
	if (just_rose || just_sat) {
	    updateTopo();
	    findNextPass();
	    computeSkyPath();
	}

	if (tle_ok || overridden) {
	    client.print (F("T_Az="));
	    client.print (az);
	    displayAsWarning (client, overridden);
	    client.print (F("T_El="));
	    client.print (el);
	    displayAsWarning (client, overridden);
	}

	if (tle_ok && !overridden) {
	    float age = circum->age(sat);
	    client.print (F("T_Age="));
	    client.print (age);
	    displayAsWarning (client, age < -10 || age > 10);

	    client.print (F("T_Sunlit="));
	    if (sat->eclipsed (sun))
		client.println (F("No"));
	    else
		client.println (F("Yes"));

	    client.print (F("T_Range=")); client.println (range);
	    client.print (F("T_RangeR=")); client.println (rate);
	    client.print (F("T_VHFDoppler=")); client.println (-rate*144000/3e8); // want kHz
	    client.print (F("T_UHFDoppler=")); client.println (-rate*440000/3e8); // want kHz


	    client.print (F("T_NextRise="));
	    if (rise_ok) {
		float dt = 24*now.diff(rise_time);
		circum->printSexa (client, dt);
		circum->printPL (client, (dt < 1.0/60.0) ? Circum::GOODNEWS : Circum::NORMAL);
	    } else
		client.println (F("??? !"));		// beware trigraphs

	    client.print (F("T_RiseAz="));
	    if (rise_ok)
		client.println (rise_az);
	    else
		client.println (F("??? !"));

	    const __FlashStringHelper *transin, *transaz, *transel;
	    client.print (F("T_NextTrans="));
	    if (trans_ok) {
		float dt = 24*now.diff(trans_time);
		circum->printSexa (client, dt);
		circum->printPL (client, Circum::NORMAL);
		if (dt < 0) {
		    transin = F("This Transited ago");
		    transaz = F("This Transit Azimuth");
		    transel = F("This Transit Elevation");
		} else {
		    transin = F("Next Transit in");
		    transaz = F("Next Transit Azimuth");
		    transel = F("Next Transit Elevation");
		}
	    } else {
		client.println (F("??? !"));
		transin = zerostr;
		transaz = zerostr;
		transel = zerostr;
	    }
	    client.print ("T_NextTrans_l=");
	    client.println (transin);

	    client.print (F("T_TransAz="));
	    if (trans_ok)
		client.println (trans_az);
	    else
		client.println (F("??? !"));
	    client.print ("T_TransAz_l=");
	    client.println (transaz);

	    client.print (F("T_TransEl="));
	    if (trans_ok)
		client.println (trans_el);
	    else
		client.println (F("??? !"));
	    client.print ("T_TransEl_l=");
	    client.println (transel);


	    client.print (F("T_NextSet="));
	    if (set_ok) {
		float dt = 24*now.diff(set_time);
		circum->printSexa (client, dt);
		circum->printPL (client, Circum::NORMAL);
	    } else
		client.println (F("??? !"));

	    client.print (F("T_SetAz="));
	    if (rise_ok)
		client.println (set_az);
	    else
		client.println (F("??? !"));

	    const __FlashStringHelper *tup;
	    client.print ("T_Up=");
	    if (rise_ok && set_ok) {
		float up = rise_time.diff(set_time);
		if (up > 0) {
		    circum->printSexa (client, up*24);			// next whole pass
		    circum->printPL (client, Circum::NORMAL);
		    tup= F("Next pass duration");
		} else {
		    up = 24*now.diff(set_time);				// this pass remaining
		    circum->printSexa (client, up);
		    circum->printPL (client, (up < 1.0/60.0) ? Circum::BADNEWS : Circum::NORMAL);
		    tup= F("This pass Ends in");
		}
	    } else {
		tup= zerostr;
		client.println (zerostr);
	    }
	    client.print ("T_Up_l=");
	    client.println (tup);
	}

	client.print (F("T_TLE="));
	if (tle_ok) {
	    client.println (TLE_L0);
	    client.println (TLE_L1);
	    client.println (TLE_L2);
	} else {
	    client.println (zerostr);
	    client.println (zerostr);
	    client.println (zerostr);
	}

	if (overridden) {
	    client.println (F("T_Age="));
	    client.println (F("T_Sunlit="));
	    client.println (F("T_Range="));
	    client.println (F("T_RangeR="));
	    client.println (F("T_VHFDoppler="));
	    client.println (F("T_UHFDoppler="));
	    client.println (F("T_NextRise="));
	    client.println (F("T_RiseAz="));
	    client.println (F("T_NextTrans="));
	    client.println (F("T_TransAz="));
	    client.println (F("T_TransEl="));
	    client.println (F("T_NextSet="));
	    client.println (F("T_SetAz="));
	}

	client.print (F("T_Status="));
	    client.println (tle_ok || overridden ? (el > 0 ? "Up+" : "Down") : "No target!");

	client.print (F("tracking="));
	if (tracking)
	    client.println (F("On"));
	else
	    client.println (F("Off"));

	client.print(F("skypath="));
	for (uint8_t i = 0; i < nskypath; i++) {
	    client.print(skypath[i].az);
	    client.print(F(","));
	    client.print(skypath[i].el);
	    client.print(F(";"));
	}
	client.println(zerostr);
}

/* optionally add code to display the value as a warning
 */
void Target::displayAsWarning (WiFiClient client, bool mark)
{
	if (mark)
	    client.println (F("!"));
	else
	    client.println (F(""));
}

/* process name = value other than T_TLE (that's done with setTLE()).
 * return whether we recognize it
 */
bool Target::overrideValue (char *name, char *value)
{
	if (!strcmp (name, "T_Az")) {
	    az = atof(value);
	    while (az < 0)
		az += 360;
	    while (az >= 360)
		az -= 360;
	    overridden = true;
	    tle_ok = false;
	    nskypath = 0;
	    return (true);
	}
	if (!strcmp (name, "T_El")) {
	    el = fmax (fmin (atof(value), 90), 0);
	    overridden = true;
	    tle_ok = false;
	    nskypath = 0;
	    return (true);
	}
	return (false);
}

/* record a TLE for possible tracking, set tle_ok if valid
 */
void Target::setTLE (char *l1, char *l2, char *l3)
{
  satname=l1;
  Serial.println("setTLE mit" + satname);
	if (tleValidChecksum (l2) && tleValidChecksum(l3)) {
	    tle_ok = true;
	    sat->tle (l2, l3);
	    strncpy (TLE_L0, l1, sizeof(TLE_L0)-1);
	    strncpy (TLE_L1, l2, sizeof(TLE_L1)-1);
	    strncpy (TLE_L2, l3, sizeof(TLE_L2)-1);
	    Serial.println (TLE_L0);
	    Serial.println (TLE_L1);
	    Serial.println (TLE_L2);
	    overridden = false;
	    tracking = false;
	    updateTopo();
	    findNextPass();		// init for track()
	    computeSkyPath();
	    webpage->setUserMessage (F("New TLE uploaded successfully for "), TLE_L0, '+');
	} else {
	    webpage->setUserMessage (F("Uploaded TLE is invalid!"));
	    tle_ok = false;
	}
}

/* find next pass for sat, if currently valid
 */
void Target::findNextPass()
{
        // init all no
	set_ok = rise_ok = trans_ok = ever_up = false;

        // finisged if no sat or custom
	if (!tle_ok || overridden)
	    return;

        const float SAT_MIN_EL = 1;     // min el considered "up", degs
	const int8_t COARSE_DT = 60;	// seconds/step forward for course search
	const int8_t FINE_DT = -1;	// seconds/step backward for refined search
	float pel = 0, ppel = 0;	// previous 2 elevations
	float paz = 0;			// previous az
	int8_t dt = COARSE_DT;		// search step size, seconds
	DateTime t_srch(circum->now());	// search time, init with now

	// search no more than two days ahead
	while ((!set_ok || !rise_ok || !trans_ok) && circum->now().diff(t_srch) < 2) {

	    // find circumstances at time t
	    float tel, taz, trange, trate;
	    sat->predict (t_srch);
	    sat->topo (circum->observer(), tel, taz, trange, trate);
	    // Serial.print (24*60*circum->now().diff(t)); Serial.print(" ");
	    // Serial.print (tel, 6); Serial.print(" ");
	    // Serial.print (rise_ok); Serial.print (trans_ok); Serial.println (set_ok);

	    // check for a visible transit event
	    // N.B. too flat to use FINE_DT
	    if (dt == COARSE_DT && tel > 0 && ppel > 0 && ppel < pel && pel > tel) {
		// found a coarse transit at previous time, good enough
		trans_time = t_srch;
		trans_time.add ((long)(-COARSE_DT));
		trans_az = paz;
		trans_el = pel;
		trans_ok = true;
	    }

	    // check for rising or setting events
	    // N.B. invalidate ppel after turning around
            if (tel >= SAT_MIN_EL) {
                ever_up = true;
                if (pel < SAT_MIN_EL) {
                    if (dt == FINE_DT) {
                        // found a refined set event (recall we are going backwards),
                        // record and resume forward time.
                        set_time = t_srch;
                        set_az = taz;
                        set_ok = true;
                        dt = COARSE_DT;
                        pel = tel;
                    } else if (!rise_ok) {
                        // found a coarse rise event, go back slower looking for better set
                        dt = FINE_DT;
                        pel = tel;
                    }
                }
	    } else {
                if (pel > SAT_MIN_EL) {
                    if (dt == FINE_DT) {
                        // found a refined rise event (recall we are going backwards).
                        // record and resume forward time but skip if set is within COARSE_DT because we
                        // would jump over it and find the NEXT set.
                        float check_tel, check_taz;
                        DateTime check_set(t_srch);
                        check_set.add((long)COARSE_DT);
                        sat->predict (check_set);
                        sat->topo (circum->observer(), check_tel, check_taz, trange, trate);
                        if (check_tel >= SAT_MIN_EL) {
                            rise_time = t_srch;
                            rise_az = taz;
                            rise_ok = true;
                        }
                        // regardless, resume forward search
                        dt = COARSE_DT;
                        pel = tel;
                    } else if (!set_ok) {
                        // found a coarse set event, go back slower looking for better rise
                        dt = FINE_DT;
                        pel = tel;
                    }
                }
            }

	    // next time step
	    paz = taz;
	    ppel = pel;
	    pel = tel;
	    t_srch.add ((long)dt);
	}
}

/* compute sky path of current pass.
 * if up now just plot until set because rise_time will be for subsequent pass
 */
void Target::computeSkyPath()
{
        if (!set_ok || !rise_ok || !ever_up)
            return;

        DateTime t;

        if (el > -1)	// allow for a bit of rise/set round off
            t = circum->now();
        else if (rise_time.diff(set_time) > 0)
            t = rise_time;
        else {
            // rise or set is unknown or for different passes
            nskypath = 0;
            return;
        }


        long secsup = (long)(t.diff(set_time)*24*3600);
        long stepsecs = secsup/(MAXSKYPATH-1);  // inclusive

        for (nskypath = 0; nskypath < MAXSKYPATH; nskypath++) {
            float srange, srate;
            sat->predict (t);
            sat->topo (circum->observer(), skypath[nskypath].el, skypath[nskypath].az, srange, srate);
            t.add (stepsecs);
        }
}

/* return whether the given line appears to be a valid TLE
 * only count digits and '-' counts as 1
 */
bool Target::tleValidChecksum (const char *line)
{
	// sum first 68 chars
	int sum = 0;
	for (uint8_t i = 0; i < 68; i++) {
	    char c = *line++;
	    if (c == '-')
		sum += 1;
	    else if (c == '\0')
		return (false);		// too short
	    else if (c >= '0' && c <= '9')
		sum += c - '0';
	}

	// last char is sum of previous modulo 10
	return ((*line - '0') == (sum%10));
}

More to follow(character limit).

Target.h

/* define and track a target
 */

#ifndef _TARGET_H
#define _TARGET_H

#include <WiFiClient.h>

#include "Circum.h"
#include "Sensor.h"
#include "Gimbal.h"
#include "Webpage.h"

#include "AutoSatTracker-ESP.h"
#include "P13.h"

class Target {

    private:

	// target
	float az, el;		// from TLE or op if overridden
	float range, rate;
	Satellite *sat;
	Sun *sun;

	// rise set transit state
	DateTime rise_time;
	DateTime set_time;
	DateTime trans_time;
	float rise_az, set_az;
	float trans_az, trans_el;
	bool set_ok, rise_ok, trans_ok;
        bool ever_up;

	// current TLE lines
	char TLE_L0[30];	// name is arbitrarily truncated to this length
	char TLE_L1[70];	// 69 + '\0'
	char TLE_L2[70];	// 69 + '\0'

	// flags
	bool tle_ok;		// whether TLE and myobj are valid
	bool tracking;		// whether currently tracking
	bool overridden;	// whether target az or el has been overridden

	// skypath for displaying graph of a pass on an all-sky map
	enum {MAXSKYPATH = 20};
	struct {
	    float az, el;
	} skypath[MAXSKYPATH];
	uint8_t nskypath;

	// handy
	void displayAsWarning (WiFiClient client, bool mark);

    public:

  bool track_status;
  String satname;
	Target();
	void track();
	bool tleValidChecksum (const char *line);
	void setTrackingState (bool on);
        void sendNewValues (WiFiClient client);
        bool overrideValue (char *name, char *value);
	void setTLE (char *l1, char *l2, char *l3);
	void updateTopo(void);
	void findNextPass(void);
	void computeSkyPath(void);

};

extern Target *target;

#endif // _TARGET_H

More to follow(character limit).

Webpage.cpp

/* this class handles the main web page and all interactions
 *
 * N.B. do not edit the html, edit ast.html then use preppage.pl. See README.
 */

#include <ctype.h>

#include "Webpage.h"
extern String satname;

/* constructor
 */
Webpage::Webpage()
{
	// ask user how to connect to wifi if we can not attach
	while (!connectWiFi())
	    askWiFi();

	// create server
	resetWatchdog();
	Serial.println ("Creating ethernet server");
	httpServer = new WiFiServer(80);				// http
	httpServer->begin();
	Serial.println (WiFi.localIP());

	// init user message mechanism
	user_message_F = F("Hello+");					// page welcome message
	memset (user_message_s, 0, sizeof(user_message_s));

	// init TLE storage and state
	memset (&tlef, 0, sizeof(tlef));
	tlef.running = false;
}

/* try to connect to wifi using creds we have in EEPROM
 * return whether it connected ok
 */
bool Webpage::connectWiFi()
{
	// start over
	// WiFi.disconnect(true);
	// WiFi.softAPdisconnect(true);
	delay(400);

	// configure
	WiFi.mode(WIFI_STA);
	WiFi.begin (nv->ssid, nv->pw);
	WiFi.config (nv->IP, nv->GW, nv->NM);

	// wait for connect
	uint32_t t0 = millis();
	uint32_t timeout = 15000;					// timeout, millis()
	while (WiFi.status() != WL_CONNECTED) {
	    resetWatchdog();
	    if (millis() - t0 > timeout) {
		Serial.println (F("connect failed, starting as AP"));
		return (false);
	    }
	    delay(100);
	}

	// ok
	return (true);
}

/* remove non-alphanumeric chars and convert to upper case IN PLACE
 */
void Webpage::scrub (char *s)
{
	char *scrub_s;
	for (scrub_s = s; *s != '\0'; s++)
	    if (isalnum(*s))
		*scrub_s++ = toupper(*s);
	*scrub_s = '\0';
}

/* call this occasionally to check for Ethernet activity
 */
void Webpage::checkEthernet()
{
	resetWatchdog();

	// do more of remote fetch if active
	resumeTLEFetch();

	// now check our page
	WiFiClient client = httpServer->available();
	if (!client)
	    return;

	// Serial.println ("client connected");
	uint32_t to = millis();		// init timeout
	char firstline[128];		// first line
	unsigned fll = 0;		// firstline length
	bool eoh = false;		// set when see end of header
	bool fldone = false;		// set when finished collecting first line
	char c, prevc = 0;		// new and previous character read from client

	// read header, collecting first line and discarding rest until find blank line
	while (!eoh && (c = readNextClientChar (client, &to))) {
	    if (c == '\n') {
		if (!fldone) {
		    firstline[fll] = '\0';
		    fldone = true;
		}
		if (prevc == '\n')
		    eoh = true;
	    } else if (!fldone && fll < sizeof(firstline)-1) {
		firstline[fll++] = c;
	    }
	    prevc = c;
	}
	if (c == 0) {
	    // Serial.println ("closing client");
	    client.stop();
	    return;
	}

	// client socket is now at first character after blank line

	// replace trailing ?time cache-buster with blank
	char *q = strrchr (firstline, '?');
	if (q)
	    *q = ' ';

	// what we do next depends on first line
	resetWatchdog();
	// Serial.println (firstline);
	if (strstr (firstline, "GET / ")) {
	    sendMainPage (client);
	} else if (strstr (firstline, "GET /getvalues.txt ")) {
	    sendNewValues (client);
	} else if (strstr (firstline, "POST / ")) {
	    overrideValue (client);
	    sendEmptyResponse (client);
	} else if (strstr (firstline, "POST /reboot ")) {
	    sendEmptyResponse (client);
	    reboot();
	} else if (strstr (firstline, "POST /start ")) {
	    target->setTrackingState(true);
	    sendEmptyResponse (client);
	} else if (strstr (firstline, "POST /stop ")) {
	    target->setTrackingState(false);
	    sendEmptyResponse (client);
	} else {
	    send404Page (client);
	}

	// finished
	// Serial.println ("closing client");
	client.stop();
}

/* given "sat,URL" search the given URL for the given satellite TLE.
 * N.B. in order for our web page to continue to function, this method is just the first step, other
 *   steps are done incrementally by resumeTLEFetch().
 */
void Webpage::startTLEFetch (char *query_text)
{
	// split query at , to get sat name and URL
	char *sat = query_text;
	char *url = strchr (query_text, ',');
	if (!url) {
	    setUserMessage (F("Invalid querySite string: "), query_text, '!');
	    return;
	}
	*url++ = '\0';		// overwrite , with EOS for sat then move to start of url

	// remove leading protocol, if any
	if (strncmp (url, "http://", 7) == 0)
	    url += 7;

	// file name
	char *path = strchr (url, '/');
	if (!path) {
	    setUserMessage (F("Invalid querySite URL: "), url, '!');
	    return;
	}
	*path++ = '\0';		// overwrite / with EOS for server then move to start of path

	// connect
	tlef.remote = new WiFiClient();
	if (!tlef.remote->connect (url, 80)) {
	    setUserMessage (F("Failed to connect to "), url, '!');
	    delete tlef.remote;
	    return;
	}

	// send query to retrieve the file containing TLEs
	// Serial.print(sat); Serial.print(F("@")); Serial.println (url);
	tlef.remote->print (F("GET /"));
	tlef.remote->print (path);
	tlef.remote->print (F(" HTTP/1.0\r\n"));
	tlef.remote->print (F("Content-Type: text/plain \r\n"));
	tlef.remote->print (F("\r\n"));

	// set up so we can resume the search later....
	scrub (sat);
	strncpy (tlef.sat, sat, sizeof(tlef.sat)-1);
	tlef.lineno = 1;
	tlef.running = true;
}

/* called to resume fetching a remote web page, started by startTLEFetch().
 * we are called periodically regardless, do nothing if no fetch is in progress.
 * we know to run based on whether tlef.remote is connected.
 */
void Webpage::resumeTLEFetch ()
{
	// skip if nothing in progress
	if (!tlef.running)
	    return;

	// init
	const uint32_t tout = millis() + 10000;		// timeout, ms
	uint8_t nfound = 0;				// n good lines found so far
	char *bp = tlef.buf;				// next buf position to use
	tlef.l0 = NULL;					// flag for sendNewValues();

	// read another line, if find sat read two more and finish up
	while (tlef.remote->connected() && nfound < 3 && millis() < tout) {
	    if (tlef.remote->available()) {
		char c = tlef.remote->read();
		if (c == '\r')
		    continue;
		if (c == '\n') {
		    // show some progress
		    char lnbuf[10];
		    setUserMessage (F("Reading line "), itoa(tlef.lineno++, lnbuf, 10), '+');

		    *bp++ = '\0';
		    switch (nfound) {
		    case 0:
			char sl0[50];			// copy enough that surely contains sat
			strncpy (sl0, tlef.buf, sizeof(sl0)-1);
			sl0[sizeof(sl0)-1] = '\0';	// insure EOS
			scrub (sl0);			// scrub the copy so l0 remains complete
			if (strstr (sl0, tlef.sat)) {	// look for scrubbed sat in scrubbed l0
			    // found sat, prepare to collect TLE line 1 in l1
			    nfound++;			// found name
			    tlef.l0 = tlef.buf;		// l0 begins at buf
			    tlef.l1 = bp;		// l1 begins at next buf position
			} else
			    return;			// try next line on next call
			break;
		    case 1:
			if (target->tleValidChecksum(tlef.l1)) {
			    // found TLE line 1, prep for line 2
			    nfound++;			// found l1
			    tlef.l2 = bp;		// l2 begins at next buf position
			} else {
			    nfound = 0;			// no good afterall
			    tlef.l0 = NULL;		// reset flag for sendNewValues()
			}
			break;
		    case 2:
			if (target->tleValidChecksum(tlef.l2)) {
			    // found last line
			    nfound++;			// found l2
			} else {
			    nfound = 0;			// no good afterall
			    tlef.l0 = NULL;		// reset flag for sendNewValues()
			}
			break;
		    default:
			// can't happen ;-)
			break;
		    }
		} else if (bp - tlef.buf < (int)(sizeof(tlef.buf)-1))
		    *bp++ = c;				// add to buf iif room, including EOS
	    } else {
		// static long n;
		// Serial.println (n++);
	    }
	}

	// get here if remote disconnected, found sat or timed out
	if (!tlef.remote->connected())
	    setUserMessage (F("TLE not found!"));
	else if (nfound == 3) 
	    setUserMessage (F("Found TLE: "), tlef.l0, '+');
	else
	    setUserMessage (F("Remote site timed out!"));

	// finished regardless
	tlef.remote->stop();
	delete tlef.remote;
	tlef.running = false;
}

/* record a brief F() message to inform the user, it will be sent on the next sendNewValues() sweep
 */
void Webpage::setUserMessage (const __FlashStringHelper *ifsh)
{
	user_message_F = ifsh;
	user_message_s[0] = '\0';
}

/* record a brief message to inform the user, it will be sent on the next sendNewValues() sweep.
 * the message consists of an F() string, then a stack string, then a trailing character, typically
 *  '!' to indicate an alarm, '+' to indicate good progress, or '\0' for no effect.
 */
void Webpage::setUserMessage (const __FlashStringHelper *ifsh, const char *msg, char state)
{
	user_message_F = ifsh;
	strncpy (user_message_s, msg, sizeof(user_message_s)-2);	// room for state and EOS
	user_message_s[strlen(user_message_s)] = state;
}

/* read next character, return 0 if it disconnects or times out.
 * '\r' is discarded completely.
 */
char Webpage::readNextClientChar (WiFiClient client, uint32_t *to)
{
	static const int timeout = 1000;		// client socket timeout, ms
	resetWatchdog();
	while (client.connected()) {
	    if (millis() > *to + timeout) {
		Serial.println ("client timed out");
		return (0);
	    }
	    if (!client.available())
		continue;
	    char c = client.read();
	    *to = millis();
	    if (c == '\r')
		continue;
	    // Serial.write(c);
	    return (c);
	}
	// Serial.println ("client disconnected");
	return (0);
}

/* op has entered manually a value to be overridden.
 * client is at beginning of NAME=VALUE line, parse and send to each subsystem
 * N.B. a few are treated specially.
 */
void Webpage::overrideValue (WiFiClient client)
{
	char c, buf[200];			// must be at least enough for a known-valid TLE
	uint8_t nbuf = 0;			// type must be large enough to count to sizeof(buf)

	// read next line into buf
	uint32_t to = millis();		// init timeout
	while ((c = readNextClientChar (client, &to)) != 0) {
	    if (c == '\n') {
		buf[nbuf++] = '\0';
		break;
	    } else if (nbuf < sizeof(buf)-1)
		buf[nbuf++] = c;
	}
	if (c == 0)
	    return;		// bogus; let caller close

	// break at = into name, value
	char *valu = strchr (buf, '=');
	if (!valu)
	    return;		// bogus; let caller close
	*valu++ = '\0';	// replace = with 0 then valu starts at next char
	// now buf is NAME and valu is VALUE

	Serial.print (F("Override: ")); Serial.print (buf); Serial.print("="); Serial.println (valu);

	if (strcmp (buf, "T_TLE") == 0) {

	    // T_TLE needs two more lines

	    char *l1 = valu;		// TLE target name is valu
	    char *l2 = &buf[nbuf];	// line 2 begins after valu
	    char *l3 = NULL;		// set when find end of line 2

	    // scan for two more lines
	    uint8_t nlines = 1;
	    while (nlines < 3 && (c = readNextClientChar (client, &to)) != 0) {
		if (c == '\n') {
		    buf[nbuf++] = '\0';
		    if (++nlines == 2)
			l3 = &buf[nbuf];	// line 3 starts next
		} else if (nbuf < sizeof(buf)-1)
		    buf[nbuf++] = c;
	    }
	    if (nlines < 3)
		return;	// premature end, let caller close

	    // new target!
	    target->setTLE (l1, l2, l3);

	} else if (strcmp (buf, "IP") == 0) {

	    // op is setting a new IP, save in EEPROM for use on next reboot
	    char *octet = valu;
	    for (uint8_t i = 0; i < 4; i++) {
		int o = atoi(octet);
		if (o < 0 || o > 255)
		    return;				// bogus IP
		nv->IP[i] = o;
		if (i == 3)
		    break;
		octet = strchr (octet, '.');		// find next .
		if (!octet)
		    return;				// bogus format
		octet++;				// point to first char after .
	    }
	    nv->put();
	    setUserMessage (F("Successfully stored new IP address in EEPROM -- reboot to engage+"));

	} else if (strcmp (buf, "querySite") == 0) {

	    // op wants to look up a target at a web site, valu is target,url
	    startTLEFetch (valu);

	} else {

	    // not ours, give to each other subsystem in turn until one accepts
	    if (!circum->overrideValue (buf, valu)
			&& !gimbal->overrideValue (buf, valu)
			&& !target->overrideValue (buf, valu)
			&& !sensor->overrideValue (buf, valu))
		setUserMessage (F("Bug: unknown override -- see Serial Monitor!"));

	}
}

/* inform each subsystem to send its latest values, including ours
 */
void Webpage::sendNewValues (WiFiClient client)
{
	// send plain text header for NAME=VALUE pairs
	sendPlainHeader(client);

	// send user message
	client.print ("op_message=");
	if (user_message_F != NULL)
	    client.print (user_message_F);
	if (user_message_s[0])
	    client.print (user_message_s);
	client.println();

	// send our values
	client.print ("IP=");
	for (uint8_t i = 0; i < 4; i++) {
	    client.print (nv->IP[i]);
	    if (i < 3)
		client.print (F("."));
	}
	client.println (F(""));

	if (tlef.l0) {
	    // set newly fetched name on web page
	    client.print (F("new_TLE="));
	    client.println (tlef.l0);
	    client.println (tlef.l1);
	    client.println (tlef.l2);
	    tlef.l0 = NULL;			// just send once
	}

	client.print (F("uptime="));
	circum->printSexa (client, millis()/1000.0/3600.0);
	circum->printPL (client, Circum::NORMAL);

	// send whatever the other modules want to
	circum->sendNewValues (client);
	gimbal->sendNewValues (client);
	sensor->sendNewValues (client);
	target->sendNewValues (client);

}

/* send the main page, in turn it will send us commands using XMLHttpRequest
 */
void Webpage::sendMainPage (WiFiClient client)
{
	sendHTMLHeader (client);

	// DO NOT HAND EDIT THE FOLLOWING HTML .. use "preppage.pl"
	// DO NOT REMOVE THIS LINE 111111111111111111111111111111
        client.print (F(
            "<!DOCTYPE html> \r\n"
            "<html> \r\n"
            "<head> \r\n"
            "    <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> \r\n"
            "    <title>Sat Tracker</title> \r\n"
            " \r\n"
            "    <style> \r\n"
            " \r\n"
            "        body { \r\n"
            "            background-color:#888; \r\n"
            "            font-family:sans-serif; \r\n"
            "            font-size:13px; \r\n"
            "        } \r\n"
            " \r\n"
            "        table { \r\n"
            "            border-collapse: collapse; \r\n"
            "            border: 3px solid brown; \r\n"
            "            background-color:#F8F8F8; \r\n"
            "            float:left; \r\n"
            "        } \r\n"
            " \r\n"
            "        th { \r\n"
            "            padding: 6px; \r\n"
            "            border: 1px solid brown; \r\n"
            "        } \r\n"
            " \r\n"
            "        .even-row { \r\n"
            "            background-color:#F8F8F8; \r\n"
            "        } \r\n"
            " \r\n"
            "        .odd-row { \r\n"
            "            background-color:#D8D8D8; \r\n"
            "        } \r\n"
            " \r\n"
            "        #title-row { \r\n"
            "            text-align: center; \r\n"
            "            padding: 2px; \r\n"
            "            border-bottom: 6px double brown; \r\n"
            "        } \r\n"
            " \r\n"
            "        #title-label { \r\n"
            "            font-size: 18px; \r\n"
            "            font-weight: bold; \r\n"
            "            color: #0066CC; \r\n"
            "        } \r\n"
            " \r\n"
            "        #title-attrib { \r\n"
            "            font-size: 8px; \r\n"
            "            font-weight: bold; \r\n"
            "            color: #0066CC; \r\n"
            "        } \r\n"
            " \r\n"
            "        a { \r\n"
            "            color: #0066CC; \r\n"
            "        } \r\n"
            " \r\n"
            "        #op_message { \r\n"
            "            font-size:16px; \r\n"
            "            display: block; \r\n"
            "            padding: 10px; \r\n"
            "        } \r\n"
            " \r\n"
            "        td { \r\n"
            "            padding: 6px; \r\n"
            "            border: 1px solid #0066CC; \r\n"
            "        } \r\n"
            " \r\n"
            "        .TLE-display { \r\n"
            "            background-color:#D8D8D8; \r\n"
            "            font-family:monospace; \r\n"
            "            resize:none; \r\n"
            "            font-size:inherit; \r\n"
            "            overflow:hidden; \r\n"
            "            border: 1px solid brown; \r\n"
            "        } \r\n"
            " \r\n"
            "        .TLE-entry { \r\n"
            "            background-color:#FFF; \r\n"
            "            font-family:monospace; \r\n"
            "            resize:none; \r\n"
            "            font-size:inherit; \r\n"
            "            overflow:hidden; \r\n"
            "            border: 1px solid brown; \r\n"
            "        } \r\n"
            " \r\n"
            "        .major-section { \r\n"
            "            border-top: 6px double brown; \r\n"
            "        } \r\n"
            " \r\n"
            "        .minor-section { \r\n"
            "            border-top: 4px double brown; \r\n"
            "        } \r\n"
            " \r\n"
            "        .override { \r\n"
            "            background-color:#FFF; \r\n"
            "            padding: 0px; \r\n"
            "            font-family:monospace; \r\n"
            "            resize:none; \r\n"
            "            font-size:inherit; \r\n"
            "            width:7em; \r\n"
        ));
        client.print (F(
            "        } \r\n"
            " \r\n"
            "        .group-head { \r\n"
            "            text-align:center; \r\n"
            "            vertical-align:top; \r\n"
            "            border-right: 4px double brown; \r\n"
            "        } \r\n"
            " \r\n"
            "        .datum-label { \r\n"
            "            text-align:left; \r\n"
            "            vertical-align:top; \r\n"
            "            color:black; \r\n"
            "        } \r\n"
            " \r\n"
            "        .datum { \r\n"
            "            font-family:monospace; \r\n"
            "            text-align:right; \r\n"
            "            color:black \r\n"
            "        } \r\n"
            " \r\n"
            "        #tracking { \r\n"
            "            font-size: 14px; \r\n"
            "            font-weight: bold; \r\n"
            "        } \r\n"
            " \r\n"
            " \r\n"
            "    </style> \r\n"
            " \r\n"
            "    <script> \r\n"
            " \r\n"
            "        // labels on track button determine state \r\n"
            "        var tracking_on_label = 'Stop Tracking'; \r\n"
            "        var tracking_off_label = 'Start Tracking'; \r\n"
            " \r\n"
            "        // sky path border \r\n"
            "        var sky_border = 25; \r\n"
            " \r\n"
            "        // handy shortcut \r\n"
            "        function byId (id) { \r\n"
            "            return document.getElementById(id); \r\n"
            "        } \r\n"
            " \r\n"
            "        // separate window for plotting skypath \r\n"
            "        var skypathwin = undefined; \r\n"
            " \r\n"
            "        // called once after DOM is loaded \r\n"
            "        window.onload = function() { \r\n"
            "            createSkyPathWin(); \r\n"
            "            setTimeout (queryNewValues, 1000); \r\n"
            "        } \r\n"
            " \r\n"
            "        // close skyplotwin when main page is closed \r\n"
            "        window.onunload = function() { \r\n"
            "            if (skypathwin) \r\n"
            "                skypathwin.close(); \r\n"
            "        } \r\n"
            " \r\n"
            "        // create separate skypathwin filled with a canvas \r\n"
            "        function createSkyPathWin() { \r\n"
            " \r\n"
            "            // create a new HTML window \r\n"
            "            skypathwin = window.open ('', '_blank', 'width=350,height=350,scrollbars=no'); \r\n"
            "            if (!skypathwin) { \r\n"
            "                alert (\"Please turn off Popup blocker if you want to see the Sky Path plot\"); \r\n"
            "                return; \r\n"
            "            } \r\n"
            "            skypathwin.document.write ('<!DOCTYPE html><html></html>'); \r\n"
            " \r\n"
            "            // fill with a canvas \r\n"
            "            var controls = '<head><title> Sky Path </title></head>'; \r\n"
            "            controls += '<body>'; \r\n"
            "            controls += '  <canvas id=\"skypath\" > </canvas>'; \r\n"
            "            controls += '</body>'; \r\n"
            "            skypathwin.document.documentElement.innerHTML = controls; \r\n"
            " \r\n"
            "            // connect click handler \r\n"
            "            var cvs = skypathwin.document.getElementById ('skypath'); \r\n"
        ));
        client.print (F(
            "            cvs.addEventListener (\"click\", onSkyPathClick); \r\n"
            " \r\n"
            "        } \r\n"
            " \r\n"
            "        // called when user clicks on the sky path, send Az/El as if override \r\n"
            "        function onSkyPathClick(event) { \r\n"
            "            var cvs = skypathwin.document.getElementById ('skypath'); \r\n"
            "            var rect = cvs.getBoundingClientRect(); \r\n"
            "            var cvsw = rect.right - rect.left; \r\n"
            "            var cvsh = rect.bottom - rect.top; \r\n"
            "            var hznr = Math.min(cvsh,cvsw)/2 - sky_border; \r\n"
            "            var skye = event.clientX-rect.left-cvsw/2;                        // right from center \r\n"
            "            var skyn = cvsh/2-(event.clientY-rect.top);                        // up from center \r\n"
            "            var az = (180.0/Math.PI*Math.atan2(skye, skyn)+360) % 360; \r\n"
            "            var el = 90*(1-Math.hypot(skye,skyn)/hznr); \r\n"
            " \r\n"
            "            POSTNV ('T_Az', az); \r\n"
            "            POSTNV ('T_El', el); \r\n"
            "        } \r\n"
            "         \r\n"
            "        // query for new values forever \r\n"
            "        function queryNewValues() { \r\n"
            "            var xhr = new XMLHttpRequest(); \r\n"
            "            xhr.onreadystatechange = function() { \r\n"
            "                if (xhr.readyState==4 && xhr.status==200) { \r\n"
            "                    // response is id=value pairs, one per line, end ! warning + good \r\n"
            "                    // id is in DOM but some require special treatment. \r\n"
            "                    var lines = xhr.responseText.replace(/\\r/g,'').split('\\n'); \r\n"
            "                    for (var i = 0; i < lines.length; i++) { \r\n"
            "                        console.log('getvalues line ' + i + ': ' + lines[i]); \r\n"
            "                        var nv = lines[i].trim().split('='); \r\n"
            "                        if (nv.length != 2) \r\n"
            "                            continue; \r\n"
            "                        var id = byId (nv[0]); \r\n"
            "                        if (nv[0] == 'T_TLE' || nv[0] == 'new_TLE') { \r\n"
            "                            console.log('getvalues line ' + (i+1) + ': ' + lines[i+1]); \r\n"
            "                            console.log('getvalues line ' + (i+2) + ': ' + lines[i+2]); \r\n"
            "                            id.value = nv[1] + '\\n' + lines[i+1] + '\\n' + lines[i+2]; \r\n"
            "                            i += 2; \r\n"
        ));
        client.print (F(
            "                        } else if (nv[0] == 'skypath') { \r\n"
            "                            plotSkyPath (nv[1]); \r\n"
            "                        } else if (nv[0] == 'tracking') { \r\n"
            "                            setTrackingButton (nv[1] == 'On' ? tracking_on_label : tracking_off_label); \r\n"
            "                        } else if (nv[0] == 'IP') { \r\n"
            "                            setNewIP (nv[1]); \r\n"
            "                        } else if (nv[0] == 'GPS_Enable') { \r\n"
            "                            setGPSEnable(nv[1]); \r\n"
            "                        } else if (nv[0] == 'SS_Save') { \r\n"
            "                            setSSSave(nv[1]); \r\n"
            "                        } else { \r\n"
            "                            var l = nv[1].length; \r\n"
            "                            if (nv[1].substr(l-1) == '!') { \r\n"
            "                                // warning \r\n"
            "                                id.innerHTML = nv[1].substr(0,l-1); \r\n"
            "                                id.style.color = 'red'; \r\n"
            "                            } else if (nv[1].substr(l-1) == '+') { \r\n"
            "                                // good news \r\n"
            "                                id.innerHTML = nv[1].substr(0,l-1); \r\n"
            "                                id.style.color = '#297'; \r\n"
            "                            } else { \r\n"
            "                                // normal \r\n"
            "                                id.innerHTML = nv[1]; \r\n"
            "                                id.style.color = 'black'; \r\n"
            "                            } \r\n"
            "                        } \r\n"
            "                    } \r\n"
            " \r\n"
            "                    // repeat after a short breather \r\n"
            "                    setTimeout (queryNewValues, 1000); \r\n"
            "                } \r\n"
            "            } \r\n"
            "            xhr.open('GET', UniqURL('/getvalues.txt'), true); \r\n"
            "            xhr.send(); \r\n"
            "        } \r\n"
            " \r\n"
            "        // handy function to POST a name=value pair \r\n"
            "        function POSTNV (name, value) { \r\n"
            "            var xhr = new XMLHttpRequest(); \r\n"
            "            xhr.open('POST', UniqURL('/'), true); \r\n"
            "            xhr.send(name + '=' + String(value) + '\\r\\n'); \r\n"
            "        } \r\n"
            " \r\n"
            "        // handy function that modifies a URL to be unique so it voids the cache \r\n"
            "        function UniqURL (url) { \r\n"
            "            return (url + '?' + (new Date()).getTime()); \r\n"
        ));
        client.print (F(
            "        } \r\n"
            " \r\n"
            "        // plot a skypath, points are az,el;... \r\n"
            "        function plotSkyPath (points) { \r\n"
            "            // ignore if not built yet \r\n"
            "            if (!skypathwin) \r\n"
            "                return; \r\n"
            " \r\n"
            "            // render to off-screen canvas then blit to void flashing \r\n"
            "            var cvs = skypathwin.document.createElement ('canvas'); \r\n"
            " \r\n"
            "            // track current window size \r\n"
            "            var cvsw = skypathwin.innerWidth - 20;                // ~ 20 to eliminate scroll bars \r\n"
            "            var cvsh = skypathwin.innerHeight - 20; \r\n"
            "            cvs.width = cvsw; \r\n"
            "            cvs.height = cvsh; \r\n"
            "            var ctx = cvs.getContext ('2d'); \r\n"
            " \r\n"
            "            var hznr = Math.min(cvsw,cvsh)/2 - sky_border;        // horizon radius \r\n"
            " \r\n"
            "            // local function to convert az el in degrees to skypath canvas x y \r\n"
            "            function azel2xy (az, el) { \r\n"
            "                var az = Math.PI*az/180;                        // cw from up, rads \r\n"
            "                var zr = hznr*(90-el)/90;                        // radius in pixels \r\n"
            "                return { \r\n"
            "                    x: cvsw/2 + zr*Math.sin(az),                // right \r\n"
            "                    y: cvsh/2 - zr*Math.cos(az),                // up is -  \r\n"
            "                }; \r\n"
            "            } \r\n"
            " \r\n"
            "            // cleaner looking lines if center on pixels \r\n"
            "            ctx.setTransform (1, 0, 0, 1, 0, 0); \r\n"
            "            ctx.translate (0.5, 0.5); \r\n"
            " \r\n"
            "            // reset background \r\n"
            "            ctx.strokeStyle = 'black' \r\n"
            "            ctx.fillStyle = '#EEE' \r\n"
            "            ctx.beginPath(); \r\n"
            "                ctx.rect (0, 0, cvsw-1, cvsh-1); \r\n"
            "            ctx.fill(); \r\n"
            "            ctx.stroke(); \r\n"
            " \r\n"
            "            // draw az and el lines \r\n"
            "            ctx.strokeStyle = '#777' \r\n"
            "            ctx.beginPath(); \r\n"
            "                for (var i = 1; i <= 3; i++) { \r\n"
            "                    ctx.moveTo (cvsw/2+i*hznr/3, cvsh/2); \r\n"
            "                    ctx.arc (cvsw/2, cvsh/2, i*hznr/3, 0, 2*Math.PI); \r\n"
            "                } \r\n"
            "                for (var i = 0; i < 12; i++) { \r\n"
            "                    ctx.moveTo (cvsw/2, cvsh/2); \r\n"
            "                    var xy = azel2xy (i*360/12, 0); \r\n"
            "                    ctx.lineTo (xy.x, xy.y); \r\n"
        ));
        client.print (F(
            "                } \r\n"
            "            ctx.stroke(); \r\n"
            " \r\n"
            "            // label cardinal directions \r\n"
            "            ctx.fillStyle = '#297' \r\n"
            "            ctx.font = '18px Arial'; \r\n"
            "            ctx.fillText ('N', cvsw/2-5, cvsh/2-hznr-4); \r\n"
            "            ctx.fillText ('E', cvsw/2+hznr+4, cvsh/2+5); \r\n"
            "            ctx.fillText ('S', cvsw/2-5, cvsh/2+hznr+20); \r\n"
            "            ctx.fillText ('W', cvsw/2-hznr-sky_border+5, cvsh/2+5); \r\n"
            " \r\n"
            "            // split path into individual points, we always get one even if points is empty \r\n"
            "            var pts = points.replace(/;$/,'').split(/;/); \r\n"
            "            if (pts.length > 1) { \r\n"
            "                // path, plotted N up E right \r\n"
            "                ctx.strokeStyle = '#22A' \r\n"
            "                ctx.lineWidth = 2; \r\n"
            "                ctx.beginPath(); \r\n"
            "                    for (var i = 0; i < pts.length; i++) { \r\n"
            "                        var azel = pts[i].split(/,/); \r\n"
            "                        var xy = azel2xy (azel[0], azel[1]); \r\n"
            "                        if (i == 0) \r\n"
            "                            ctx.moveTo (xy.x, xy.y); \r\n"
            "                        else \r\n"
            "                            ctx.lineTo (xy.x, xy.y); \r\n"
            "                    } \r\n"
            "                ctx.stroke(); \r\n"
            " \r\n"
            "                // label set location \r\n"
            "                // N.B. first location will not be rise if path computed while up \r\n"
            "                ctx.font = '14px Arial'; \r\n"
            "                ctx.fillStyle = '#22A'; \r\n"
            "                var az = pts[pts.length-1].split(/,/)[0]; \r\n"
            "                var el = (az < 90 || az > 270) ? -5 : -12; \r\n"
            "                var xy = azel2xy (az, el); \r\n"
            "                ctx.fillText ('S', xy.x-5, xy.y); \r\n"
            "            } \r\n"
            " \r\n"
            "            // plot target, get loc from text fields \r\n"
            "            var taz = parseFloat(byId('T_Az').innerHTML); \r\n"
            "            var tel = parseFloat(byId('T_El').innerHTML); \r\n"
            "            if (tel >= 0) { \r\n"
            "                var xy = azel2xy (taz, tel); \r\n"
            "                ctx.fillStyle = '#FD0000'; \r\n"
            "                var r = 5; \r\n"
            "                var px = cvsw/2-hznr-sky_border+r+5, py = cvsh/2-hznr-8-r; \r\n"
            "                ctx.beginPath(); \r\n"
            "                    ctx.moveTo (xy.x + r, xy.y); \r\n"
            "                    ctx.arc (xy.x, xy.y, r, 0, 2*Math.PI); \r\n"
        ));
        client.print (F(
            "                    ctx.moveTo (px + r, py); \r\n"
            "                    ctx.arc (px, py, r, 0, 2*Math.PI); \r\n"
            "                ctx.fill(); \r\n"
            "                ctx.fillStyle = 'black' \r\n"
            "                ctx.font = '14px Arial'; \r\n"
            "                ctx.fillText ('Target', px+2*r, py+r); \r\n"
            "            } \r\n"
            " \r\n"
            "            // plot sensor position, get loc from text fields \r\n"
            "            var saz = parseFloat(byId('SS_Az').innerHTML); \r\n"
            "            var sel = parseFloat(byId('SS_El').innerHTML); \r\n"
            "            if (sel >= -10) {        // allow for symbol size \r\n"
            "                var xy = azel2xy (saz, sel); \r\n"
            "                ctx.strokeStyle = '#297' \r\n"
            "                var r = 8; \r\n"
            "                var px = cvsw/2-hznr-sky_border+r+5, py = cvsh/2+hznr+(20-r); \r\n"
            "                ctx.beginPath(); \r\n"
            "                    ctx.moveTo (xy.x + r, xy.y); \r\n"
            "                    ctx.arc (xy.x, xy.y, r, 0, 2*Math.PI); \r\n"
            "                    ctx.moveTo (px + r, py); \r\n"
            "                    ctx.arc (px, py, r, 0, 2*Math.PI); \r\n"
            "                ctx.stroke(); \r\n"
            "                ctx.fillStyle = 'black' \r\n"
            "                ctx.font = '14px Arial'; \r\n"
            "                ctx.fillText ('Sensor', px+2*r, py+r); \r\n"
            "            } \r\n"
            " \r\n"
            "            // display pointing error from text fields \r\n"
            "            // haversine form is better than law of cosines for small separations \r\n"
            "            var tazr = taz*Math.PI/180; \r\n"
            "            var telr = tel*Math.PI/180; \r\n"
            "            var sazr = saz*Math.PI/180; \r\n"
            "            var selr = sel*Math.PI/180; \r\n"
            "            // var sep = 180/Math.PI*acos(sin(telr)*sin(selr) + cos(telr)*cos(selr)*sin(tazr-sazr)); \r\n"
            "            var delel = telr - selr; \r\n"
            "            var delaz = tazr - sazr; \r\n"
            "            var a = Math.sin(delel/2)*Math.sin(delel/2) + \r\n"
            "                            Math.cos(telr) * Math.cos(selr) * Math.sin(delaz/2) * Math.sin(delaz/2); \r\n"
            "            var sep = 2*180/Math.PI*Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); \r\n"
            "            if (!isNaN(sep)) { \r\n"
            "                ctx.fillStyle = 'black' \r\n"
            "                ctx.font = '14px Arial'; \r\n"
            "                ctx.fillText ('Error: ' + sep.toFixed(1) + '\\u00B0', cvsw/2+hznr+sky_border-90, cvsh/2-hznr-8); \r\n"
        ));
        client.print (F(
            "            } \r\n"
            " \r\n"
            "            // blit onto screen \r\n"
            "            var spcvs = skypathwin.document.getElementById ('skypath'); \r\n"
            "            spcvs.width = cvsw; \r\n"
            "            spcvs.height = cvsh; \r\n"
            "            var spctx = spcvs.getContext ('2d'); \r\n"
            "            spctx.drawImage (cvs, 0, 0); \r\n"
            "        } \r\n"
            " \r\n"
            "        // called when op wants to read a TLE from a file \r\n"
            "        function handleFileSelect(file) { \r\n"
            " \r\n"
            "            // get target \r\n"
            "            var target = byId('target_name').value.trim(); \r\n"
            "            if (!target || target.length<1) { \r\n"
            "                alert ('Please enter name of target in file'); \r\n"
            "                return; \r\n"
            "            } \r\n"
            " \r\n"
            "            // use FileReader to read file \r\n"
            "            var reader = new FileReader(); \r\n"
            " \r\n"
            "            // define callback called after reader is triggered \r\n"
            "            reader.onload = function(event) { \r\n"
            "                var fr = event.target;                      // FileReader \r\n"
            "                var text = fr.result;                       // file text as string \r\n"
            " \r\n"
            "                // scan file looking for named target, allowing a very generous match \r\n"
            "                var target_scrubbed = target.replace(/\\W/g,'').toUpperCase(); \r\n"
            "                var lines = text.replace(/\\r/g,'').split(/\\n/); \r\n"
            "                for (i = 0; i < lines.length; i++) { \r\n"
            "                    var line = lines[i].trim(); \r\n"
            "                    var line_scrubbed = line.replace(/\\W/g,'').toUpperCase(); \r\n"
            "                    if (line_scrubbed.indexOf(target_scrubbed) >= 0) { \r\n"
            "                        if (i < lines.length-2) { \r\n"
            "                            var l1 = lines[i+1].trim(); \r\n"
            "                            var l2 = lines[i+2].trim(); \r\n"
            "                            var candidate = line + '\\n' + l1 + '\\n' + l2; \r\n"
            "                            var telok = validateTLE(candidate); \r\n"
            "                            if (telok != null) \r\n"
            "                                alert ('Found \"' + target + '\" in ' + file.name + ' but ' + telok); \r\n"
            "                            else \r\n"
            "                                byId('new_TLE').value = candidate; \r\n"
            "                        } else \r\n"
            "                            alert ('Found \"' + target + '\" in ' + file.name + ' but not followed by a valid TLE'); \r\n"
        ));
        client.print (F(
            "                        return; \r\n"
            "                    } \r\n"
            "                } \r\n"
            "                alert ('Can not find \"' + target + '\" in file ' + file.name); \r\n"
            " \r\n"
            "            }; \r\n"
            " \r\n"
            "            // read file, triggers onload when complete \r\n"
            "            reader.readAsText(file); \r\n"
            "        } \r\n"
            " \r\n"
            " \r\n"
            " \r\n"
            "        // send new value in response to operator typing an override value. \r\n"
            "        function onOvd(event) { \r\n"
            "            if (event.keyCode == 13) { \r\n"
            "                var oid = event.target.id; \r\n"
            "                var nam = oid.replace ('_Ovd', ''); \r\n"
            "                var vid = byId(nam); \r\n"
            "                if (vid) { \r\n"
            "                    var val = event.target.value.trim(); \r\n"
            "                    POSTNV (nam, val); \r\n"
            "                } \r\n"
            "            } \r\n"
            "        } \r\n"
            " \r\n"
            "        // called when op wants to look for a target at a remote web site \r\n"
            "        function querySite(event) { \r\n"
            "            var url = event.target.value; \r\n"
            "            var sat = byId('target_name').value.trim(); \r\n"
            "            console.log(url); \r\n"
            "            POSTNV ('querySite', sat + ',' + url); \r\n"
            "        } \r\n"
            " \r\n"
            "        // called when op wants to upload a new TLE \r\n"
            "        function onUploadTLE() { \r\n"
            "            var tid = byId('new_TLE'); \r\n"
            "            var newtle = tid.value.trim(); \r\n"
            "            var telok = validateTLE(newtle); \r\n"
            "            if (telok != null) \r\n"
            "                alert (telok); \r\n"
            "            else { \r\n"
            "                tid.value = newtle;                // show trimmed version \r\n"
            "                POSTNV ('T_TLE', newtle); \r\n"
            "            } \r\n"
            "        } \r\n"
            " \r\n"
            "        // called to enable GPS \r\n"
            "        function onGPSEnable() { \r\n"
            "            POSTNV ('GPS_Enable', 'true'); \r\n"
            "        } \r\n"
            " \r\n"
            "        // called to save Sensor calibration to EEPROM \r\n"
            "        function onSSSave() { \r\n"
            "            POSTNV ('SS_Save', 'true'); \r\n"
            "        } \r\n"
            " \r\n"
            "        // called to upload a new IP, either with Set (k==0) or by typing Enter (k==1) \r\n"
            "        function onIP (k,event) { \r\n"
            "            if (k && event.keyCode != 13) \r\n"
            "                return;        // wait for Enter \r\n"
            "            var ip = byId ('IP').value.trim(); \r\n"
            "            var octets = ip.split(/\\./); \r\n"
            "            for (var i = 0; i < octets.length; i++) { \r\n"
        ));
        client.print (F(
            "                var o = octets[i]; \r\n"
            "                if (!o.match(/^\\d+$/)) \r\n"
            "                    break; \r\n"
            "                var v = parseInt(o); \r\n"
            "                if (v < 0 || v > 255) \r\n"
            "                    break; \r\n"
            "            } \r\n"
            "            if (octets.length != 4 || i < octets.length) \r\n"
            "                alert (ip + ': not a valid IP address format'); \r\n"
            "            else \r\n"
            "                POSTNV ('IP', ip); \r\n"
            "        } \r\n"
            " \r\n"
            "        // called to display the current IP.  N.B. leave IP text alone if it or Set currently has focus \r\n"
            "        function setNewIP (ip) { \r\n"
            "            var ip_text = byId('IP') \r\n"
            "            var ip_set  = byId('IP-set') \r\n"
            "            var focus = document.activeElement; \r\n"
            "            if (focus != ip_text && focus != ip_set) \r\n"
            "                ip_text.value = ip; \r\n"
            "        } \r\n"
            " \r\n"
            "        // called to set visibility of GPS_Enable \r\n"
            "        function setGPSEnable (whether) { \r\n"
            "            var gid = byId ('GPS_Enable'); \r\n"
            "            gid.style.visibility = (whether == 'true') ? 'visible' : 'hidden'; \r\n"
            "        } \r\n"
            " \r\n"
            "        // called to set visibility of SS_Save \r\n"
            "        function setSSSave (whether) { \r\n"
            "            var sid = byId ('SS_Save'); \r\n"
            "            sid.style.visibility = (whether == 'true') ? 'visible' : 'hidden'; \r\n"
            "        } \r\n"
            " \r\n"
            "        // send command to start tracking \r\n"
            "        function commandStartTracking() { \r\n"
            "            var xhr = new XMLHttpRequest(); \r\n"
            "            xhr.open('POST', UniqURL('/start'), true); \r\n"
            "            xhr.send(); \r\n"
            "        } \r\n"
            " \r\n"
            "        // send command to stop tracking \r\n"
            "        function commandStopTracking() { \r\n"
            "            var xhr = new XMLHttpRequest(); \r\n"
            "            xhr.open('POST', UniqURL('/stop'), true); \r\n"
            "            xhr.send(); \r\n"
            "        } \r\n"
            " \r\n"
            "        // the Run/Stop tracking button was clicked, label determines action \r\n"
            "        function onTracking() { \r\n"
            "            var tb = byId('tracking'); \r\n"
            "            // just issue command, let next getvalues update button appearance \r\n"
            "            if (tb.innerHTML == tracking_off_label) \r\n"
            "                commandStartTracking(); \r\n"
            "            else \r\n"
            "                commandStopTracking(); \r\n"
            "        } \r\n"
            " \r\n"
            "        // given one of tracking_on/off_label, set the tracking button appearance \r\n"
        ));
        client.print (F(
            "        function setTrackingButton (label) { \r\n"
            "            var tb = byId('tracking'); \r\n"
            "            if (label == tracking_off_label) { \r\n"
            "                tb.innerHTML = label; \r\n"
            "                tb.style.color = 'black'; \r\n"
            "            } else if (label == tracking_on_label) { \r\n"
            "                tb.innerHTML = label; \r\n"
            "                tb.style.color = 'red'; \r\n"
            "            } else { \r\n"
            "                tb.innerHTML = '?'; \r\n"
            "                tb.style.color = 'blue'; \r\n"
            "            } \r\n"
            "        } \r\n"
            " \r\n"
            "        // send command to reboot the Ardunio then reload our page after a short while  \r\n"
            "        function onReboot() { \r\n"
            "            if (confirm('Are you sure you want to reboot the Tracker?')) { \r\n"
            " \r\n"
            "                var xhr = new XMLHttpRequest(); \r\n"
            "                xhr.open ('POST', UniqURL('/reboot'), true); \r\n"
            "                xhr.send (); \r\n"
            " \r\n"
            "                byId ('op_message').style.color = 'red'; \r\n"
            " \r\n"
            "                function reloadMessage (n) { \r\n"
            "                    var msg = 'This page will reload in ' + n + ' second' + ((n == 1) ? '' : 's'); \r\n"
            "                    byId ('op_message').innerHTML = msg; \r\n"
            "                    if (n == 0) \r\n"
            "                        location.reload(); \r\n"
            "                    else \r\n"
            "                        setTimeout (function() {reloadMessage(n-1);}, 1000); \r\n"
            "                } \r\n"
            "                reloadMessage(5); \r\n"
            "            } \r\n"
            "        } \r\n"
            " \r\n"
            "        // return why the given text appears not to be a valid TLE, else null \r\n"
            "        function validateTLE (text) { \r\n"
            "            var lines = text.replace(/\\r/g,'').split('\\n'); \r\n"
            "            if (lines.length != 3) \r\n"
            "                return ('TLE must be exactly 3 lines'); \r\n"
            "            var l1 = lines[0].trim(); \r\n"
            "            if (l1.length < 1) \r\n"
            "                return ('Missing name on line 1'); \r\n"
            "            var l2 = lines[1].trim(); \r\n"
            "            if (!TLEChecksum(l2)) \r\n"
            "                return ('Invalid checksum on line 2'); \r\n"
            "            var l3 = lines[2].trim(); \r\n"
            "            if (!TLEChecksum(l3)) \r\n"
            "                return ('Invalid checksum on line 3'); \r\n"
            "            return null;        // ok! \r\n"
            "        } \r\n"
            " \r\n"
            "        // return whether the given line has a valid TLE checksum \r\n"
        ));
        client.print (F(
            "        function TLEChecksum (line) { \r\n"
            "            if (line.length < 69) \r\n"
            "                return false; \r\n"
            "            var scrub = line.replace(/[^\\d-]/g,'').replace(/-/g,'1');        // only digits and - is worth 1 \r\n"
            "            var sl = scrub.length; \r\n"
            "            var sum = 0; \r\n"
            "            for (var i = 0; i < sl-1; i++)                                // last char is checksum itself \r\n"
            "                sum += parseInt(scrub.charAt(i)); \r\n"
            "            return ((sum%10) == parseInt(scrub.charAt(sl-1))); \r\n"
            "        } \r\n"
            " \r\n"
            "        // called when op wants to erase the TLE text entry \r\n"
            "        function onEraseTLE() { \r\n"
            "            byId ('new_TLE').value = ''; \r\n"
            "        } \r\n"
            " \r\n"
            " \r\n"
            "    </script>  \r\n"
            " \r\n"
            "</head> \r\n"
            " \r\n"
            "<body> \r\n"
            " \r\n"
            "    <!-- table floats left, so this actually centers what remains, ie, the skypath canvas --> \r\n"
            "    <center> \r\n"
            " \r\n"
            "    <table> \r\n"
            "        <tr> \r\n"
            "            <td id='title-row' colspan='7' > \r\n"
            "                <table style='border:none;' width='100%'> \r\n"
            "                    <tr> \r\n"
            "                        <td width='25%' style='text-align:left; border:none' > \r\n"
            "                            IP: \r\n"
            "                            <input id='IP' type='text' onkeypress='onIP(1,event)' size='14' > </input> \r\n"
            "                            <button id='IP-set' onclick='onIP(0,event)'>Change</button \r\n"
            "                        </td> \r\n"
            "                        <td width='50%' style='border:none' > \r\n"
            "                            <label id='title-label' title='Version 2020061701' >Autonomous Satellite Tracker</label> \r\n"
            "                            <br> \r\n"
            "                            <label id='title-attrib' > by \r\n"
            "                                <a target='_blank' href='http://www.clearskyinstitute.com/ham'>WB&Oslash;OEW</a> \r\n"
            "                            </label> \r\n"
            "                        </td> \r\n"
            "                        <td width='25%' style='text-align:right; border:none' > \r\n"
            "                            <button id='reboot_b' onclick='onReboot()'> Reboot Tracker </button> \r\n"
            "                            <br> \r\n"
            "                            Up: <label id='uptime' style='padding:10px;'  ></label> \r\n"
            "                        </td> \r\n"
            "                    </tr> \r\n"
        ));
        client.print (F(
            "                    <tr> \r\n"
            "                        <td colspan='3' width='100%' style='text-align:center; border:none'> \r\n"
            "                            <label id='op_message' > Hello </label> \r\n"
            "                        </td> \r\n"
            "                    </tr> \r\n"
            "                </table> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            "        <tr class='major-section' > \r\n"
            "            <td colspan='7' style='text-align:left; border-bottom-style:none; font-weight:bold' > \r\n"
            "                <table width='100%' style='border:none'> \r\n"
            "                    <tr> \r\n"
            "                        <td width='33%' style='text-align:left; border:none; font-weight:bold' > \r\n"
            "                            Loaded TLE: \r\n"
            "                        </td> \r\n"
            "                        <td width='33%' style='text-align:center; border:none' > \r\n"
            "                            <button id='tracking' onclick='onTracking()' > </button> \r\n"
            "                        </td> \r\n"
            "                        <td width='33%' style='border-style:none' > \r\n"
            "                        </td> \r\n"
            "                    </tr> \r\n"
            "                </table> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            "        <tr> \r\n"
            "            <td colspan='7' style='text-align:center; border:none; padding-bottom:10px' > \r\n"
            "                <textarea id='T_TLE' class='TLE-display' rows='3' cols='69' readonly> \r\n"
            "                </textarea> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            "        <tr> \r\n"
            "            <td colspan='7' style='text-align:left; border: none; ' > \r\n"
            "                <table width='100%' style='border:none'> \r\n"
            "                    <tr> \r\n"
            "                        <td style='text-align:left; border:none; font-weight:bold' > \r\n"
            "                            Paste next TLE or find \r\n"
            "                            <input id='target_name' type='text' size='8' > </input> \r\n"
            "                            at \r\n"
            "                            <button onclick='querySite(event)' value='http://amsat.org/amsat/ftp/keps/current/nasa.all'>AMSAT</button> \r\n"
            "                            <button onclick='querySite(event)' value='http://celestrak.com/NORAD/elements/amateur.txt' >Celestrak</button> \r\n"
            "                            or in \r\n"
            "                            <input type='file' id='filesel' onchange='handleFileSelect(this.files[0])' /> \r\n"
        ));
        client.print (F(
            "                            <button onclick='onUploadTLE()'>Upload</button> \r\n"
            "                        </td> \r\n"
            "                        <td style='text-align:right; border:none;' > \r\n"
            "                            <button onclick='onEraseTLE()'>Erase</button> \r\n"
            "                        </td> \r\n"
            "                    </tr> \r\n"
            "                </table> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            "        <tr> \r\n"
            "            <td colspan='7' style='text-align:center; border-top-style:none; border-bottom-style:none; padding-bottom:10px' > \r\n"
            "                <textarea id='new_TLE' class='TLE-entry' rows='3' cols='69' > \r\n"
            "                </textarea> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            "        <tr class='major-section' > \r\n"
            "            <th class='group-head' > Subsystem </th> \r\n"
            "            <th> Parameter </th> \r\n"
            "            <th> Value </th> \r\n"
            "            <th> Override </th> \r\n"
            "            <th> Parameter </th> \r\n"
            "            <th> Value </th> \r\n"
            "            <th> Override </th> \r\n"
            "        </tr> \r\n"
            " \r\n"
            " \r\n"
            " \r\n"
            "        <tr class='minor-section even-row' > \r\n"
            "            <th rowspan='8' class='group-head' > \r\n"
            "                    Target \r\n"
            "                <br> \r\n"
            "                <label id='T_Status'></label> \r\n"
            "            </th> \r\n"
            " \r\n"
            "            <td class='datum-label' > Azimuth, degrees E of N </td> \r\n"
            "            <td id='T_Az' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='T_Az_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Next Rise in H:M:S</td> \r\n"
            "            <td id='T_NextRise' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' > Elevation, degrees Up </td> \r\n"
            "            <td id='T_El' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='T_El_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Next Rise Azimuth</td> \r\n"
            "            <td id='T_RiseAz' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='even-row' > \r\n"
            "            <td class='datum-label' > TLE age, days </td> \r\n"
        ));
        client.print (F(
            "            <td id='T_Age' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td id='T_NextTrans_l' class='datum-label' > Next Transit in </td> \r\n"
            "            <td id='T_NextTrans' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' > Range, km </td> \r\n"
            "            <td id='T_Range' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td id='T_TransAz_l' class='datum-label' > Next Transit Azimuth </td> \r\n"
            "            <td id='T_TransAz' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='even-row' > \r\n"
            "            <td class='datum-label' > Range rate, m/s</td> \r\n"
            "            <td id='T_RangeR' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td id='T_TransEl_l' class='datum-label' > Next Transit Elevation </td> \r\n"
            "            <td id='T_TransEl' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' > Doppler, kHz @ 144 MHz</td> \r\n"
            "            <td id='T_VHFDoppler' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Next Set in </td> \r\n"
            "            <td id='T_NextSet' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='even-row' > \r\n"
            "            <td class='datum-label' > Doppler, kHz @ 440 MHz</td> \r\n"
            "            <td id='T_UHFDoppler' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Next Set Azimuth</td> \r\n"
            "            <td id='T_SetAz' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' > Sunlit</td> \r\n"
            "            <td id='T_Sunlit' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td id='T_Up_l' class='datum-label' > Next pass duration </td> \r\n"
            "            <td id='T_Up' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            " \r\n"
            "        <tr class='minor-section even-row' > \r\n"
            "            <th rowspan='4' class='group-head' > \r\n"
            "                    Spatial sensor \r\n"
            "                <br> \r\n"
            "                <label id='SS_Status'></label> \r\n"
        ));
        client.print (F(
            "                <br> \r\n"
            "                <button id='SS_Save' onclick='onSSSave()' > Save Cal </button> \r\n"
            "            </th> \r\n"
            " \r\n"
            "            <td class='datum-label' > Azimuth, degrees E of N </td> \r\n"
            "            <td id='SS_Az' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td class='datum-label' > System status, 0 .. 3 </td> \r\n"
            "            <td id='SS_SStatus' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' > Elevation, degrees Up </td> \r\n"
            "            <td id='SS_El' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Gyro status </td> \r\n"
            "            <td id='SS_GStatus' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='even-row' > \r\n"
            "            <td class='datum-label' > Temperature, degrees C </td> \r\n"
            "            <td id='SS_Temp' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Magnetometer status </td> \r\n"
            "            <td id='SS_MStatus' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' ></td> \r\n"
            "            <td id='SS_XXX' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Accelerometer status </td> \r\n"
            "            <td id='SS_AStatus' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            " \r\n"
            " \r\n"
            " \r\n"
            "        <tr class='minor-section even-row' > \r\n"
            "            <th rowspan='4' class='group-head' > \r\n"
            "                    GPS \r\n"
            "                <br> \r\n"
            "                <label id='GPS_Status'></label> \r\n"
            "                <br> \r\n"
            "                <button id='GPS_Enable' onclick='onGPSEnable()' > Enable </button> \r\n"
            "            </th> \r\n"
            " \r\n"
            "            <td class='datum-label' > UTC, H:M:S </td> \r\n"
            "            <td id='GPS_UTC' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='GPS_UTC_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Altitude, m </td> \r\n"
            "            <td id='GPS_Alt' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='GPS_Alt_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
        ));
        client.print (F(
            "                </input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' > Date, Y M D </td> \r\n"
            "            <td id='GPS_Date' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='GPS_Date_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Mag decl, true - mag </td> \r\n"
            "            <td id='GPS_MagDecl' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='even-row' > \r\n"
            "            <td class='datum-label' > Latitude, degrees +N </td> \r\n"
            "            <td id='GPS_Lat' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='GPS_Lat_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > HDOP, ~1 .. 20 </td> \r\n"
            "            <td id='GPS_HDOP' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' > Longitude, degrees +E </td> \r\n"
            "            <td id='GPS_Long' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='GPS_Long_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > N Satellites </td> \r\n"
            "            <td id='GPS_NSat' class='datum' > </td> \r\n"
            "            <td></td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            " \r\n"
            " \r\n"
            "        <!-- N.B. beware that some ID's are used in a match in onOvd(event) --> \r\n"
            "        <tr class='minor-section even-row ' > \r\n"
            "            <th rowspan='3' class='group-head' > \r\n"
            "                    Gimbal \r\n"
            "                <br> \r\n"
            "                <label id='G_Status'></label> \r\n"
            "            </th> \r\n"
            " \r\n"
            "            <td class='datum-label' > Servo 1 pulse length, &micro;s </td> \r\n"
            "            <td id='G_Mot1Pos' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='G_Mot1Pos_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Servo 2 pulse length, &micro;s </td> \r\n"
        ));
        client.print (F(
            "            <td id='G_Mot2Pos' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='G_Mot2Pos_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            "        <tr class='odd-row' > \r\n"
            "            <td class='datum-label' > Servo 1 minimum pulse </td> \r\n"
            "            <td id='G_Mot1Min' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='G_Mot1Min_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Servo 2 minimum pulse </td> \r\n"
            "            <td id='G_Mot2Min' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='G_Mot2Min_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            "        <tr class='even-row' > \r\n"
            "            <td class='datum-label' > Servo 1 maximum pulse </td> \r\n"
            "            <td id='G_Mot1Max' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='G_Mot1Max_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            " \r\n"
            "            <td class='datum-label' > Servo 2 maximum pulse </td> \r\n"
            "            <td id='G_Mot2Max' class='datum' > </td> \r\n"
            "            <td> \r\n"
            "                <input id='G_Mot2Max_Ovd' type='text' onkeypress='onOvd(event)' class='override' > \r\n"
            "                </input> \r\n"
            "            </td> \r\n"
            "        </tr> \r\n"
            " \r\n"
            "    </table> \r\n"
            " \r\n"
            "</body> \r\n"
            "</html> \r\n"
        ));
	// DO NOT REMOVE THIS LINE 222222222222222222222222222222
}

/* send HTTP header for plain text content
 */
void Webpage::sendPlainHeader (WiFiClient client)
{
	client.print (F(
	    "HTTP/1.0 200 OK \r\n"
	    "Content-Type: text/plain \r\n"
	    "Connection: close \r\n"
	    "\r\n"
	));
}

/* send HTTP header for html content
 */
void Webpage::sendHTMLHeader (WiFiClient client)
{
	client.print (F(
	    "HTTP/1.0 200 OK \r\n"
	    "Content-Type: text/html \r\n"
	    "Connection: close \r\n"
	    "\r\n"
	));
}

/* send empty response
 */
void Webpage::sendEmptyResponse (WiFiClient client)
{
	client.print (F(
	    "HTTP/1.0 200 OK \r\n"
	    "Content-Type: text/html \r\n"
	    "Connection: close \r\n"
	    "Content-Length: 0 \r\n"
	    "\r\n"
	));
}

/* send back error 404 when requested page not found.
 * N.B. important for chrome otherwise it keeps asking for favicon.ico
 */
void Webpage::send404Page (WiFiClient client)
{
	Serial.println ("Sending 404");
	client.print (F(
	    "HTTP/1.0 404 Not Found \r\n"
	    "Content-Type: text/html \r\n"
	    "Connection: close \r\n"
	    "\r\n"
	    "<html> \r\n"
	    "<body> \r\n"
	    "<h2>404: Not found</h2>\r\n \r\n"
	    "</body> \r\n"
	    "</html> \r\n"
	));
}

/* reboot
 */
void Webpage::reboot()
{
	resetWatchdog();
	Serial.println("rebooting");
	delay(5000);
	ESP.restart();
}

More to follow(character limit).

Webpage.h

/* this class handles the web page and interactions
 */

#ifndef _WEBPAGE_H
#define _WEBPAGE_H

#include <ESP8266WiFi.h>
#include <WiFiServer.h>
#include <WiFiClient.h>

#include "AutoSatTracker-ESP.h"
#include "Sensor.h"
#include "Circum.h"
#include "Gimbal.h"
#include "Target.h"
#include "NV.h"

// persistent state info to fetch a TLE from a remote web site incrementally
typedef struct {
    bool running;			// set while reading a remote file
    char sat[30];			// scrubbed name of satellite we are looking for
    char buf[200];			// long enough for a complete name and TLE: ~30+70+70
    char *l0, *l1, *l2;			// start of each TLE line within buf[], l0==NULL until complete
    WiFiClient *remote;			// remote connection object
    int lineno;				// show line number as progress
} TLEFetch;

class Webpage
{

    public:

	Webpage();
	void checkEthernet();
	void setUserMessage (const __FlashStringHelper *ifsh);
	void setUserMessage (const __FlashStringHelper *ifsh, const char *msg, char state);

    private:

	WiFiServer *httpServer;

	const __FlashStringHelper *user_message_F;
	char user_message_s[100];

	void startTLEFetch (char *query_text);
	void resumeTLEFetch (void);
	TLEFetch tlef;

	bool connectWiFi();
	void askWiFi();
	void sendAskPage (WiFiClient client);
	void scrub (char *s);
	char readNextClientChar (WiFiClient client, uint32_t *to);
	void overrideValue (WiFiClient client);
	void sendMainPage (WiFiClient client);
	void sendNewValues (WiFiClient client);
	void sendPlainHeader (WiFiClient client);
	void sendHTMLHeader (WiFiClient client);
	void sendEmptyResponse (WiFiClient client);
	void send404Page (WiFiClient client);
	void reboot();
};

extern Webpage *webpage;

#endif // _WEBPAGE_H

More to follow(character limit).

This file probably has nothing wrong with it... but it is in a location where it is using variables in files not in the expected place... file references might use relative location, an not hard-coded locations. Try re-doing this in the normal "sketches" folder, and not in your new avr subfolder.

magdecl.cpp

/* inline World Magnetic Model good from 2015 through 2020.
 * from http://www.ngdc.noaa.gov
 */


#include <math.h>
#include <stdio.h>
#include <string.h>

#include "AutoSatTracker-ESP.h"

// wmm.cof starting year
static float epoc = 2020.0;

// wmm.cof as two arrays
static const float c0[13][13] = {
    {      0.0, -29404.5,  -2500.0,   1363.9,    903.1,   -234.4,     65.9,     80.6,     23.6,      5.0,     -1.9,      3.0,     -2.0,},
    {   4652.9,  -1450.7,   2982.0,  -2381.0,    809.4,    363.1,     65.6,    -76.8,      9.8,      8.2,     -6.2,     -1.4,     -0.1,},
    {  -2991.6,   -734.8,   1676.8,   1236.2,     86.2,    187.8,     73.0,     -8.3,    -17.5,      2.9,     -0.1,     -2.5,      0.5,},
    {    -82.2,    241.8,   -542.9,    525.7,   -309.4,   -140.7,   -121.5,     56.5,     -0.4,     -1.4,      1.7,      2.4,      1.3,},
    {    282.0,   -158.4,    199.8,   -350.1,     47.9,   -151.2,    -36.2,     15.8,    -21.1,     -1.1,     -0.9,     -0.9,     -1.2,},
    {     47.7,    208.4,   -121.3,     32.2,     99.1,     13.7,     13.5,      6.4,     15.3,    -13.3,      0.6,      0.3,      0.7,},
    {    -19.1,     25.0,     52.7,    -64.4,      9.0,     68.1,    -64.7,     -7.2,     13.7,      1.1,     -0.9,     -0.7,      0.3,},
    {    -51.4,    -16.8,      2.3,     23.5,     -2.2,    -27.2,     -1.9,      9.8,    -16.5,      8.9,      1.9,     -0.1,      0.5,},
    {      8.4,    -15.3,     12.8,    -11.8,     14.9,      3.6,     -6.9,      2.8,     -0.3,     -9.3,      1.4,      1.4,     -0.2,},
    {    -23.3,     11.1,      9.8,     -5.1,     -6.2,      7.8,      0.4,     -1.5,      9.7,    -11.9,     -2.4,     -0.6,     -0.5,},
    {      3.4,     -0.2,      3.5,      4.8,     -8.6,     -0.1,     -4.2,     -3.4,     -0.1,     -8.8,     -3.9,      0.2,      0.1,},
    {     -0.0,      2.6,     -0.5,     -0.4,      0.6,     -0.2,     -1.7,     -1.6,     -3.0,     -2.0,     -2.6,      3.1,     -1.1,},
    {     -1.2,      0.5,      1.3,     -1.8,      0.1,      0.7,     -0.1,      0.6,      0.2,     -0.9,     -0.0,      0.5,     -0.3,},
};

static const float cd0[13][13] = {
    {      0.0,      6.7,    -11.5,      2.8,     -1.1,     -0.3,     -0.6,     -0.1,     -0.1,     -0.1,      0.0,     -0.0,      0.0,},
    {    -25.1,      7.7,     -7.1,     -6.2,     -1.6,      0.6,     -0.4,     -0.3,      0.1,     -0.2,     -0.0,     -0.1,     -0.0,},
    {    -30.2,    -23.9,     -2.2,      3.4,     -6.0,     -0.7,      0.5,     -0.1,     -0.1,     -0.0,     -0.0,     -0.0,     -0.0,},
    {      5.7,     -1.0,      1.1,    -12.2,      5.4,      0.1,      1.4,      0.7,      0.5,      0.4,      0.2,      0.0,      0.0,},
    {      0.2,      6.9,      3.7,     -5.6,     -5.5,      1.2,     -1.4,      0.2,     -0.1,     -0.3,     -0.1,     -0.0,     -0.0,},
    {      0.1,      2.5,     -0.9,      3.0,      0.5,      1.0,     -0.0,     -0.5,      0.4,     -0.0,     -0.2,     -0.1,     -0.0,},
    {      0.1,     -1.8,     -1.4,      0.9,      0.1,      1.0,      0.8,     -0.8,      0.5,      0.3,     -0.0,      0.0,      0.0,},
    {      0.5,      0.6,     -0.7,     -0.2,     -1.2,      0.2,      0.3,      1.0,      0.0,     -0.0,     -0.1,     -0.0,     -0.0,},
    {     -0.3,      0.7,     -0.2,      0.5,     -0.3,     -0.5,      0.4,      0.1,      0.4,     -0.0,     -0.2,     -0.1,      0.0,},
    {     -0.3,      0.2,     -0.4,      0.4,      0.1,     -0.0,     -0.2,      0.5,      0.2,     -0.4,     -0.1,     -0.1,     -0.0,},
    {     -0.0,      0.1,     -0.3,      0.1,     -0.2,      0.1,     -0.0,     -0.1,      0.2,     -0.0,     -0.0,     -0.1,     -0.0,},
    {     -0.0,      0.1,      0.0,      0.2,     -0.0,      0.0,      0.1,     -0.0,     -0.1,      0.0,     -0.0,     -0.1,     -0.0,},
    {     -0.0,      0.0,     -0.1,      0.1,     -0.0,      0.0,     -0.0,      0.1,     -0.0,     -0.0,      0.0,     -0.1,     -0.1,},
};


static int E0000(int *maxdeg, double alt,
double glat, double glon, double t, double *dec, double *mdp, double *ti,
double *gv)
{
     /* N.B. storage types are a tradeoff between stack and program memory.
      * N.B. the algorithm modifies c[][] and cd[][] IN PLACE so they must be inited each time upon entry.
      */
     static int maxord,n,m,j,D1,D2,D3,D4;
     static double c[13][13],cd[13][13],tc[13][13],dp[13][13];
     static double snorm[169],sp[13],cp[13],fn[13],fm[13],pp[13],k[13][13],dtr,a,b,re,
	  a2,b2,c2,a4,b4,c4,flnmj,
	  dt,rlon,rlat,srlon,srlat,crlon,crlat,srlat2,
	  crlat2,q,q1,q2,ct,st,r2,r,d,ca,sa,aor,ar,br,bt,bp,bpp,
	  par,temp1,temp2,parp,bx,by,bz,bh;
     static double *p = snorm;


// GEOMAG:

/* INITIALIZE CONSTANTS */
      maxord = *maxdeg;
      sp[0] = 0.0;
      cp[0] = *p = pp[0] = 1.0;
      dp[0][0] = 0.0;
      a = 6378.137;
      b = 6356.7523142;
      re = 6371.2;
      a2 = a*a;
      b2 = b*b;
      c2 = a2-b2;
      a4 = a2*a2;
      b4 = b2*b2;
      c4 = a4 - b4;

      resetWatchdog();
      for (int i = 0; i < 13; i++) {
	  for (int j = 0; j < 13; j++) {
	      c[i][j] = c0[i][j];
	      cd[i][j] = cd0[i][j];
	  }
      }


/* CONVERT SCHMIDT NORMALIZED GAUSS COEFFICIENTS TO UNNORMALIZED */
      *snorm = 1.0;
      for (n=1; n<=maxord; n++) 
      {
	*(snorm+n) = *(snorm+n-1)*(double)(2*n-1)/(double)n;
	j = 2;
	for (m=0,D1=1,D2=(n-m+D1)/D1; D2>0; D2--,m+=D1) 
	{
	  k[m][n] = (double)(((n-1)*(n-1))-(m*m))/(double)((2*n-1)*(2*n-3));
	  if (m > 0) 
	  {
	    flnmj = (double)((n-m+1)*j)/(double)(n+m);
	    *(snorm+n+m*13) = *(snorm+n+(m-1)*13)*sqrt(flnmj);
	    j = 1;
	    c[n][m-1] = *(snorm+n+m*13)*c[n][m-1];
	    cd[n][m-1] = *(snorm+n+m*13)*cd[n][m-1];
	  }
	  c[m][n] = *(snorm+n+m*13)*c[m][n];
	  cd[m][n] = *(snorm+n+m*13)*cd[m][n];
	}
	fn[n] = (double)(n+1);
	fm[n] = (double)n;
      }
      k[1][1] = 0.0;

/*************************************************************************/

// GEOMG1:

      dt = t - epoc;
      if (dt < 0.0 || dt > 5.0) {
	  *ti = epoc;			/* pass back base time for diag msg */
	  return (-1);
      }

      dtr = M_PI/180.0;
      rlon = glon*dtr;
      rlat = glat*dtr;
      srlon = sin(rlon);
      srlat = sin(rlat);
      crlon = cos(rlon);
      crlat = cos(rlat);
      srlat2 = srlat*srlat;
      crlat2 = crlat*crlat;
      sp[1] = srlon;
      cp[1] = crlon;

/* CONVERT FROM GEODETIC COORDS. TO SPHERICAL COORDS. */
      q = sqrt(a2-c2*srlat2);
      q1 = alt*q;
      q2 = ((q1+a2)/(q1+b2))*((q1+a2)/(q1+b2));
      ct = srlat/sqrt(q2*crlat2+srlat2);
      st = sqrt(1.0-(ct*ct));
      r2 = (alt*alt)+2.0*q1+(a4-c4*srlat2)/(q*q);
      r = sqrt(r2);
      d = sqrt(a2*crlat2+b2*srlat2);
      ca = (alt+d)/r;
      sa = c2*crlat*srlat/(r*d);
      for (m=2; m<=maxord; m++) 
      {
	sp[m] = sp[1]*cp[m-1]+cp[1]*sp[m-1];
	cp[m] = cp[1]*cp[m-1]-sp[1]*sp[m-1];
      }
      aor = re/r;
      ar = aor*aor;
      br = bt = bp = bpp = 0.0;
      for (n=1; n<=maxord; n++) 
      {
	ar = ar*aor;
	for (m=0,D3=1,D4=(n+m+D3)/D3; D4>0; D4--,m+=D3) 
	{
/*
   COMPUTE UNNORMALIZED ASSOCIATED LEGENDRE POLYNOMIALS
   AND DERIVATIVES VIA RECURSION RELATIONS
*/
	  if (n == m) 
	  {
	    *(p+n+m*13) = st**(p+n-1+(m-1)*13);
	    dp[m][n] = st*dp[m-1][n-1]+ct**(p+n-1+(m-1)*13);
	    goto S50;
	  }
	  if (n == 1 && m == 0) 
	  {
	    *(p+n+m*13) = ct**(p+n-1+m*13);
	    dp[m][n] = ct*dp[m][n-1]-st**(p+n-1+m*13);
	    goto S50;
	  }
	  if (n > 1 && n != m) 
	  {
	    if (m > n-2) *(p+n-2+m*13) = 0.0;
	    if (m > n-2) dp[m][n-2] = 0.0;
	    *(p+n+m*13) = ct**(p+n-1+m*13)-k[m][n]**(p+n-2+m*13);
	    dp[m][n] = ct*dp[m][n-1] - st**(p+n-1+m*13)-k[m][n]*dp[m][n-2];
	  }
S50:
/*
    TIME ADJUST THE GAUSS COEFFICIENTS
*/
	  tc[m][n] = c[m][n]+dt*cd[m][n];
	  if (m != 0) tc[n][m-1] = c[n][m-1]+dt*cd[n][m-1];
/*
    ACCUMULATE TERMS OF THE SPHERICAL HARMONIC EXPANSIONS
*/
	  par = ar**(p+n+m*13);
	  if (m == 0) 
	  {
	    temp1 = tc[m][n]*cp[m];
	    temp2 = tc[m][n]*sp[m];
	  }
	  else 
	  {
	    temp1 = tc[m][n]*cp[m]+tc[n][m-1]*sp[m];
	    temp2 = tc[m][n]*sp[m]-tc[n][m-1]*cp[m];
	  }
	  bt = bt-ar*temp1*dp[m][n];
	  bp += (fm[m]*temp2*par);
	  br += (fn[n]*temp1*par);
/*
    SPECIAL CASE:  NORTH/SOUTH GEOGRAPHIC POLES
*/
	  if (st == 0.0 && m == 1) 
	  {
	    if (n == 1) pp[n] = pp[n-1];
	    else pp[n] = ct*pp[n-1]-k[m][n]*pp[n-2];
	    parp = ar*pp[n];
	    bpp += (fm[m]*temp2*parp);
	  }
	}
      }
      if (st == 0.0) bp = bpp;
      else bp /= st;
/*
    ROTATE MAGNETIC VECTOR COMPONENTS FROM SPHERICAL TO
    GEODETIC COORDINATES
*/
      bx = -bt*ca-br*sa;
      by = bp;
      bz = bt*sa-br*ca;
/*
    COMPUTE DECLINATION (DEC), INCLINATION (DIP) AND
    TOTAL INTENSITY (TI)
*/
      bh = sqrt((bx*bx)+(by*by));
      *ti = sqrt((bh*bh)+(bz*bz));
      *dec = atan2(by,bx)/dtr;
      *mdp = atan2(bz,bh)/dtr;
/*
    COMPUTE MAGNETIC GRID VARIATION IF THE CURRENT
    GEODETIC POSITION IS IN THE ARCTIC OR ANTARCTIC
    (I.E. GLAT > +55 DEGREES OR GLAT < -55 DEGREES)

    OTHERWISE, SET MAGNETIC GRID VARIATION TO -999.0
*/
      *gv = -999.0;
      if (fabs(glat) >= 55.) 
      {
	if (glat > 0.0 && glon >= 0.0) *gv = *dec-glon;
	if (glat > 0.0 && glon < 0.0) *gv = *dec+fabs(glon);
	if (glat < 0.0 && glon >= 0.0) *gv = *dec+glon;
	if (glat < 0.0 && glon < 0.0) *gv = *dec-fabs(glon);
	if (*gv > +180.0) *gv -= 360.0;
	if (*gv < -180.0) *gv += 360.0;
      }
      return (0);
}


/* compute magnetic declination for given location, elevation and time.
 * sign is such that mag bearing = true az + mag deviation.
 * return 0 if ok.
 */
int
magdecl (
double l, double L,		/* geodesic lat, +N, long, +E, degrees */
double e,			/* elevation, m */
double y,			/* time, decimal year */
double *mdp			/* return magnetic deviation, degrees E of N */
)
{
	double alt = e/1000.;
	double dp, ti, gv;
	int maxdeg = 12;

	int ok = E0000(&maxdeg,alt,l,L,y,mdp,&dp,&ti,&gv);
	return (ok);
}

#ifdef TEST_MAIN

#include <stdlib.h>

/* stand-alone test program
 */

int main (int ac, char *av[])
{
	if (ac != 5) {
	    char *slash = strrchr (av[0], '/');
	    char *base = slash ? slash+1 : av[0];
	    fprintf (stderr, "Purpose: test stand-alone magnetic declination model.\n");
	    fprintf (stderr, "Usage: %s lat_degsN lng_degsE elevation_m decimal_year\n", base);
	    exit(1);
	}

	double l = atof (av[1]);
	double L = atof (av[2]);
	double e = atof (av[3]);
	double y = atof (av[4]);
	double mdp;

	int ok = magdecl (l, L, e, y, &mdp);

	printf ("%d %g\n", ok, mdp);

	return (!!ok);
}

#endif // TEST_MAIN

More to follow(character limit).