Added draft SMS support.
This commit is contained in:
		| @@ -15,3 +15,7 @@ func (resp Resp) RmFront(str string) Resp { | ||||
| func (resp Resp) String() string { | ||||
| 	return string(resp) | ||||
| } | ||||
|  | ||||
| func (resp Resp) Bytes() []byte { | ||||
| 	return []byte(resp) | ||||
| } | ||||
|   | ||||
| @@ -37,6 +37,7 @@ func (gps *GpsData) calculateSpeed(newLatitude, newLongitude float64, lastUpdate | ||||
| 	gps.Speed = earthRad * c / (math.Abs(float64(time.Since(lastUpdateTime)))) | ||||
| } | ||||
|  | ||||
| // Parse string from AT command that contains gps data | ||||
| func (gps *GpsData) decode(str string) error { | ||||
| 	var err error | ||||
| 	newGpsInfo := GpsData{} | ||||
|   | ||||
| @@ -90,9 +90,9 @@ func (c *conn) checkReqs() error { | ||||
| 	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) | ||||
| 	} | ||||
| 	// 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 | ||||
|   | ||||
							
								
								
									
										69
									
								
								api/modem/sms/errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								api/modem/sms/errors.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| package sms | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| ) | ||||
|  | ||||
| func DecodeError(code int) string { | ||||
| 	switch code { | ||||
| 	case 300: | ||||
| 		return "ME failure" | ||||
| 	case 301: | ||||
| 		return "SMS service of ME reserved" | ||||
| 	case 302: | ||||
| 		return "Operation not allowed" | ||||
| 	case 303: | ||||
| 		return "Operation not supported" | ||||
| 	case 304: | ||||
| 		return "Invalid PDU mode parameter" | ||||
| 	case 305: | ||||
| 		return "Invalid text mode parameter" | ||||
| 	case 310: | ||||
| 		return "SIM not inserted" | ||||
| 	case 311: | ||||
| 		return "SIM PIN required" | ||||
| 	case 312: | ||||
| 		return "PH-SIM PIN required" | ||||
| 	case 313: | ||||
| 		return "SIM failure" | ||||
| 	case 314: | ||||
| 		return "SIM busy" | ||||
| 	case 315: | ||||
| 		return "SIM wrong" | ||||
| 	case 316: | ||||
| 		return "SIM PUK required" | ||||
| 	case 317: | ||||
| 		return "SIM PIN2 required" | ||||
| 	case 318: | ||||
| 		return "SIM PUK2 required" | ||||
| 	case 320: | ||||
| 		return "Memory failure" | ||||
| 	case 321: | ||||
| 		return "Invalid memory index" | ||||
| 	case 322: | ||||
| 		return "Memory full" | ||||
| 	case 330: | ||||
| 		return "SMSC address unknown" | ||||
| 	case 331: | ||||
| 		return "No network service" | ||||
| 	case 332: | ||||
| 		return "Network timeout" | ||||
| 	case 340: | ||||
| 		return "NO +CNMA ACK EXPECTED" | ||||
| 	case 341: | ||||
| 		return "Buffer overflow" | ||||
| 	case 342: | ||||
| 		return "SMS size more than expected" | ||||
| 	case 500: | ||||
| 		return "Unknown error" | ||||
| 	} | ||||
| 	return "UNDEFINED ERROR CODE" | ||||
| } | ||||
|  | ||||
| func GetError(msg []byte) (int, error) { | ||||
| 	if len(msg) >= len("+CMS ERROR: ")+3 && string(msg[:len("+CMS ERROR: ")]) == "+CMS ERROR: " { | ||||
| 		return strconv.Atoi(string(msg[len("+CMS ERROR: ") : len("+CMS ERROR: ")+3])) | ||||
| 	} | ||||
| 	return 0, fmt.Errorf("failed to parse error") | ||||
| } | ||||
							
								
								
									
										61
									
								
								api/modem/sms/sms.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								api/modem/sms/sms.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| package sms | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"log" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/CGSG-2021-AE4/modem-test/api/modem/at" | ||||
| ) | ||||
|  | ||||
| type dialer struct { | ||||
| 	logger *log.Logger | ||||
| 	port   at.Port | ||||
| } | ||||
|  | ||||
| type Dialer interface { | ||||
| 	Init() error | ||||
| 	Send(number, msg string) error | ||||
| 	ReadNew() ([]string, error) | ||||
| 	io.Closer | ||||
| } | ||||
|  | ||||
| func (d *dialer) Init() error { | ||||
| 	// Ensure serial port | ||||
| 	if !d.port.IsConnected() { | ||||
| 		return fmt.Errorf("serial port is not connected") | ||||
| 	} | ||||
| 	// Ensure text format | ||||
| 	if resp, err := d.port.Send("AT+CMGF=1"); err != nil || !resp.Check() { | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("AT+CMGF=1 request: %w", err) | ||||
| 		} | ||||
| 		return fmt.Errorf("failed to set SMS format") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (d *dialer) Send(number, msg string) error { | ||||
| 	cmd := fmt.Sprintf("AT+CMGS=\"%s\"\r%s%c", number, msg, 26) | ||||
| 	if resp, err := d.port.Send(cmd); err != nil || !resp.Check() { | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("AT+CGMS= request: %w", err) | ||||
| 		} | ||||
| 		if errCode, err := GetError(resp.Bytes()); err != nil { | ||||
| 			return fmt.Errorf("failed to send with SMS error: %s", DecodeError(errCode)) | ||||
| 		} | ||||
| 		return fmt.Errorf("failed to send SMS") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Reads all new messages | ||||
| func (d *dialer) ReadNew() ([]string, error) { | ||||
| 	resp, err := d.port.Send("AT+CMGL") | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("AT+CMGL request: %w", err) | ||||
| 	} | ||||
| 	msgs := strings.Split(strings.Replace(string(resp), "\r", "", -1), "\n") | ||||
| 	return msgs, nil // TODO | ||||
| } | ||||
		Reference in New Issue
	
	Block a user