Skip to content

Commit 2a17701

Browse files
committed
Untested basic driver for 8810ft completed
1 parent 4a464aa commit 2a17701

File tree

4 files changed

+198
-22
lines changed

4 files changed

+198
-22
lines changed

drivers/8810ft.go

Lines changed: 150 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,64 @@
11
package drivers
22

3-
43
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
57
"net/http"
8+
"net/url"
9+
"strconv"
10+
"time"
611
)
712

813
// DO NOT USE DIRECTLY
9-
type zte8810ft struct {
10-
TargetIP string
11-
basePath string
12-
}
14+
type (
15+
zte8810ft struct {
16+
ip string
17+
basePath string
18+
}
19+
20+
result struct {
21+
Result string `json:"result"`
22+
}
23+
24+
pppConnected struct {
25+
Connected string `json:"ppp_connected"`
26+
}
27+
)
28+
29+
var httpClient *http.Client
1330

1431
func init() {
15-
registerModel("8810FT", newZTE8810FT)
32+
httpClient = &http.Client{Timeout: time.Second * 10}
33+
registerDriver("ZTE 8810FT", newZTE8810FT)
1634
}
1735

1836
func newZTE8810FT(ip string) BaseModem {
19-
return &zte8810ft{TargetIP: ip, basePath: "/goform/goform_set_cmd_process"}
37+
return &zte8810ft{ip: ip, basePath: "/goform/goform_set_cmd_process"}
38+
}
39+
40+
func (m *zte8810ft) getBaseURL(path string) *url.URL {
41+
return &url.URL{Scheme: "https", Host: m.ip, Path: path}
42+
}
43+
44+
func (m *zte8810ft) getNewRequest(method string, url *url.URL) *http.Request {
45+
return &http.Request{
46+
Proto: "HTTP/1.1",
47+
Method: method,
48+
URL: url,
49+
Header: http.Header{
50+
"Referer": {fmt.Sprintf("http://%s/index.html", m.ip)},
51+
},
52+
}
2053
}
2154

2255
func (m *zte8810ft) SetTargetIP(ip string) error {
23-
m.TargetIP = ip
56+
m.ip = ip
2457
return nil
2558
}
2659

2760
func (m *zte8810ft) GetTargetIP() string {
28-
return m.TargetIP
61+
return m.ip
2962
}
3063

