Saturday, October 20, 2018

Update #2: SMS with a Huawei E8372

This is the next edition of the series of posts about interfacing with the Huawei E8372 Cellular Dongle, sometimes called the Wingle for WiFi-Dongle. This device is really a cool little device that can both provide internet access through USB and also through the WiFi network it can host.



I am using this device to supply internet to a remote island in Canada by pairing it with a directional antenna mounted on an antenna tower. I started out interfacing with this device very simply. (See the two previous posts on this subject) This dongle has the ability to send and receive SMS messages over the cell network, so I decided that I needed to be able to access those capabilities. Very quickly it became clear that using the scripts I was developing would not work so I started searching for a library or other software that could help me.



After searching around a bit, I found the following library written by a guy named Pablo Santa Cruz. He wrote a library in python that can login and send and receive SMS messages from/to the dongle. The library, huawei-modem-python-api-client met my needs but there was an issue: I did not know python. Luckily, the library included some samples and through trial and error and lots of Google searches, I was able to cobble together a script that would login to the dongle, read any new messages and, if needed, send a message. From that beginning, I slowly added more capability to the script, having it do things when I text command messages to it. I wanted to be able to send commands because I wanted a way to instruct the Raspberry Pi host computer to do things if I could not login to the computer.

But wait, I may be getting ahead of myself, let me back up a little; this whole project was started because I wanted to be able to have a computer running on a remote island in Canada and be able to have it send weather and other data. The island is 17 miles from the nearest cell tower, but luckily, since this is in the wilds of Ontario, the cell towers are very high so they can be used from far away. The island where the Pi will be located has a radio tower, so I was able to mount a directional antenna on it and make a reliable 3G connection to the internet.

Solar Panels, antennas and weather instruments


From my experiments with the Huawei Wingle, I found that even though the computer was connected to the internet and with port forwarding setup, I could not access the computer from the internet. I assume this is because the cellular companies restrict this type of access for security purposes. So to be able to access the computer on the island, I needed to have it reach out and establish a VPN connection. Once the connection is made, I can use that and reach back and login to the Pi. Since I have the ability to send a message to the computer using SMS, I use that to instruct the computer to establish the VPN connection whenever I needed it. It works perfectly, I send the SMS message with the proper command, and the Pi establishes the VPN connection and sends a response back.

Here is the script I wrote that will read and respond to the commands in the SMS messages:


import sys
import subprocess
from pprint import pprint

from huaweisms.api import webserver, device, monitoring, user, sms, ussd
from huaweisms.api.common import ApiCtx

USER="admin"
PASSWORD="xxxxxxx"

def get_session():
    ctx = ApiCtx()
    token = webserver.SesTokInfo()
    ctx.session_id = token['response']['SesInfo'].split("=")[1]
    ctx.token = token['response']['TokInfo']
    lgn = user.login(ctx, USER, PASSWORD)
    #pprint(lgn)
    return ctx

ctx = get_session()

inbox = 1 
outbox = 2
page =1 
howmany = 20 

# Delete all the previously sent messages first
msgs = sms.get_sms(ctx,outbox,page,howmany)
nummsgs = int(msgs['response']['Count'])
if nummsgs > 0:
   for k in range(0,nummsgs):
      idx=int(msgs['response']['Messages']['Message'][k]['Index'])
      res=sms.delete_sms(ctx,idx)


#Now get the new ones
msgs = sms.get_sms(ctx,inbox,page,howmany)
nummsgs = int(msgs['response']['Count'])

if nummsgs > 0:
   for k in range(0,nummsgs):
      idx=int(msgs['response']['Messages']['Message'][k]['Index'])
      content=str(msgs['response']['Messages']['Message'][k]['Content'])
      num=str(msgs['response']['Messages']['Message'][k]['Phone'])
      print("Msg from" + num + " msg=" + content)

      #if the message starts with cmd: then it is a command...
      if content.lower().startswith("cmd:"):
         print("command")
         
         #establish the VPN?
         if content.lower().startswith("cmd:pptp on") \
                 or content.lower().startswith("cmd:vpn on"):
            output = subprocess.run("sudo pon PPTP_VPN", shell=True, stdout=subprocess.PIPE, universal_newlines=True)
            print(output.stdout)
            sent = sms.send_sms(ctx, num, "tried to start VPN")
            print("pptp on received")

         #turn off the VPN?
         elif content.lower().startswith("cmd:pptp off") \
                or content.lower().startswith("cmd:vpn off"):
            output = subprocess.run("sudo poff PPTP_VPN", shell=True, stdout=subprocess.PIPE, universal_newlines=True)
            print(output.stdout)
            sent = sms.send_sms(ctx, num, "tried to stop VPN")
            print("pptp off received")

         #Reboot the Pi
         elif content.lower().startswith("cmd:reboot"):
            sent = sms.send_sms(ctx, num, "Reboot command received")
            print("Reboot received")
            output = subprocess.run("sudo reboot", shell=True, stdout=subprocess.PIPE, universal_newlines=True)
            print(output.stdout)

         #Take a picture adn upload it to Dropbox
         elif content.lower().startswith("cmd:picture"):
            output = subprocess.run("python3 /home/pi/camera/uploader.py", shell=True, stdout=subprocess.PIPE, universal_newlines=True)
            sent = sms.send_sms(ctx, num, "Picture uploaded.")

         #respond with a generic message to know that something was received...
         else:
            sent = sms.send_sms(ctx, num, "pong - " + content)

      #if the message contains the word weather...
      elif content.lower().rfind("weather")!=-1:
         print("weather request received")
         with open("/var/www/html/weewx/SMS") as f:
            file_content = f.read().rstrip("\n")
            f.close()
         sent = sms.send_sms(ctx, num, file_content)

      #a message with no command nor weather was received.
      else:
         print("unknown message received")
         sent = sms.send_sms(ctx, num, "Hi from Beaverstone Bay! Ask me about the Weather!")


      #delete the message we just received
      res=sms.delete_sms(ctx,idx)


3 comments:

  1. Awesome! Keep up the great work! Best regards.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete