Created
March 25, 2022 13:47
-
-
Save ThomasLobker/59c5001e5a4bc9ba4a8e9701276d6226 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sys | |
import os | |
import thread | |
import threading | |
import time | |
import syslog | |
import netifaces | |
import serial | |
import Queue | |
from systemd import daemon | |
syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_DAEMON) | |
def log(message, level="info"): | |
if level == "info": | |
syslog.syslog(syslog.LOG_INFO, message) | |
daemon.notify("STATUS=%s" % message) | |
return | |
if level == "notice": | |
syslog.syslog(syslog.LOG_NOTICE, message) | |
daemon.notify("STATUS=%s" % message) | |
return | |
if level == "critical": | |
syslog.syslog(syslog.LOG_CRIT, message) | |
daemon.notify("STATUS=%s" % message) | |
return | |
syslog.syslog(syslog.LOG_DEBUG, message) | |
return | |
def init_pppd(provider): | |
log("Calling mobile network operator to establish the internet connection") | |
time.sleep(1) | |
pppd = os.system("pppd call %s" % provider) | |
log("PPPD status: %s" % pppd) | |
return os.WEXITSTATUS(pppd) | |
def ping(target): | |
response = os.system("ping -c 1 -q %s" % target) | |
return os.WEXITSTATUS(response) | |
class background(threading.Thread): | |
def __init__(self, queue, event, interval, target): | |
threading.Thread.__init__(self) | |
self.queue = queue | |
self.event = event | |
self.interval = interval | |
self.state = 0 | |
self.target = target | |
super(background, self).__init__() | |
def run(self): | |
try: | |
log("Waiting for network interface [ppp0] to become online", "debug") | |
while self.state == 0 and not self.event.wait(self.interval): | |
interfaces = netifaces.interfaces() | |
try: | |
index = interfaces.index('ppp0') | |
for interface in netifaces.ifaddresses('ppp0'): | |
if interface == netifaces.AF_INET: | |
address = netifaces.ifaddresses('ppp0')[netifaces.AF_INET][0]['addr'].encode('ascii','ignore') | |
log("Interface [ppp0] has been detected at index [%s] with address [%s]" % (interfaces.index('ppp0'), address)) | |
self.state = 1 | |
except ValueError: | |
log("Unable to get interface [ppp0]", "debug") | |
log("Waiting for remote target [%s] to be responsive" % self.target, "debug") | |
while self.state == 1 and not self.event.wait(self.interval): | |
interfaces = netifaces.interfaces() | |
try: | |
response = ping(self.target) | |
if response == 0: | |
log("Target [%s] is now reachable" % self.target) | |
self.state = 2 | |
except ValueError: | |
log("Unable to get response from target [%s]" % self.target, "debug") | |
self.queue.put({ "type": "success", "message": "PPP connection with mobile network is now ready" }) | |
except Exception: | |
self.queue.put({ "type": "error", "message": "Background task has failed" }) | |
if not len(sys.argv) == 2: | |
log("Invalid number of arguments", "critical") | |
sys.exit(1) | |
baudrate = 230400 | |
log("Initializing the serial interface with [%s] baudrate" % baudrate) | |
os.system("raspi-gpio set 17 op") | |
os.system("raspi-gpio set 16 op") | |
os.system("raspi-gpio set 6 op") | |
os.system("raspi-gpio set 5 op") | |
os.system("raspi-gpio set 5 dl") | |
os.system("raspi-gpio set 6 dl") | |
os.system("raspi-gpio set 17 dl") | |
os.system("raspi-gpio set 16 dl") | |
time.sleep(5) | |
port = serial.Serial('/dev/ttyAMA0', 115200) | |
port.write("AT\r\n") | |
time.sleep(1) | |
port.write("AT+IPR=%s\r\n" % baudrate) | |
port.close() | |
provider = str(sys.argv[1]) | |
pppd = init_pppd(provider) | |
if not pppd == 0: | |
log("Unable to start PPP connection with mobile network", "critical") | |
sys.exit(1) | |
queue = Queue.Queue() | |
event = threading.Event() | |
monitoring = background(queue, event, 1, "8.8.8.8").start() | |
while True: | |
try: | |
time.sleep(1) | |
item = queue.get(block=False) | |
except Queue.Empty: | |
pass | |
else: | |
if item["type"] == "error": | |
log(item["message"], "critical") | |
sys.exit(1) | |
if item["type"] == "success": | |
log(item["message"], "notice") | |
daemon.notify("READY=1") | |
sys.exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/dev/ttyAMA0 230400 crtscts | |
connect '/usr/sbin/chat -v -f /etc/ppp/vodafone' | |
noauth | |
name vodafone | |
usepeerdns | |
defaultroute | |
replacedefaultroute |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ABORT "NO CARRIER" | |
ABORT "ERROR" | |
ABORT "BUSY" | |
ECHO OFF | |
"" "ATZ" | |
OK "ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0" | |
SAY "Connecting with Vodafone...\n" | |
OK "AT+COPS=2" | |
OK "AT+CGDCONT=1,\"IP\",\"live.vodafone.com\"" | |
OK "AT+COPS=0" | |
OK "ATDT*99#" | |
TIMEOUT 120 | |
SAY "Connecting" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Unit] | |
Description=MediaServe 2G/LTE mobile terminal service (PPPD) | |
PartOf=mobile.service | |
After=network.service | |
Before=network-online.target | |
Wants=mobile.service | |
[Service] | |
Type=oneshot | |
ExecStart=/bin/true | |
ExecReload=/bin/true | |
WorkingDirectory=/etc | |
[Install] | |
WantedBy=multi-user.target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Unit] | |
Description=MediaServe 2G/LTE mobile terminal service (PPPD) (%i) | |
PartOf=pppd.service | |
After=network.target | |
Before=network-online.target | |
Wants=pppd.service | |
ReloadPropagatedFrom=pppd.service | |
[Service] | |
Type=forking | |
ExecStart=/usr/local/bin/mobile-pppd %i | |
WorkingDirectory=/etc | |
Restart=on-failure | |
RestartSec=30s | |
[Install] | |
WantedBy=multi-user.target |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
MediaServe 2G/LTE mobile terminal service (PPPD)
Introduction
We have created a small script to let a Raspberry Pi connect with a Seeed LTE Cat 1 Pi Hat using pppd and keep the connection alive. The script is started as a systemd service and through monitoring it should try to keep the connection alive or restart when no connection is available.
We are using an OpenVPN session that is depending on this systemd service and starting when the connection is up. This allows us to give SSH access over the GSM network to the Raspberry Pi wherever it is plugged in. In our case we use
minicom
to remotely manage routers or switches over a serial port.Installation
Using Raspbian as a basis. We have installed the LTE adapter to the GPIO of the Raspberry Pi. We are not using USB.
You should now have a working pppd connection and you should be able to access the internet. Try to unhook the UTP connection and reboot the Raspberry Pi. It should get an internet connection. Happy hacking, let me know if I need to make any improvements.