3164
func (m *zte8810ft) GetModel() string {
@@ -34,17 +67,123 @@ func (m *zte8810ft) GetModel() string {
3467

3568
func (m *zte8810ft) ConnectCell() error {
3669
// GET /goform/goform_set_cmd_process?goformId=CONNECT_NETWORK
70+
// Prepare everything to make a request
71+
u := m.getBaseURL("/goform/goform_set_cmd_process")
72+
query := u.Query()
73+
query.Add("goformId", "CONNECT_NETWORK")
74+
u.RawQuery = query.Encode()
75+
request := m.getNewRequest("GET", u)
76+
77+
resp, err := httpClient.Do(request)
78+
79+
// Process errors
80+
switch {
81+
case err != nil:
82+
return ActionError{Action: "connect", Err: err}
83+
case resp.StatusCode != 200:
84+
return ActionError{Action: "connect", Err: fmt.Errorf("response status %d", resp.StatusCode)}
85+
}
86+
87+
// Read the response
88+
defer resp.Body.Close()
89+
body, err := io.ReadAll(resp.Body)
90+
if err != nil {
91+
return ErrUnknown
92+
}
93+
94+
result := new(result)
95+
if err := json.Unmarshal(body, result); err != nil {
96+
return ActionError{Action: "connect", Err: UnmarshalError{RawData: &body, Err: err}}
97+
}
98+
99+
if result.Result != "success" {
100+
return ActionError{Action: "connect", Err: fmt.Errorf("result: %s", result.Result)}
101+
}
102+
37103
return nil
38104
}
39105

40106
func (m *zte8810ft) DisconnectCell() error {
41107
// GET /goform/goform_set_cmd_process?goformId=DISCONNECT_NETWORK
108+
// Prepare everything to make a request
109+
u := m.getBaseURL("/goform/goform_set_cmd_process")
110+
query := u.Query()
111+
query.Add("goformId", "DISCONNECT_NETWORK")
112+
u.RawQuery = query.Encode()
113+
request := m.getNewRequest("GET", u)
114+
115+
resp, err := httpClient.Do(request)
116+
117+
// Process errors
118+
switch {
119+
case err != nil:
120+
return ActionError{Action: "disconnect", Err: err}
121+
case resp.StatusCode != 200:
122+
return ActionError{Action: "disconnect", Err: fmt.Errorf("response status %d", resp.StatusCode)}
123+
}
124+
125+
// Read the response
126+
defer resp.Body.Close()
127+
body, err := io.ReadAll(resp.Body)
128+
if err != nil {
129+
return ErrUnknown
130+
}
131+
132+
result := new(result)
133+
if err := json.Unmarshal(body, result); err != nil {
134+
return ActionError{Action: "disconnect", Err: UnmarshalError{RawData: &body, Err: err}}
135+
}
136+
137+
if result.Result != "success" {
138+
return ActionError{Action: "disconnect", Err: fmt.Errorf("result: %s", result.Result)}
139+
}
140+
42141
return nil
43142
}
44143

45144
func (m *zte8810ft) GetCellConnStatus() (bool, error) {
46145
// Lines 251-258
47-
resp, err := http.Get()
48146
// /goform/goform_get_cmd_process?isTest=False&cmd=ppp_connected,multi_data=1&sms_received_flag_flag=0&sts_received_flag_flag=0&_=<curr_time>
49-
return false, nil
147+
148+
// Build URL
149+
u := m.getBaseURL("/goform/goform_get_cmd_process")
150+
query := u.Query()
151+
query.Add("isTest", "False")
152+
query.Add("cmd", "ppp_connected")
153+
query.Add("multi_data", "1")
154+
query.Add("sms_received_flag_flag", "0")
155+
query.Add("sts_received_flag_flag", "0")
156+
query.Add("_", strconv.FormatInt((time.Now().UnixMilli)(), 10))
157+
u.RawQuery = query.Encode()
158+
159+
request := m.getNewRequest("POST", u)
160+
161+
resp, err := httpClient.Do(request)
162+
163+
// Process errors
164+
switch {
165+
case err != nil:
166+
return false, ActionError{Action: "status", Err: err}
167+
case resp.StatusCode != 200:
168+
return false, ActionError{Action: "status", Err: fmt.Errorf("response status %d", resp.StatusCode)}
169+
}
170+
171+
// Read the response
172+
defer resp.Body.Close()
173+
body, err := io.ReadAll(resp.Body)
174+
if err != nil {
175+
return false, ErrUnknown
176+
}
177+
178+
result := new(pppConnected)
179+
if err := json.Unmarshal(body, result); err != nil {
180+
return false, ActionError{Action: "status", Err: UnmarshalError{RawData: &body, Err: err}}
181+
}
182+
183+
// Process the result
184+
if result.Connected != "ppp_connected" {
185+
return false, nil
186+
}
187+
188+
return true, nil
50189
}

drivers/common.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,32 +28,40 @@ type ModemSMS interface {
2828
GetAllSMS() ([]SMS, error)
2929
}
3030

31-
var models map[string]func(ip string) BaseModem = map[string]func(ip string) BaseModem{}
31+
var drivers map[string]func(ip string) BaseModem = map[string]func(ip string) BaseModem{}
3232

3333
func isRegistered(name string) bool {
34-
// Check if model has already been registered
35-
_, ok := models[name]
34+
// Check if driver has already been registered
35+
_, ok := drivers[name]
3636
return ok
3737
}
3838

39-
func registerModel(name string, generator func(ip string) BaseModem) {
40-
// Check if model has already been registered
39+
func registerDriver(name string, generator func(ip string) BaseModem) {
40+
// Check if driver has already been registered
4141
if isRegistered(name) {
4242
panic(fmt.Sprintf("attempted to register %s twice", name))
4343
}
4444

45-
// Register the model
46-
models[name] = generator
45+
// Register the driver
46+
drivers[name] = generator
4747
}
4848

4949
func GetModemDriver(model string, ip string) (BaseModem, error) {
5050
if !isRegistered(model) {
5151
return nil, ErrUnknownModel
5252
}
5353

54-
return models[model](ip), nil
54+
return drivers[model](ip), nil
5555
}
5656

5757
func GetAvailableDrivers() *[]string {
58-
return nil
58+
keys := make([]string, len(drivers))
59+
60+
i := 0
61+
for k := range drivers {
62+
keys[i] = k
63+
i++
64+
}
65+
66+
return &keys
5967
}

drivers/errors.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,36 @@ package drivers
22

33
import (
44
"errors"
5+
"fmt"
56
)
67

78
// Basic Errors
89
var ErrUnknownModel = errors.New("attempting to get unknown model")
10+
var ErrUnknown = errors.New("unknown error")
11+
12+
// Complex Errors
13+
type ActionError struct {
14+
Action string
15+
Err error
16+
}
17+
18+
func (e ActionError) Unwrap() error {
19+
return e.Err
20+
}
21+
22+
func (e ActionError) Error() string {
23+
return fmt.Sprintf("action error: %s failed with %e", e.Action, e.Err)
24+
}
25+
26+
type UnmarshalError struct {
27+
RawData *[]byte
28+
Err error
29+
}
30+
31+
func (e UnmarshalError) Unwrap() error {
32+
return e.Err
33+
}
34+
35+
func (e UnmarshalError) Error() string {
36+
return "failed to unmarshal response"
37+
}

main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414

1515
type SMSArgs struct {
1616
Action string `arg:""`
17-
PhoneNumber string `arg:"-n" help:"Recievers"`
17+
PhoneNumber string `arg:"-n" help:"Receiver's phone number"`
1818
Message string `arg:"-m"`
1919
}
2020

@@ -66,7 +66,7 @@ func run() error {
6666

6767
if err != nil {
6868
fmt.Println("Failed to get connection status")
69-
return
69+
return
7070
}
7171
if isConnected {
7272
fmt.Println("Status: up")

0 commit comments

Comments
 (0)