func uuidSlice(uu []ble.UUID) [][]byte { us := [][]byte{} for _, u := range uu { us = append(us, ble.Reverse(u)) } return us }
// AdvertiseIBeacon advertises iBeacon packet. func (d *Device) AdvertiseIBeacon(ctx context.Context, u ble.UUID, major, minor uint16, pwr int8) error { b := make([]byte, 21) copy(b, ble.Reverse(u)) // Big endian binary.BigEndian.PutUint16(b[16:], major) // Big endian binary.BigEndian.PutUint16(b[18:], minor) // Big endian b[20] = uint8(pwr) // Measured Tx Power return d.AdvertiseIBeaconData(ctx, b) }
func (a *adv) Services() []ble.UUID { xUUIDs, ok := a.ad["kCBAdvDataServiceUUIDs"] if !ok { return nil } var uuids []ble.UUID for _, xUUID := range xUUIDs.(xpc.Array) { uuids = append(uuids, ble.UUID(ble.Reverse(xUUID.([]byte)))) } return uuids }
// IBeacon returns an iBeacon advertising packet with specified parameters. func IBeacon(u ble.UUID, major, minor uint16, pwr int8) Field { return func(p *Packet) error { if u.Len() != 16 { return ErrInvalid } md := make([]byte, 23) md[0] = 0x02 // Data type: iBeacon md[1] = 0x15 // Data length: 21 bytes copy(md[2:], ble.Reverse(u)) // Big endian binary.BigEndian.PutUint16(md[18:], major) // Big endian binary.BigEndian.PutUint16(md[20:], minor) // Big endian md[22] = uint8(pwr) // Measured Tx Power return ManufacturerData(0x004C, md)(p) } }
// AddService adds a service to device's database. // The following services are ignored as they are provided by OS X. // // 0x1800 (Generic Access) // 0x1801 (Generic Attribute) // 0x1805 (Current Time Service) // 0x180A (Device Information) // 0x180F (Battery Service) // 0x1812 (Human Interface Device) func (d *Device) AddService(s *ble.Service) error { if s.UUID.Equal(ble.GAPUUID) || s.UUID.Equal(ble.GATTUUID) || s.UUID.Equal(ble.CurrentTimeUUID) || s.UUID.Equal(ble.DeviceInfoUUID) || s.UUID.Equal(ble.BatteryUUID) || s.UUID.Equal(ble.HIDUUID) { return nil } xs := xpc.Dict{ "kCBMsgArgAttributeID": d.base, "kCBMsgArgAttributeIDs": []int{}, "kCBMsgArgCharacteristics": nil, "kCBMsgArgType": 1, // 1 => primary, 0 => excluded "kCBMsgArgUUID": ble.Reverse(s.UUID), } d.base++ xcs := xpc.Array{} for _, c := range s.Characteristics { props := 0 perm := 0 if c.Property&ble.CharRead != 0 { props |= 0x02 if ble.CharRead&c.Secure != 0 { perm |= 0x04 } else { perm |= 0x01 } } if c.Property&ble.CharWriteNR != 0 { props |= 0x04 if c.Secure&ble.CharWriteNR != 0 { perm |= 0x08 } else { perm |= 0x02 } } if c.Property&ble.CharWrite != 0 { props |= 0x08 if c.Secure&ble.CharWrite != 0 { perm |= 0x08 } else { perm |= 0x02 } } if c.Property&ble.CharNotify != 0 { if c.Secure&ble.CharNotify != 0 { props |= 0x100 } else { props |= 0x10 } } if c.Property&ble.CharIndicate != 0 { if c.Secure&ble.CharIndicate != 0 { props |= 0x200 } else { props |= 0x20 } } xc := xpc.Dict{ "kCBMsgArgAttributeID": d.base, "kCBMsgArgUUID": ble.Reverse(c.UUID), "kCBMsgArgAttributePermissions": perm, "kCBMsgArgCharacteristicProperties": props, "kCBMsgArgData": c.Value, } c.Handle = uint16(d.base) d.chars[d.base] = c d.base++ xds := xpc.Array{} for _, d := range c.Descriptors { if d.UUID.Equal(ble.ClientCharacteristicConfigUUID) { // skip CCCD continue } xd := xpc.Dict{ "kCBMsgArgData": d.Value, "kCBMsgArgUUID": ble.Reverse(d.UUID), } xds = append(xds, xd) } xc["kCBMsgArgDescriptors"] = xds xcs = append(xcs, xc) } xs["kCBMsgArgCharacteristics"] = xcs return d.sendReq(d.pm, 10, xs).err() }