diff --git a/adapter_linux.go b/adapter_linux.go index 15aa354..b225348 100644 --- a/adapter_linux.go +++ b/adapter_linux.go @@ -12,7 +12,7 @@ import ( type Adapter struct { adapter *adapter.Adapter1 - id string + ID string cancelChan chan struct{} defaultAdvertisement *Advertisement @@ -32,12 +32,12 @@ var DefaultAdapter = &Adapter{ // Enable configures the BLE stack. It must be called before any // Bluetooth-related calls (unless otherwise indicated). func (a *Adapter) Enable() (err error) { - if a.id == "" { + if a.ID == "" { a.adapter, err = api.GetDefaultAdapter() if err != nil { return } - a.id, err = a.adapter.GetAdapterID() + a.ID, err = a.adapter.GetAdapterID() } return nil } diff --git a/gap.go b/gap.go index 63998f4..ccea884 100644 --- a/gap.go +++ b/gap.go @@ -123,6 +123,9 @@ type AdvertisementPayload interface { // UUIDs and 128-bit UUIDs. HasServiceUUID(UUID) bool + //Optputs what i think is the raw data packet + ServiceUUIDOut() []UUID + // Bytes returns the raw advertisement packet, if available. It returns nil // if this data is not available. Bytes() []byte @@ -164,6 +167,16 @@ func (p *advertisementFields) HasServiceUUID(uuid UUID) bool { return false } +func (p *advertisementFields) ServiceUUIDOut() []UUID { + return p.AdvertisementFields.ServiceUUIDs +} + +/* +func (p *advertisementFields) ServiceUUIDOut() []UUID { + return p.AdvertisementFields.ServiceUUIDs +} +*/ + // Bytes returns nil, as structured advertisement data does not have the // original raw advertisement data available. func (p *advertisementFields) Bytes() []byte { @@ -174,13 +187,13 @@ func (p *advertisementFields) Bytes() []byte { // get the data (such as LocalName()) will parse just the needed field. Scanning // the data should be fast as most advertisement packets only have a very small // (3 or so) amount of fields. -type rawAdvertisementPayload struct { +type RawAdvertisementPayload struct { data [31]byte len uint8 } // Bytes returns the raw advertisement packet as a byte slice. -func (buf *rawAdvertisementPayload) Bytes() []byte { +func (buf *RawAdvertisementPayload) Bytes() []byte { return buf.data[:buf.len] } @@ -188,7 +201,7 @@ func (buf *rawAdvertisementPayload) Bytes() []byte { // // See this list of field types: // https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/ -func (buf *rawAdvertisementPayload) findField(fieldType byte) []byte { +func (buf *RawAdvertisementPayload) FindField(fieldType byte) []byte { data := buf.Bytes() for len(data) >= 2 { fieldLength := data[0] @@ -206,12 +219,12 @@ func (buf *rawAdvertisementPayload) findField(fieldType byte) []byte { // LocalName returns the local name (complete or shortened) in the advertisement // payload. -func (buf *rawAdvertisementPayload) LocalName() string { - b := buf.findField(9) // Complete Local Name +func (buf *RawAdvertisementPayload) LocalName() string { + b := buf.FindField(9) // Complete Local Name if len(b) != 0 { return string(b) } - b = buf.findField(8) // Shortened Local Name + b = buf.FindField(8) // Shortened Local Name if len(b) != 0 { return string(b) } @@ -221,11 +234,11 @@ func (buf *rawAdvertisementPayload) LocalName() string { // HasServiceUUID returns true whether the given UUID is present in the // advertisement payload as a Service Class UUID. It checks both 16-bit UUIDs // and 128-bit UUIDs. -func (buf *rawAdvertisementPayload) HasServiceUUID(uuid UUID) bool { +func (buf *RawAdvertisementPayload) HasServiceUUID(uuid UUID) bool { if uuid.Is16Bit() { - b := buf.findField(0x03) // Complete List of 16-bit Service Class UUIDs + b := buf.FindField(0x03) // Complete List of 16-bit Service Class UUIDs if len(b) == 0 { - b = buf.findField(0x02) // Incomplete List of 16-bit Service Class UUIDs + b = buf.FindField(0x02) // Incomplete List of 16-bit Service Class UUIDs } uuid := uuid.Get16Bit() for i := 0; i < len(b)/2; i++ { @@ -236,9 +249,9 @@ func (buf *rawAdvertisementPayload) HasServiceUUID(uuid UUID) bool { } return false } else { - b := buf.findField(0x07) // Complete List of 128-bit Service Class UUIDs + b := buf.FindField(0x07) // Complete List of 128-bit Service Class UUIDs if len(b) == 0 { - b = buf.findField(0x06) // Incomplete List of 128-bit Service Class UUIDs + b = buf.FindField(0x06) // Incomplete List of 128-bit Service Class UUIDs } uuidBuf1 := uuid.Bytes() for i := 0; i < len(b)/16; i++ { @@ -258,8 +271,27 @@ func (buf *rawAdvertisementPayload) HasServiceUUID(uuid UUID) bool { } } +/// Very dumb attempts at reworking this code ************************************************ +var FUUID uint16 + +func (buf *RawAdvertisementPayload) FindServiceUUIDInfo(uuid UUID) uint16 { + if uuid.Is16Bit() { + b := buf.FindField(0x03) // Complete List of 16-bit Service Class UUIDs + if len(b) == 0 { + b = buf.FindField(0x02) // Incomplete List of 16-bit Service Class UUIDs + } + for i := 0; i < len(b)/2; i++ { + foundUUID := uint16(b[i*2]) | (uint16(b[i*2+1]) << 8) + + FUUID = foundUUID + } + + } + return FUUID +} + // reset restores this buffer to the original state. -func (buf *rawAdvertisementPayload) reset() { +func (buf *RawAdvertisementPayload) reset() { // The data is not reset (only the length), because with a zero length the // data is undefined. buf.len = 0 @@ -268,7 +300,7 @@ func (buf *rawAdvertisementPayload) reset() { // addFromOptions constructs a new advertisement payload (assumed to be empty // before the call) from the advertisement options. It returns true if it fits, // false otherwise. -func (buf *rawAdvertisementPayload) addFromOptions(options AdvertisementOptions) (ok bool) { +func (buf *RawAdvertisementPayload) addFromOptions(options AdvertisementOptions) (ok bool) { buf.addFlags(0x06) if options.LocalName != "" { if !buf.addCompleteLocalName(options.LocalName) { @@ -290,7 +322,7 @@ func (buf *rawAdvertisementPayload) addFromOptions(options AdvertisementOptions) // addFlags adds a flags field to the advertisement buffer. It returns true on // success (the flags can be added) and false on failure. -func (buf *rawAdvertisementPayload) addFlags(flags byte) (ok bool) { +func (buf *RawAdvertisementPayload) addFlags(flags byte) (ok bool) { if int(buf.len)+3 > len(buf.data) { return false // flags don't fit } @@ -304,7 +336,7 @@ func (buf *rawAdvertisementPayload) addFlags(flags byte) (ok bool) { // addCompleteLocalName adds the Complete Local Name field to the advertisement // buffer. It returns true on success (the name fits) and false on failure. -func (buf *rawAdvertisementPayload) addCompleteLocalName(name string) (ok bool) { +func (buf *RawAdvertisementPayload) addCompleteLocalName(name string) (ok bool) { if int(buf.len)+len(name)+2 > len(buf.data) { return false // name doesn't fit } @@ -319,7 +351,7 @@ func (buf *rawAdvertisementPayload) addCompleteLocalName(name string) (ok bool) // addServiceUUID adds a Service Class UUID (16-bit or 128-bit). It has // currently only been designed for adding single UUIDs: multiple UUIDs are // stored in separate fields without joining them together in one field. -func (buf *rawAdvertisementPayload) addServiceUUID(uuid UUID) (ok bool) { +func (buf *RawAdvertisementPayload) addServiceUUID(uuid UUID) (ok bool) { // Don't bother with 32-bit UUID support, it doesn't seem to be used in // practice. if uuid.Is16Bit() { diff --git a/gap_linux.go b/gap_linux.go index 9d3fd14..1a23e14 100644 --- a/gap_linux.go +++ b/gap_linux.go @@ -59,7 +59,7 @@ func (a *Advertisement) Start() error { if a.advertisement != nil { panic("todo: start advertisement a second time") } - _, err := api.ExposeAdvertisement(a.adapter.id, a.properties, uint32(a.properties.Timeout)) + _, err := api.ExposeAdvertisement(a.adapter.ID, a.properties, uint32(a.properties.Timeout)) if err != nil { return err } @@ -219,6 +219,8 @@ func makeScanResult(props *device.Device1Properties) ScanResult { serviceUUIDs = append(serviceUUIDs, parsedUUID) } + //var ManufactuerData UUID + a := Address{MACAddress{MAC: addr}} a.SetRandom(props.AddressType == "random") diff --git a/gattc_linux.go b/gattc_linux.go index 8a8c5dc..2a7113f 100644 --- a/gattc_linux.go +++ b/gattc_linux.go @@ -39,6 +39,7 @@ func (s *DeviceService) UUID() UUID { // services haven't been resolved yet) and uses this list of cached services. func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) { for { + resolved, err := d.device.GetServicesResolved() if err != nil { return nil, err @@ -47,7 +48,7 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) { break } // This is a terrible hack, but I couldn't find another way. - time.Sleep(10 * time.Millisecond) + time.Sleep(50 * time.Millisecond) } services := []DeviceService{} @@ -178,6 +179,8 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter } } + time.Sleep(50 * time.Millisecond) + if _, ok := uuidChars[char.Properties.UUID]; ok { // There is more than one characteristic with the same UUID? // Don't overwrite it, to keep the servicesFound count correct. @@ -242,3 +245,4 @@ func (c *DeviceCharacteristic) Read(data []byte) (int, error) { copy(data, result) return len(result), nil } + diff --git a/gatts_linux.go b/gatts_linux.go index 0422c44..5e1d3ef 100644 --- a/gatts_linux.go +++ b/gatts_linux.go @@ -18,7 +18,7 @@ type Characteristic struct { // Service struct. func (a *Adapter) AddService(s *Service) error { app, err := service.NewApp(service.AppOptions{ - AdapterID: a.id, + AdapterID: a.ID, }) if err != nil { return err diff --git a/go.mod b/go.mod index 9331273..c4b168d 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module tinygo.org/x/bluetooth +module git.tcp.direct/kayos/prototooth go 1.15