func GetBalance(ussdRequest string) (float64, error) { log.Println("GetBalance...") //re-set encoding here? //m.SendCommand("AT+CSCS=\"GSM\"\r", true) //TODO: Is it necessery to run AT+CMGF=0 ??? SendCommand("AT+CMGF=0\r", true) SendCommand("AT^USSDMODE=1\r", true) request := strings.ToUpper(fmt.Sprintf("%x", pdu.Encode7Bit(ussdRequest))) _, err = SendCommand(fmt.Sprintf("AT+CUSD=1,\"%s\",15\r", request), true) if err != nil { return 0.0, err } status, err := WaitForOutput(10, "15\r\n") regex := regexp.MustCompile(`\+CUSD: \d{1},\"([a-zA-Z0-9]*)\",\d*`) if regex.MatchString(status) { balanceRaw := regex.FindStringSubmatch(status)[1] bytesWritten, _ := hex.DecodeString(balanceRaw) log.Println("Before decode", bytesWritten) balanceRaw, _ = pdu.Decode7Bit(bytesWritten) log.Println("After decode", balanceRaw) balanceParsed := regexp.MustCompile(`\d+\.\d+`).FindString(balanceRaw) if balanceParsed == "" { return 0.0, fmt.Errorf("GetBalance: Failed to find balance string in \"%s\"", balanceRaw) } balance, err := strconv.ParseFloat(balanceParsed, 64) if err != nil { return 0.0, fmt.Errorf("GetBalance: Failed to convert to float64 \"%s\"", balanceRaw) } return balance, nil } if err != nil { return 0.0, err } return 0.0, errors.New("GetBalace: Failed to get balance.") }
// Encode converts the query string into bytes according to the // specified encoding. func (u *Ussd) Encode(enc Encoding) ([]byte, error) { switch enc { case Encodings.Gsm7Bit: return pdu.Encode7Bit(u.String()), nil case Encodings.UCS2: return pdu.EncodeUcs2(u.String()), nil default: return nil, ErrUnknownEncoding } }
// Test USSD queries, the result will be reported asynchroniously. func TestUssd(t *testing.T) { err := openDevice() if !assert.NoError(t, err) { return } defer func() { dev.Close() }() err = dev.Commands.CUSD(UssdResultReporting.Enable, pdu.Encode7Bit(BalanceUSSD), Encodings.Gsm7Bit) if !assert.NoError(t, err) { return } waitDevice(10) }
// SendUSSD sends an USSD request, the encoding and other parameters are default. func (d *Device) SendUSSD(req string) (err error) { err = d.Commands.CUSD(UssdResultReporting.Enable, pdu.Encode7Bit(req), Encodings.Gsm7Bit) return }
// PDU serializes the message into octets ready to be transferred. // Returns the number of TPDU bytes in the produced PDU. // Complies with 3GPP TS 23.040. func (s *Message) PDU() (int, []byte, error) { var buf bytes.Buffer if len(s.ServiceCenterAddress) < 1 { buf.WriteByte(0x00) // SMSC info length } else { _, octets, err := s.ServiceCenterAddress.PDU() if err != nil { return 0, nil, err } buf.WriteByte(byte(len(octets))) buf.Write(octets) } switch s.Type { case MessageTypes.Deliver: var sms smsDeliver sms.MessageTypeIndicator = byte(s.Type) sms.MoreMessagesToSend = s.MoreMessagesToSend sms.LoopPrevention = s.LoopPrevention sms.ReplyPath = s.ReplyPathExists sms.UserDataHeaderIndicator = s.UserDataStartsWithHeader sms.StatusReportIndication = s.StatusReportIndication addrLen, addr, err := s.Address.PDU() if err != nil { return 0, nil, err } var addrBuf bytes.Buffer addrBuf.WriteByte(byte(addrLen)) addrBuf.Write(addr) sms.OriginatingAddress = addrBuf.Bytes() sms.ProtocolIdentifier = 0x00 // Short Message Type 0 sms.DataCodingScheme = byte(s.Encoding) sms.ServiceCentreTimestamp = s.ServiceCenterTime.PDU() var userData []byte if s.Encoding == Encodings.Gsm7Bit { userData = pdu.Encode7Bit(s.Text) sms.UserDataLength = byte(len(s.Text)) } else if s.Encoding == Encodings.UCS2 { userData = pdu.EncodeUcs2(s.Text) sms.UserDataLength = byte(len(userData)) } else { return 0, nil, ErrUnknownEncoding } sms.UserDataLength = byte(len(userData)) sms.UserData = userData n, err := buf.Write(sms.Bytes()) if err != nil { return 0, nil, err } return n, buf.Bytes(), nil case MessageTypes.Submit: var sms smsSubmit sms.MessageTypeIndicator = byte(s.Type) sms.RejectDuplicates = s.RejectDuplicates sms.ValidityPeriodFormat = byte(s.VPFormat) sms.ReplyPath = s.ReplyPathExists sms.UserDataHeaderIndicator = s.UserDataStartsWithHeader sms.StatusReportRequest = s.StatusReportRequest sms.MessageReference = s.MessageReference addrLen, addr, err := s.Address.PDU() if err != nil { return 0, nil, err } var addrBuf bytes.Buffer addrBuf.WriteByte(byte(addrLen)) addrBuf.Write(addr) sms.DestinationAddress = addrBuf.Bytes() sms.ProtocolIdentifier = 0x00 // Short Message Type 0 sms.DataCodingScheme = byte(s.Encoding) switch s.VPFormat { case ValidityPeriodFormats.Relative: sms.ValidityPeriod = byte(s.VP.Octet()) case ValidityPeriodFormats.Absolute, ValidityPeriodFormats.Enhanced: return 0, nil, ErrNonRelative } var userData []byte if s.Encoding == Encodings.Gsm7Bit { userData = pdu.Encode7Bit(s.Text) sms.UserDataLength = byte(len(s.Text)) } else if s.Encoding == Encodings.UCS2 { userData = pdu.EncodeUcs2(s.Text) sms.UserDataLength = byte(len(userData)) } else { return 0, nil, ErrUnknownEncoding } sms.UserData = userData n, err := buf.Write(sms.Bytes()) if err != nil { return 0, nil, err } return n, buf.Bytes(), nil default: return 0, nil, ErrUnknownMessageType } }
// Gsm7Bit encodes USSD query into GSM 7-Bit packed octets. func (u USSD) Gsm7Bit() []byte { return pdu.Encode7Bit(string(u)) }