Monday, November 30, 2015

Esp8266 - Interactive SMS from the Web Page

UPDATE: Mon Nov 30 21:34:56 PST 2015
Added Links and Detail
Added RAW HTML listing

In the previous post I listed a code snippet that provides non-interactive SMS from the Esp8266. But sometime it is desirable to provide a simple interactive SMS interface for the Web User. An interactive SMS interface could be used to "page the SysAdmin" with the web user's supplied message.
Example Interactive Web SMS Interface
The interactive SMS interface is simple and requires only some HTML code to be inserted within a web page. Note: the previous post was a SMS method where user interaction was not needed nor desired.

Note: the Open SMS Gateway domain name that is used in the example is "", read their web page for details for Canadian and International use.

The following are excerpts from my ERB-EspWebServer.

Note: the RAW HTML code could be extracted from the example below and used with any Web Server.

The Setup:

// The Setup

    // ERB - Force format stings and string constants into FLASH Memory
    // I use E() as an Alias for F() so that DEBUG code can be inserted
    #define  E(x) F(x)
    // Used as an F() when being used as the first Element
    // of a Multi-Element Expression
    #define sE(x) String( F(x) )

// Defaults for Pager
    #define DEFAULT_PAGER_NUMBER  "202-555-1212"


Web Server Code Arduino Sketch Snippet:

    // Pager - User Interactive Web Interface
    sz += wprintln( E("\r\n<!-- Pager - User Interactive Web Interface -->") );
    sz += wprintln( E("<center>") );
    sz += wprintln( E("<hr width='75%' />") );

    sz += wprintln(sE("<form action="http://")
          + DEFAULT_PAGER_GATEWAY + E("/text method='POST' target='SMS_Report' >") );
       sz += wprintln( E("  <b>Page SysAdmin with </b>") );
       sz += wprintln(sE("  <input name='number' type='hidden' value='")
             + SYSTEM_ADMIN_PAGER_NUMBER + E("' />") );
       sz += wprintln( E("  <b>Message:</b>") );
       sz += wprintln(sE("  <input name='message' type='text' value='")
             + gDeviceName + E(": ' />") );
       sz += wprintln( E("  <input type='submit' value='GO' />") );
    sz += wprintln( E("</form>") );
    sz += wprintln( E("Or<br>") );
    sz += wprintln(sE("<form action="http://")
          + DEFAULT_PAGER_GATEWAY + E("/text method='POST' target='SMS_Report' >") );
       sz += wprintln( E("  <b>SMS Number:</b>") );
       sz += wprintln( E("  <input name='number' type='tel' />") );
       sz += wprintln( E("  <b>Message:</b>") );
       sz += wprintln(sE("  <input name='message' type='text' value='")
             + gDeviceName + E(": ' />") );
       sz += wprintln( E("  <input type='submit' value='GO' />") );
    sz += wprintln( E("</form>") );

    sz += wprintln( E("</center>") );

Note: I use my own custom "wprintln" function within the above example, modify as necessary.

For reference and to make things simple, I have extracted just the HTML from the above Sketch, as shown below.


<!-- Pager - User Interactive Web Interface -->
<hr width='75%'>

<form method='POST' action='' target='SMS_Report' >
  <b>Page SysAdmin with </b>
  <input type='hidden' name='number' value='202-555-1212' />
  <input type='text' name='message' value='Nod129: ' />
  <input type='submit' value='GO' />


<form method='POST' action='' target='SMS_Report' >
  <b>SMS Number:</b>
  <input type='tel' name='number' />
  <input type='text' name='message' value='Nod129: ' />
  <input type='submit' value='GO' />


If you find this useful, leave a comment.

-- Home Page:

Sunday, November 29, 2015

Esp8266 - with SMS

UPDATE: Sun Nov 29 22:14:04 PST 2015
Added details and Links

For my Esp8266 I wanted a easy way to send to my Cell Phone an SMS message.

For example: On a normal computers (Workstations and Raspberry PI) it is a simple mater of using "curl" to access an Open SMS Gateway (see previous post). I used this feature to report simple things like "reboot" and "backup finished" messages.

One such Open SMS Gateway is "", which is the one that I use. But, recently they were "black listed" by some of the Phone Carriers (my carrier) for abuse, apparently there was too much illegal traffic by the Gateway's users.

Textbelt has recently fixed the abuse and their Gateways is up and running again, or at least for my carrier.

For the Exp8266, I have created some functions that implements the "curl" protocol, (the heavy lifting), so now paging to my Cell Phone is a snap.

I am providing the functions here as just application snippets, hopefully you find them useful. I will put this in my ERB-EspWebServer GitHub (eventually).

The Setup:

// The Setup

    // ERB - Force format stings and string constants into FLASH Memory
    // I use E() as an Alias for F() so that DEBUG code can be inserted
    #define  E(x) F(x)
    // Used as an F() when being used as the first Element of a Multi-Element Expression
    #define sE(x) String( F(x) )

// Defaults for Pager
    #define DEFAULT_PAGE_PORT     80
    #define DEFAULT_PAGE_NUMBER  "202-555-1212"
    #define DEFAULT_PAGE_MESSAGE "Test"

    boolean gPageStnReady = false;

The Functions:

// Pager

// ###########################################################
// Provides easy access to page via SMS Gateway
page( String aMesgText = DEFAULT_PAGE_MESSAGE,
      String aNumber   = DEFAULT_PAGE_NUMBER,
      String aHost     = DEFAULT_PAGE_GATEWAY,
         int aPort     = DEFAULT_PAGE_PORT )
    digitalWrite ( gBluLED, ON );
        #if (OPT_MONITOR_DEBUG_OUTPUT) > 0
            Serial.println ( );
            Serial.println ( E("Starting Pager Client ...") );
        String timeUTCBuf = "";
        String mesgTextHeader = String(gDeviceName)
            + E(": ")
            + String(gRev)
            + E(", ")
            + timeUTC(timeUTCBuf, gTimeZONE)
            + E(" - ");
        String mesg="number=" + aNumber
               + "&message=" + mesgTextHeader + aMesgText ;
        #if (OPT_MONITOR_DEBUG_OUTPUT) > 0
            Serial.println( sE("  Connecting to: ") + aHost );
        // Use WiFiClient class to create TCP connections
        WiFiClient client;
        if (!client.connect(aHost.c_str(), aPort)) {
          #if (OPT_MONITOR_DEBUG_OUTPUT) > 0
              Serial.println("  Connection Failed");
          return false;
        #if (OPT_MONITOR_DEBUG_OUTPUT) > 0 
            Serial.println( sE("  MESG: ") + mesg );
        // This will send the request to the server
        client.print( sE("POST /text/ HTTP/1.1\r\n")
                     + E("User-Agent: Esp8266/") + gRev + E("\r\n")
                     + E("Host: ") + aHost + E("\r\n")
                     + E("Accept: */*\r\n")
                     + E("Content-Length: ")
                     + String( mesg.length() ) + E("\r\n")
                     + E("Content-Type: application/x-www-form-urlencoded\r\n")
                     + E("\r\n")  // The Required Blank Line
                     + mesg + E("\r\n") );

        // Wait for Client to Start Sending
        int i = 0;
        while( !client.available() ) {
          if (i++ > 200) break;
        // Read all the lines of the reply from server and print some to Serial
        boolean myStatus = false;
          String line = client.readStringUntil('\n');
          if(line.indexOf("\"success\": true") >= 0) {
              myStatus = true;
          #if (OPT_MONITOR_DEBUG_OUTPUT) > 0 
              if(line.indexOf("\"success\": ") >= 0 ||
                 line.indexOf("\"message\": ") >= 0
              ) Serial.println(line);
        #if (OPT_MONITOR_DEBUG_OUTPUT) > 0 
            Serial.println("  Connection Closed");
    digitalWrite ( gBluLED, OFF );

    return myStatus;

// ###########################################################
// Provides easy access to Pager via SMS Gateway
unsigned long gPageHoldOff = millis();
pageOnStnReady() {
      if ( gPageHoldOff < millis() ) {
          gPageHoldOff = millis() + 1 * MINs;
          if ( gPageStnReady == false ) {
               gPageStnReady = page("Stn Ready");

// ###########################################################
// End

Let me know if you find this useful, leave a comment.

-- Home Page:

Wednesday, November 25, 2015

Email sent from Raspberry PI

Added details and Links

Sending Email from a Raspberry PI (or any typical Linux workstation) is NOT normally configured. But with the help of some optional commands it can be done with ease.

Also, see my previous post.

Some History

In the early days of Unix Workstations and Server, "sendmail" was typically configured by default, and therefore sending email was easy. In fact, it was "too easy", which allowed the bad guys to anomalously send SPAM. To combat SPAM most ISP's started requiring mail be "signed" (user name and password) by the originator, so it could be traced back to the point of origin.


Often it is useful to send a simple status report, information, attachments, or a quick SMS messages from; a Linux Workstation, a small Raspberry PI, or a Beagle Bone.

Today "most" email must be signed, and because of that it has become more difficult to use email for sending mail even to oneself.

Note: There are a "few" Open Mail (SMTP) Gateways that can be used. But the gateways can not, and will not guarantee any kind of performance, or can not provide any reasonable expectations. These Open SMTP's  are often used by SPAMMER.

Google'ing "Raspberry PI email" will provide several solutions.

But, most (if not all), require you use/save your EmailAddress and EmailPasswd as clear open-text on the command line or within a configuration file. I do not like that idea. There has got to be a better way?

One of the suggested solutions is "sendEmail", unfortunately it has a (some what) "complex" command line interface, and as above it normally requires the user to type an email password as clear open-text on the command line.

Note the upper case "E" in the sendEmail name.

To simplify, I have created a "Wapper Script", that can be used similar to those used in the early days of UNIX.


      $ date | mysendgmail


      $ mysendgmail < textfile

or, SMS

      $ echo "Meet me for Lunch" | mysendgmail

or, with an attachement

      $ echo "Here is my report" | mysendgmail -a myfile


      $ mysendgmail -s "My Status" -m I am driving, Do you want a ride.

Note: in the above example, is the Verizon SMS gateway, others could be used as necessary.

For the above examples, using my "Wapper Script", the users Gmail Password is prompted for, but does not display, see help text.

Also, see the included Help text for install instructions.

This Script makes my life easy, I hope you also find it useful. It is a little long for a blog post, but I wanted to provide it here before going to the trouble of setting up its own GitHub.

Note: some of the options of "sendEmail" have been used/perverted by this script to make the user interface easy and simple, which I find is a good compromise for functionality and usability.

Note: there is a BUG in the Raspberry PI implementation of "sendEmail",  Again, see the Help text.

If all else fails, "sendEmail" is a useful tool even when used by itself.

This following is mysendgmail script:

#! /bin/bash
# mysendgmail - Command line mail interface for Linux users,
# often on Raspberry Pi and other similar
# This script is a user friendly wrapper for "sendEmail"

# Because this script requires customization for each user,
# it should be save in each users $HONE/bin directory,
# as $HOME/bin/mysendgmail (or what ever name you like).

AUTHOR='Eldon R. Brown  - WA0UWH - 2015/11/22'

# Notes:
#   I think Google gmail allows 99 SMTP emails to be sent per day.
#   Note: an SMS sent to a Cell Phone has a 160 Character Limit.

progname=`basename $0`

# The Gmail Account, these must be customized per user

#This is for Google Gmail, others could be used

# Setup for Bold, Highlight, and Normal output
 B=`tput bold` G=`tput setf 2` N=`tput sgr0` H=${B}${G}


${B}${progname}-${REV}, by: ${AUTHOR}${N}


        ${progname} [mode] [-t] [[-s|-u] subject] [sendEmail args] -m message . .
  . . | ${progname} [mode] [-t] [[-s|-u] subject] [sendEmail args]

        Where: [mode] =
               -n     = Dry Run
               -v     = Verbose
               -h     = This help message
              --h     = This help message, plus more Info
              --help  = sendEmail help message, also see the
                        man page, as: man sendEmail


  ${H}More Info:${N}

        To Install supporting functions:
        $ sudo aptitude install sendEmail perl
        $ sudo aptitude install libio-socket-ssl-perl libnet-ssleay-perl

        See some sendEmail Examples, at:

        NOTE: There is a BUG in Raspberry PI's implementation
              of: /usr/bin/sendEmail REV=1.56
                 replace 'SSLv3 TLSv1' with 'SSLv3' within /usr/bin/sendEmail

 NOTE: The Gmail Passwd can be saved (and somewhat hidden)
              in the current environment with:
              $ export GPW; read -s -p 'Gmail Passwd: ' GPW; echo
       And then later, it can be removed with:
              $ unset GPW

# Main

 # Check first arg for Help Message, or Version Info
 case "${1}" in
 (-V)    echo -e "${progname}-${REV} by ${AUTHOR}"; exit;;
 (-h|"") echo -e "${Usage}" >&2; exit;;
 (--h)   echo -e "${Usage} ${Info}" >&2; exit;;
 (-help|--help) sendEmail --help >&2; exit;;
 # Check first arg for Dry Run or Verbose
 case "${1}" in
 (-n) DRYRUN='yes'; shift;;
 (-v) VERBOSE='yes'; shift;;

 # Check next arg for Dry Run or Verbose, again to avoid order conflict
 case "${1}" in
 (-n) DRYRUN='yes'; shift;;
 (-v) VERBOSE='yes'; shift;;

 # Prompt for Gmail Account Passwd, OR used the Environment Varrible $GPW
 if [ -z "${GPW}" ]
 then read -s -p "Gmail Password: " gmail_passwd </dev/tty; echo

# Parse Mail Address and Subject Args
 # Check if First arg is "-t", if so ignore, ignore it and
 # assume the next is email address
 case "${1}" in (-t) shift;; esac

 # Assume Next arg is the TO address
 to="${1}"; shift
 # Check if Next arg is "-s" or "-u", if so, ignore it and
 # assume the next is the Subject
 case "${1}" in (-u|-s) shift;; esac

 Default_Subject="Sent: `date '+%Y/%m/%d %H:%M:%S'`"
 # Assume Next arg is Subject
 sub="${1:-${Default_Subject}}"; shift

# Setup DEBUG modes

 # Check for DRYRUN mode, if so, Munge passwd for DRYRUN
 if [ "${DRYRUN}" = "yes" ]; then gmail_passwd='"*****"'; fi

 # Check for VERBOSE, For Debug
 if [ "${VERBOSE}" = "yes" ]; then MODE='set -xv'; fi

# Build the Command
 CMD="sendEmail -o tls=yes -s ${SMTP} \
  -xu ${gmail_user} -xp ${gmail_passwd} \
  -f ${from_user} -t ${to} -u ${sub} \
  $@" # Adds user supplied sendEmail options

# Finally,  Run Command
 case "${DRYRUN}" in
 (yes) echo $CMD;;  # For Debug
 (*) ${MODE}; $CMD | grep "`date '+%b %d'`";; # Report just the "basic" status

# End

-- Home Page:

Saturday, November 14, 2015

More 10m WSPR

Added details and Links

Here is my: Today's 10m WSPR Report:

My 2015/11/14 10m WSPR Report
Info from Database
Most of the USA spots were logged during daylight hours, and then late in the day Australia and Japan spots were logged.

Sadly, even though I got up very early (2am local) to start my 10m WSPR Beacon, I did not receive any spots from Europe. Maybe I will get a Europe-Spot later next summer when we will share more daylight hours.

-- Home Page:

Thursday, November 12, 2015

10m WSPR from PNW

Added details and Links

After reading Roger's - G3XBM 10m WSPR to USA Blog, I decided to try to help make a USA to Europe WSPR connection.

It took a little futzing to adjust the normal WSPR Radio Dial Frequency 28.1246MHz (down by 110Hz) to get my RF into the center of the 200Hz wide WSPR band. My first spot report indicated that I was above the band by a few Hertz. Setting to 28.1245MHz fixed the problem.

Sever spots later, it is obvious that the Pacific Northwest was very much under represented on the 10m WSPR map, my station is the only one, see: upper-left on the map below.

I am the only Northwest 10m WSPR Station
My goal now is to wait for the band to change for Europe and/or Far East stations. I will have to wait and see if it opens.

Currently I am running my Phone WSPR Beacon APP, with acustic/VOX connection to the Radio (see previous post). I have a Proper wired Phone/Tablet "Radio Interface" on order. With the new interface I will be able to run this and other Digital APPs without room noise interference.

But for proper encode/decode WSPR operations, a Workstation running the complete "WSPR" program is really necessary as the Android WSPR App does not decode received signals, it runs in Beacon mode only. Some other Digital Phone Apps will encode and decode, see DroidPSK.

UPDATE: 21:45Z

Now 10m is opening West to Australia.
10m at 21:45Z
It will be interesting to see what happen when the "Gray Line" gets nearer my location.

Interesting, some people spell it "Gray Line" and others "Grey Line"?  I think "Gray Line" is correct.

UPDATE: 01:30Z

Well, the "Gray Line" was uneventful, only one station, I was expecting more Far East spots.

10m Spots At and After Gray Line

UPDATE: 01:50Z

QSY to 40m WSPR.

-- Home Page:

Wednesday, November 11, 2015

Working WSPR With a Phone APP

Added, additional details.

Today for fun, I wanted to try working with WSPR again, I have not done that for a long time.

I found a Android Phone WSPR Beacon APP, that generates the WSPR tones, which when acoustically coupled to a Radio with VOX, transmits as necessary.

The Acoustic WSPR Interface
(Note: Unlike what the photo shows,
the Power was actually set to 5 Watts)
The Radio was Set Up for VOX on 20M
The WSPR Beacon App runs on both my Cell Phone and my Samsung Android Tablet. As with all WSPR programs, the system clock must be set within a second (or two) of the real time.

The Cell Phone network maintains my phone with an accurate system clock.

But my Tablet does NOT allow itself or "third party" Apps to "Automatically" change the clock from an Internet or GPS time standard. And therefore, an Interactive Clock Set is necessary. I use the ClockSync App for this. It is reasonably simple - just set the Time to the next whole minute, and then press an on-screen button at the beep (after a count down, it tell you when).

Using my Cell Phone to Generate WSPR Tones, here are the results on the WSPR Map:

16 Stations, 89 Spots
From My Location
After 2.5 hours of working 40m and 20m, my WSPR Beacon was received by 16 stations for a total of 89 Spots, some spots were obviously repeats. The furtherest station was 3894km.

 Timestamp        Call   MHz       SNR Dft Grid   Pwr Repter RGrid    km  az
 2015-11-11 18:44 WA0UWH 14.097177 -24   3 CN88xc  5  XE1NW  EK08    3894 140 
 2015-11-11 18:56 WA0UWH 14.097171 -30   0 CN88xc  5  W0RPK  FM15hn  3891  94 
 2015-11-11 18:44 WA0UWH 14.097182 -30   4 CN88xc  5  KU4QI  EM87bx  3260  96 
 2015-11-11 18:44 WA0UWH 14.097189 -26   4 CN88xc  5  K5CZD  EM32vn  3032 114 
 2015-11-11 18:56 WA0UWH 14.097211 -24   0 CN88xc  5  KD6RF  EM22lb  2883 118 
 2015-11-11 19:00 WA0UWH 14.097208 -20   0 CN88xc  5  K9DZT  EN52wx  2679  90 
 2015-11-11 18:44 WA0UWH 14.097189 -11   3 CN88xc  5  AL7Q   BP40fc  2310 316 
 2015-11-11 18:44 WA0UWH 14.097180 -27   3 CN88xc  5  WD0AKZ EN34mx  2238  88 
 2015-11-11 18:48 WA0UWH 14.097250  -3   0 CN88xc  5  NO1D   DM34tn  1705 148 
 2015-11-11 19:28 WA0UWH 14.097225 -10   0 CN88xc  5  N6RDR  DM13cx  1610 166 
 2015-11-11 19:00 WA0UWH 14.097196 -27   1 CN88xc  5  K6PZB  CM88nk  1077 184 
 2015-11-11 17:48 WA0UWH  7.040173  -4   1 CN88xc 20  W0AY   DN26xo   625 103 
 2015-11-11 17:52 WA0UWH  7.040175  +2   0 CN88xc 20  KD7OA  DN16     418 114 
 2015-11-11 17:24 WA0UWH  7.040178 -20   1 CN88xc 20  KF7O   CN85oh   316 191 
 2015-11-11 18:12 WA0UWH  7.040180  -4   2 CN88xc 20  NC7U   CN87qp    67 221 
 2015-11-11 17:52 WA0UWH  7.040180 -24   0 CN88xc 20  KD7HGL CN87ts    45 214 

Note: The WSPR Phone APP is "Beacon-ONLY", that is, it does NOT receive, decode, or report on signals.

It was fun and simple !

-- Home Page: