diff --git a/src/BLECharacteristic.cpp b/src/BLECharacteristic.cpp
index bfaee3ff..2fbd9b94 100644
--- a/src/BLECharacteristic.cpp
+++ b/src/BLECharacteristic.cpp
@@ -236,6 +236,32 @@ int BLECharacteristic::readValue(int32_t& value)
   return readValue((uint8_t*)&value, sizeof(value));
 }
 
+int BLECharacteristic::write(const char* value, bool withResponse)
+{
+  if (_local) {
+    return _local->write(value);
+  }
+
+  if (_remote) {
+    return _remote->write(value, withResponse);
+  }
+
+  return 0;
+}
+
+int BLECharacteristic::write(const uint8_t value[], int length, bool withResponse)
+{
+  if (_local) {
+    return _local->write(value, length);
+  }
+
+  if (_remote) {
+    return _remote->write(value, length, withResponse);
+  }
+
+  return 0;
+}
+
 int BLECharacteristic::writeValue(const uint8_t value[], int length, bool withResponse)
 {
   if (_local) {
diff --git a/src/BLECharacteristic.h b/src/BLECharacteristic.h
index da9721e0..8c117b25 100644
--- a/src/BLECharacteristic.h
+++ b/src/BLECharacteristic.h
@@ -77,6 +77,9 @@ class BLECharacteristic  {
   int writeValue(int16_t value, bool withResponse = true);
   int writeValue(uint32_t value, bool withResponse = true);
   int writeValue(int32_t value, bool withResponse = true);
+  int write(const uint8_t value[], int length, bool withResponse = true);
+  int write(const char* value, bool withResponse = true);
+
 
   // deprecated, use writeValue(...)
   int setValue(const uint8_t value[], int length) { return writeValue(value, length); }
diff --git a/src/local/BLELocalCharacteristic.cpp b/src/local/BLELocalCharacteristic.cpp
index 207425bd..9dcf0e8c 100644
--- a/src/local/BLELocalCharacteristic.cpp
+++ b/src/local/BLELocalCharacteristic.cpp
@@ -142,6 +142,47 @@ int BLELocalCharacteristic::writeValue(const char* value)
   return writeValue((uint8_t*)value, strlen(value));
 }
 
+int BLELocalCharacteristic::write(const uint8_t value[], int length)
+{
+  _valueLength = min(length, _valueSize);
+  memcpy(_value, value, _valueLength);
+
+  if (_fixedLength) {
+    _valueLength = _valueSize;
+  }
+
+  if ((_properties & BLEIndicate) && (_cccdValue & 0x0002)) {
+    uint8_t res = ATT.handleInd(valueHandle(), _value,  &_valueLength);
+    if (res != 1){
+      return res;
+    }
+    return _valueLength;
+  } else if ((_properties & BLENotify) && (_cccdValue & 0x0001)) {
+    uint8_t res = ATT.handleNotify(valueHandle(), _value,  &_valueLength);
+     if (res != 1){
+      return res;
+    }
+    return _valueLength;
+  }
+
+  if (_broadcast) {
+    uint16_t serviceUuid = GATT.serviceUuidForCharacteristic(this);
+
+    BLE.setAdvertisedServiceData(serviceUuid, value, length);
+
+    if (!ATT.connected() && GAP.advertising()) {
+      BLE.advertise();
+    }
+  }
+
+  return _valueLength;
+}
+
+int BLELocalCharacteristic::write(const char* value)
+{
+  return write((uint8_t*)value, strlen(value));
+}
+
 int BLELocalCharacteristic::broadcast()
 {
   if (_properties & BLEBroadcast) {
diff --git a/src/local/BLELocalCharacteristic.h b/src/local/BLELocalCharacteristic.h
index 331cdd5c..c73d0512 100644
--- a/src/local/BLELocalCharacteristic.h
+++ b/src/local/BLELocalCharacteristic.h
@@ -49,6 +49,8 @@ class BLELocalCharacteristic : public BLELocalAttribute {
 
   int writeValue(const uint8_t value[], int length);
   int writeValue(const char* value);
+  int write(const uint8_t value[], int length);
+  int write(const char* value);
 
   int broadcast();
 
diff --git a/src/remote/BLERemoteCharacteristic.cpp b/src/remote/BLERemoteCharacteristic.cpp
index 454438b6..52dc480b 100644
--- a/src/remote/BLERemoteCharacteristic.cpp
+++ b/src/remote/BLERemoteCharacteristic.cpp
@@ -86,6 +86,59 @@ uint8_t BLERemoteCharacteristic::operator[] (int offset) const
   return 0;
 }
 
+int BLERemoteCharacteristic::write(const uint8_t value[], int length, bool withResponse)
+{
+  if (!ATT.connected(_connectionHandle)) {
+    return false;
+  }
+
+  uint16_t maxLength = ATT.mtu(_connectionHandle) - 3;
+
+  if (length > (int)maxLength) {
+    // cap to MTU max length
+    length = maxLength;
+  }
+
+  _value = (uint8_t*)realloc(_value, length);
+  if (_value == NULL) {
+    // realloc failed
+    return 0;
+  }
+
+  if ((_properties & BLEWrite) && withResponse) {
+    uint8_t resp[4];
+    int respLength = ATT.writeReq(_connectionHandle, _valueHandle, value, length, resp);
+
+    if (!respLength) {
+      return 0;
+    }
+
+    if (resp[0] == 0x01) {
+      // error
+      return 0;
+    }
+
+    memcpy(_value, value, length);
+    _valueLength = length;
+
+    return length;
+  } else if (_properties & BLEWriteWithoutResponse) {
+    ATT.writeCmd(_connectionHandle, _valueHandle, value, length);
+
+    memcpy(_value, value, length);
+    _valueLength = length;
+
+    return length;
+  }
+
+  return 0;
+}
+
+int BLERemoteCharacteristic::write(const char* value, bool withResponse)
+{
+  return write((uint8_t*)value, strlen(value), withResponse);
+}
+
 int BLERemoteCharacteristic::writeValue(const uint8_t value[], int length, bool withResponse)
 {
   if (!ATT.connected(_connectionHandle)) {
diff --git a/src/remote/BLERemoteCharacteristic.h b/src/remote/BLERemoteCharacteristic.h
index b53ab031..9b2e493c 100644
--- a/src/remote/BLERemoteCharacteristic.h
+++ b/src/remote/BLERemoteCharacteristic.h
@@ -41,6 +41,8 @@ class BLERemoteCharacteristic : public BLERemoteAttribute {
 
   int writeValue(const uint8_t value[], int length, bool withResponse = true);
   int writeValue(const char* value, bool withResponse = true);
+  int write(const uint8_t value[], int length, bool withResponse = true);
+  int write(const char* value, bool withResponse = true);
 
   bool valueUpdated();
   bool updatedValueRead();
diff --git a/src/utility/ATT.cpp b/src/utility/ATT.cpp
index b1796c90..0dd979e9 100644
--- a/src/utility/ATT.cpp
+++ b/src/utility/ATT.cpp
@@ -582,7 +582,12 @@ BLEDevice ATTClass::central()
   return BLEDevice();
 }
 
-bool ATTClass::handleNotify(uint16_t handle, const uint8_t* value, int length)
+bool ATTClass::handleNotify(uint16_t handle, const uint8_t *value, int length)
+{
+  return handleNotify(handle, value, (uint16_t*)&length);
+}
+
+bool ATTClass::handleNotify(uint16_t handle, const uint8_t* value, uint16_t *length)
 {
   int numNotifications = 0;
 
@@ -600,9 +605,9 @@ bool ATTClass::handleNotify(uint16_t handle, const uint8_t* value, int length)
     memcpy(&notification[1], &handle, sizeof(handle));
     notificationLength += sizeof(handle);
 
-    length = min((uint16_t)(_peers[i].mtu - notificationLength), (uint16_t)length);
-    memcpy(&notification[notificationLength], value, length);
-    notificationLength += length;
+    *length = min((uint16_t)(_peers[i].mtu - notificationLength), *length);
+    memcpy(&notification[notificationLength], value, *length);
+    notificationLength += *length;
 
     /// TODO: Set encryption requirement on notify.
     HCI.sendAclPkt(_peers[i].connectionHandle, ATT_CID, notificationLength, notification);
@@ -613,7 +618,12 @@ bool ATTClass::handleNotify(uint16_t handle, const uint8_t* value, int length)
   return (numNotifications > 0);
 }
 
-bool ATTClass::handleInd(uint16_t handle, const uint8_t* value, int length)
+bool ATTClass::handleInd(uint16_t handle, const uint8_t *value, int length)
+{
+  return handleInd(handle, value, (uint16_t*)&length);
+}
+
+bool ATTClass::handleInd(uint16_t handle, const uint8_t* value, uint16_t *length)
 {
   int numIndications = 0;
 
@@ -631,9 +641,10 @@ bool ATTClass::handleInd(uint16_t handle, const uint8_t* value, int length)
     memcpy(&indication[1], &handle, sizeof(handle));
     indicationLength += sizeof(handle);
 
-    length = min((uint16_t)(_peers[i].mtu - indicationLength), (uint16_t)length);
-    memcpy(&indication[indicationLength], value, length);
-    indicationLength += length;
+    *length = min((uint16_t)(_peers[i].mtu - indicationLength), *length);
+
+    memcpy(&indication[indicationLength], value, *length);
+    indicationLength += *length;
 
     _cnf = false;
 
diff --git a/src/utility/ATT.h b/src/utility/ATT.h
index c9f007f9..fd44d8a8 100644
--- a/src/utility/ATT.h
+++ b/src/utility/ATT.h
@@ -84,7 +84,9 @@ class ATTClass {
   virtual BLEDevice central();
 
   virtual bool handleNotify(uint16_t handle, const uint8_t* value, int length);
+  virtual bool handleNotify(uint16_t handle, const uint8_t* value, uint16_t *length);
   virtual bool handleInd(uint16_t handle, const uint8_t* value, int length);
+  virtual bool handleInd(uint16_t handle, const uint8_t* value, uint16_t *length);
 
   virtual void setEventHandler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);