Exemple #1
0
// Init invokes a set of methods that will make the initial setup of the modem.
func (p *DefaultProfile) Init(d *Device) (err error) {
	p.dev = d
	p.dev.Send(NoopCmd) // kinda flush
	if err = p.COPS(true, true); err != nil {
		return errors.New("at init: unable to adjust the format of operator's name")
	}
	var info *SystemInfoReport
	if info, err = p.SYSINFO(); err != nil {
		return errors.New("at init: unable to read system info")
	}
	p.dev.State = &DeviceState{
		ServiceState:  info.ServiceState,
		ServiceDomain: info.ServiceDomain,
		RoamingState:  info.RoamingState,
		SystemMode:    info.SystemMode,
		SystemSubmode: info.SystemSubmode,
		SimState:      info.SimState,
	}
	if p.dev.State.OperatorName, err = p.OperatorName(); err != nil {
		return errors.New("at init: unable to read operator's name")
	}
	if p.dev.State.ModelName, err = p.ModelName(); err != nil {
		return errors.New("at init: unable to read modem's model name")
	}
	if p.dev.State.IMEI, err = p.IMEI(); err != nil {
		return errors.New("at init: unable to read modem's IMEI code")
	}
	if err = p.CMGF(false); err != nil {
		return errors.New("at init: unable to switch message format to PDU")
	}
	if err = p.CPMS(MemoryTypes.NvRAM, MemoryTypes.NvRAM, MemoryTypes.NvRAM); err != nil {
		return errors.New("at init: unable to set messages storage")
	}
	if err = p.CNMI(1, 1, 0, 0, 0); err != nil {
		return errors.New("at init: unable to turn on message notifications")
	}
	var octets map[uint64][]byte
	if octets, err = p.CMGL(MessageFlags.Any); err != nil {
		return errors.New("at init: unable to check message inbox")
	}
	for n, oct := range octets {
		var msg sms.Message
		if _, err := msg.ReadFrom(oct); err != nil {
			return errors.New("at init: error while parsing message inbox")
		}
		if err := p.CMGD(n, DeleteOptions.Index); err != nil {
			return errors.New("at init: error while cleaning message inbox")
		}
		d.messages <- &msg
	}
	return nil
}
Exemple #2
0
// 处理短信PUD字符串.
// s 串口接收到的PDU字符串.
func (g *Gsm) handleSMS(s string) {
	b, err := hex.DecodeString(s)
	if nil != err {
		g.mLogger.Error(`GSMSMS: Decode sms hex string error "%v"`, err)
		return
	}

	var msg sms.Message
	_, err = msg.ReadFrom(b)
	if err != nil {
		g.mLogger.Error(`GSMSMS: Decode sms message error "%v"`, err)
		return
	}

	select {
	case g.mChanSMS <- &msg:
	default:
		g.mLogger.Debug(`GSMSMS: Drop [%v]"%v"`, string(msg.Address), msg.Text)
	}
}
Exemple #3
0
// 发送短信.
// num 接收者的号码.
// msg 需要发送的短信内容.
// return 错误; ==nil 发送正常.
func (g *Gsm) SendSMS(num, msg string) error {
	g.mMutex.Lock()
	defer g.mMutex.Unlock()
	if _, err := g.atcmd("AT", "OK", time.Millisecond*250); nil != err {
		return err
	}

	s := sms.Message{
		Encoding: sms.Encodings.Gsm7Bit,
		Text:     msg,
		Address:  sms.PhoneNumber(num),
		VP:       sms.ValidityPeriod(time.Hour * 24 * 4),
		VPFormat: sms.ValidityPeriodFormats.Relative,
		Type:     sms.MessageTypes.Submit,
	}

	if len(msg) != len([]rune(msg)) {
		s.Encoding = sms.Encodings.UCS2
	}

	n, octets, err := s.PDU()

	if err != nil {
		return err
	}

	cmd := fmt.Sprintf("AT+CMGS=%d", n)
	if _, err := g.atcmd(cmd, "", time.Millisecond*300); nil != err {
		return err
	}

	buf := make([]byte, hex.EncodedLen(len(octets))+1)
	n = hex.Encode(buf, octets)
	buf[n] = 0x1A

	if _, err := g.mPort.Write(buf); nil != err {
		return err
	}
	_, err = g.atcmd("", "OK", time.Second*10)
	return err
}
Exemple #4
0
// SendSMS sends an SMS message with given text to the given address,
// the encoding and other parameters are default.
func (d *Device) SendSMS(text string, address sms.PhoneNumber) (err error) {
	msg := sms.Message{
		Text:     text,
		Type:     sms.MessageTypes.Submit,
		Encoding: sms.Encodings.Gsm7Bit,
		Address:  address,
		VPFormat: sms.ValidityPeriodFormats.Relative,
		VP:       sms.ValidityPeriod(24 * time.Hour * 4),
	}
	for _, w := range text {
		// detected a double-width char
		if w > 1 {
			msg.Encoding = sms.Encodings.UCS2
			break
		}
	}
	n, octets, err := msg.PDU()
	if err != nil {
		return err
	}
	err = d.Commands.CMGS(n, octets)
	return
}
Exemple #5
0
// handleReport detects and parses a report from the notification port represented
// as a string. The parsed values may change the inner state or be sent over out channels.
func (d *Device) handleReport(str string) (err error) {
	report := Reports.Resolve(str)
	str = strings.TrimSpace(strings.TrimPrefix(str, report.ID))
	switch report {
	case Reports.Message:
		var report messageReport
		if err = report.Parse(str); err != nil {
			return
		}
		var octets []byte
		octets, err = d.Commands.CMGR(report.Index)
		if err != nil {
			return
		}
		if err = d.Commands.CMGD(report.Index, DeleteOptions.Index); err != nil {
			return
		}
		var msg sms.Message
		if _, err = msg.ReadFrom(octets); err != nil {
			return
		}
		d.messages <- &msg
	case Reports.Ussd:
		var ussd ussdReport
		if err = ussd.Parse(str); err != nil {
			return
		}
		var text string
		if ussd.Enc == Encodings.UCS2 {
			text, err = pdu.DecodeUcs2(ussd.Octets)
			if err != nil {
				return
			}
		} else if ussd.Enc == Encodings.Gsm7Bit {
			text, err = pdu.Decode7Bit(ussd.Octets)
			if err != nil {
				return
			}
		} else {
			return ErrUnknownEncoding
		}
		d.ussd <- Ussd(text)
	case Reports.SignalStrength:
		var rssi signalStrengthReport
		if err = rssi.Parse(str); err != nil {
			return
		}
		if d.State.SignalStrength != int(rssi) {
			d.State.SignalStrength = int(rssi)
			d.updated <- struct{}{}
		}
	case Reports.Mode:
		var report modeReport
		if err = report.Parse(str); err != nil {
			return
		}
		var updated bool
		if d.State.SystemMode != report.Mode {
			d.State.SystemMode = report.Mode
			updated = true
		}
		if d.State.SystemSubmode != report.Submode {
			d.State.SystemSubmode = report.Submode
			updated = true
		}
		if updated {
			d.updated <- struct{}{}
		}
	case Reports.ServiceState:
		var report serviceStateReport
		if err = report.Parse(str); err != nil {
			return
		}
		if d.State.ServiceState != Opt(report) {
			d.State.ServiceState = Opt(report)
			d.updated <- struct{}{}
		}
	case Reports.SimState:
		var report simStateReport
		if err = report.Parse(str); err != nil {
			return
		}
		if d.State.SimState != Opt(report) {
			d.State.SimState = Opt(report)
			d.updated <- struct{}{}
		}
	case Reports.BootHandshake:
		var token bootHandshakeReport
		if err = token.Parse(str); err != nil {
			return
		}
		if err = d.Commands.BOOT(uint64(token)); err != nil {
			return
		}
	case Reports.Stin:
		// ignore. what is this btw?
	default:
		switch FinalResults.Resolve(str) {
		case FinalResults.Noop, FinalResults.NotSupported, FinalResults.Timeout:
			// ignore
		default:
			return errors.New("at: unknown report: " + str)
		}
	}
	return
}