sim-modem/api/modem/internet/ic.go

242 lines
5.6 KiB
Go
Raw Normal View History

package internet
import (
"fmt"
"io"
"log"
"os"
"os/exec"
"strings"
"github.com/CGSG-2021-AE4/modem-test/api/modem/at"
)
var apns = map[string]string{
"Tinkoff": "m.tinkoff",
}
const pppConfigName = "annalistnet"
const pppConfig = `
# Annalist project custom internet connection
# APN:
connect "/usr/sbin/chat -v -f /etc/chatscripts/gprs -T %s"
# Port:
%s
# Baudrate:
%d
noipdefault
usepeerdns
defaultroute
persist
noauth
nocrtscts
local
`
type conn struct {
logger *log.Logger
port at.Port
}
type Conn interface {
Init() error
ConfigurePPP() error
Ping() bool // Is connected
io.Closer
}
func New(logger *log.Logger, port at.Port) Conn {
return &conn{
logger: logger,
port: port,
}
}
func (c *conn) checkPackageExist(pname string) bool {
2024-07-29 11:02:06 +00:00
resp, err := exec.Command("apt-mark", "showmanual", pname).Output()
c.logger.Println("CHECK:", resp)
if err != nil {
c.logger.Println("CHECK PACKAGE ERROR: ", err.Error())
return false
}
2024-07-29 11:02:06 +00:00
return string(resp[:len(pname)]) == pname
}
func (c *conn) ensurePackage(pname string) error {
if c.checkPackageExist(pname) {
return nil
}
2024-07-29 11:02:06 +00:00
return fmt.Errorf("package %s not installed", pname)
// c.logger.Println("Installing", pname, "package...")
// resp, err := exec.Command("apt-get", "install", pname).Output()
// if err != nil {
2024-07-29 11:11:38 +00:00
// return fmt.Errorf("execute install cmd: %w", err)
2024-07-29 11:02:06 +00:00
// }
// c.logger.Println(resp)
// c.logger.Println("\x1b[38;2;255;0;0mComplete\x1b[38;2;255;255;255m")
// return nil
}
// Check requirenments
func (c *conn) checkReqs() error {
// Check AT port for sure
if c.port == nil || !c.port.IsConnected() {
return fmt.Errorf("AT port is not connect or nil")
}
// Ensure all necessary packages installed
if err := c.ensurePackage("ppp"); err != nil {
return fmt.Errorf("ensure ppp package: %w", err)
}
2024-07-28 18:01:18 +00:00
// if err := c.ensurePackage("net-tools"); err != nil {
// return fmt.Errorf("ensure net-tools package: %w", err)
// }
// Check SIM is valid
// AT+CPIN? and just check
resp, err := c.port.Send("AT+CPIN?")
if err != nil {
return fmt.Errorf("AT+CPIN? request: %w", err)
}
if !resp.Check() {
return fmt.Errorf("SIM card is not inserted")
}
return nil
}
func (c *conn) ConfigurePPP() error {
// Get provider name and its APN
2024-07-29 11:11:38 +00:00
resp, err := c.port.Send("AT+CSPN?")
if err != nil {
return fmt.Errorf("AT+CSPN? request: %w", err)
}
if !resp.Check() {
return fmt.Errorf("failed to check SIM provider")
}
strs := strings.Split(string(resp), "\"")
if len(strs) < 3 {
return fmt.Errorf("parse AT+CSPN response: %s", string(resp))
}
provider := strs[1]
apn := apns[provider]
if apn == "" {
return fmt.Errorf("no apn for provider: %s", provider)
}
2024-07-29 11:11:38 +00:00
// Make config
c.logger.Printf("Config values: %s, %s, %d", apn, c.port.GetName(), c.port.GetBaudrate())
config := fmt.Sprintf(pppConfig, apn, c.port.GetName(), c.port.GetBaudrate())
2024-07-29 11:11:38 +00:00
// Write to file
2024-08-02 16:16:39 +00:00
f, err := os.OpenFile("/etc/ppp/peers/"+pppConfigName, os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return fmt.Errorf("open ppp config file %w", err)
}
defer f.Close()
if _, err := f.Write([]byte(config)); err != nil {
return fmt.Errorf("write to ppp config file: %w", err)
}
return nil
}
func (c *conn) setup() error {
c.logger.Println("Check requirenments...")
if err := c.checkReqs(); err != nil {
return fmt.Errorf("check requirenments: %w", err)
}
// DEBUG show networks and signal
resp, err := c.port.Send("AT+COPS?")
if err != nil {
return fmt.Errorf("AT+COPS? request: %w", err)
}
c.logger.Println("DEBUG networks:", resp)
resp, err = c.port.Send("AT+CSQ")
if err != nil {
return fmt.Errorf("AT+CSQ request: %w", err)
}
c.logger.Println("DEBUG signal quality:", resp)
// Configure ppp
// what is better ASK If /etc/ppp/peers/annalistnet not exists
c.logger.Println("Configure ppp...")
if err := c.ConfigurePPP(); err != nil {
return fmt.Errorf("configure ppp: %w", err)
}
return nil
}
func (c *conn) connect() error {
2024-07-29 11:02:06 +00:00
resp, err := exec.Command("pon", pppConfigName).Output()
if err != nil {
return fmt.Errorf("execute connect cmd: %w", err)
}
c.logger.Println("DEBUG pon response:", string(resp))
return nil
}
func (c *conn) diconnect() error {
2024-07-29 11:02:06 +00:00
resp, err := exec.Command("poff", pppConfigName).Output()
if err != nil {
return fmt.Errorf("execute disconnect cmd: %w", err)
}
c.logger.Println("DEBUG poff response:", string(resp))
return nil
}
func (c *conn) Init() error {
// Setup
c.logger.Println("Setup...")
if err := c.setup(); err != nil {
return fmt.Errorf("setup: %w", err)
}
// Connect
c.logger.Println("Connect...")
if err := c.connect(); err != nil {
return fmt.Errorf("connect: %w", err)
}
//DEBUG
resp, err := exec.Command("ifconfig").Output()
if err != nil {
return fmt.Errorf("execute ifconfig cmd: %w", err)
}
c.logger.Println("DEBUG ifconfig resp:", string(resp))
// Test connectin using Ping
c.logger.Println("Test...")
if !c.Ping() {
return fmt.Errorf("ping failed")
}
return nil
}
func (c *conn) Ping() bool {
// Test - try to connect to Google DNS
// ping -I ppp0 8.8.8.8
resp, err := exec.Command("ping", "8.8.8.8").Output()
if err != nil {
c.logger.Println("Ping 1 cmd error:", err)
}
c.logger.Println("Ping 1 resp:", string(resp))
resp, err = exec.Command("ping", "-I", "ppp0", "8.8.8.8").Output()
if err != nil {
c.logger.Println("Ping 2 cmd error:", err)
}
c.logger.Println("Ping 2 resp:", string(resp))
2024-08-02 16:16:39 +00:00
return !(strings.Contains(string(resp), "Destination Host Unreachable") || strings.Contains(string(resp), "Destination Net Unreachable")) // tmp solution
}
func (c *conn) Close() error {
if err := c.diconnect(); err != nil {
return fmt.Errorf("diconnect: %w", err)
}
return nil
}