package reset import ( "crypto/tls" "fmt" "math/rand" "net/http" "github.com/tiaguinho/gosoap" "src.dualinventive.com/go/cp3000-interface/internal/storage" "src.dualinventive.com/go/dinet" "src.dualinventive.com/go/dinet/ditime" "src.dualinventive.com/go/dinet/rpc" ) const ( vodafoneM2MResetMethod = "submitSMSv2" vodafoneM2MSuccessMajorCode = "000" resetCommand = "RElKQkxQIE1DVS1TVEFUVVMgMkNGRkZGNzE1MA==" ) // Reset contains helper functions for resetting CP3000 devices type Reset struct { vodafoneM2MSoapClient *gosoap.Client messagingProxy dinet.ReadWriter } // New creates a new Reset struct which contains helper functions for resetting CP3000 devices func New(certFile, keyFile, wsdlFile, userID, password string, msgProxyConn dinet.ReadWriter) (*Reset, error) { tlsConfig, err := resetM2MTlsConfig(certFile, keyFile) if err != nil { return nil, err } transport := &http.Transport{TLSClientConfig: tlsConfig} httpClient := &http.Client{Transport: transport} soap, err := gosoap.SoapClient(wsdlFile) if err != nil { return nil, err } soap.HttpClient = httpClient soap.HeaderName = "m:gdspHeader" soap.HeaderParams = gosoap.HeaderParams{ gosoap.Param{ Key: "gdspCredentials", Value: gosoap.HeaderParams{ gosoap.Param{Key: "userId", Value: userID}, gosoap.Param{Key: "password", Value: password}, }, }, } return &Reset{ vodafoneM2MSoapClient: soap, messagingProxy: msgProxyConn, }, nil } func resetM2MTlsConfig(certFile, keyFile string) (*tls.Config, error) { cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return nil, err } tlsConfig := &tls.Config{ Certificates: []tls.Certificate{cert}, } tlsConfig.BuildNameToCertificate() return tlsConfig, nil } // Reset will reset a CP3000 device using the Vodafone m2m platform or via a reset SMS func (r *Reset) Reset(d *storage.Device) error { if d.VodafoneM2mAPIEnabled() { return r.ResetM2M(d.IMSI) } deviceUID, err := d.DeviceUID() if err != nil { return err } return r.ResetSMS(deviceUID, d.TelephoneNR) } // ResetSMS will reset a CP3000 device using a reset SMS func (r *Reset) ResetSMS(deviceUID, telephoneNR string) error { err := r.messagingProxy.Send(&rpc.Msg{ Dinetrpc: rpc.CurrentDinetrpc, ID: rand.Uint32(), Time: ditime.Now(), DeviceUID: deviceUID, ClassMethod: rpc.ClassMethodMessageSms, Type: rpc.MsgTypeRequest, Params: rpc.NewParams([]rpc.MessageSms{ { Destinations: []string{ telephoneNR, }, Message: resetCommand, }, }), }) if err != nil { return err } reply, err := r.messagingProxy.Recv() if err != nil { return err } if reply.Error != nil { return reply.Error } return nil } // ResetM2M will reset a CP3000 device using the Vodafone m2m platform func (r *Reset) ResetM2M(imsi string) error { params := gosoap.Params{ gosoap.Param{Key: "deviceId", Value: imsi}, gosoap.Param{Key: "sourceId", Value: "310000206"}, gosoap.Param{Key: "messageData", Value: resetCommand}, gosoap.Param{Key: "messageType", Value: "Text"}, gosoap.Param{Key: "messageUDH", Value: "N"}, gosoap.Param{Key: "priority", Value: "3"}, gosoap.Param{Key: "validityPeriod", Value: "000100000000000R"}, gosoap.Param{Key: "replaceIfPresent", Value: "N"}, } if err := r.vodafoneM2MSoapClient.Call(vodafoneM2MResetMethod, params); err != nil { return err } var res SoapReturnValue if err := r.vodafoneM2MSoapClient.Unmarshal(&res); err != nil { return err } if !res.IsError() { return nil } return res } // SoapReturnValue contains the data that the Vodafone soap API is returning type SoapReturnValue struct { MajorReturnCode string `xml:"return>returnCode>majorReturnCode"` MinorReturnCode string `xml:"return>returnCode>minorReturnCode"` } // IsError returns true when the soap return value should be threaded as an error func (s SoapReturnValue) IsError() bool { return s.MajorReturnCode != vodafoneM2MSuccessMajorCode } // Error returns a descriptive error message func (s SoapReturnValue) Error() string { return fmt.Sprintf("soap error: %s:%s", s.MajorReturnCode, s.MinorReturnCode) }