Added internet connection(not debugged yet).
This commit is contained in:
		| @@ -26,6 +26,7 @@ type atPort struct { | ||||
|  | ||||
| type Port interface { | ||||
| 	GetName() string | ||||
| 	GetBaudrate() int | ||||
| 	GetSerialPort() serial.Port // For extra need | ||||
|  | ||||
| 	Connect() error | ||||
| @@ -50,6 +51,10 @@ func (p *atPort) GetName() string { | ||||
| 	return p.portName | ||||
| } | ||||
|  | ||||
| func (p *atPort) GetBaudrate() int { | ||||
| 	return p.baudrate | ||||
| } | ||||
|  | ||||
| func (p *atPort) GetSerialPort() serial.Port { | ||||
| 	return p.port | ||||
| } | ||||
|   | ||||
							
								
								
									
										219
									
								
								api/modem/internet/ic.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								api/modem/internet/ic.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | ||||
| 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 { | ||||
| 	resp, err := exec.Command("sudo", "apt-mark", "showmanual", pname).Output() | ||||
| 	if err != nil { | ||||
| 		c.logger.Println("CHECK PACKAGE ERROR: ", err.Error()) | ||||
| 		return false | ||||
| 	} | ||||
| 	return string(resp) == pname | ||||
| } | ||||
|  | ||||
| func (c *conn) ensurePackage(pname string) error { | ||||
| 	if c.checkPackageExist(pname) { | ||||
| 		return nil | ||||
| 	} | ||||
| 	c.logger.Println("Installing", pname, "package...") | ||||
| 	resp, err := exec.Command("sudo", "apt-get", "install", pname).Output() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("execute install cmd: %w", err) | ||||
| 	} | ||||
| 	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) | ||||
| 	} | ||||
| 	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 | ||||
| 	//   AT+CSPN | ||||
| 	provider := "" | ||||
| 	apn := apns[provider] | ||||
| 	if apn == "" { | ||||
| 		return fmt.Errorf("no apn for provider: %s", provider) | ||||
| 	} | ||||
| 	config := fmt.Sprintf(pppConfig, apn, c.port.GetName(), c.port.GetBaudrate()) | ||||
|  | ||||
| 	f, err := os.OpenFile("etc/ppp/pears/"+pppConfigName, os.O_CREATE, 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 { | ||||
| 	resp, err := exec.Command("sudo", "pon", pppConfigName).Output() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("execute connect cmd: %w", err) | ||||
| 	} | ||||
| 	c.logger.Println("DEBUG pon response:", resp) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *conn) diconnect() error { | ||||
| 	resp, err := exec.Command("sudo", "poff", pppConfigName).Output() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("execute disconnect cmd: %w", err) | ||||
| 	} | ||||
| 	c.logger.Println("DEBUG poff response:", 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:", 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", "-I", "ppp0", "8.8.8.8").Output() | ||||
| 	if err != nil { | ||||
| 		c.logger.Println("Ping cmd error:", err) | ||||
| 	} | ||||
| 	c.logger.Println("Ping resp:", resp) | ||||
|  | ||||
| 	return !strings.Contains(string(resp), "Destination Host Unreachable") // tmp solution | ||||
| } | ||||
|  | ||||
| func (c *conn) Close() error { | ||||
| 	if err := c.diconnect(); err != nil { | ||||
| 		return fmt.Errorf("diconnect: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -11,6 +11,7 @@ import ( | ||||
|  | ||||
| 	"github.com/CGSG-2021-AE4/modem-test/api/modem/at" | ||||
| 	"github.com/CGSG-2021-AE4/modem-test/api/modem/gpio" | ||||
| 	"github.com/CGSG-2021-AE4/modem-test/api/modem/internet" | ||||
| ) | ||||
|  | ||||
| type ModemData struct { | ||||
| @@ -32,8 +33,13 @@ type modem struct { | ||||
| 	onOffPin gpio.Pin | ||||
|  | ||||
| 	// Other values | ||||
| 	gpsInfo        GpsData | ||||
| 	lastUpdateTime time.Time | ||||
|  | ||||
| 	// GPS | ||||
| 	gpsInfo GpsData | ||||
|  | ||||
| 	// Internet connection | ||||
| 	ic internet.Conn | ||||
| } | ||||
|  | ||||
| type Modem interface { | ||||
| @@ -48,14 +54,14 @@ func New(logger *log.Logger) Modem { | ||||
| 	return &modem{ | ||||
| 		logger:         logger, | ||||
| 		baudrate:       115200, | ||||
| 		onOffPin:       gpio.New(logger, 6), | ||||
| 		onOffPin:       gpio.New(log.New(logger.Writer(), "gpio", log.LstdFlags), 6), | ||||
| 		lastUpdateTime: time.Now(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (m *modem) Init() error { | ||||
| 	// Turn module on | ||||
| 	log.Println("=============================== Turn on module") | ||||
| 	m.logger.Println("=============================== Turn on module") | ||||
| 	if err := m.onOffPin.Init(); err != nil { | ||||
| 		return fmt.Errorf("gpio pin init: %w", err) | ||||
| 	} | ||||
| @@ -88,6 +94,13 @@ func (m *modem) Init() error { | ||||
| 	if err := m.testGPS(); err != nil { | ||||
| 		return fmt.Errorf("testGPS: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Establish internet connection | ||||
| 	m.logger.Println("=============================== Internet") | ||||
| 	m.ic = internet.New(log.New(m.logger.Writer(), "internet", log.LstdFlags), m.port) | ||||
| 	if err := m.Init(); err != nil { | ||||
| 		return fmt.Errorf("internet connection init: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -145,23 +158,27 @@ func (m *modem) GetInfo() ModemData { | ||||
| func (m *modem) Close() error { | ||||
| 	// Not right way I think | ||||
| 	if err := m.port.Close(); err != nil { | ||||
| 		return err | ||||
| 		return fmt.Errorf("serial port: %w", err) | ||||
| 	} | ||||
| 	if err := m.onOffPin.Close(); err != nil { | ||||
| 		return err | ||||
| 		return fmt.Errorf("gpio pin: %w", err) | ||||
| 	} | ||||
| 	if err := m.ic.Close(); err != nil { | ||||
| 		return fmt.Errorf("internet connection: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *modem) connect() error { | ||||
| 	if !m.Validate() { | ||||
| 	if m.port == nil { | ||||
| 		return fmt.Errorf("port is not defined") | ||||
| 	} | ||||
| 	return m.port.Connect() | ||||
| } | ||||
|  | ||||
| func (m *modem) disconnect() error { | ||||
| 	if !m.Validate() { | ||||
| 	if m.port == nil { | ||||
| 		return fmt.Errorf("port is not defined") | ||||
| 	} | ||||
| 	return m.port.Disconnect() | ||||
| @@ -218,8 +235,8 @@ func (m *modem) testConsole() { | ||||
| 		if err != nil { | ||||
| 			m.logger.Println("ERROR:", err.Error()) | ||||
| 		} | ||||
| 		log.Println(resp) | ||||
| 		log.Println("------------------") | ||||
| 		m.logger.Println(resp) | ||||
| 		m.logger.Println("------------------") | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user