You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
3.7 KiB
154 lines
3.7 KiB
package sdb
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type IridiumSDB struct {
|
|
ProtocolRevision byte
|
|
Length uint16
|
|
Elements []interface{}
|
|
}
|
|
|
|
type MOHeader struct {
|
|
IEI byte
|
|
Length uint16
|
|
CDRReference uint32
|
|
IMEI [15]byte
|
|
Status byte
|
|
MOMSN uint16
|
|
MTMSN uint16
|
|
TimeSession uint32
|
|
}
|
|
|
|
func (h MOHeader) SessionTime() time.Time {
|
|
return time.Unix(int64(h.TimeSession), 0)
|
|
}
|
|
|
|
func (h MOHeader) StatusString() string {
|
|
switch h.Status {
|
|
case 0:
|
|
return "The SBD session completed successfully."
|
|
case 1:
|
|
return "The MO message transfer, if any, was successful. The MT message queued at the Iridium Gateway is too large to be transferred within a single SBD session."
|
|
case 2:
|
|
return "The MO message transfer, if any, was successful. The reported location was determined to be of unacceptable quality. This value is only applicable to IMEIs using SBD protocol revision 1."
|
|
case 10:
|
|
return "The SBD session timed out before session completion."
|
|
case 12:
|
|
return "The MO message being transferred by the IMEI is too large to be transferred within a single SBD session."
|
|
case 13:
|
|
return "An RF link loss occurred during the SBD session."
|
|
case 14:
|
|
return "An IMEI protocol anomaly occurred during SBD session."
|
|
case 15:
|
|
return "The IMEI is prohibited from accessing the Iridium Gateway."
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
type MOPayload struct {
|
|
IEI byte
|
|
Length uint16
|
|
Payload []byte
|
|
}
|
|
|
|
type MOLocation struct {
|
|
IEI byte
|
|
Length uint16
|
|
LocationFlags byte
|
|
LatitudeDegrees uint8
|
|
LatitudeTHMinute uint16
|
|
LongitudeDegrees uint8
|
|
LongitudeTHMinute uint16
|
|
CEPRadius uint32
|
|
}
|
|
|
|
type MOConfirmation struct {
|
|
IEI byte
|
|
Length uint16
|
|
Status byte
|
|
}
|
|
|
|
func ParseSDB(raw []byte) (*IridiumSDB, error) {
|
|
raw_len := len(raw)
|
|
if raw_len < 3 {
|
|
return nil, fmt.Errorf("message structure too short: %d bytes",
|
|
len(raw))
|
|
}
|
|
|
|
sdb := IridiumSDB{}
|
|
sdb.ProtocolRevision = raw[0]
|
|
sdb.Length = binary.BigEndian.Uint16(raw[1:3])
|
|
|
|
if (int(sdb.Length) + 3) != raw_len {
|
|
return nil, fmt.Errorf("invalid message length (expected %d, got %d)",
|
|
(sdb.Length + 3), raw_len)
|
|
}
|
|
|
|
for i := 3; i < raw_len; {
|
|
if (i + 3) > raw_len {
|
|
return nil, fmt.Errorf("invalid element length (at %d)",
|
|
i)
|
|
}
|
|
el_iei := raw[i]
|
|
el_len := binary.BigEndian.Uint16(raw[i+1 : i+3])
|
|
|
|
if (i + 3 + int(el_len)) > raw_len {
|
|
return nil, fmt.Errorf("invalid element length (at %d): %d",
|
|
i+1, el_len)
|
|
}
|
|
|
|
switch el_iei {
|
|
// MO Header IEI
|
|
case 1:
|
|
buf := bytes.NewReader(raw[i : i+3+int(el_len)])
|
|
moheader := MOHeader{}
|
|
err := binary.Read(buf, binary.BigEndian, &moheader)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error reading MO header (at %d): %s",
|
|
i, err.Error())
|
|
}
|
|
sdb.Elements = append(sdb.Elements, moheader)
|
|
|
|
// MO Payload IEI
|
|
case 2:
|
|
mopayload := MOPayload{}
|
|
mopayload.IEI = el_iei
|
|
mopayload.Length = el_len
|
|
mopayload.Payload = raw[i+3 : i+3+int(el_len)]
|
|
sdb.Elements = append(sdb.Elements, mopayload)
|
|
|
|
// MO Location IEI
|
|
case 3:
|
|
buf := bytes.NewReader(raw[i : i+3+int(el_len)])
|
|
molocation := MOLocation{}
|
|
err := binary.Read(buf, binary.BigEndian, &molocation)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error reading MO location (at %d): %s",
|
|
i, err.Error())
|
|
}
|
|
sdb.Elements = append(sdb.Elements, molocation)
|
|
|
|
// MO Confirmation IEI
|
|
case 5:
|
|
moconfirmation := MOConfirmation{}
|
|
moconfirmation.IEI = el_iei
|
|
moconfirmation.Length = el_len
|
|
moconfirmation.Status = raw[i+3]
|
|
sdb.Elements = append(sdb.Elements, moconfirmation)
|
|
|
|
default:
|
|
return nil, fmt.Errorf("invalid element IEI (at %d): %d",
|
|
i, el_iei)
|
|
}
|
|
|
|
i += (3 + int(el_len))
|
|
}
|
|
|
|
return &sdb, nil
|
|
}
|